Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions .claude/agents/serverless-plugin-author.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
---
name: serverless-plugin-author
description: >-
Implements and reviews changes to the CoorpAcademy/serverless-plugins monorepo
(serverless-offline-s3/sqs/kinesis/dynamodb-streams, dynamodb-streams-readable,
serverless-apigateway-access-logs). Use for v4 migration work, bug fixes, re-implementing
community-PR ideas as our own code, adding docker-free unit tests, and pre-PR review. Knows
the shared plugin lifecycle, the v4 logger contract, lodash/fp conventions, and the
eslint/ava/docker gating. Give it ONE well-scoped task with a TODO doc to follow.
tools: Read, Edit, Write, Grep, Glob, Bash
model: sonnet
---

You implement and review changes to **CoorpAcademy/serverless-plugins** — our own Serverless
Framework plugin monorepo. You produce correct, house-style, gated code and credit original authors
when re-implementing a community-PR idea. You own the work.

## Operating rules

1. **Load context first.** Read the task's TODO doc under `docs/plans/`, plus `docs/architecture.md`,
`docs/conventions.md`, and `docs/testing-and-ci.md`. Read the actual `src/` you're changing.
2. **Match the house pattern** (see `.claude/skills/serverless-plugin-dev/SKILL.md`):
- CommonJS, lodash/fp, classes-with-pure-helpers, Node ≥16 syntax (dynamic import OK).
- **Never** `require('@serverless/utils/log')`. Take `{log}` from the 3rd constructor arg, normalize
with `normalizeLog`, thread `this.log` into sub-modules, use `notice`/`debug`/`warning` (not `warn`).
- Keep the `await import('serverless-offline/lambda')` dynamic import.
3. **Extract pure functions** for any logic worth testing; keep AWS clients, `process.exit`, listeners,
and timers at the edges. This is both house style and what makes docker-free unit tests possible.
4. **Test what you touch.** Add/extend `packages/<pkg>/test/*.js` AVA unit tests (the AVA glob is
`packages/**/test/*.js`). The offline plugins start with zero unit tests — improve that.
5. **Gate before declaring done:**
- `npm run eslint` MUST be green (it includes Prettier). Fix all lint/format errors.
- Run `npx ava` for unit tests. Run integration only if Docker is available; otherwise say so.
- Never claim integration/v4-e2e passed if you didn't run it. Report honestly what ran.
6. **Preserve v3 compatibility.** Keep peer ranges wide (`serverless-offline: ">=11"`). Prefer
**minor** version bumps for backward-compatible changes. If you add a file to a package, add it to
that package's `package.json` `files` array and update the README.
7. **Stay in scope.** Do exactly the assigned unit. Note adjacent bugs you spot; don't fix them unless
the task says so.

## Known live bugs (fix only if your task covers them)

- `this.region` is undefined in `sqs.js`/`kinesis.js`/`dynamodb-streams.js` → use `this.options.region`.
- `kinesis.js`/`dynamodb-streams.js` swallow handler errors → thread `this.log` and log warnings.
- `s3.js` dead methods `_create`/`_s3Event` → safe to delete.
- `kinesis-event-definition.js` omits `tableName` (should be `streamName`).
- SQS delete-batch uses `MessageId` as entry `Id` → use the array index (unique, ≤80 chars).
- `_createQueue` JSON-stringifies CFN intrinsics (`Fn::GetAtt`/`Ref`) → resolve/skip them.
- Kinesis retries handler failures forever → add a bounded retry + logging (mirror dynamodb).

## Output

Return a tight report: what changed (file:line), why, which gates ran and their result (paste the key
output), any deferred/adjacent issues, and the suggested version bump. If something didn't pass, say
so plainly with the failing output — do not paper over it.
</content>
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"session_id": "03355ac2-04f1-4c79-b226-c48f5d5a7275",
"prompts": [
"this sls offiline package would nee a bump to node 22 or even 24, checl out the recent work /Users/silouane/coorp/serverless-plugins/docs and current plan in motion from other session and let's make a PR ( we would need to rebase later but thats fine I guess) to bump to node 22 then 24 if possible"
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"session_id": "2119c290-7515-4234-a1d9-5a11529eece7",
"prompts": [
"/prime & explore currrent / recent work , read /Users/silouane/coorp/serverless-plugins/docs, this is us taking back the support of this sls offfline open source repository and amongst our target I wonder if we could/should support other aws ms: /Users/silouane/coorp/serverless-plugins/packages'/var/folders/yl/b9rjyzbn5kg5y0_b61qdb_wm0000gq/T/TemporaryItems/NSIRD_screencaptureui_fuKR12/Screenshot 2026-06-20 at 01.17.08.png'. because read this project /Users/silouane/coorp/translated-language-service and priotize what we should support NEXT to get a full TLS support by our offline sls. a LOT os aws ms is ATM not support which is preventing us to launcht the TLS stack 100% locally"
]
}
12 changes: 12 additions & 0 deletions .claude/data/sessions/4f65f198-0c0c-47a2-b6ab-5f2e30ae5cbe.json

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"session_id": "abc7156b-6420-4373-a150-9b2eecad6805",
"prompts": [
"/prime & check out our recent work /Users/silouane/coorp/serverless-plugins/docs then lets focus taking back this repository to its feet. A LOT OF ISSUE: https://github.com/CoorpAcademy/serverless-plugins/issues?q=sort%3Aupdated-desc+is%3Aissue+state%3Aopen+ let's read them all and perform categorization. I need everything written in the doc locally. Report on actual issue, issue we need to fix, issue we already fixed issue we cant ditch. THIS IS READ ONLY WORKFLOW FOR NOW, but local doc must be representative of the action plan for each issue so I can get clarity",
"ok, leading from my PR sls v4 can we create 10 PR for the real bug small fix ? and also adress the keep valuable and create PR for them ? this is like 19 PR to be created. THIS IS SOME MASSIVE WORKFLOW WE NEED TO SETUP HERE. SET A CLEAR GOAL FOR THIS WORK. and create the workflow. ensure gating ( all PR need to be green before being push) and post push a loop mus tbe created to check PR CI and verify its still GREEN in travis. ANd all PR have clear description. Even if the work is maybe decorelated IT IS NOT, same REPO, HIGH CHANCE OF OVERLAP, spawn 19 different workflow, but work will be sequentially merged. so it might be better to work on the same brand and sequentially adress issue ? help me out there for the good practice of this open source repository."
]
}
124 changes: 124 additions & 0 deletions .claude/skills/serverless-plugin-dev/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
---
name: serverless-plugin-dev
description: >-
Use when modifying, fixing, testing, adding features to, or publishing any package in the
CoorpAcademy/serverless-plugins monorepo — serverless-offline-s3, serverless-offline-sqs,
serverless-offline-kinesis, serverless-offline-dynamodb-streams, dynamodb-streams-readable,
serverless-apigateway-access-logs. Encodes the shared plugin lifecycle, the Serverless v4
logger contract, the lodash/fp + FP-with-classes conventions, the gating commands
(eslint/prettier + ava + docker integration), and the lerna publish flow. Load this BEFORE
editing plugin source so changes match the house pattern and pass CI.
---

# serverless-plugins — developer skill

CoorpAcademy's own collection of Serverless Framework plugins. Lerna **independent**-versioned
monorepo, npm workspaces, AVA + Docker integration tests, Travis CI, ESLint (with Prettier baked
in via `@coorpacademy/coorpacademy/prettier`). We **own** this repo.

## Read these first (deep references)

- `docs/architecture.md` — the shared 4-plugin lifecycle, hooks, Lambda runner, event extraction.
- `docs/conventions.md` — lodash/fp, FP-with-classes, immutability, error handling, naming.
- `docs/testing-and-ci.md` — AVA gap, the Docker harness, "what can I run / what it needs".
- `docs/publishing-and-versioning.md` — lerna, peer coupling, v4 strategy, publish playbook.
- `docs/serverless-v4-migration-review.md` + `docs/open-pr-triage.md` — the v4 work + PR triage.

## The shared plugin shape (the 4 `serverless-offline-*` plugins)

Each is a class in `packages/<pkg>/src/index.js` with a tiny emulator sub-module
(`s3.js` / `sqs.js` / `kinesis.js` / `dynamodb-streams.js`) and `*-event.js` / `*-event-definition.js`.

```
constructor(serverless, cliOptions, {log} = {}) // v4 injects {log,writeText,progress} as 3rd arg
hooks: offline:start:init → start()
offline:start:ready → ready()
offline:start → _startWithReady()
offline:start:end → end()

start() → _mergeOptions() → _getEvents() → _createLambda() → _create<Service>()
ready() → _listenForTermination() (SIGINT/SIGTERM → end())
end() → cleanup lambda + emulator → process.exit(0) unless skipExit
```

- **Lambda runner** is loaded lazily: `const {default: Lambda} = await import('serverless-offline/lambda')`
(serverless-offline is ESM-only). Keep the dynamic import — do not convert to `require('.../src/lambda')`.
- **Option precedence** in `_mergeOptions` (lowest→highest): `defaultOptions`, `provider`,
`serverless-offline` opts (`location`,`localEnvironment`), the plugin's `custom` opts, `cliOptions`.
- **Event extraction** `_getEvents()` walks `service.getAllFunctions()`; `_resolveFn` resolves
CloudFormation `Fn::GetAtt` ARNs to concrete queue/stream/table names.

## ⚠️ Serverless v4 logger contract (the #1 rule)

v4 **removed** `@serverless/utils/log` and `serverless.cli.log`. **Never** `require('@serverless/utils/log')`.
Take the logger from the **3rd constructor arg** (works on v3.0+ AND v4) and console-fallback:

```js
// src/log.js (per package — published, so it must live inside the package)
const noop = () => {};
const defaultLog = {
debug: noop, // quiet by default; serverless controls verbosity
info: console.log.bind(console),
notice: console.log.bind(console),
warning: console.warn.bind(console),
error: console.error.bind(console),
success: console.log.bind(console)
};
const normalizeLog = log => ({...defaultLog, ...log}); // spread of null/undefined is a no-op
module.exports = {defaultLog, normalizeLog};
```

- Constructor: `this.log = normalizeLog(log)` then **thread `this.log` into sub-modules**
(`new S3(this.lambda, resources, this.options, this.log)`).
- Use `this.log.notice(...)` (was `serverless.cli.log`), `this.log.debug(...)`, `this.log.warning(...)`.
- The v4 logger uses **`warning`**, not `warn`. (Old code's `log.warn` was a latent bug.)

## Known live bugs / gotchas (verified against master)

- **`this.region` is undefined** in `sqs.js`, `kinesis.js`, `dynamodb-streams.js` (constructors only
set `this.options`). Use `this.options.region`. Emitted events' `awsRegion` is wrong until fixed.
- `kinesis.js` / `dynamodb-streams.js` **swallow handler errors silently** (no logger). Thread `this.log`.
- `s3.js` has **dead methods** `_create`/`_s3Event` (the latter calls `listener.stop()` immediately). Safe to delete.
- `kinesis-event-definition.js` omits `tableName` (copy-paste) — should omit `streamName`.
- SQS delete-batch uses `MessageId` as the batch entry `Id` — not guaranteed unique/≤80 chars; use the array index.
- `_createQueue` blindly `JSON.stringify`s all queue properties incl. CFN intrinsics (`Fn::GetAtt`, `Ref`).
- Kinesis retries failed handlers **forever** with no cap (dynamodb has a bounded retry — mirror it).

## Conventions (house style)

- **CommonJS** (`require`/`module.exports`), Node ≥16 syntax (dynamic import allowed).
- **lodash/fp** everywhere (`get`, `pipe`, `omitBy`, `assign`, …). Prefer point-free, data-last.
- Classes are allowed (`fp/no-class` off) but keep logic in **small pure functions** with side effects
(AWS clients, process.exit, listeners) at the edges — this also makes them unit-testable without Docker.
- `no-param-reassign` is **off** but avoid mutating inputs; prefer building new objects.
- `no-console` is off (the console fallback relies on it).

## Gating — run before every commit/PR

| Gate | Command | Needs |
|---|---|---|
| Lint **and** format (Prettier) | `npm run eslint` | nothing — always run this |
| Unit tests | `npx ava` (or `npm run test:unit`) | `nyc ava`'s pretest spins Docker; `npx ava` alone runs JS-only tests |
| Integration | `npm run test:integration` | Docker (minio/elasticmq/kinesalite/dynamodb-local) |
| v4 end-to-end | `sls package` / `sls offline` in a consumer | Docker + `serverless@4` + `SERVERLESS_ACCESS_KEY` |

**Always** make `npm run eslint` green. **Add docker-free AVA unit tests** for any pure logic you
touch (the offline plugins currently have none) — put them in `packages/<pkg>/test/*.js` (the AVA glob).

## Versioning & publishing (lerna independent)

- Preserve **v3 compatibility**: keep peer ranges wide (`serverless-offline: ">=11"`); the v4 fix is
backward compatible, so prefer **minor** bumps over majors unless you truly drop old support.
- If you add a new file to a package (e.g. `src/log.js`), add it to that package's `package.json` `files` array.
- Publish: `npm run publish` (`lerna publish`). **Canary first**, smoke-test one consumer, then stable.
- v4 `deploy` needs `SERVERLESS_ACCESS_KEY`; `package`/`offline` do not.

## How to add a fix or feature (playbook)

1. Read the relevant `docs/*` + the package's `src/`.
2. Make the change in the house style; extract pure helpers for anything testable.
3. Add/extend `packages/<pkg>/test/*.js` AVA unit tests for the pure logic.
4. `npm run eslint` → green. Run AVA. Run integration if Docker available.
5. Bump the package version (minor for back-compatible) and update its README + `files` if needed.
6. PR with a clear description; credit any original community-PR author whose idea you re-implemented.
</content>
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v18.18.2
v24.17.0
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ sudo: required
language: node_js

node_js:
- "20"
- "18"
- "24"
- "22"

services:
- docker
Expand Down
13 changes: 13 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# serverless-plugins — engineering docs

Working notes for the CoorpAcademy ownership of `serverless-plugins` (CLXP-103).

| Doc | What it covers |
|---|---|
| [`serverless-v4-migration-review.md`](./serverless-v4-migration-review.md) | Critical review of the v4 migration & PR #264. What's right, what to challenge, recommended path. |
| [`open-pr-triage.md`](./open-pr-triage.md) | Triage of all 17 open PRs: keep / merge-as-is / merge-after-work / re-implement / close. |
| [`open-issue-triage.md`](./open-issue-triage.md) | Triage of all 65 open issues against current code: fixed-on-release / real bug / keep / ditch + 2 investigation clusters, with a per-issue action plan. |

> Status: 2026-06-20 — read-only analysis. PR triage (2026-06-19) + issue triage (2026-06-20). No code changed.
</content>
</invoke>
Loading