@ez4/aws-topic 0.27.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 +40 -0
- package/dist/client.cjs +10 -0
- package/dist/client.d.ts +5 -0
- package/dist/client.mjs +7 -0
- package/dist/main.cjs +137 -0
- package/dist/main.d.ts +9 -0
- package/dist/main.mjs +123 -0
- package/dist/subscription/client.d.ts +15 -0
- package/dist/subscription/function/bundler.d.ts +3 -0
- package/dist/subscription/function/service.d.ts +5 -0
- package/dist/subscription/function/types.d.ts +18 -0
- package/dist/subscription/handler.d.ts +3 -0
- package/dist/subscription/helpers/protocol.d.ts +2 -0
- package/dist/subscription/provider.d.ts +1 -0
- package/dist/subscription/service.d.ts +6 -0
- package/dist/subscription/types.d.ts +21 -0
- package/dist/subscription/utils.d.ts +3 -0
- package/dist/topic/client.d.ts +13 -0
- package/dist/topic/errors.d.ts +3 -0
- package/dist/topic/handler.d.ts +3 -0
- package/dist/topic/provider.d.ts +1 -0
- package/dist/topic/service.d.ts +9 -0
- package/dist/topic/types.d.ts +13 -0
- package/dist/topic/utils.d.ts +7 -0
- package/dist/triggers/client.d.ts +3 -0
- package/dist/triggers/defaults.d.ts +14 -0
- package/dist/triggers/errors.d.ts +7 -0
- package/dist/triggers/import.d.ts +4 -0
- package/dist/triggers/policy.d.ts +2 -0
- package/dist/triggers/register.d.ts +1 -0
- package/dist/triggers/service.d.ts +4 -0
- package/dist/triggers/subscription.d.ts +6 -0
- package/dist/triggers/utils.d.ts +4 -0
- package/dist/utils/policy.d.ts +3 -0
- package/lib/message.ts +93 -0
- package/package.json +64 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Silas B.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# EZ4: AWS Topic
|
|
2
|
+
|
|
3
|
+
It provides all the components to manage SNS topics on AWS.
|
|
4
|
+
|
|
5
|
+
## Getting started
|
|
6
|
+
|
|
7
|
+
#### Install
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npm install @ez4/aws-topic -D
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
#### Permission
|
|
14
|
+
|
|
15
|
+
Ensure the user performing deployments has the permissions below:
|
|
16
|
+
|
|
17
|
+
```json
|
|
18
|
+
{
|
|
19
|
+
"Version": "2012-10-17",
|
|
20
|
+
"Statement": [
|
|
21
|
+
{
|
|
22
|
+
"Sid": "TopicManagement",
|
|
23
|
+
"Effect": "Allow",
|
|
24
|
+
"Action": [
|
|
25
|
+
"sns:CreateTopic",
|
|
26
|
+
"sns:DeleteTopic",
|
|
27
|
+
"sns:Subscribe",
|
|
28
|
+
"sns:Unsubscribe",
|
|
29
|
+
"sns:TagResource",
|
|
30
|
+
"sns:UntagResource"
|
|
31
|
+
],
|
|
32
|
+
"Resource": ["arn:aws:sns:*:{account-id}:{prefix}-*"]
|
|
33
|
+
}
|
|
34
|
+
]
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## License
|
|
39
|
+
|
|
40
|
+
MIT License
|
package/dist/client.cjs
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";var n=Object.defineProperty;var u=Object.getOwnPropertyDescriptor;var d=Object.getOwnPropertyNames;var M=Object.prototype.hasOwnProperty;var p=(s,e)=>n(s,"name",{value:e,configurable:!0});var l=(s,e)=>{for(var o in e)n(s,o,{get:e[o],enumerable:!0})},T=(s,e,o,i)=>{if(e&&
|
|
2
|
+
typeof e=="object"||typeof e=="function")for(let t of d(e))!M.call(s,t)&&t!==o&&
|
|
3
|
+
n(s,t,{get:()=>e[t],enumerable:!(i=u(e,t))||i.enumerable});return s};var f=s=>T(n({},"__esModule",{value:!0}),s);var w={};l(w,{Client:()=>m});module.exports=f(w);var r=require("@ez4/topic/utils"),
|
|
4
|
+
a=require("@aws-sdk/client-sns");var y=new a.SNSClient({}),m;(e=>e.make=p((o,i,t)=>new class{async sendMessage(c){
|
|
5
|
+
let g=await(0,r.getJsonStringMessage)(c,i);await y.send(new a.PublishCommand({TargetArn:o,
|
|
6
|
+
Message:g,...t&&{...I(c,t)}}))}},"make"))(m||={});var I=p((s,e)=>{let o={};if(e){
|
|
7
|
+
let{groupId:i,uniqueId:t}=e;if(o.MessageGroupId=`${s[i]}`,!o.MessageGroupId)throw new r.MissingMessageGroupError(
|
|
8
|
+
i.toString());t&&s[t]&&(o.MessageDeduplicationId=`${s[t]}`)}return o},"getFifoPa\
|
|
9
|
+
rameters");0&&(module.exports={Client});
|
|
10
|
+
//# sourceMappingURL=client.cjs.map
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Topic, Client as SnsClient } from '@ez4/topic';
|
|
2
|
+
import type { MessageSchema } from '@ez4/topic/utils';
|
|
3
|
+
export declare namespace Client {
|
|
4
|
+
const make: <T extends Topic.Message>(topicArn: string, messageSchema: MessageSchema, fifoMode?: Topic.FifoMode<T>) => SnsClient<T>;
|
|
5
|
+
}
|
package/dist/client.mjs
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
var p=Object.defineProperty;var n=(e,s)=>p(e,"name",{value:s,configurable:!0});import{getJsonStringMessage as c,MissingMessageGroupError as m}from"@ez4/topic/utils";
|
|
2
|
+
import{PublishCommand as g,SNSClient as u}from"@aws-sdk/client-sns";var d=new u({}),M;(s=>s.make=n((t,i,o)=>new class{async sendMessage(r){let a=await c(
|
|
3
|
+
r,i);await d.send(new g({TargetArn:t,Message:a,...o&&{...l(r,o)}}))}},"make"))(M||=
|
|
4
|
+
{});var l=n((e,s)=>{let t={};if(s){let{groupId:i,uniqueId:o}=s;if(t.MessageGroupId=
|
|
5
|
+
`${e[i]}`,!t.MessageGroupId)throw new m(i.toString());o&&e[o]&&(t.MessageDeduplicationId=
|
|
6
|
+
`${e[o]}`)}return t},"getFifoParameters");export{M as Client};
|
|
7
|
+
//# sourceMappingURL=client.mjs.map
|
package/dist/main.cjs
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"use strict";var h=Object.defineProperty;var rt=Object.getOwnPropertyDescriptor;var ot=Object.getOwnPropertyNames;var it=Object.prototype.hasOwnProperty;var i=(e,t)=>h(e,"name",{value:t,configurable:!0});var nt=(e,t)=>{for(var r in t)h(e,r,{get:t[r],enumerable:!0})},st=(e,t,r,o)=>{if(t&&
|
|
2
|
+
typeof t=="object"||typeof t=="function")for(let n of ot(t))!it.call(e,n)&&n!==r&&
|
|
3
|
+
h(e,n,{get:()=>t[n],enumerable:!(o=rt(t,n))||o.enumerable});return e};var pt=e=>st(h({},"__esModule",{value:!0}),e);var At={};nt(At,{SubscriptionServiceName:()=>a,SubscriptionServiceType:()=>d,TopicServiceName:()=>S,
|
|
4
|
+
TopicServiceType:()=>y,createSubscription:()=>$,createSubscriptionFunction:()=>V,
|
|
5
|
+
createTopic:()=>A,createTopicStateId:()=>k,getTopic:()=>bt,getTopicArn:()=>W,getTopicState:()=>Z,
|
|
6
|
+
isSubscriptionState:()=>Rt,isTopicState:()=>O,registerTriggers:()=>xt});module.exports=
|
|
7
|
+
pt(At);var Ze=require("@ez4/aws-common"),We=require("@ez4/aws-identity"),Ve=require("@ez4/aws-function"),
|
|
8
|
+
Xe=require("@ez4/aws-queue"),Ye=require("@ez4/topic/library"),et=require("@ez4/project/library");var ue=require("@ez4/aws-common");var F=require("@ez4/aws-common"),D=require("@ez4/aws-identity"),ce=require("@ez4/utils");var x=require("@ez4/aws-identity");var v=i((e,t,r)=>`arn:aws:sns:${t}:${r}:${e}`,"buildTopicArn"),oe=i(async e=>{let[
|
|
9
|
+
t,r]=await Promise.all([(0,x.getRegion)(),(0,x.getAccountId)()]);return(0,x.createPolicyDocument)(
|
|
10
|
+
[{permissions:["sns:Publish"],resourceIds:e.map(o=>v(`${o}-*`,t,r))}])},"getPoli\
|
|
11
|
+
cyDocument");var m=require("@aws-sdk/client-sns"),u=require("@ez4/aws-common");var S="AWS:SNS/Topic",y="aws:sns.topic";var z=new m.SNSClient({}),ie=i(async e=>{let{topicName:t,fifoMode:r}=e;return u.Logger.
|
|
12
|
+
logCreate(S,t),{topicArn:(await z.send(new m.CreateTopicCommand({Name:t,Attributes:{
|
|
13
|
+
...r&&{ContentBasedDeduplication:"true",FifoThroughputScope:"MessageGroup",FifoTopic:"\
|
|
14
|
+
true"}},Tags:(0,u.getTagList)({...e.tags,ManagedBy:"EZ4"})}))).TopicArn}},"creat\
|
|
15
|
+
eTopic"),ne=i(async e=>{let t=(0,u.tryParseArn)(e)?.resourceName??e;u.Logger.logDelete(
|
|
16
|
+
S,t);try{return await z.send(new m.DeleteTopicCommand({TopicArn:e})),!0}catch(r){
|
|
17
|
+
if(!(r instanceof m.NotFoundException))throw r;return!1}},"deleteTopic"),se=i(async(e,t)=>{
|
|
18
|
+
let r=(0,u.tryParseArn)(e)?.resourceName??e;u.Logger.logTag(S,r),await z.send(new m.TagResourceCommand(
|
|
19
|
+
{ResourceArn:e,Tags:(0,u.getTagList)({...t,ManagedBy:"EZ4"})}))},"tagTopic"),pe=i(
|
|
20
|
+
async(e,t)=>{let r=(0,u.tryParseArn)(e)?.resourceName??e;u.Logger.logUntag(S,r),
|
|
21
|
+
await z.send(new m.UntagResourceCommand({ResourceArn:e,TagKeys:t}))},"untagTopic");var ae=i(()=>({equals:ct,create:me,replace:mt,preview:at,update:ut,delete:St}),"\
|
|
22
|
+
getTopicHandler"),ct=i((e,t)=>!!e.result&&e.result.topicArn===t.result?.topicArn,
|
|
23
|
+
"equalsResource"),at=i(async(e,t)=>{let r={...e.parameters,dependencies:e.dependencies},
|
|
24
|
+
o={...t.parameters,dependencies:t.dependencies},n=(0,ce.deepCompare)(r,o);if(n.counts)
|
|
25
|
+
return{...n,name:r.topicName}},"previewResource"),mt=i(async(e,t)=>{if(t.result)
|
|
26
|
+
throw new F.ReplaceResourceError(S,e.entryId,t.entryId);return me(e)},"replaceRe\
|
|
27
|
+
source"),me=i(async e=>{let t=e.parameters;if(t.import){let[o,n]=await Promise.all(
|
|
28
|
+
[(0,D.getRegion)(),(0,D.getAccountId)()]);return{topicArn:v(t.topicName,o,n)}}let{
|
|
29
|
+
topicArn:r}=await ie(t);return{topicArn:r}},"createResource"),ut=i(async(e,t)=>{
|
|
30
|
+
let{result:r,parameters:o}=e;r&&!o.import&&await ft(r.topicArn,o,t.parameters)},
|
|
31
|
+
"updateResource"),St=i(async e=>{let{result:t,parameters:r}=e;t&&!r.import&&await ne(
|
|
32
|
+
t.topicArn)},"deleteResource"),ft=i(async(e,t,r)=>{await(0,F.applyTagUpdates)(t.
|
|
33
|
+
tags,r.tags,o=>se(e,o),o=>pe(e,o))},"checkTagUpdates");var Se=i(()=>{(0,ue.registerProvider)(y,ae())},"registerTopicProvider");var ve=require("@ez4/aws-common");var de=require("@ez4/aws-common"),Te=require("@ez4/utils");var b=require("@ez4/aws-common");var T=require("@aws-sdk/client-sns"),E=require("@ez4/aws-common");var a="AWS:SNS/Subscription",d="aws:sns.subscription";var fe=new T.SNSClient({});var le=i(async e=>{let t=(0,E.tryParseArn)(e.topicArn)?.resourceName??e.topicArn;
|
|
34
|
+
E.Logger.logCreate(a,t);let{topicArn:r,protocol:o,endpoint:n}=e;return{subscriptionArn:(await fe.
|
|
35
|
+
send(new T.SubscribeCommand({TopicArn:r,Protocol:o,Endpoint:n,ReturnSubscriptionArn:!0,
|
|
36
|
+
Attributes:{...o==="sqs"&&{RawMessageDelivery:"true"}}}))).SubscriptionArn}},"cr\
|
|
37
|
+
eateSubscription"),ye=i(async e=>{let t=(0,E.tryParseArn)(e)?.resourceName??e;E.Logger.
|
|
38
|
+
logDelete(a,t);try{return await fe.send(new T.UnsubscribeCommand({SubscriptionArn:e})),
|
|
39
|
+
!0}catch(r){if(!(r instanceof T.NotFoundException))throw r;return!1}},"deleteSub\
|
|
40
|
+
scription");var ge=i((e,t)=>{if(!(0,b.isArn)(t))throw new b.InvalidParameterError(e,`endpoin\
|
|
41
|
+
t ${t} is not supported.`);let{service:r}=(0,b.parseArn)(t);switch(r){case"lambd\
|
|
42
|
+
a":case"sqs":return r}throw new b.InvalidParameterError(e,`protocol ${r} is not \
|
|
43
|
+
supported.`)},"getSubscriptionProtocol");var be=i(()=>({equals:lt,create:xe,replace:gt,preview:yt,update:dt,delete:Tt}),"\
|
|
44
|
+
getSubscriptionHandler"),lt=i((e,t)=>!!e.result&&e.result.subscriptionArn===t.result?.
|
|
45
|
+
subscriptionArn,"equalsResource"),yt=i(async(e,t)=>{let r={...e.parameters,dependencies:e.
|
|
46
|
+
dependencies},o={...t.parameters,dependencies:t.dependencies},n=(0,Te.deepCompare)(
|
|
47
|
+
r,o,{exclude:{getTopicArn:!0,getEndpoint:!0}});if(n.counts)return{...n,name:r.fromService}},
|
|
48
|
+
"previewResource"),gt=i(async(e,t,r)=>{if(t.result)throw new de.ReplaceResourceError(
|
|
49
|
+
a,e.entryId,t.entryId);return xe(e,r)},"replaceResource"),xe=i(async(e,t)=>{let r=e.
|
|
50
|
+
parameters,[o,n]=await Promise.all([r.getTopicArn(t),r.getEndpoint(t)]),{subscriptionArn:s}=await le(
|
|
51
|
+
{protocol:ge(a,n),topicArn:o,endpoint:n});return{subscriptionArn:s,topicArn:o,endpoint:n}},
|
|
52
|
+
"createResource"),dt=i(async()=>{},"updateResource"),Tt=i(async e=>{let{result:t}=e;
|
|
53
|
+
t&&await ye(t.subscriptionArn)},"deleteResource");var Ee=i(()=>{(0,ve.registerProvider)(d,be())},"registerSubscriptionProvider");var U=require("@ez4/topic/library"),$e=require("@ez4/project/library");var Re=require("@ez4/stateful"),Ae=require("@ez4/utils");var we=require("@ez4/aws-common"),M=require("@ez4/utils");var L=class extends Error{static{i(this,"TopicNotFoundError")}constructor(t){super(
|
|
54
|
+
`Topic service ${t} wasn't found.`)}};var k=i((e,t=!0)=>(0,M.hashData)(y,t?(0,M.toKebabCase)(e):e),"createTopicStateId"),
|
|
55
|
+
O=i(e=>e.type===y,"isTopicState"),Z=i((e,t,r)=>{let o=e.getServiceState(t,r);if(!O(
|
|
56
|
+
o))throw new L(t);return o},"getTopicState"),W=i((e,t,r)=>{let o=r.getDependencies(
|
|
57
|
+
y).at(0)?.result;if(!o?.topicArn)throw new we.IncompleteResourceError(e,t,"topic\
|
|
58
|
+
Arn");return o.topicArn},"getTopicArn");var A=i((e,t)=>{let r=(0,Ae.toKebabCase)(t.topicName),o=t.fifoMode?`${r}.fifo`:r,
|
|
59
|
+
n=k(o,!1);return(0,Re.attachEntry)(e,{type:y,entryId:n,dependencies:[],parameters:{
|
|
60
|
+
...t,topicName:o}})},"createTopic"),bt=i((e,t)=>{let r=k(t),o=e[r];return o&&O(o)?
|
|
61
|
+
o:null},"getTopic");var Y=require("@ez4/project/library"),I=require("@ez4/topic/library"),q=require("@ez4/aws-function"),
|
|
62
|
+
Q=require("@ez4/aws-common"),ee=require("@ez4/aws-identity"),ke=require("@ez4/aws-logs"),
|
|
63
|
+
te=require("@ez4/aws-queue");var ze=require("@ez4/aws-function");var Pe=require("node:path"),Ne=require("@ez4/project/library"),Ce=require("@ez4/aws-function"),
|
|
64
|
+
Ie=require("@ez4/aws-common");var he=i(async(e,t)=>{let{extras:r,debug:o,handler:n,listener:s,messageSchema:p}=t,
|
|
65
|
+
c=(0,Ne.getDefinitionsObject)(e);return(0,Ie.getFunctionBundle)(Ce.MappingServiceName,
|
|
66
|
+
{templateFile:(0,Pe.join)(__dirname,"../lib/message.ts"),filePrefix:"sns",define:{
|
|
67
|
+
...c,__EZ4_SCHEMA:p?JSON.stringify(p):"undefined"},handler:n,listener:s,extras:r,
|
|
68
|
+
debug:o})},"bundleSubscriptionFunction");var V=i((e,t,r,o)=>{let{handler:n}=o;return(0,ze.createFunction)(e,t,r,{handlerName:"\
|
|
69
|
+
snsEntryPoint",sourceFile:n.sourceFile,functionName:o.functionName,description:o.
|
|
70
|
+
description,variables:o.variables,timeout:o.timeout,memory:o.memory,debug:o.debug,
|
|
71
|
+
tags:o.tags,getFunctionBundle:i(s=>{let p=s.getDependencies();return he(p,o)},"g\
|
|
72
|
+
etFunctionBundle"),getFunctionFiles:i(()=>[n.sourceFile,n.dependencies],"getFunc\
|
|
73
|
+
tionFiles")})},"createSubscriptionFunction");var g=require("@ez4/aws-function"),R=require("@ez4/aws-queue"),w=require("@ez4/aws-identity"),
|
|
74
|
+
Fe=require("@ez4/stateful"),De=require("@ez4/utils");var $=i((e,t,r,o)=>{let n=t.parameters.topicName,s=[t.entryId,r.entryId];if((0,g.isFunctionState)(
|
|
75
|
+
r)){let c=(0,g.getPermission)(e,t,r)??(0,g.createPermission)(e,t,r,{fromService:o.
|
|
76
|
+
fromService,getPermission:i(async()=>{let[f,l]=await Promise.all([(0,w.getRegion)(),
|
|
77
|
+
(0,w.getAccountId)()]);return{principal:"sns.amazonaws.com",sourceArn:v(n,f,l)}},
|
|
78
|
+
"getPermission")});s.push(c.entryId)}if((0,R.isQueueState)(r)){let c=(0,R.attachQueuePolicy)(
|
|
79
|
+
e,r,t,{fromService:o.fromService,policyGetters:[async()=>{let[f,l]=await Promise.
|
|
80
|
+
all([(0,w.getRegion)(),(0,w.getAccountId)()]);return{principal:"sns.amazonaws.co\
|
|
81
|
+
m",sourceArn:v(n,f,l)}}]});s.push(c.entryId)}let p=(0,De.hashData)(d,t.entryId,r.
|
|
82
|
+
entryId);return(0,Fe.attachEntry)(e,{type:d,entryId:p,dependencies:s,parameters:{
|
|
83
|
+
...o,getTopicArn:i(c=>W(S,p,c),"getTopicArn"),getEndpoint:i(c=>(0,g.isFunctionState)(
|
|
84
|
+
r)?(0,g.getFunctionArn)(a,p,c):(0,R.getQueueArn)(a,p,c),"getEndpoint")}})},"crea\
|
|
85
|
+
teSubscription");var Le=require("@ez4/project/library"),j=require("@ez4/utils");var X=i((e,t)=>`${(0,j.toKebabCase)(e.name)}-${(0,j.toKebabCase)(t)}`,"getIntern\
|
|
86
|
+
alName"),Me=i((e,t,r)=>`${(0,Le.getServiceName)(e,r)}-${(0,j.toKebabCase)(t)}`,"\
|
|
87
|
+
getFunctionName");var P=class extends Error{static{i(this,"RoleMissingError")}constructor(){super(
|
|
88
|
+
"Execution role for SNS is missing.")}},N=class extends Error{constructor(r){super(
|
|
89
|
+
`Imported project ${r} wasn't found.`);this.projectName=r}static{i(this,"Project\
|
|
90
|
+
MissingError")}};var C;(o=>(o.LogRetention=90,o.Timeout=90,o.Memory=192))(C||={});var G=i(async(e,t,r,o,n)=>{if(!n.role||!(0,ee.isRoleState)(n.role))throw new P;for(let s of t.
|
|
91
|
+
subscriptions)switch(s.type){default:throw new Q.InvalidParameterError(a,"subscr\
|
|
92
|
+
iption not supported.");case I.TopicSubscriptionType.Lambda:{if(t.fifoMode)throw new Q.InvalidParameterError(
|
|
93
|
+
a,"lambda subscription not supported for FIFO topics.");let{handler:p,listener:c}=s,
|
|
94
|
+
f=X(t,p.name),l=(0,q.tryGetFunctionState)(n,f,o);if(!l){let re=Me(t,p.name,o),tt=(0,ke.createLogGroup)(
|
|
95
|
+
e,{retention:s.logRetention??C.LogRetention,groupName:re,tags:o.tags});l=V(e,n.role,
|
|
96
|
+
tt,{functionName:re,description:p.description,messageSchema:t.schema,timeout:s.timeout??
|
|
97
|
+
C.Timeout,memory:s.memory??C.Memory,extras:t.extras,debug:o.debug,tags:o.tags,variables:{
|
|
98
|
+
...o.variables,...t.variables,...s.variables},handler:{dependencies:n.getDependencies(
|
|
99
|
+
p.file),functionName:p.name,sourceFile:p.file,module:p.module},...c&&{listener:{
|
|
100
|
+
functionName:c.name,sourceFile:c.file,module:c.module}}}),n.setServiceState(l,f,
|
|
101
|
+
o)}$(e,r,l,{fromService:l.parameters.functionName});break}case I.TopicSubscriptionType.
|
|
102
|
+
Queue:{let p=(0,te.getQueueState)(n,s.service,o);$(e,r,p,{fromService:p.parameters.
|
|
103
|
+
queueName});break}}},"prepareSubscriptions"),H=i((e,t,r,o)=>{if(t.extras){if(!o.
|
|
104
|
+
role||!(0,ee.isRoleState)(o.role))throw new P;for(let n of t.subscriptions)switch(n.
|
|
105
|
+
type){default:throw new Q.InvalidParameterError(a,"subscription not supported.");case I.TopicSubscriptionType.
|
|
106
|
+
Lambda:{let s=X(t,n.handler.name),p=(0,q.getFunctionState)(o,s,r);(0,Y.linkServiceExtras)(
|
|
107
|
+
e,p.entryId,t.extras);break}case I.TopicSubscriptionType.Queue:{let s=(0,te.getQueueState)(
|
|
108
|
+
o,n.service,r);(0,Y.linkServiceExtras)(e,s.entryId,t.extras);break}}}},"connectS\
|
|
109
|
+
ubscriptions");var Oe=require("@ez4/project/library");var _=i((e,t,r)=>{let n=Z(e,t.name,r).entryId,s=(0,Oe.getDefinitionName)(n,"topi\
|
|
110
|
+
cArn"),p=JSON.stringify(t.fifoMode??null),c=JSON.stringify(t.schema);return{entryIds:[
|
|
111
|
+
n],constructor:`make(${s}, ${c}, ${p})`,from:"@ez4/aws-topic/client",module:"Cli\
|
|
112
|
+
ent"}},"prepareLinkedClient");var je=i(e=>{let{service:t,options:r,context:o}=e;return(0,U.isTopicService)(t)?
|
|
113
|
+
_(o,t,r):null},"prepareLinkedServices"),Qe=i(async e=>{let{state:t,service:r,options:o,
|
|
114
|
+
context:n}=e;if(!(0,U.isTopicService)(r))return!1;let{fifoMode:s}=r,p=A(t,{topicName:(0,$e.getServiceName)(
|
|
115
|
+
r,o),fifoMode:!!s,tags:o.tags});return n.setServiceState(p,r,o),await G(t,r,p,o,
|
|
116
|
+
n),!0},"prepareServices"),qe=i(e=>{let{state:t,service:r,options:o,context:n}=e;
|
|
117
|
+
(0,U.isTopicService)(r)&&H(t,r,o,n)},"connectServices");var B=require("@ez4/topic/library"),Ge=require("@ez4/project/library");var He=i(e=>{let{service:t,options:r,context:o}=e;if(!(0,B.isTopicImport)(t))return null;
|
|
118
|
+
let{project:n}=t,{imports:s}=r;if(!s||!s[n])throw new N(n);return _(o,t,s[n])},"\
|
|
119
|
+
prepareLinkedImports"),_e=i(async e=>{let{state:t,service:r,options:o,context:n}=e;
|
|
120
|
+
if(!(0,B.isTopicImport)(r))return!1;let{reference:s,project:p}=r,{imports:c}=o;if(!c||
|
|
121
|
+
!c[p])throw new N(p);let f=A(t,{topicName:(0,Ge.getServiceName)(s,c[p]),fifoMode:!!r.
|
|
122
|
+
fifoMode,import:!0});return n.setServiceState(f,r,o),await G(t,r,f,o,n),!0},"pre\
|
|
123
|
+
pareImports"),Ue=i(e=>{let{state:t,service:r,options:o,context:n}=e;(0,B.isTopicImport)(
|
|
124
|
+
r)&&H(t,r,o,n)},"connectImports");var K=require("@ez4/topic/library"),J=require("@ez4/aws-identity"),Be=require("@ez4/project/library");var Ke=i(async e=>{let{state:t,serviceType:r,options:o}=e;if(r!==K.ServiceType&&
|
|
125
|
+
r!==K.ImportType)return null;let n=Object.values({options:o,...o.imports}).map(c=>(0,Be.getServiceName)(
|
|
126
|
+
"",c)),[s]=n,p=`${s}-topic-policy`;return(0,J.tryGetPolicy)(t,p)??(0,J.createPolicy)(
|
|
127
|
+
t,{tags:o.tags,policyDocument:await oe(n),policyName:p})},"prepareExecutionPolic\
|
|
128
|
+
y");var Je=!1,xt=i(()=>{Je||((0,Ze.registerTriggers)(),(0,We.registerTriggers)(),(0,Ve.registerTriggers)(),
|
|
129
|
+
(0,Xe.registerTriggers)(),(0,Ye.registerTriggers)(),(0,et.createTrigger)("@ez4/a\
|
|
130
|
+
ws-topic",{"deploy:prepareExecutionPolicy":Ke,"deploy:prepareLinkedService":vt,"\
|
|
131
|
+
deploy:prepareResources":Et,"deploy:connectResources":wt}),Se(),Ee(),Je=!0)},"re\
|
|
132
|
+
gisterTriggers"),vt=i(e=>je(e)??He(e)??null,"prepareLinkedService"),Et=i(async e=>await Qe(
|
|
133
|
+
e)||await _e(e),"prepareQueueResources"),wt=i(async e=>{await Promise.all([qe(e),
|
|
134
|
+
Ue(e)])},"connectQueueResources");var Rt=i(e=>e.type===d,"isSubscriptionState");0&&(module.exports={SubscriptionServiceName,SubscriptionServiceType,TopicServiceName,
|
|
135
|
+
TopicServiceType,createSubscription,createSubscriptionFunction,createTopic,createTopicStateId,
|
|
136
|
+
getTopic,getTopicArn,getTopicState,isSubscriptionState,isTopicState,registerTriggers});
|
|
137
|
+
//# sourceMappingURL=main.cjs.map
|
package/dist/main.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from './triggers/register';
|
|
2
|
+
export * from './topic/service';
|
|
3
|
+
export * from './topic/types';
|
|
4
|
+
export * from './topic/utils';
|
|
5
|
+
export * from './subscription/function/service';
|
|
6
|
+
export * from './subscription/function/types';
|
|
7
|
+
export * from './subscription/service';
|
|
8
|
+
export * from './subscription/types';
|
|
9
|
+
export * from './subscription/utils';
|
package/dist/main.mjs
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
var Ee=Object.defineProperty;var i=(e,t)=>Ee(e,"name",{value:t,configurable:!0});import{registerTriggers as Lt}from"@ez4/aws-common";import{registerTriggers as Mt}from"@ez4/aws-identity";
|
|
2
|
+
import{registerTriggers as kt}from"@ez4/aws-function";import{registerTriggers as Ot}from"@ez4/aws-queue";
|
|
3
|
+
import{registerTriggers as $t}from"@ez4/topic/library";import{createTrigger as jt}from"@ez4/project/library";import{registerProvider as He}from"@ez4/aws-common";import{applyTagUpdates as Fe,ReplaceResourceError as De}from"@ez4/aws-common";import{
|
|
4
|
+
getAccountId as Le,getRegion as Me}from"@ez4/aws-identity";import{deepCompare as ke}from"@ez4/utils";import{getAccountId as we,getRegion as Re,createPolicyDocument as Ae}from"@ez4/aws-identity";var y=i((e,t,r)=>`arn:aws:sns:${t}:${r}:${e}`,"buildTopicArn"),O=i(async e=>{let[
|
|
5
|
+
t,r]=await Promise.all([Re(),we()]);return Ae([{permissions:["sns:Publish"],resourceIds:e.
|
|
6
|
+
map(o=>y(`${o}-*`,t,r))}])},"getPolicyDocument");import{SNSClient as Pe,CreateTopicCommand as Ne,DeleteTopicCommand as Ce,TagResourceCommand as Ie,
|
|
7
|
+
UntagResourceCommand as he,NotFoundException as ze}from"@aws-sdk/client-sns";import{
|
|
8
|
+
getTagList as $,Logger as b,tryParseArn as N}from"@ez4/aws-common";var S="AWS:SNS/Topic",f="aws:sns.topic";var x=new Pe({}),j=i(async e=>{let{topicName:t,fifoMode:r}=e;return b.logCreate(
|
|
9
|
+
S,t),{topicArn:(await x.send(new Ne({Name:t,Attributes:{...r&&{ContentBasedDeduplication:"\
|
|
10
|
+
true",FifoThroughputScope:"MessageGroup",FifoTopic:"true"}},Tags:$({...e.tags,ManagedBy:"\
|
|
11
|
+
EZ4"})}))).TopicArn}},"createTopic"),Q=i(async e=>{let t=N(e)?.resourceName??e;b.
|
|
12
|
+
logDelete(S,t);try{return await x.send(new Ce({TopicArn:e})),!0}catch(r){if(!(r instanceof
|
|
13
|
+
ze))throw r;return!1}},"deleteTopic"),q=i(async(e,t)=>{let r=N(e)?.resourceName??
|
|
14
|
+
e;b.logTag(S,r),await x.send(new Ie({ResourceArn:e,Tags:$({...t,ManagedBy:"EZ4"})}))},
|
|
15
|
+
"tagTopic"),G=i(async(e,t)=>{let r=N(e)?.resourceName??e;b.logUntag(S,r),await x.
|
|
16
|
+
send(new he({ResourceArn:e,TagKeys:t}))},"untagTopic");var H=i(()=>({equals:Oe,create:_,replace:je,preview:$e,update:Qe,delete:qe}),"ge\
|
|
17
|
+
tTopicHandler"),Oe=i((e,t)=>!!e.result&&e.result.topicArn===t.result?.topicArn,"\
|
|
18
|
+
equalsResource"),$e=i(async(e,t)=>{let r={...e.parameters,dependencies:e.dependencies},
|
|
19
|
+
o={...t.parameters,dependencies:t.dependencies},n=ke(r,o);if(n.counts)return{...n,
|
|
20
|
+
name:r.topicName}},"previewResource"),je=i(async(e,t)=>{if(t.result)throw new De(
|
|
21
|
+
S,e.entryId,t.entryId);return _(e)},"replaceResource"),_=i(async e=>{let t=e.parameters;
|
|
22
|
+
if(t.import){let[o,n]=await Promise.all([Me(),Le()]);return{topicArn:y(t.topicName,
|
|
23
|
+
o,n)}}let{topicArn:r}=await j(t);return{topicArn:r}},"createResource"),Qe=i(async(e,t)=>{
|
|
24
|
+
let{result:r,parameters:o}=e;r&&!o.import&&await Ge(r.topicArn,o,t.parameters)},
|
|
25
|
+
"updateResource"),qe=i(async e=>{let{result:t,parameters:r}=e;t&&!r.import&&await Q(
|
|
26
|
+
t.topicArn)},"deleteResource"),Ge=i(async(e,t,r)=>{await Fe(t.tags,r.tags,o=>q(e,
|
|
27
|
+
o),o=>G(e,o))},"checkTagUpdates");var U=i(()=>{He(f,H())},"registerTopicProvider");import{registerProvider as ot}from"@ez4/aws-common";import{ReplaceResourceError as We}from"@ez4/aws-common";import{deepCompare as Ve}from"@ez4/utils";import{InvalidParameterError as V,isArn as Je,parseArn as Ze}from"@ez4/aws-common";import{NotFoundException as _e,SNSClient as Ue,SubscribeCommand as Be,UnsubscribeCommand as Ke}from"@aws-sdk/client-sns";
|
|
28
|
+
import{Logger as B,tryParseArn as K}from"@ez4/aws-common";var a="AWS:SNS/Subscription",l="aws:sns.subscription";var J=new Ue({});var Z=i(async e=>{let t=K(e.topicArn)?.resourceName??e.topicArn;B.logCreate(a,t);
|
|
29
|
+
let{topicArn:r,protocol:o,endpoint:n}=e;return{subscriptionArn:(await J.send(new Be(
|
|
30
|
+
{TopicArn:r,Protocol:o,Endpoint:n,ReturnSubscriptionArn:!0,Attributes:{...o==="s\
|
|
31
|
+
qs"&&{RawMessageDelivery:"true"}}}))).SubscriptionArn}},"createSubscription"),W=i(
|
|
32
|
+
async e=>{let t=K(e)?.resourceName??e;B.logDelete(a,t);try{return await J.send(new Ke(
|
|
33
|
+
{SubscriptionArn:e})),!0}catch(r){if(!(r instanceof _e))throw r;return!1}},"dele\
|
|
34
|
+
teSubscription");var X=i((e,t)=>{if(!Je(t))throw new V(e,`endpoint ${t} is not supported.`);let{service:r}=Ze(
|
|
35
|
+
t);switch(r){case"lambda":case"sqs":return r}throw new V(e,`protocol ${r} is not\
|
|
36
|
+
supported.`)},"getSubscriptionProtocol");var Y=i(()=>({equals:Xe,create:ee,replace:et,preview:Ye,update:tt,delete:rt}),"g\
|
|
37
|
+
etSubscriptionHandler"),Xe=i((e,t)=>!!e.result&&e.result.subscriptionArn===t.result?.
|
|
38
|
+
subscriptionArn,"equalsResource"),Ye=i(async(e,t)=>{let r={...e.parameters,dependencies:e.
|
|
39
|
+
dependencies},o={...t.parameters,dependencies:t.dependencies},n=Ve(r,o,{exclude:{
|
|
40
|
+
getTopicArn:!0,getEndpoint:!0}});if(n.counts)return{...n,name:r.fromService}},"p\
|
|
41
|
+
reviewResource"),et=i(async(e,t,r)=>{if(t.result)throw new We(a,e.entryId,t.entryId);
|
|
42
|
+
return ee(e,r)},"replaceResource"),ee=i(async(e,t)=>{let r=e.parameters,[o,n]=await Promise.
|
|
43
|
+
all([r.getTopicArn(t),r.getEndpoint(t)]),{subscriptionArn:s}=await Z({protocol:X(
|
|
44
|
+
a,n),topicArn:o,endpoint:n});return{subscriptionArn:s,topicArn:o,endpoint:n}},"c\
|
|
45
|
+
reateResource"),tt=i(async()=>{},"updateResource"),rt=i(async e=>{let{result:t}=e;
|
|
46
|
+
t&&await W(t.subscriptionArn)},"deleteResource");var te=i(()=>{ot(l,Y())},"registerSubscriptionProvider");import{isTopicService as L}from"@ez4/topic/library";import{getServiceName as Nt}from"@ez4/project/library";import{attachEntry as pt}from"@ez4/stateful";import{toKebabCase as ct}from"@ez4/utils";import{IncompleteResourceError as it}from"@ez4/aws-common";import{hashData as nt,
|
|
47
|
+
toKebabCase as st}from"@ez4/utils";var v=class extends Error{static{i(this,"TopicNotFoundError")}constructor(t){super(
|
|
48
|
+
`Topic service ${t} wasn't found.`)}};var C=i((e,t=!0)=>nt(f,t?st(e):e),"createTopicStateId"),I=i(e=>e.type===f,"isTop\
|
|
49
|
+
icState"),re=i((e,t,r)=>{let o=e.getServiceState(t,r);if(!I(o))throw new v(t);return o},
|
|
50
|
+
"getTopicState"),oe=i((e,t,r)=>{let o=r.getDependencies(f).at(0)?.result;if(!o?.
|
|
51
|
+
topicArn)throw new it(e,t,"topicArn");return o.topicArn},"getTopicArn");var E=i((e,t)=>{let r=ct(t.topicName),o=t.fifoMode?`${r}.fifo`:r,n=C(o,!1);return pt(
|
|
52
|
+
e,{type:f,entryId:n,dependencies:[],parameters:{...t,topicName:o}})},"createTopi\
|
|
53
|
+
c"),Kr=i((e,t)=>{let r=C(t),o=e[r];return o&&I(o)?o:null},"getTopic");import{linkServiceExtras as me}from"@ez4/project/library";import{TopicSubscriptionType as w}from"@ez4/topic/library";
|
|
54
|
+
import{getFunctionState as wt,tryGetFunctionState as Rt}from"@ez4/aws-function";
|
|
55
|
+
import{InvalidParameterError as D}from"@ez4/aws-common";import{isRoleState as ue}from"@ez4/aws-identity";
|
|
56
|
+
import{createLogGroup as At}from"@ez4/aws-logs";import{getQueueState as Se}from"@ez4/aws-queue";import{createFunction as ft}from"@ez4/aws-function";import{join as at}from"node:path";import{getDefinitionsObject as mt}from"@ez4/project/library";
|
|
57
|
+
import{MappingServiceName as ut}from"@ez4/aws-function";import{getFunctionBundle as St}from"@ez4/aws-common";var ie=i(async(e,t)=>{let{extras:r,debug:o,handler:n,listener:s,messageSchema:p}=t,
|
|
58
|
+
c=mt(e);return St(ut,{templateFile:at(import.meta.dirname,"../lib/message.ts"),filePrefix:"\
|
|
59
|
+
sns",define:{...c,__EZ4_SCHEMA:p?JSON.stringify(p):"undefined"},handler:n,listener:s,
|
|
60
|
+
extras:r,debug:o})},"bundleSubscriptionFunction");var ne=i((e,t,r,o)=>{let{handler:n}=o;return ft(e,t,r,{handlerName:"snsEntryPoin\
|
|
61
|
+
t",sourceFile:n.sourceFile,functionName:o.functionName,description:o.description,
|
|
62
|
+
variables:o.variables,timeout:o.timeout,memory:o.memory,debug:o.debug,tags:o.tags,
|
|
63
|
+
getFunctionBundle:i(s=>{let p=s.getDependencies();return ie(p,o)},"getFunctionBu\
|
|
64
|
+
ndle"),getFunctionFiles:i(()=>[n.sourceFile,n.dependencies],"getFunctionFiles")})},
|
|
65
|
+
"createSubscriptionFunction");import{createPermission as lt,getFunctionArn as yt,getPermission as gt,isFunctionState as se}from"@ez4/aws-function";
|
|
66
|
+
import{attachQueuePolicy as dt,getQueueArn as Tt,isQueueState as bt}from"@ez4/aws-queue";
|
|
67
|
+
import{getAccountId as pe,getRegion as ce}from"@ez4/aws-identity";import{attachEntry as xt}from"@ez4/stateful";
|
|
68
|
+
import{hashData as vt}from"@ez4/utils";var h=i((e,t,r,o)=>{let n=t.parameters.topicName,s=[t.entryId,r.entryId];if(se(r)){
|
|
69
|
+
let c=gt(e,t,r)??lt(e,t,r,{fromService:o.fromService,getPermission:i(async()=>{let[
|
|
70
|
+
m,u]=await Promise.all([ce(),pe()]);return{principal:"sns.amazonaws.com",sourceArn:y(
|
|
71
|
+
n,m,u)}},"getPermission")});s.push(c.entryId)}if(bt(r)){let c=dt(e,r,t,{fromService:o.
|
|
72
|
+
fromService,policyGetters:[async()=>{let[m,u]=await Promise.all([ce(),pe()]);return{
|
|
73
|
+
principal:"sns.amazonaws.com",sourceArn:y(n,m,u)}}]});s.push(c.entryId)}let p=vt(
|
|
74
|
+
l,t.entryId,r.entryId);return xt(e,{type:l,entryId:p,dependencies:s,parameters:{
|
|
75
|
+
...o,getTopicArn:i(c=>oe(S,p,c),"getTopicArn"),getEndpoint:i(c=>se(r)?yt(a,p,c):
|
|
76
|
+
Tt(a,p,c),"getEndpoint")}})},"createSubscription");import{getServiceName as Et}from"@ez4/project/library";import{toKebabCase as z}from"@ez4/utils";var F=i((e,t)=>`${z(e.name)}-${z(t)}`,"getInternalName"),ae=i((e,t,r)=>`${Et(e,r)}\
|
|
77
|
+
-${z(t)}`,"getFunctionName");var g=class extends Error{static{i(this,"RoleMissingError")}constructor(){super(
|
|
78
|
+
"Execution role for SNS is missing.")}},d=class extends Error{constructor(r){super(
|
|
79
|
+
`Imported project ${r} wasn't found.`);this.projectName=r}static{i(this,"Project\
|
|
80
|
+
MissingError")}};var T;(o=>(o.LogRetention=90,o.Timeout=90,o.Memory=192))(T||={});var R=i(async(e,t,r,o,n)=>{if(!n.role||!ue(n.role))throw new g;for(let s of t.subscriptions)
|
|
81
|
+
switch(s.type){default:throw new D(a,"subscription not supported.");case w.Lambda:{
|
|
82
|
+
if(t.fifoMode)throw new D(a,"lambda subscription not supported for FIFO topics.");
|
|
83
|
+
let{handler:p,listener:c}=s,m=F(t,p.name),u=Rt(n,m,o);if(!u){let k=ae(t,p.name,o),
|
|
84
|
+
ve=At(e,{retention:s.logRetention??T.LogRetention,groupName:k,tags:o.tags});u=ne(
|
|
85
|
+
e,n.role,ve,{functionName:k,description:p.description,messageSchema:t.schema,timeout:s.
|
|
86
|
+
timeout??T.Timeout,memory:s.memory??T.Memory,extras:t.extras,debug:o.debug,tags:o.
|
|
87
|
+
tags,variables:{...o.variables,...t.variables,...s.variables},handler:{dependencies:n.
|
|
88
|
+
getDependencies(p.file),functionName:p.name,sourceFile:p.file,module:p.module},...c&&
|
|
89
|
+
{listener:{functionName:c.name,sourceFile:c.file,module:c.module}}}),n.setServiceState(
|
|
90
|
+
u,m,o)}h(e,r,u,{fromService:u.parameters.functionName});break}case w.Queue:{let p=Se(
|
|
91
|
+
n,s.service,o);h(e,r,p,{fromService:p.parameters.queueName});break}}},"prepareSu\
|
|
92
|
+
bscriptions"),A=i((e,t,r,o)=>{if(t.extras){if(!o.role||!ue(o.role))throw new g;for(let n of t.
|
|
93
|
+
subscriptions)switch(n.type){default:throw new D(a,"subscription not supported.");case w.
|
|
94
|
+
Lambda:{let s=F(t,n.handler.name),p=wt(o,s,r);me(e,p.entryId,t.extras);break}case w.
|
|
95
|
+
Queue:{let s=Se(o,n.service,r);me(e,s.entryId,t.extras);break}}}},"connectSubscr\
|
|
96
|
+
iptions");import{getDefinitionName as Pt}from"@ez4/project/library";var P=i((e,t,r)=>{let n=re(e,t.name,r).entryId,s=Pt(n,"topicArn"),p=JSON.stringify(
|
|
97
|
+
t.fifoMode??null),c=JSON.stringify(t.schema);return{entryIds:[n],constructor:`ma\
|
|
98
|
+
ke(${s}, ${c}, ${p})`,from:"@ez4/aws-topic/client",module:"Client"}},"prepareLin\
|
|
99
|
+
kedClient");var fe=i(e=>{let{service:t,options:r,context:o}=e;return L(t)?P(o,t,r):null},"pr\
|
|
100
|
+
epareLinkedServices"),le=i(async e=>{let{state:t,service:r,options:o,context:n}=e;
|
|
101
|
+
if(!L(r))return!1;let{fifoMode:s}=r,p=E(t,{topicName:Nt(r,o),fifoMode:!!s,tags:o.
|
|
102
|
+
tags});return n.setServiceState(p,r,o),await R(t,r,p,o,n),!0},"prepareServices"),
|
|
103
|
+
ye=i(e=>{let{state:t,service:r,options:o,context:n}=e;L(r)&&A(t,r,o,n)},"connect\
|
|
104
|
+
Services");import{isTopicImport as M}from"@ez4/topic/library";import{getServiceName as Ct}from"@ez4/project/library";var ge=i(e=>{let{service:t,options:r,context:o}=e;if(!M(t))return null;let{project:n}=t,
|
|
105
|
+
{imports:s}=r;if(!s||!s[n])throw new d(n);return P(o,t,s[n])},"prepareLinkedImpo\
|
|
106
|
+
rts"),de=i(async e=>{let{state:t,service:r,options:o,context:n}=e;if(!M(r))return!1;
|
|
107
|
+
let{reference:s,project:p}=r,{imports:c}=o;if(!c||!c[p])throw new d(p);let m=E(t,
|
|
108
|
+
{topicName:Ct(s,c[p]),fifoMode:!!r.fifoMode,import:!0});return n.setServiceState(
|
|
109
|
+
m,r,o),await R(t,r,m,o,n),!0},"prepareImports"),Te=i(e=>{let{state:t,service:r,options:o,
|
|
110
|
+
context:n}=e;M(r)&&A(t,r,o,n)},"connectImports");import{ServiceType as It,ImportType as ht}from"@ez4/topic/library";import{createPolicy as zt,
|
|
111
|
+
tryGetPolicy as Ft}from"@ez4/aws-identity";import{getServiceName as Dt}from"@ez4/project/library";var be=i(async e=>{let{state:t,serviceType:r,options:o}=e;if(r!==It&&r!==ht)return null;
|
|
112
|
+
let n=Object.values({options:o,...o.imports}).map(c=>Dt("",c)),[s]=n,p=`${s}-top\
|
|
113
|
+
ic-policy`;return Ft(t,p)??zt(t,{tags:o.tags,policyDocument:await O(n),policyName:p})},
|
|
114
|
+
"prepareExecutionPolicy");var xe=!1,Ei=i(()=>{xe||(Lt(),Mt(),kt(),Ot(),$t(),jt("@ez4/aws-topic",{"deploy:p\
|
|
115
|
+
repareExecutionPolicy":be,"deploy:prepareLinkedService":Qt,"deploy:prepareResour\
|
|
116
|
+
ces":qt,"deploy:connectResources":Gt}),U(),te(),xe=!0)},"registerTriggers"),Qt=i(
|
|
117
|
+
e=>fe(e)??ge(e)??null,"prepareLinkedService"),qt=i(async e=>await le(e)||await de(
|
|
118
|
+
e),"prepareQueueResources"),Gt=i(async e=>{await Promise.all([ye(e),Te(e)])},"co\
|
|
119
|
+
nnectQueueResources");var Pi=i(e=>e.type===l,"isSubscriptionState");export{a as SubscriptionServiceName,l as SubscriptionServiceType,S as TopicServiceName,
|
|
120
|
+
f as TopicServiceType,h as createSubscription,ne as createSubscriptionFunction,E as createTopic,
|
|
121
|
+
C as createTopicStateId,Kr as getTopic,oe as getTopicArn,re as getTopicState,Pi as isSubscriptionState,
|
|
122
|
+
I as isTopicState,Ei as registerTriggers};
|
|
123
|
+
//# sourceMappingURL=main.mjs.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Arn } from '@ez4/aws-common';
|
|
2
|
+
export declare const enum SubscriptionProtocol {
|
|
3
|
+
Lambda = "lambda",
|
|
4
|
+
SQS = "sqs"
|
|
5
|
+
}
|
|
6
|
+
export type CreateRequest = {
|
|
7
|
+
topicArn: string;
|
|
8
|
+
protocol: SubscriptionProtocol;
|
|
9
|
+
endpoint: string;
|
|
10
|
+
};
|
|
11
|
+
export type CreateResponse = {
|
|
12
|
+
subscriptionArn: Arn;
|
|
13
|
+
};
|
|
14
|
+
export declare const createSubscription: (request: CreateRequest) => Promise<CreateResponse>;
|
|
15
|
+
export declare const deleteSubscription: (subscriptionArn: string) => Promise<boolean>;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { EntryState, EntryStates } from '@ez4/stateful';
|
|
2
|
+
import type { LogGroupState } from '@ez4/aws-logs';
|
|
3
|
+
import type { RoleState } from '@ez4/aws-identity';
|
|
4
|
+
import type { SubscriptionFunctionParameters } from './types';
|
|
5
|
+
export declare const createSubscriptionFunction: <E extends EntryState>(state: EntryStates<E>, roleState: RoleState, logGroupState: LogGroupState, parameters: SubscriptionFunctionParameters) => import("@ez4/aws-function").FunctionState;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { TopicMessageSchema } from '@ez4/topic/library';
|
|
2
|
+
import type { FunctionParameters } from '@ez4/aws-function';
|
|
3
|
+
import type { ExtraSource } from '@ez4/project/library';
|
|
4
|
+
export type SubscriptionFunction = {
|
|
5
|
+
functionName: string;
|
|
6
|
+
sourceFile: string;
|
|
7
|
+
module?: string;
|
|
8
|
+
};
|
|
9
|
+
export type SubscriptionEntryPoint = SubscriptionFunction & {
|
|
10
|
+
dependencies: string[];
|
|
11
|
+
};
|
|
12
|
+
export type SubscriptionFunctionParameters = Omit<FunctionParameters, 'getFunctionBundle' | 'getFunctionFiles' | 'sourceFile' | 'handlerName'> & {
|
|
13
|
+
handler: SubscriptionEntryPoint;
|
|
14
|
+
listener?: SubscriptionFunction;
|
|
15
|
+
messageSchema?: TopicMessageSchema | null;
|
|
16
|
+
extras?: Record<string, ExtraSource>;
|
|
17
|
+
debug?: boolean;
|
|
18
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const registerSubscriptionProvider: () => void;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { EntryState, EntryStates } from '@ez4/stateful';
|
|
2
|
+
import type { FunctionState } from '@ez4/aws-function';
|
|
3
|
+
import type { QueueState } from '@ez4/aws-queue';
|
|
4
|
+
import type { TopicState } from '../topic/types';
|
|
5
|
+
import type { SubscriptionParameters, SubscriptionState } from './types';
|
|
6
|
+
export declare const createSubscription: <E extends EntryState>(state: EntryStates<E>, topicState: TopicState, endpointState: FunctionState | QueueState, parameters: Pick<SubscriptionParameters, "fromService">) => SubscriptionState;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Arn } from '@ez4/aws-common';
|
|
2
|
+
import type { EntryState, StepContext } from '@ez4/stateful';
|
|
3
|
+
import type { CreateResponse } from './client';
|
|
4
|
+
export declare const SubscriptionServiceName = "AWS:SNS/Subscription";
|
|
5
|
+
export declare const SubscriptionServiceType = "aws:sns.subscription";
|
|
6
|
+
export type GetSubscriptionTopicArn = (context: StepContext) => Promise<Arn> | Arn;
|
|
7
|
+
export type GetSubscriptionEndpoint = (context: StepContext) => Promise<string> | string;
|
|
8
|
+
export type SubscriptionParameters = {
|
|
9
|
+
getTopicArn: GetSubscriptionTopicArn;
|
|
10
|
+
getEndpoint: GetSubscriptionEndpoint;
|
|
11
|
+
fromService: string;
|
|
12
|
+
};
|
|
13
|
+
export type SubscriptionResult = CreateResponse & {
|
|
14
|
+
topicArn: Arn;
|
|
15
|
+
endpoint: string;
|
|
16
|
+
};
|
|
17
|
+
export type SubscriptionState = EntryState & {
|
|
18
|
+
type: typeof SubscriptionServiceType;
|
|
19
|
+
parameters: SubscriptionParameters;
|
|
20
|
+
result?: SubscriptionResult;
|
|
21
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Arn, ResourceTags } from '@ez4/aws-common';
|
|
2
|
+
export type CreateRequest = {
|
|
3
|
+
topicName: string;
|
|
4
|
+
fifoMode: boolean;
|
|
5
|
+
tags?: ResourceTags;
|
|
6
|
+
};
|
|
7
|
+
export type CreateResponse = {
|
|
8
|
+
topicArn: Arn;
|
|
9
|
+
};
|
|
10
|
+
export declare const createTopic: (request: CreateRequest) => Promise<CreateResponse>;
|
|
11
|
+
export declare const deleteTopic: (topicArn: string) => Promise<boolean>;
|
|
12
|
+
export declare const tagTopic: (topicArn: string, tags: ResourceTags) => Promise<void>;
|
|
13
|
+
export declare const untagTopic: (topicArn: string, tagKeys: string[]) => Promise<void>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const registerTopicProvider: () => void;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { EntryState, EntryStates } from '@ez4/stateful';
|
|
2
|
+
import type { TopicParameters, TopicState } from './types';
|
|
3
|
+
import { TopicServiceType } from './types';
|
|
4
|
+
export declare const createTopic: <E extends EntryState>(state: EntryStates<E>, parameters: TopicParameters) => TopicState;
|
|
5
|
+
export declare const getTopic: <E extends EntryState>(state: EntryStates<E>, topicName: string) => (E & EntryState & {
|
|
6
|
+
type: typeof TopicServiceType;
|
|
7
|
+
parameters: TopicParameters;
|
|
8
|
+
result?: import("./types").TopicResult;
|
|
9
|
+
}) | null;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { EntryState } from '@ez4/stateful';
|
|
2
|
+
import type { CreateRequest, CreateResponse } from './client';
|
|
3
|
+
export declare const TopicServiceName = "AWS:SNS/Topic";
|
|
4
|
+
export declare const TopicServiceType = "aws:sns.topic";
|
|
5
|
+
export type TopicParameters = CreateRequest & {
|
|
6
|
+
import?: boolean;
|
|
7
|
+
};
|
|
8
|
+
export type TopicResult = CreateResponse;
|
|
9
|
+
export type TopicState = EntryState & {
|
|
10
|
+
type: typeof TopicServiceType;
|
|
11
|
+
parameters: TopicParameters;
|
|
12
|
+
result?: TopicResult;
|
|
13
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { DeployOptions, EventContext } from '@ez4/project/library';
|
|
2
|
+
import type { EntryState, StepContext } from '@ez4/stateful';
|
|
3
|
+
import type { TopicState } from './types';
|
|
4
|
+
export declare const createTopicStateId: (topicName: string, normalize?: boolean) => string;
|
|
5
|
+
export declare const isTopicState: (resource: EntryState) => resource is TopicState;
|
|
6
|
+
export declare const getTopicState: (context: EventContext, topicName: string, options: DeployOptions) => TopicState;
|
|
7
|
+
export declare const getTopicArn: (serviceName: string, resourceId: string, context: StepContext) => `arn:aws:${string}:${string}:${string}:${string}`;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { TopicImport, TopicService } from '@ez4/topic/library';
|
|
2
|
+
import type { DeployOptions, EventContext, ExtraSource } from '@ez4/project/library';
|
|
3
|
+
export declare const prepareLinkedClient: (context: EventContext, service: TopicService | TopicImport, options: DeployOptions) => ExtraSource;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ConnectResourceEvent, PrepareResourceEvent, ServiceEvent } from '@ez4/project/library';
|
|
2
|
+
export declare const prepareLinkedImports: (event: ServiceEvent) => import("@ez4/project/library").ExtraSource | null;
|
|
3
|
+
export declare const prepareImports: (event: PrepareResourceEvent) => Promise<boolean>;
|
|
4
|
+
export declare const connectImports: (event: ConnectResourceEvent) => void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const registerTriggers: () => void;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ConnectResourceEvent, PrepareResourceEvent, ServiceEvent } from '@ez4/project/library';
|
|
2
|
+
export declare const prepareLinkedServices: (event: ServiceEvent) => import("@ez4/project/library").ExtraSource | null;
|
|
3
|
+
export declare const prepareServices: (event: PrepareResourceEvent) => Promise<boolean>;
|
|
4
|
+
export declare const connectServices: (event: ConnectResourceEvent) => void;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { TopicService, TopicImport } from '@ez4/topic/library';
|
|
2
|
+
import type { DeployOptions, EventContext } from '@ez4/project/library';
|
|
3
|
+
import type { EntryStates } from '@ez4/stateful';
|
|
4
|
+
import type { TopicState } from '../topic/types';
|
|
5
|
+
export declare const prepareSubscriptions: (state: EntryStates, service: TopicService | TopicImport, topicState: TopicState, options: DeployOptions, context: EventContext) => Promise<void>;
|
|
6
|
+
export declare const connectSubscriptions: (state: EntryStates, service: TopicService | TopicImport, options: DeployOptions, context: EventContext) => void;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { TopicService, TopicImport } from '@ez4/topic/library';
|
|
2
|
+
import type { DeployOptions } from '@ez4/project/library';
|
|
3
|
+
export declare const getInternalName: (service: TopicService | TopicImport, suffixName: string) => string;
|
|
4
|
+
export declare const getFunctionName: (service: TopicService | TopicImport, handlerName: string, options: DeployOptions) => string;
|
package/lib/message.ts
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import type { SNSEvent, Context } from 'aws-lambda';
|
|
2
|
+
import type { MessageSchema } from '@ez4/topic/utils';
|
|
3
|
+
import type { Topic } from '@ez4/topic';
|
|
4
|
+
|
|
5
|
+
import * as TopicUtils from '@ez4/topic/utils';
|
|
6
|
+
|
|
7
|
+
import { ServiceEventType } from '@ez4/common';
|
|
8
|
+
|
|
9
|
+
declare const __EZ4_SCHEMA: MessageSchema | null;
|
|
10
|
+
declare const __EZ4_CONTEXT: object;
|
|
11
|
+
|
|
12
|
+
declare function dispatch(event: Topic.ServiceEvent<Topic.Message>, context: object): Promise<void>;
|
|
13
|
+
declare function handle(message: Topic.Incoming<Topic.Message>, context: object): Promise<any>;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Entrypoint to handle SNS events.
|
|
17
|
+
*/
|
|
18
|
+
export async function snsEntryPoint(event: SNSEvent, context: Context): Promise<void> {
|
|
19
|
+
let currentRequest: Topic.Incoming<Topic.Message> | undefined;
|
|
20
|
+
|
|
21
|
+
const request = {
|
|
22
|
+
requestId: context.awsRequestId
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
await onBegin(request);
|
|
27
|
+
|
|
28
|
+
if (!__EZ4_SCHEMA) {
|
|
29
|
+
throw new Error(`Validation schema for SNS message not found.`);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
for (const record of event.Records) {
|
|
33
|
+
const payload = JSON.parse(record.Sns.Message);
|
|
34
|
+
const message = await TopicUtils.getJsonMessage(payload, __EZ4_SCHEMA);
|
|
35
|
+
|
|
36
|
+
currentRequest = {
|
|
37
|
+
...request,
|
|
38
|
+
message
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
await onReady(currentRequest);
|
|
42
|
+
|
|
43
|
+
await handle(currentRequest, __EZ4_CONTEXT);
|
|
44
|
+
}
|
|
45
|
+
} catch (error) {
|
|
46
|
+
await onError(error, currentRequest ?? request);
|
|
47
|
+
} finally {
|
|
48
|
+
await onEnd(request);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const onBegin = async (request: Topic.Request) => {
|
|
53
|
+
return dispatch(
|
|
54
|
+
{
|
|
55
|
+
type: ServiceEventType.Begin,
|
|
56
|
+
request
|
|
57
|
+
},
|
|
58
|
+
__EZ4_CONTEXT
|
|
59
|
+
);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const onReady = async (request: Topic.Incoming<Topic.Message>) => {
|
|
63
|
+
return dispatch(
|
|
64
|
+
{
|
|
65
|
+
type: ServiceEventType.Ready,
|
|
66
|
+
request
|
|
67
|
+
},
|
|
68
|
+
__EZ4_CONTEXT
|
|
69
|
+
);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const onError = async (error: Error, request: Topic.Request | Topic.Incoming<Topic.Message>) => {
|
|
73
|
+
console.error(error);
|
|
74
|
+
|
|
75
|
+
return dispatch(
|
|
76
|
+
{
|
|
77
|
+
type: ServiceEventType.Error,
|
|
78
|
+
request,
|
|
79
|
+
error
|
|
80
|
+
},
|
|
81
|
+
__EZ4_CONTEXT
|
|
82
|
+
);
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const onEnd = async (request: Topic.Request) => {
|
|
86
|
+
return dispatch(
|
|
87
|
+
{
|
|
88
|
+
type: ServiceEventType.End,
|
|
89
|
+
request
|
|
90
|
+
},
|
|
91
|
+
__EZ4_CONTEXT
|
|
92
|
+
);
|
|
93
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ez4/aws-topic",
|
|
3
|
+
"description": "EZ4: Self-managed AWS SNS topics provider",
|
|
4
|
+
"version": "0.27.0",
|
|
5
|
+
"author": "Silas B.",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"keywords": [
|
|
9
|
+
"ez4"
|
|
10
|
+
],
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "git+https://github.com/sbalmt/ez4.git",
|
|
14
|
+
"directory": "providers/aws/aws-topic"
|
|
15
|
+
},
|
|
16
|
+
"engines": {
|
|
17
|
+
"node": ">=22.7"
|
|
18
|
+
},
|
|
19
|
+
"exports": {
|
|
20
|
+
".": {
|
|
21
|
+
"types": "./dist/main.d.ts",
|
|
22
|
+
"require": "./dist/main.cjs",
|
|
23
|
+
"import": "./dist/main.mjs"
|
|
24
|
+
},
|
|
25
|
+
"./client": {
|
|
26
|
+
"types": "./dist/client.d.ts",
|
|
27
|
+
"require": "./dist/client.cjs",
|
|
28
|
+
"import": "./dist/client.mjs"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"workspaces": [
|
|
32
|
+
"foundation/*",
|
|
33
|
+
"contracts/*",
|
|
34
|
+
"providers/aws/*"
|
|
35
|
+
],
|
|
36
|
+
"scripts": {
|
|
37
|
+
"lint": "eslint --cache",
|
|
38
|
+
"clean": "rm -f *.tsbuildinfo && rm -rf dist/*",
|
|
39
|
+
"build": "tsc && node tools/bundler.mjs",
|
|
40
|
+
"test": "npm run build && ez4 test -e ../../../local.env",
|
|
41
|
+
"local:publish": "npm run build && npm run clean:registry && npm publish --registry http://localhost:4873",
|
|
42
|
+
"clean:registry": "rm -rf ../../../.registry/@ez4/aws-topic",
|
|
43
|
+
"live:publish": "npm run build && npm publish --access public"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@types/aws-lambda": "^8.10.147"
|
|
47
|
+
},
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"@aws-sdk/client-sns": "^3.758.0",
|
|
50
|
+
"@ez4/aws-common": "^0.27.0",
|
|
51
|
+
"@ez4/aws-identity": "^0.27.0",
|
|
52
|
+
"@ez4/aws-function": "^0.27.0",
|
|
53
|
+
"@ez4/aws-logs": "^0.27.0",
|
|
54
|
+
"@ez4/aws-queue": "^0.27.0",
|
|
55
|
+
"@ez4/topic": "^0.27.0",
|
|
56
|
+
"@ez4/project": "^0.27.0",
|
|
57
|
+
"@ez4/queue": "^0.27.0",
|
|
58
|
+
"@ez4/schema": "^0.27.0",
|
|
59
|
+
"@ez4/stateful": "^0.27.0",
|
|
60
|
+
"@ez4/transform": "^0.27.0",
|
|
61
|
+
"@ez4/validator": "^0.27.0",
|
|
62
|
+
"@ez4/utils": "^0.27.0"
|
|
63
|
+
}
|
|
64
|
+
}
|