@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.
- package/LICENSE +21 -0
- package/README.md +433 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/SqsGroupNotificationConsumer.d.ts +28 -0
- package/dist/lib/SqsGroupNotificationConsumer.js +107 -0
- package/dist/lib/SqsGroupNotificationConsumer.js.map +1 -0
- package/dist/lib/SqsGroupNotificationFactory.d.ts +22 -0
- package/dist/lib/SqsGroupNotificationFactory.js +40 -0
- package/dist/lib/SqsGroupNotificationFactory.js.map +1 -0
- package/dist/lib/SqsGroupNotificationPublisher.d.ts +38 -0
- package/dist/lib/SqsGroupNotificationPublisher.js +102 -0
- package/dist/lib/SqsGroupNotificationPublisher.js.map +1 -0
- package/dist/lib/SqsNotificationConsumer.d.ts +44 -0
- package/dist/lib/SqsNotificationConsumer.js +123 -0
- package/dist/lib/SqsNotificationConsumer.js.map +1 -0
- package/dist/lib/SqsNotificationFactory.d.ts +29 -0
- package/dist/lib/SqsNotificationFactory.js +40 -0
- package/dist/lib/SqsNotificationFactory.js.map +1 -0
- package/dist/lib/SqsNotificationPublisher.d.ts +39 -0
- package/dist/lib/SqsNotificationPublisher.js +109 -0
- package/dist/lib/SqsNotificationPublisher.js.map +1 -0
- package/dist/lib/channelNameResolver.d.ts +12 -0
- package/dist/lib/channelNameResolver.js +18 -0
- package/dist/lib/channelNameResolver.js.map +1 -0
- package/dist/lib/groupNotificationSchemas.d.ts +49 -0
- package/dist/lib/groupNotificationSchemas.js +31 -0
- package/dist/lib/groupNotificationSchemas.js.map +1 -0
- package/dist/lib/notificationSchemas.d.ts +66 -0
- package/dist/lib/notificationSchemas.js +40 -0
- package/dist/lib/notificationSchemas.js.map +1 -0
- package/dist/lib/triggers/AbstractSqsTrigger.d.ts +62 -0
- package/dist/lib/triggers/AbstractSqsTrigger.js +104 -0
- package/dist/lib/triggers/AbstractSqsTrigger.js.map +1 -0
- package/dist/lib/triggers/SqsGroupInvalidationTrigger.d.ts +39 -0
- package/dist/lib/triggers/SqsGroupInvalidationTrigger.js +46 -0
- package/dist/lib/triggers/SqsGroupInvalidationTrigger.js.map +1 -0
- package/dist/lib/triggers/SqsInvalidationTrigger.d.ts +56 -0
- package/dist/lib/triggers/SqsInvalidationTrigger.js +47 -0
- package/dist/lib/triggers/SqsInvalidationTrigger.js.map +1 -0
- package/dist/lib/triggers/dispatch.d.ts +19 -0
- package/dist/lib/triggers/dispatch.js +69 -0
- package/dist/lib/triggers/dispatch.js.map +1 -0
- package/dist/lib/triggers/types.d.ts +54 -0
- package/dist/lib/triggers/types.js +12 -0
- package/dist/lib/triggers/types.js.map +1 -0
- 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
|
+
}
|