Skip to content

feat: Serverless Framework v4 support + plugin hardening (offline s3/sqs/kinesis/dynamodb-streams)#265

Merged
silouone merged 7 commits into
masterfrom
feat/serverless-v4-support
Jun 20, 2026
Merged

feat: Serverless Framework v4 support + plugin hardening (offline s3/sqs/kinesis/dynamodb-streams)#265
silouone merged 7 commits into
masterfrom
feat/serverless-v4-support

Conversation

@silouone

Copy link
Copy Markdown
Member

What & why

Serverless Framework v4 removed @serverless/utils/log and serverless.cli.log. Our four
serverless-offline-* plugins require that module at load time, so they crash on every sls
command under v4
(sls package, sls offline, …). This PR migrates all four to the logger that
the framework injects as the plugin constructor's 3rd argument ({log}) — which has existed
since serverless v3.0, so the change is backward compatible with v3.

While we were in here owning this code, we also re-implemented the worthwhile ideas from several
long-open community PRs as our own, tested code, and fixed a batch of latent bugs the migration
surfaced.

Supersedes the partial v4 PR #264 (s3+sqs only): this covers all four plugins, keeps peers
wide (no forced v14 cutover), and adds the unit tests + correctness fixes that one was missing.
See docs/serverless-v4-migration-review.md and docs/open-pr-triage.md for the full analysis.

Changes per package

All four — remove the dead @serverless/utils/log require; take {log} from the 3rd ctor arg via a
new src/log.js shim (full level set, console fallback); thread it into the emulator; replace
serverless.cli.logthis.log.notice. Minor version bump; peer kept ^10.0.2 || >=11.

Compatibility

  • Works on serverless v3 and v4 (the {log} 3rd arg exists in both; console fallback if absent).
  • Peer ranges kept wide (serverless-offline: ^10.0.2 || >=11) — services can migrate one at a time.
  • Minor version bumps (behavior-preserving + additive). No new runtime dependencies.

Testing

Tooling added

Repo docs under docs/ (architecture, conventions, testing-and-ci, publishing-and-versioning, the
review + triage, and per-task plans), plus a serverless-plugin-dev skill and a
serverless-plugin-author agent under .claude/ to help future work on these plugins.

Credits

Re-implements ideas from community PRs #166 (@zlalvani), #253 (@flipscholtz), #211
(@mfamilia), #98 & #100 (@dolsem), #249 (@gabsong) — thank you. 🙏

Follow-ups (not in this PR)

🤖 Generated with Claude Code

silouone and others added 5 commits June 20, 2026 00:57
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Drop the removed @serverless/utils/log require; take {log} from the 3rd constructor arg via a new src/log.js shim (console fallback) and thread it into the S3 emulator.
- Replace removed serverless.cli.log with this.log.notice; fix log.warn -> log.warning.
- Remove dead _create/_s3Event methods and the now-orphaned s3-event-definition.js.
- Backward compatible with serverless v3 (peer kept wide). Adds docker-free unit tests. v7.1.0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ueName fixes

- Serverless v4 logger migration (src/log.js shim threaded into the SQS emulator).
- Fix undefined this.region -> this.options.region so emitted events carry awsRegion. Re-implements #166 (thanks @zlalvani).
- Make SQS deleteMessageBatch entry Ids unique within a batch (index-based, <=80 chars). Re-implements #253 (thanks @flipscholtz).
- Add custom.serverless-offline-sqs.queueName override (non-mutating; strips arn so it wins for arn-bearing shapes). Re-implements #211 (thanks @mfamilia).
- Backward compatible with serverless v3. Adds docker-free unit tests. v8.1.0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…nt-def fixes

- Serverless v4 logger migration (src/log.js shim threaded in; handler errors are now logged instead of silently swallowed).
- Fix undefined this.region -> this.options.region so emitted events carry awsRegion. Re-implements #166 (thanks @zlalvani).
- Replace the infinite silent handler retry with a bounded, logged retry (default maximumRetryAttempts=10, mirrors dynamodb-streams). Re-implements #100 (thanks @dolsem).
- Await this.lambda.create(...). Re-implements #249 (thanks @gabsong).
- Fix kinesis-event-definition omit list (tableName -> streamName copy-paste bug).
- Backward compatible with serverless v3. Adds docker-free unit tests. v7.1.0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…no-streams fixes

- Serverless v4 logger migration (src/log.js shim threaded in; handler errors are now logged).
- Fix undefined this.region -> this.options.region so emitted events carry awsRegion. Re-implements #166 (thanks @zlalvani).
- Throw a clear 'Table <name> does not have streams enabled' error instead of failing cryptically. Re-implements #98 (thanks @dolsem).
- Rename the copy-pasted KinesisEvent class to DynamodbStreamsEvent.
- Backward compatible with serverless v3. Adds docker-free unit tests. v7.1.0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@silouone silouone force-pushed the feat/serverless-v4-support branch 2 times, most recently from 18852c0 to ff500c6 Compare June 19, 2026 23:26
@silouone silouone self-assigned this Jun 19, 2026
@silouone silouone added bug Something isn't working enhancement New feature or request labels Jun 19, 2026
@silouone silouone force-pushed the feat/serverless-v4-support branch 4 times, most recently from 1b687e8 to df99a00 Compare June 20, 2026 12:05
silouone and others added 2 commits June 20, 2026 14:28
…fork), Node 22/24

Serverless Framework v4 requires a paid login for every command (incl. offline), so it can't run in CI. Switch the dev/test harness to osls — the Bref-maintained, MIT, license-free fork of Serverless Framework v3 with modern-Node support — via the alias serverless = npm:osls@^3.76.0 (satisfies serverless-offline's serverless peer and provides the sls bin). A root 'overrides' pins serverless-offline to 13.10.1 so the harness deterministically runs offline 13 on osls 3 (the plugins' wide >=11 peer would otherwise let npm resolve offline 14, which needs serverless 4); .npmrc legacy-peer-deps lets that install proceed. CI runs Node 22 + 24. Published plugins keep engines >=18 and wide peers (still support Serverless v3 AND v4). Drops unused harness deps (pump, signal-exit). Adds CHANGELOG.md crediting re-implemented community PRs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…+ batch/forbidden assertions

Rewritten around a shared runOfflineTest helper: merge stdout+stderr, wait for readiness, detached process-group kill, distinct lambdaPort AND httpPort per config (no port races), hard timeout, and onReady rejection fails fast. Invocations are detected via a handler marker '__INVOKED__ <fn> <source> <count>' with a source id STABLE per (handler, source) so retries/splits dedupe. The helper asserts EXACT coverage of expectedKeys (a count threshold could let surplus markers mask a non-firing handler), hard-fails on forbiddenKeys with a drain window (catches the S3 prefix/suffix rule over-matching), and asserts expectBatch (the 70-message SQS batch is delivered batched, not one-per-invocation). EOL python3.7 handlers converted to JS and the orphaned handler.py removed (myPythonHandler renamed mySecondCallbackHandler). The autoCreate DLQ/Policy CFN-intrinsic fixture is removed (deferred #183).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced Jun 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant