@layered-loader/sqs 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +433 -0
  3. package/dist/index.d.ts +13 -0
  4. package/dist/index.js +13 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/lib/SqsGroupNotificationConsumer.d.ts +28 -0
  7. package/dist/lib/SqsGroupNotificationConsumer.js +107 -0
  8. package/dist/lib/SqsGroupNotificationConsumer.js.map +1 -0
  9. package/dist/lib/SqsGroupNotificationFactory.d.ts +22 -0
  10. package/dist/lib/SqsGroupNotificationFactory.js +40 -0
  11. package/dist/lib/SqsGroupNotificationFactory.js.map +1 -0
  12. package/dist/lib/SqsGroupNotificationPublisher.d.ts +38 -0
  13. package/dist/lib/SqsGroupNotificationPublisher.js +102 -0
  14. package/dist/lib/SqsGroupNotificationPublisher.js.map +1 -0
  15. package/dist/lib/SqsNotificationConsumer.d.ts +44 -0
  16. package/dist/lib/SqsNotificationConsumer.js +123 -0
  17. package/dist/lib/SqsNotificationConsumer.js.map +1 -0
  18. package/dist/lib/SqsNotificationFactory.d.ts +29 -0
  19. package/dist/lib/SqsNotificationFactory.js +40 -0
  20. package/dist/lib/SqsNotificationFactory.js.map +1 -0
  21. package/dist/lib/SqsNotificationPublisher.d.ts +39 -0
  22. package/dist/lib/SqsNotificationPublisher.js +109 -0
  23. package/dist/lib/SqsNotificationPublisher.js.map +1 -0
  24. package/dist/lib/channelNameResolver.d.ts +12 -0
  25. package/dist/lib/channelNameResolver.js +18 -0
  26. package/dist/lib/channelNameResolver.js.map +1 -0
  27. package/dist/lib/groupNotificationSchemas.d.ts +49 -0
  28. package/dist/lib/groupNotificationSchemas.js +31 -0
  29. package/dist/lib/groupNotificationSchemas.js.map +1 -0
  30. package/dist/lib/notificationSchemas.d.ts +66 -0
  31. package/dist/lib/notificationSchemas.js +40 -0
  32. package/dist/lib/notificationSchemas.js.map +1 -0
  33. package/dist/lib/triggers/AbstractSqsTrigger.d.ts +62 -0
  34. package/dist/lib/triggers/AbstractSqsTrigger.js +104 -0
  35. package/dist/lib/triggers/AbstractSqsTrigger.js.map +1 -0
  36. package/dist/lib/triggers/SqsGroupInvalidationTrigger.d.ts +39 -0
  37. package/dist/lib/triggers/SqsGroupInvalidationTrigger.js +46 -0
  38. package/dist/lib/triggers/SqsGroupInvalidationTrigger.js.map +1 -0
  39. package/dist/lib/triggers/SqsInvalidationTrigger.d.ts +56 -0
  40. package/dist/lib/triggers/SqsInvalidationTrigger.js +47 -0
  41. package/dist/lib/triggers/SqsInvalidationTrigger.js.map +1 -0
  42. package/dist/lib/triggers/dispatch.d.ts +19 -0
  43. package/dist/lib/triggers/dispatch.js +69 -0
  44. package/dist/lib/triggers/dispatch.js.map +1 -0
  45. package/dist/lib/triggers/types.d.ts +54 -0
  46. package/dist/lib/triggers/types.js +12 -0
  47. package/dist/lib/triggers/types.js.map +1 -0
  48. package/package.json +75 -0
@@ -0,0 +1,69 @@
1
+ function toArray(output) {
2
+ if (output == null)
3
+ return [];
4
+ // T is a discriminated-union object type, never an array, so narrowing via
5
+ // Array.isArray is safe — but TS can't prove that for an arbitrary T.
6
+ return Array.isArray(output) ? output : [output];
7
+ }
8
+ function assertNever(value, label) {
9
+ throw new Error(`Unhandled ${label} kind: ${JSON.stringify(value)}`);
10
+ }
11
+ /**
12
+ * Apply a resolved {@link InvalidationAction} to a flat
13
+ * {@link NotificationPublisher}.
14
+ */
15
+ export async function applyFlatAction(action, publisher) {
16
+ switch (action.kind) {
17
+ case 'delete':
18
+ await publisher.delete(action.key);
19
+ return;
20
+ case 'deleteMany':
21
+ await publisher.deleteMany([...action.keys]);
22
+ return;
23
+ case 'set':
24
+ await publisher.set(action.key, action.value);
25
+ return;
26
+ case 'clear':
27
+ await publisher.clear();
28
+ return;
29
+ default:
30
+ assertNever(action, 'InvalidationAction');
31
+ }
32
+ }
33
+ /**
34
+ * Apply a resolved {@link GroupInvalidationAction} to a
35
+ * {@link GroupNotificationPublisher}.
36
+ */
37
+ export async function applyGroupAction(action, publisher) {
38
+ switch (action.kind) {
39
+ case 'deleteFromGroup':
40
+ await publisher.deleteFromGroup(action.key, action.group);
41
+ return;
42
+ case 'deleteGroup':
43
+ await publisher.deleteGroup(action.group);
44
+ return;
45
+ case 'clear':
46
+ await publisher.clear();
47
+ return;
48
+ default:
49
+ assertNever(action, 'GroupInvalidationAction');
50
+ }
51
+ }
52
+ /**
53
+ * Run the resolver and apply each emitted action sequentially. Errors
54
+ * propagate to the caller, allowing the transport adapter to decide whether
55
+ * to retry the source message.
56
+ */
57
+ export async function runFlatPipeline(message, resolver, publisher) {
58
+ const result = await resolver(message);
59
+ for (const action of toArray(result)) {
60
+ await applyFlatAction(action, publisher);
61
+ }
62
+ }
63
+ export async function runGroupPipeline(message, resolver, publisher) {
64
+ const result = await resolver(message);
65
+ for (const action of toArray(result)) {
66
+ await applyGroupAction(action, publisher);
67
+ }
68
+ }
69
+ //# sourceMappingURL=dispatch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatch.js","sourceRoot":"","sources":["../../../lib/triggers/dispatch.ts"],"names":[],"mappings":"AAQA,SAAS,OAAO,CAAI,MAAyB;IAC3C,IAAI,MAAM,IAAI,IAAI;QAAE,OAAO,EAAE,CAAA;IAC7B,2EAA2E;IAC3E,sEAAsE;IACtE,OAAO,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,MAAM,CAAkB,CAAA;AACpE,CAAC;AAED,SAAS,WAAW,CAAC,KAAY,EAAE,KAAa;IAC9C,MAAM,IAAI,KAAK,CAAC,aAAa,KAAK,UAAU,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;AACtE,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,MAA0B,EAC1B,SAAyC;IAEzC,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,KAAK,QAAQ;YACX,MAAM,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YAClC,OAAM;QACR,KAAK,YAAY;YACf,MAAM,SAAS,CAAC,UAAU,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAA;YAC5C,OAAM;QACR,KAAK,KAAK;YACR,MAAM,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAA;YAC7C,OAAM;QACR,KAAK,OAAO;YACV,MAAM,SAAS,CAAC,KAAK,EAAE,CAAA;YACvB,OAAM;QACR;YACE,WAAW,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAA;IAC7C,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,MAA+B,EAC/B,SAA8C;IAE9C,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,KAAK,iBAAiB;YACpB,MAAM,SAAS,CAAC,eAAe,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAA;YACzD,OAAM;QACR,KAAK,aAAa;YAChB,MAAM,SAAS,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;YACzC,OAAM;QACR,KAAK,OAAO;YACV,MAAM,SAAS,CAAC,KAAK,EAAE,CAAA;YACvB,OAAM;QACR;YACE,WAAW,CAAC,MAAM,EAAE,yBAAyB,CAAC,CAAA;IAClD,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,OAAiB,EACjB,QAA4D,EAC5D,SAAyC;IAEzC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,CAAA;IACtC,KAAK,MAAM,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACrC,MAAM,eAAe,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;IAC1C,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,OAAiB,EACjB,QAAiE,EACjE,SAA8C;IAE9C,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,CAAA;IACtC,KAAK,MAAM,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACrC,MAAM,gBAAgB,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;IAC3C,CAAC;AACH,CAAC"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Transport-agnostic primitives for building invalidation triggers.
3
+ *
4
+ * A trigger consumes domain events from an arbitrary upstream messaging system
5
+ * (SNS topic, SQS queue, RabbitMQ exchange, Kafka topic, ...) that has no
6
+ * knowledge of the caching layer. A {@link InvalidationResolver} maps each
7
+ * incoming message to one or more {@link InvalidationAction}s, which the
8
+ * trigger then dispatches via a configured layered-loader notification
9
+ * publisher to fan out across the cache cluster.
10
+ */
11
+ /** Invalidation operations supported by `NotificationPublisher`. */
12
+ export type InvalidationAction = {
13
+ kind: 'delete';
14
+ key: string;
15
+ } | {
16
+ kind: 'deleteMany';
17
+ keys: readonly string[];
18
+ } | {
19
+ kind: 'set';
20
+ key: string;
21
+ value: unknown;
22
+ } | {
23
+ kind: 'clear';
24
+ };
25
+ /** Invalidation operations supported by `GroupNotificationPublisher`. */
26
+ export type GroupInvalidationAction = {
27
+ kind: 'deleteFromGroup';
28
+ key: string;
29
+ group: string;
30
+ } | {
31
+ kind: 'deleteGroup';
32
+ group: string;
33
+ } | {
34
+ kind: 'clear';
35
+ };
36
+ export type ResolverOutput<TAction> = TAction | readonly TAction[] | null | undefined;
37
+ /**
38
+ * Pure function turning a parsed upstream message into invalidation
39
+ * action(s). Return `undefined`/`null` to skip the message.
40
+ */
41
+ export type InvalidationResolver<TMessage, TAction> = (message: TMessage) => ResolverOutput<TAction> | Promise<ResolverOutput<TAction>>;
42
+ /** Lifecycle contract every trigger implementation honours. */
43
+ export interface InvalidationTrigger {
44
+ /** Begin consuming messages from the upstream source. Idempotent. */
45
+ start(): Promise<void>;
46
+ /** Stop consuming and release resources. Idempotent. */
47
+ stop(): Promise<void>;
48
+ }
49
+ /**
50
+ * Invoked when the trigger pipeline (resolver + publish) fails for a single
51
+ * message. The transport may re-deliver the message regardless; this hook is
52
+ * for observability only.
53
+ */
54
+ export type TriggerErrorHandler = (err: Error, channel: string) => void;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Transport-agnostic primitives for building invalidation triggers.
3
+ *
4
+ * A trigger consumes domain events from an arbitrary upstream messaging system
5
+ * (SNS topic, SQS queue, RabbitMQ exchange, Kafka topic, ...) that has no
6
+ * knowledge of the caching layer. A {@link InvalidationResolver} maps each
7
+ * incoming message to one or more {@link InvalidationAction}s, which the
8
+ * trigger then dispatches via a configured layered-loader notification
9
+ * publisher to fan out across the cache cluster.
10
+ */
11
+ export {};
12
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../lib/triggers/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG"}
package/package.json ADDED
@@ -0,0 +1,75 @@
1
+ {
2
+ "name": "@layered-loader/sqs",
3
+ "version": "1.0.0",
4
+ "description": "SNS/SQS remote invalidation adapter for layered-loader",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "main": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "publishConfig": {
10
+ "access": "public"
11
+ },
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/index.d.ts",
15
+ "default": "./dist/index.js"
16
+ },
17
+ "./package.json": "./package.json"
18
+ },
19
+ "engines": {
20
+ "node": ">=20"
21
+ },
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "git://github.com/kibertoad/layered-loader.git",
25
+ "directory": "packages/sqs"
26
+ },
27
+ "files": [
28
+ "dist/*",
29
+ "README.md",
30
+ "LICENSE"
31
+ ],
32
+ "keywords": [
33
+ "layered-loader",
34
+ "sqs",
35
+ "sns",
36
+ "aws",
37
+ "cache",
38
+ "invalidation",
39
+ "notification",
40
+ "pub-sub"
41
+ ],
42
+ "peerDependencies": {
43
+ "@aws-sdk/client-sns": "^3.632.0",
44
+ "@aws-sdk/client-sqs": "^3.632.0",
45
+ "@aws-sdk/client-sts": "^3.632.0",
46
+ "@lokalise/node-core": "^14.0.0",
47
+ "@message-queue-toolkit/core": ">=24.0.0",
48
+ "@message-queue-toolkit/sns": ">=24.0.0",
49
+ "@message-queue-toolkit/sqs": ">=23.0.0",
50
+ "zod": "^4.0.0",
51
+ "layered-loader": "^14.3.1"
52
+ },
53
+ "devDependencies": {
54
+ "@aws-sdk/client-sns": "^3.926.0",
55
+ "@aws-sdk/client-sqs": "^3.926.0",
56
+ "@aws-sdk/client-sts": "^3.926.0",
57
+ "@lokalise/node-core": "^14.8.1",
58
+ "@message-queue-toolkit/core": "^25.4.0",
59
+ "@message-queue-toolkit/sns": "^24.6.1",
60
+ "@message-queue-toolkit/sqs": "^24.2.1",
61
+ "@types/node": "^22.19.15",
62
+ "@vitest/coverage-v8": "^4.1.0",
63
+ "fauxqs": "^2.5.0",
64
+ "typescript": "^5.9.3",
65
+ "vitest": "^4.1.0",
66
+ "zod": "^4.4.3",
67
+ "layered-loader": "^14.3.1"
68
+ },
69
+ "scripts": {
70
+ "build": "tsc",
71
+ "test": "vitest run",
72
+ "test:coverage": "vitest run --coverage",
73
+ "lint": "tsc --noEmit"
74
+ }
75
+ }