@nlabs/reaktor 1.17.0 → 1.18.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/README.md +182 -0
- package/docs/ASSISTANT.md +138 -0
- package/docs/GENERATION.md +15 -0
- package/docs/NATIVE_PUSH.md +56 -0
- package/lib/actions/alfredFaq.d.ts +80 -0
- package/lib/actions/alfredFaq.js +206 -0
- package/lib/actions/contentGeneration.d.ts +1 -0
- package/lib/actions/contentGeneration.js +25 -6
- package/lib/actions/conversations.d.ts +1 -1
- package/lib/actions/conversations.js +19 -9
- package/lib/actions/crud.js +26 -1
- package/lib/actions/index.d.ts +1 -0
- package/lib/actions/index.js +2 -1
- package/lib/actions/messages.js +23 -7
- package/lib/actions/users.js +57 -4
- package/lib/assistant/core.d.ts +53 -0
- package/lib/assistant/core.js +123 -0
- package/lib/assistant/faq.d.ts +26 -0
- package/lib/assistant/faq.js +238 -0
- package/lib/assistant/faqCore.d.ts +23 -0
- package/lib/assistant/faqCore.js +20 -0
- package/lib/assistant/index.d.ts +7 -0
- package/lib/assistant/index.js +5 -0
- package/lib/assistant/service.d.ts +35 -0
- package/lib/assistant/service.js +201 -0
- package/lib/durableChat/conversations.d.ts +62 -0
- package/lib/durableChat/conversations.js +729 -0
- package/lib/durableChat/errors.d.ts +6 -0
- package/lib/durableChat/errors.js +11 -0
- package/lib/durableChat/events.d.ts +22 -0
- package/lib/durableChat/events.js +50 -0
- package/lib/durableChat/index.d.ts +8 -0
- package/lib/durableChat/index.js +10 -0
- package/lib/durableChat/membership.d.ts +24 -0
- package/lib/durableChat/membership.js +85 -0
- package/lib/durableChat/messageTypes.d.ts +76 -0
- package/lib/durableChat/messageTypes.js +3 -0
- package/lib/durableChat/messages.d.ts +16 -0
- package/lib/durableChat/messages.js +257 -0
- package/lib/durableChat/transaction.d.ts +10 -0
- package/lib/durableChat/transaction.js +53 -0
- package/lib/durableChat/types.d.ts +81 -0
- package/lib/durableChat/types.js +3 -0
- package/lib/index.d.ts +4 -4
- package/lib/index.js +5 -3
- package/lib/lambdas/actions/websockets.js +4 -4
- package/lib/nativePush/graphql.d.ts +14 -0
- package/lib/nativePush/graphql.js +105 -0
- package/lib/nativePush/index.d.ts +7 -0
- package/lib/nativePush/index.js +9 -0
- package/lib/nativePush/migrations.d.ts +2 -0
- package/lib/nativePush/migrations.js +36 -0
- package/lib/nativePush/nativePushContract.fixture.d.ts +22 -0
- package/lib/nativePush/nativePushContract.fixture.js +27 -0
- package/lib/nativePush/payload.d.ts +2 -0
- package/lib/nativePush/payload.js +106 -0
- package/lib/nativePush/repository.d.ts +9 -0
- package/lib/nativePush/repository.js +120 -0
- package/lib/nativePush/service.d.ts +2 -0
- package/lib/nativePush/service.js +110 -0
- package/lib/nativePush/snsProvider.d.ts +17 -0
- package/lib/nativePush/snsProvider.js +165 -0
- package/lib/nativePush/types.d.ts +89 -0
- package/lib/nativePush/types.js +3 -0
- package/lib/organizations/accountLifecycle.d.ts +7 -0
- package/lib/organizations/accountLifecycle.js +106 -0
- package/lib/organizations/authorization.d.ts +9 -0
- package/lib/organizations/authorization.js +40 -0
- package/lib/organizations/billing.d.ts +38 -0
- package/lib/organizations/billing.js +277 -0
- package/lib/organizations/billingProvider.d.ts +4 -0
- package/lib/organizations/billingProvider.js +287 -0
- package/lib/organizations/billingUpdates.d.ts +9 -0
- package/lib/organizations/billingUpdates.js +388 -0
- package/lib/organizations/index.d.ts +10 -0
- package/lib/organizations/index.js +12 -0
- package/lib/organizations/mail.d.ts +10 -0
- package/lib/organizations/mail.js +60 -0
- package/lib/organizations/memberDirectory.d.ts +15 -0
- package/lib/organizations/memberDirectory.js +28 -0
- package/lib/organizations/membership.d.ts +19 -0
- package/lib/organizations/membership.js +248 -0
- package/lib/organizations/passwordRecovery.d.ts +9 -0
- package/lib/organizations/passwordRecovery.js +50 -0
- package/lib/organizations/plans.d.ts +6 -0
- package/lib/organizations/plans.js +40 -0
- package/lib/organizations/providerPagination.d.ts +6 -0
- package/lib/organizations/providerPagination.js +23 -0
- package/lib/organizations/reconciliation.d.ts +11 -0
- package/lib/organizations/reconciliation.js +400 -0
- package/lib/organizations/signup.d.ts +25 -0
- package/lib/organizations/signup.js +169 -0
- package/lib/organizations/store.d.ts +25 -0
- package/lib/organizations/store.js +167 -0
- package/lib/organizations/types.d.ts +138 -0
- package/lib/organizations/types.js +3 -0
- package/lib/organizations/verification.d.ts +3 -0
- package/lib/organizations/verification.js +51 -0
- package/package.json +16 -3
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { GraphQLEnumType, GraphQLInputObjectType, GraphQLObjectType } from 'graphql';
|
|
2
|
+
import type { NativePushService, PushActor } from './types.js';
|
|
3
|
+
export declare const createNativePushGraphql: <Context>({ resolveActor, service }: {
|
|
4
|
+
resolveActor: (context: Context) => Promise<PushActor | null | undefined> | PushActor | null | undefined;
|
|
5
|
+
service: NativePushService;
|
|
6
|
+
}) => {
|
|
7
|
+
mutationFields: {
|
|
8
|
+
nativePush: {
|
|
9
|
+
resolve: () => {};
|
|
10
|
+
type: GraphQLObjectType<unknown, Context, any>;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
types: (GraphQLEnumType | GraphQLInputObjectType | GraphQLObjectType<any, any, any>)[];
|
|
14
|
+
};
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { GraphQLBoolean, GraphQLEnumType, GraphQLID, GraphQLInputObjectType, GraphQLInt, GraphQLNonNull, GraphQLObjectType, GraphQLString } from 'graphql';
|
|
2
|
+
export const createNativePushGraphql = ({ resolveActor, service })=>{
|
|
3
|
+
const platform = new GraphQLEnumType({
|
|
4
|
+
name: 'NativePushPlatform',
|
|
5
|
+
values: {
|
|
6
|
+
ANDROID: {},
|
|
7
|
+
IOS: {}
|
|
8
|
+
}
|
|
9
|
+
});
|
|
10
|
+
const input = new GraphQLInputObjectType({
|
|
11
|
+
fields: {
|
|
12
|
+
apnsEnvironment: {
|
|
13
|
+
type: GraphQLString
|
|
14
|
+
},
|
|
15
|
+
installationId: {
|
|
16
|
+
type: new GraphQLNonNull(GraphQLID)
|
|
17
|
+
},
|
|
18
|
+
platform: {
|
|
19
|
+
type: new GraphQLNonNull(platform)
|
|
20
|
+
},
|
|
21
|
+
token: {
|
|
22
|
+
type: new GraphQLNonNull(GraphQLString)
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
name: 'NativePushRegistrationInput'
|
|
26
|
+
});
|
|
27
|
+
const registration = new GraphQLObjectType({
|
|
28
|
+
fields: {
|
|
29
|
+
createdAt: {
|
|
30
|
+
type: new GraphQLNonNull(GraphQLString)
|
|
31
|
+
},
|
|
32
|
+
enabled: {
|
|
33
|
+
type: new GraphQLNonNull(GraphQLBoolean)
|
|
34
|
+
},
|
|
35
|
+
installationId: {
|
|
36
|
+
type: new GraphQLNonNull(GraphQLID)
|
|
37
|
+
},
|
|
38
|
+
platform: {
|
|
39
|
+
type: new GraphQLNonNull(platform)
|
|
40
|
+
},
|
|
41
|
+
registrationId: {
|
|
42
|
+
type: new GraphQLNonNull(GraphQLID)
|
|
43
|
+
},
|
|
44
|
+
revision: {
|
|
45
|
+
type: new GraphQLNonNull(GraphQLInt)
|
|
46
|
+
},
|
|
47
|
+
updatedAt: {
|
|
48
|
+
type: new GraphQLNonNull(GraphQLString)
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
name: 'NativePushRegistration'
|
|
52
|
+
});
|
|
53
|
+
const authenticatedActor = async (context)=>{
|
|
54
|
+
const actor = await resolveActor(context);
|
|
55
|
+
if (!actor?.userId || !actor.sessionId) {
|
|
56
|
+
throw new Error('Authenticated push session required');
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
sessionId: actor.sessionId,
|
|
60
|
+
userId: actor.userId
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
const group = new GraphQLObjectType({
|
|
64
|
+
fields: {
|
|
65
|
+
register: {
|
|
66
|
+
args: {
|
|
67
|
+
input: {
|
|
68
|
+
type: new GraphQLNonNull(input)
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
resolve: async (_parent, args, context)=>service.register(await authenticatedActor(context), args.input),
|
|
72
|
+
type: registration
|
|
73
|
+
},
|
|
74
|
+
unregister: {
|
|
75
|
+
args: {
|
|
76
|
+
registrationId: {
|
|
77
|
+
type: new GraphQLNonNull(GraphQLID)
|
|
78
|
+
},
|
|
79
|
+
revision: {
|
|
80
|
+
type: GraphQLInt
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
resolve: async (_parent, args, context)=>service.unregister(await authenticatedActor(context), args.registrationId, args.revision),
|
|
84
|
+
type: new GraphQLNonNull(GraphQLBoolean)
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
name: 'NativePushMutation'
|
|
88
|
+
});
|
|
89
|
+
return {
|
|
90
|
+
mutationFields: {
|
|
91
|
+
nativePush: {
|
|
92
|
+
resolve: ()=>({}),
|
|
93
|
+
type: group
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
types: [
|
|
97
|
+
platform,
|
|
98
|
+
input,
|
|
99
|
+
registration,
|
|
100
|
+
group
|
|
101
|
+
]
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9Vc2Vycy9uaXRyb2c3L0RldmVsb3BtZW50L3JlYWt0b3IvcGFja2FnZXMvcmVha3Rvci9zcmMvbmF0aXZlUHVzaC9ncmFwaHFsLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEdyYXBoUUxCb29sZWFuLCBHcmFwaFFMRW51bVR5cGUsIEdyYXBoUUxJRCwgR3JhcGhRTElucHV0T2JqZWN0VHlwZSwgR3JhcGhRTEludCxcbiAgR3JhcGhRTE5vbk51bGwsIEdyYXBoUUxPYmplY3RUeXBlLCBHcmFwaFFMU3RyaW5nXG59IGZyb20gJ2dyYXBocWwnO1xuXG5pbXBvcnQgdHlwZSB7TmF0aXZlUHVzaFJlZ2lzdHJhdGlvbklucHV0LCBOYXRpdmVQdXNoU2VydmljZSwgUHVzaEFjdG9yfSBmcm9tICcuL3R5cGVzLmpzJztcblxuZXhwb3J0IGNvbnN0IGNyZWF0ZU5hdGl2ZVB1c2hHcmFwaHFsID0gPENvbnRleHQ+KHtyZXNvbHZlQWN0b3IsIHNlcnZpY2V9OiB7XG4gIHJlc29sdmVBY3RvcjogKGNvbnRleHQ6IENvbnRleHQpID0+IFByb21pc2U8UHVzaEFjdG9yIHwgbnVsbCB8IHVuZGVmaW5lZD4gfCBQdXNoQWN0b3IgfCBudWxsIHwgdW5kZWZpbmVkO1xuICBzZXJ2aWNlOiBOYXRpdmVQdXNoU2VydmljZTtcbn0pID0+IHtcbiAgY29uc3QgcGxhdGZvcm0gPSBuZXcgR3JhcGhRTEVudW1UeXBlKHtuYW1lOiAnTmF0aXZlUHVzaFBsYXRmb3JtJywgdmFsdWVzOiB7QU5EUk9JRDoge30sIElPUzoge319fSk7XG4gIGNvbnN0IGlucHV0ID0gbmV3IEdyYXBoUUxJbnB1dE9iamVjdFR5cGUoe1xuICAgIGZpZWxkczoge1xuICAgICAgYXBuc0Vudmlyb25tZW50OiB7dHlwZTogR3JhcGhRTFN0cmluZ30sXG4gICAgICBpbnN0YWxsYXRpb25JZDoge3R5cGU6IG5ldyBHcmFwaFFMTm9uTnVsbChHcmFwaFFMSUQpfSxcbiAgICAgIHBsYXRmb3JtOiB7dHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKHBsYXRmb3JtKX0sXG4gICAgICB0b2tlbjoge3R5cGU6IG5ldyBHcmFwaFFMTm9uTnVsbChHcmFwaFFMU3RyaW5nKX1cbiAgICB9LFxuICAgIG5hbWU6ICdOYXRpdmVQdXNoUmVnaXN0cmF0aW9uSW5wdXQnXG4gIH0pO1xuICBjb25zdCByZWdpc3RyYXRpb24gPSBuZXcgR3JhcGhRTE9iamVjdFR5cGUoe1xuICAgIGZpZWxkczoge1xuICAgICAgY3JlYXRlZEF0OiB7dHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKEdyYXBoUUxTdHJpbmcpfSxcbiAgICAgIGVuYWJsZWQ6IHt0eXBlOiBuZXcgR3JhcGhRTE5vbk51bGwoR3JhcGhRTEJvb2xlYW4pfSxcbiAgICAgIGluc3RhbGxhdGlvbklkOiB7dHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKEdyYXBoUUxJRCl9LFxuICAgICAgcGxhdGZvcm06IHt0eXBlOiBuZXcgR3JhcGhRTE5vbk51bGwocGxhdGZvcm0pfSxcbiAgICAgIHJlZ2lzdHJhdGlvbklkOiB7dHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKEdyYXBoUUxJRCl9LFxuICAgICAgcmV2aXNpb246IHt0eXBlOiBuZXcgR3JhcGhRTE5vbk51bGwoR3JhcGhRTEludCl9LFxuICAgICAgdXBkYXRlZEF0OiB7dHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKEdyYXBoUUxTdHJpbmcpfVxuICAgIH0sXG4gICAgbmFtZTogJ05hdGl2ZVB1c2hSZWdpc3RyYXRpb24nXG4gIH0pO1xuICBjb25zdCBhdXRoZW50aWNhdGVkQWN0b3IgPSBhc3luYyAoY29udGV4dDogQ29udGV4dCk6IFByb21pc2U8UHVzaEFjdG9yPiA9PiB7XG4gICAgY29uc3QgYWN0b3IgPSBhd2FpdCByZXNvbHZlQWN0b3IoY29udGV4dCk7XG4gICAgaWYoIWFjdG9yPy51c2VySWQgfHwgIWFjdG9yLnNlc3Npb25JZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdBdXRoZW50aWNhdGVkIHB1c2ggc2Vzc2lvbiByZXF1aXJlZCcpO1xuICAgIH1cbiAgICByZXR1cm4ge3Nlc3Npb25JZDogYWN0b3Iuc2Vzc2lvbklkLCB1c2VySWQ6IGFjdG9yLnVzZXJJZH07XG4gIH07XG4gIGNvbnN0IGdyb3VwID0gbmV3IEdyYXBoUUxPYmplY3RUeXBlPHVua25vd24sIENvbnRleHQ+KHtcbiAgICBmaWVsZHM6IHtcbiAgICAgIHJlZ2lzdGVyOiB7XG4gICAgICAgIGFyZ3M6IHtpbnB1dDoge3R5cGU6IG5ldyBHcmFwaFFMTm9uTnVsbChpbnB1dCl9fSxcbiAgICAgICAgcmVzb2x2ZTogYXN5bmMgKF9wYXJlbnQsIGFyZ3M6IHtpbnB1dDogTmF0aXZlUHVzaFJlZ2lzdHJhdGlvbklucHV0fSwgY29udGV4dCkgPT5cbiAgICAgICAgICBzZXJ2aWNlLnJlZ2lzdGVyKGF3YWl0IGF1dGhlbnRpY2F0ZWRBY3Rvcihjb250ZXh0KSwgYXJncy5pbnB1dCksXG4gICAgICAgIHR5cGU6IHJlZ2lzdHJhdGlvblxuICAgICAgfSxcbiAgICAgIHVucmVnaXN0ZXI6IHtcbiAgICAgICAgYXJnczoge3JlZ2lzdHJhdGlvbklkOiB7dHlwZTogbmV3IEdyYXBoUUxOb25OdWxsKEdyYXBoUUxJRCl9LCByZXZpc2lvbjoge3R5cGU6IEdyYXBoUUxJbnR9fSxcbiAgICAgICAgcmVzb2x2ZTogYXN5bmMgKF9wYXJlbnQsIGFyZ3M6IHtyZWdpc3RyYXRpb25JZDogc3RyaW5nOyByZXZpc2lvbj86IG51bWJlcn0sIGNvbnRleHQpID0+XG4gICAgICAgICAgc2VydmljZS51bnJlZ2lzdGVyKGF3YWl0IGF1dGhlbnRpY2F0ZWRBY3Rvcihjb250ZXh0KSwgYXJncy5yZWdpc3RyYXRpb25JZCwgYXJncy5yZXZpc2lvbiksXG4gICAgICAgIHR5cGU6IG5ldyBHcmFwaFFMTm9uTnVsbChHcmFwaFFMQm9vbGVhbilcbiAgICAgIH1cbiAgICB9LFxuICAgIG5hbWU6ICdOYXRpdmVQdXNoTXV0YXRpb24nXG4gIH0pO1xuICByZXR1cm4ge1xuICAgIG11dGF0aW9uRmllbGRzOiB7bmF0aXZlUHVzaDoge3Jlc29sdmU6ICgpID0+ICh7fSksIHR5cGU6IGdyb3VwfX0sXG4gICAgdHlwZXM6IFtwbGF0Zm9ybSwgaW5wdXQsIHJlZ2lzdHJhdGlvbiwgZ3JvdXBdXG4gIH07XG59O1xuIl0sIm5hbWVzIjpbIkdyYXBoUUxCb29sZWFuIiwiR3JhcGhRTEVudW1UeXBlIiwiR3JhcGhRTElEIiwiR3JhcGhRTElucHV0T2JqZWN0VHlwZSIsIkdyYXBoUUxJbnQiLCJHcmFwaFFMTm9uTnVsbCIsIkdyYXBoUUxPYmplY3RUeXBlIiwiR3JhcGhRTFN0cmluZyIsImNyZWF0ZU5hdGl2ZVB1c2hHcmFwaHFsIiwicmVzb2x2ZUFjdG9yIiwic2VydmljZSIsInBsYXRmb3JtIiwibmFtZSIsInZhbHVlcyIsIkFORFJPSUQiLCJJT1MiLCJpbnB1dCIsImZpZWxkcyIsImFwbnNFbnZpcm9ubWVudCIsInR5cGUiLCJpbnN0YWxsYXRpb25JZCIsInRva2VuIiwicmVnaXN0cmF0aW9uIiwiY3JlYXRlZEF0IiwiZW5hYmxlZCIsInJlZ2lzdHJhdGlvbklkIiwicmV2aXNpb24iLCJ1cGRhdGVkQXQiLCJhdXRoZW50aWNhdGVkQWN0b3IiLCJjb250ZXh0IiwiYWN0b3IiLCJ1c2VySWQiLCJzZXNzaW9uSWQiLCJFcnJvciIsImdyb3VwIiwicmVnaXN0ZXIiLCJhcmdzIiwicmVzb2x2ZSIsIl9wYXJlbnQiLCJ1bnJlZ2lzdGVyIiwibXV0YXRpb25GaWVsZHMiLCJuYXRpdmVQdXNoIiwidHlwZXMiXSwibWFwcGluZ3MiOiJBQUFBLFNBQ0VBLGNBQWMsRUFBRUMsZUFBZSxFQUFFQyxTQUFTLEVBQUVDLHNCQUFzQixFQUFFQyxVQUFVLEVBQzlFQyxjQUFjLEVBQUVDLGlCQUFpQixFQUFFQyxhQUFhLFFBQzNDLFVBQVU7QUFJakIsT0FBTyxNQUFNQywwQkFBMEIsQ0FBVSxFQUFDQyxZQUFZLEVBQUVDLE9BQU8sRUFHdEU7SUFDQyxNQUFNQyxXQUFXLElBQUlWLGdCQUFnQjtRQUFDVyxNQUFNO1FBQXNCQyxRQUFRO1lBQUNDLFNBQVMsQ0FBQztZQUFHQyxLQUFLLENBQUM7UUFBQztJQUFDO0lBQ2hHLE1BQU1DLFFBQVEsSUFBSWIsdUJBQXVCO1FBQ3ZDYyxRQUFRO1lBQ05DLGlCQUFpQjtnQkFBQ0MsTUFBTVo7WUFBYTtZQUNyQ2EsZ0JBQWdCO2dCQUFDRCxNQUFNLElBQUlkLGVBQWVIO1lBQVU7WUFDcERTLFVBQVU7Z0JBQUNRLE1BQU0sSUFBSWQsZUFBZU07WUFBUztZQUM3Q1UsT0FBTztnQkFBQ0YsTUFBTSxJQUFJZCxlQUFlRTtZQUFjO1FBQ2pEO1FBQ0FLLE1BQU07SUFDUjtJQUNBLE1BQU1VLGVBQWUsSUFBSWhCLGtCQUFrQjtRQUN6Q1csUUFBUTtZQUNOTSxXQUFXO2dCQUFDSixNQUFNLElBQUlkLGVBQWVFO1lBQWM7WUFDbkRpQixTQUFTO2dCQUFDTCxNQUFNLElBQUlkLGVBQWVMO1lBQWU7WUFDbERvQixnQkFBZ0I7Z0JBQUNELE1BQU0sSUFBSWQsZUFBZUg7WUFBVTtZQUNwRFMsVUFBVTtnQkFBQ1EsTUFBTSxJQUFJZCxlQUFlTTtZQUFTO1lBQzdDYyxnQkFBZ0I7Z0JBQUNOLE1BQU0sSUFBSWQsZUFBZUg7WUFBVTtZQUNwRHdCLFVBQVU7Z0JBQUNQLE1BQU0sSUFBSWQsZUFBZUQ7WUFBVztZQUMvQ3VCLFdBQVc7Z0JBQUNSLE1BQU0sSUFBSWQsZUFBZUU7WUFBYztRQUNyRDtRQUNBSyxNQUFNO0lBQ1I7SUFDQSxNQUFNZ0IscUJBQXFCLE9BQU9DO1FBQ2hDLE1BQU1DLFFBQVEsTUFBTXJCLGFBQWFvQjtRQUNqQyxJQUFHLENBQUNDLE9BQU9DLFVBQVUsQ0FBQ0QsTUFBTUUsU0FBUyxFQUFFO1lBQ3JDLE1BQU0sSUFBSUMsTUFBTTtRQUNsQjtRQUNBLE9BQU87WUFBQ0QsV0FBV0YsTUFBTUUsU0FBUztZQUFFRCxRQUFRRCxNQUFNQyxNQUFNO1FBQUE7SUFDMUQ7SUFDQSxNQUFNRyxRQUFRLElBQUk1QixrQkFBb0M7UUFDcERXLFFBQVE7WUFDTmtCLFVBQVU7Z0JBQ1JDLE1BQU07b0JBQUNwQixPQUFPO3dCQUFDRyxNQUFNLElBQUlkLGVBQWVXO29CQUFNO2dCQUFDO2dCQUMvQ3FCLFNBQVMsT0FBT0MsU0FBU0YsTUFBNENQLFVBQ25FbkIsUUFBUXlCLFFBQVEsQ0FBQyxNQUFNUCxtQkFBbUJDLFVBQVVPLEtBQUtwQixLQUFLO2dCQUNoRUcsTUFBTUc7WUFDUjtZQUNBaUIsWUFBWTtnQkFDVkgsTUFBTTtvQkFBQ1gsZ0JBQWdCO3dCQUFDTixNQUFNLElBQUlkLGVBQWVIO29CQUFVO29CQUFHd0IsVUFBVTt3QkFBQ1AsTUFBTWY7b0JBQVU7Z0JBQUM7Z0JBQzFGaUMsU0FBUyxPQUFPQyxTQUFTRixNQUFtRFAsVUFDMUVuQixRQUFRNkIsVUFBVSxDQUFDLE1BQU1YLG1CQUFtQkMsVUFBVU8sS0FBS1gsY0FBYyxFQUFFVyxLQUFLVixRQUFRO2dCQUMxRlAsTUFBTSxJQUFJZCxlQUFlTDtZQUMzQjtRQUNGO1FBQ0FZLE1BQU07SUFDUjtJQUNBLE9BQU87UUFDTDRCLGdCQUFnQjtZQUFDQyxZQUFZO2dCQUFDSixTQUFTLElBQU8sQ0FBQSxDQUFDLENBQUE7Z0JBQUlsQixNQUFNZTtZQUFLO1FBQUM7UUFDL0RRLE9BQU87WUFBQy9CO1lBQVVLO1lBQU9NO1lBQWNZO1NBQU07SUFDL0M7QUFDRixFQUFFIn0=
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from './payload.js';
|
|
2
|
+
export * from './snsProvider.js';
|
|
3
|
+
export * from './types.js';
|
|
4
|
+
export * from './migrations.js';
|
|
5
|
+
export * from './repository.js';
|
|
6
|
+
export * from './service.js';
|
|
7
|
+
export * from './graphql.js';
|
|
8
|
+
|
|
9
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9Vc2Vycy9uaXRyb2c3L0RldmVsb3BtZW50L3JlYWt0b3IvcGFja2FnZXMvcmVha3Rvci9zcmMvbmF0aXZlUHVzaC9pbmRleC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgKiBmcm9tICcuL3BheWxvYWQuanMnO1xuZXhwb3J0ICogZnJvbSAnLi9zbnNQcm92aWRlci5qcyc7XG5leHBvcnQgKiBmcm9tICcuL3R5cGVzLmpzJztcbmV4cG9ydCAqIGZyb20gJy4vbWlncmF0aW9ucy5qcyc7XG5leHBvcnQgKiBmcm9tICcuL3JlcG9zaXRvcnkuanMnO1xuZXhwb3J0ICogZnJvbSAnLi9zZXJ2aWNlLmpzJztcbmV4cG9ydCAqIGZyb20gJy4vZ3JhcGhxbC5qcyc7XG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsY0FBYyxlQUFlO0FBQzdCLGNBQWMsbUJBQW1CO0FBQ2pDLGNBQWMsYUFBYTtBQUMzQixjQUFjLGtCQUFrQjtBQUNoQyxjQUFjLGtCQUFrQjtBQUNoQyxjQUFjLGVBQWU7QUFDN0IsY0FBYyxlQUFlIn0=
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { useDb } from '../utils/arangodbUtils.js';
|
|
2
|
+
export const migrateNativePushRegistry = async ({ collectionName = 'native_push_registrations', databaseFactory = useDb, databaseName })=>{
|
|
3
|
+
const collection = databaseFactory(databaseName).collection(collectionName);
|
|
4
|
+
if (!await collection.exists()) {
|
|
5
|
+
await collection.create();
|
|
6
|
+
}
|
|
7
|
+
await collection.ensureIndex({
|
|
8
|
+
fields: [
|
|
9
|
+
'appId',
|
|
10
|
+
'environment',
|
|
11
|
+
'installationId'
|
|
12
|
+
],
|
|
13
|
+
type: 'persistent',
|
|
14
|
+
unique: true
|
|
15
|
+
});
|
|
16
|
+
await collection.ensureIndex({
|
|
17
|
+
fields: [
|
|
18
|
+
'appId',
|
|
19
|
+
'environment',
|
|
20
|
+
'platform',
|
|
21
|
+
'tokenHash'
|
|
22
|
+
],
|
|
23
|
+
type: 'persistent'
|
|
24
|
+
});
|
|
25
|
+
await collection.ensureIndex({
|
|
26
|
+
fields: [
|
|
27
|
+
'appId',
|
|
28
|
+
'environment',
|
|
29
|
+
'userId',
|
|
30
|
+
'enabled'
|
|
31
|
+
],
|
|
32
|
+
type: 'persistent'
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9Vc2Vycy9uaXRyb2c3L0RldmVsb3BtZW50L3JlYWt0b3IvcGFja2FnZXMvcmVha3Rvci9zcmMvbmF0aXZlUHVzaC9taWdyYXRpb25zLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7dXNlRGJ9IGZyb20gJy4uL3V0aWxzL2FyYW5nb2RiVXRpbHMuanMnO1xuXG5pbXBvcnQgdHlwZSB7TmF0aXZlUHVzaERhdGFiYXNlT3B0aW9uc30gZnJvbSAnLi9yZXBvc2l0b3J5LmpzJztcblxuZXhwb3J0IGNvbnN0IG1pZ3JhdGVOYXRpdmVQdXNoUmVnaXN0cnkgPSBhc3luYyAoe1xuICBjb2xsZWN0aW9uTmFtZSA9ICduYXRpdmVfcHVzaF9yZWdpc3RyYXRpb25zJywgZGF0YWJhc2VGYWN0b3J5ID0gdXNlRGIsIGRhdGFiYXNlTmFtZVxufTogTmF0aXZlUHVzaERhdGFiYXNlT3B0aW9ucyk6IFByb21pc2U8dm9pZD4gPT4ge1xuICBjb25zdCBjb2xsZWN0aW9uID0gZGF0YWJhc2VGYWN0b3J5KGRhdGFiYXNlTmFtZSkuY29sbGVjdGlvbihjb2xsZWN0aW9uTmFtZSk7XG4gIGlmKCFhd2FpdCBjb2xsZWN0aW9uLmV4aXN0cygpKSB7XG4gICAgYXdhaXQgY29sbGVjdGlvbi5jcmVhdGUoKTtcbiAgfVxuICBhd2FpdCBjb2xsZWN0aW9uLmVuc3VyZUluZGV4KHtmaWVsZHM6IFsnYXBwSWQnLCAnZW52aXJvbm1lbnQnLCAnaW5zdGFsbGF0aW9uSWQnXSwgdHlwZTogJ3BlcnNpc3RlbnQnLCB1bmlxdWU6IHRydWV9KTtcbiAgYXdhaXQgY29sbGVjdGlvbi5lbnN1cmVJbmRleCh7ZmllbGRzOiBbJ2FwcElkJywgJ2Vudmlyb25tZW50JywgJ3BsYXRmb3JtJywgJ3Rva2VuSGFzaCddLCB0eXBlOiAncGVyc2lzdGVudCd9KTtcbiAgYXdhaXQgY29sbGVjdGlvbi5lbnN1cmVJbmRleCh7ZmllbGRzOiBbJ2FwcElkJywgJ2Vudmlyb25tZW50JywgJ3VzZXJJZCcsICdlbmFibGVkJ10sIHR5cGU6ICdwZXJzaXN0ZW50J30pO1xufTtcbiJdLCJuYW1lcyI6WyJ1c2VEYiIsIm1pZ3JhdGVOYXRpdmVQdXNoUmVnaXN0cnkiLCJjb2xsZWN0aW9uTmFtZSIsImRhdGFiYXNlRmFjdG9yeSIsImRhdGFiYXNlTmFtZSIsImNvbGxlY3Rpb24iLCJleGlzdHMiLCJjcmVhdGUiLCJlbnN1cmVJbmRleCIsImZpZWxkcyIsInR5cGUiLCJ1bmlxdWUiXSwibWFwcGluZ3MiOiJBQUFBLFNBQVFBLEtBQUssUUFBTyw0QkFBNEI7QUFJaEQsT0FBTyxNQUFNQyw0QkFBNEIsT0FBTyxFQUM5Q0MsaUJBQWlCLDJCQUEyQixFQUFFQyxrQkFBa0JILEtBQUssRUFBRUksWUFBWSxFQUN6RDtJQUMxQixNQUFNQyxhQUFhRixnQkFBZ0JDLGNBQWNDLFVBQVUsQ0FBQ0g7SUFDNUQsSUFBRyxDQUFDLE1BQU1HLFdBQVdDLE1BQU0sSUFBSTtRQUM3QixNQUFNRCxXQUFXRSxNQUFNO0lBQ3pCO0lBQ0EsTUFBTUYsV0FBV0csV0FBVyxDQUFDO1FBQUNDLFFBQVE7WUFBQztZQUFTO1lBQWU7U0FBaUI7UUFBRUMsTUFBTTtRQUFjQyxRQUFRO0lBQUk7SUFDbEgsTUFBTU4sV0FBV0csV0FBVyxDQUFDO1FBQUNDLFFBQVE7WUFBQztZQUFTO1lBQWU7WUFBWTtTQUFZO1FBQUVDLE1BQU07SUFBWTtJQUMzRyxNQUFNTCxXQUFXRyxXQUFXLENBQUM7UUFBQ0MsUUFBUTtZQUFDO1lBQVM7WUFBZTtZQUFVO1NBQVU7UUFBRUMsTUFBTTtJQUFZO0FBQ3pHLEVBQUUifQ==
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export declare const nativePushContractFixture: {
|
|
2
|
+
notification: {
|
|
3
|
+
body: string;
|
|
4
|
+
createdAt: string;
|
|
5
|
+
data: {
|
|
6
|
+
conversationId: string;
|
|
7
|
+
flags: boolean[];
|
|
8
|
+
nested: {
|
|
9
|
+
count: number;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
kind: string;
|
|
13
|
+
notificationId: string;
|
|
14
|
+
title: string;
|
|
15
|
+
version: 1;
|
|
16
|
+
};
|
|
17
|
+
recipientUserId: string;
|
|
18
|
+
scope: {
|
|
19
|
+
appId: string;
|
|
20
|
+
environment: string;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export const nativePushContractFixture = {
|
|
2
|
+
notification: {
|
|
3
|
+
body: 'Open the app',
|
|
4
|
+
createdAt: '2026-10-02T12:00:00Z',
|
|
5
|
+
data: {
|
|
6
|
+
conversationId: 'chat-1',
|
|
7
|
+
flags: [
|
|
8
|
+
true,
|
|
9
|
+
null
|
|
10
|
+
],
|
|
11
|
+
nested: {
|
|
12
|
+
count: 2
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
kind: 'MESSAGE',
|
|
16
|
+
notificationId: 'contract-1',
|
|
17
|
+
title: 'New message',
|
|
18
|
+
version: 1
|
|
19
|
+
},
|
|
20
|
+
recipientUserId: 'user-1',
|
|
21
|
+
scope: {
|
|
22
|
+
appId: 'pulsify',
|
|
23
|
+
environment: 'dev'
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9Vc2Vycy9uaXRyb2c3L0RldmVsb3BtZW50L3JlYWt0b3IvcGFja2FnZXMvcmVha3Rvci9zcmMvbmF0aXZlUHVzaC9uYXRpdmVQdXNoQ29udHJhY3QuZml4dHVyZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgY29uc3QgbmF0aXZlUHVzaENvbnRyYWN0Rml4dHVyZSA9IHtcbiAgbm90aWZpY2F0aW9uOiB7XG4gICAgYm9keTogJ09wZW4gdGhlIGFwcCcsIGNyZWF0ZWRBdDogJzIwMjYtMTAtMDJUMTI6MDA6MDBaJyxcbiAgICBkYXRhOiB7Y29udmVyc2F0aW9uSWQ6ICdjaGF0LTEnLCBmbGFnczogW3RydWUsIG51bGxdLCBuZXN0ZWQ6IHtjb3VudDogMn19LFxuICAgIGtpbmQ6ICdNRVNTQUdFJywgbm90aWZpY2F0aW9uSWQ6ICdjb250cmFjdC0xJywgdGl0bGU6ICdOZXcgbWVzc2FnZScsIHZlcnNpb246IDEgYXMgY29uc3RcbiAgfSxcbiAgcmVjaXBpZW50VXNlcklkOiAndXNlci0xJywgc2NvcGU6IHthcHBJZDogJ3B1bHNpZnknLCBlbnZpcm9ubWVudDogJ2Rldid9XG59O1xuIl0sIm5hbWVzIjpbIm5hdGl2ZVB1c2hDb250cmFjdEZpeHR1cmUiLCJub3RpZmljYXRpb24iLCJib2R5IiwiY3JlYXRlZEF0IiwiZGF0YSIsImNvbnZlcnNhdGlvbklkIiwiZmxhZ3MiLCJuZXN0ZWQiLCJjb3VudCIsImtpbmQiLCJub3RpZmljYXRpb25JZCIsInRpdGxlIiwidmVyc2lvbiIsInJlY2lwaWVudFVzZXJJZCIsInNjb3BlIiwiYXBwSWQiLCJlbnZpcm9ubWVudCJdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxNQUFNQSw0QkFBNEI7SUFDdkNDLGNBQWM7UUFDWkMsTUFBTTtRQUFnQkMsV0FBVztRQUNqQ0MsTUFBTTtZQUFDQyxnQkFBZ0I7WUFBVUMsT0FBTztnQkFBQztnQkFBTTthQUFLO1lBQUVDLFFBQVE7Z0JBQUNDLE9BQU87WUFBQztRQUFDO1FBQ3hFQyxNQUFNO1FBQVdDLGdCQUFnQjtRQUFjQyxPQUFPO1FBQWVDLFNBQVM7SUFDaEY7SUFDQUMsaUJBQWlCO0lBQVVDLE9BQU87UUFBQ0MsT0FBTztRQUFXQyxhQUFhO0lBQUs7QUFDekUsRUFBRSJ9
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import type { NativePlatform, NativePushEnvelope, NativePushOptions, NativePushPayload } from './types.js';
|
|
2
|
+
export declare const buildNativePushPayload: (platform: NativePlatform, apnsEnvironment: 'production' | 'sandbox' | undefined, envelope: NativePushEnvelope, options?: NativePushOptions, now?: Date) => NativePushPayload;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
const validJson = (value, seen = new Set())=>{
|
|
2
|
+
if (value === null || typeof value === 'boolean' || typeof value === 'string') {
|
|
3
|
+
return true;
|
|
4
|
+
}
|
|
5
|
+
if (typeof value === 'number') {
|
|
6
|
+
return Number.isFinite(value);
|
|
7
|
+
}
|
|
8
|
+
if (typeof value !== 'object' || seen.has(value)) {
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
if (!Array.isArray(value) && Object.getPrototypeOf(value) !== Object.prototype) {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
seen.add(value);
|
|
15
|
+
const valid = Object.values(value).every((item)=>validJson(item, seen));
|
|
16
|
+
seen.delete(value);
|
|
17
|
+
return valid;
|
|
18
|
+
};
|
|
19
|
+
export const buildNativePushPayload = (platform, apnsEnvironment, envelope, options = {}, now = new Date())=>{
|
|
20
|
+
if (!validJson(envelope) || envelope.notification?.version !== 1 || !envelope.scope?.appId || !envelope.scope?.environment || !envelope.recipientUserId || !envelope.notification.notificationId || !envelope.notification.kind || typeof envelope.notification.title !== 'string' || typeof envelope.notification.body !== 'string' || !Number.isFinite(Date.parse(envelope.notification.createdAt))) {
|
|
21
|
+
throw new Error('Invalid native notification envelope');
|
|
22
|
+
}
|
|
23
|
+
if (options.badge !== undefined && (!Number.isInteger(options.badge) || options.badge < 0)) {
|
|
24
|
+
throw new Error('Invalid native notification badge');
|
|
25
|
+
}
|
|
26
|
+
const expiration = options.expiresAt === undefined ? undefined : Date.parse(options.expiresAt);
|
|
27
|
+
if (expiration !== undefined && (!Number.isFinite(expiration) || expiration <= now.getTime())) {
|
|
28
|
+
throw new Error('Native notification expired');
|
|
29
|
+
}
|
|
30
|
+
const ttl = expiration === undefined ? undefined : Math.max(1, Math.ceil((expiration - now.getTime()) / 1000));
|
|
31
|
+
const { body, title } = envelope.notification;
|
|
32
|
+
const attributes = {};
|
|
33
|
+
let key;
|
|
34
|
+
let content;
|
|
35
|
+
if (platform === 'IOS') {
|
|
36
|
+
if (apnsEnvironment !== 'sandbox' && apnsEnvironment !== 'production') {
|
|
37
|
+
throw new Error('APNs environment required');
|
|
38
|
+
}
|
|
39
|
+
key = apnsEnvironment === 'sandbox' ? 'APNS_SANDBOX' : 'APNS';
|
|
40
|
+
content = {
|
|
41
|
+
aps: {
|
|
42
|
+
alert: {
|
|
43
|
+
body,
|
|
44
|
+
title
|
|
45
|
+
},
|
|
46
|
+
...options.badge !== undefined && {
|
|
47
|
+
badge: options.badge
|
|
48
|
+
},
|
|
49
|
+
sound: 'default'
|
|
50
|
+
},
|
|
51
|
+
envelope: JSON.stringify(envelope)
|
|
52
|
+
};
|
|
53
|
+
attributes['AWS.SNS.MOBILE.APNS.PUSH_TYPE'] = {
|
|
54
|
+
DataType: 'String',
|
|
55
|
+
StringValue: 'alert'
|
|
56
|
+
};
|
|
57
|
+
if (ttl !== undefined) {
|
|
58
|
+
attributes[`AWS.SNS.MOBILE.${key}.TTL`] = {
|
|
59
|
+
DataType: 'Number',
|
|
60
|
+
StringValue: String(ttl)
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
} else if (platform === 'ANDROID') {
|
|
64
|
+
key = 'GCM';
|
|
65
|
+
if (ttl !== undefined && ttl > 2419200) {
|
|
66
|
+
throw new Error('FCM expiry exceeds 28 days');
|
|
67
|
+
}
|
|
68
|
+
content = {
|
|
69
|
+
fcmV1Message: {
|
|
70
|
+
message: {
|
|
71
|
+
...ttl !== undefined && {
|
|
72
|
+
android: {
|
|
73
|
+
ttl: `${ttl}s`
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
data: {
|
|
77
|
+
envelope: JSON.stringify(envelope)
|
|
78
|
+
},
|
|
79
|
+
notification: {
|
|
80
|
+
body,
|
|
81
|
+
title
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
} else {
|
|
87
|
+
throw new Error('Invalid native platform');
|
|
88
|
+
}
|
|
89
|
+
const serialized = JSON.stringify(content);
|
|
90
|
+
if (Buffer.byteLength(serialized, 'utf8') > 4096) {
|
|
91
|
+
throw new Error('Native notification size exceeds provider limit');
|
|
92
|
+
}
|
|
93
|
+
const message = JSON.stringify({
|
|
94
|
+
default: body,
|
|
95
|
+
[key]: serialized
|
|
96
|
+
});
|
|
97
|
+
if (Buffer.byteLength(message, 'utf8') > 262144) {
|
|
98
|
+
throw new Error('Native notification size exceeds SNS limit');
|
|
99
|
+
}
|
|
100
|
+
return {
|
|
101
|
+
attributes,
|
|
102
|
+
message
|
|
103
|
+
};
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9Vc2Vycy9uaXRyb2c3L0RldmVsb3BtZW50L3JlYWt0b3IvcGFja2FnZXMvcmVha3Rvci9zcmMvbmF0aXZlUHVzaC9wYXlsb2FkLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlIHtOYXRpdmVQbGF0Zm9ybSwgTmF0aXZlUHVzaEVudmVsb3BlLCBOYXRpdmVQdXNoT3B0aW9ucywgTmF0aXZlUHVzaFBheWxvYWR9IGZyb20gJy4vdHlwZXMuanMnO1xuXG5jb25zdCB2YWxpZEpzb24gPSAodmFsdWU6IHVua25vd24sIHNlZW4gPSBuZXcgU2V0PG9iamVjdD4oKSk6IGJvb2xlYW4gPT4ge1xuICBpZih2YWx1ZSA9PT0gbnVsbCB8fCB0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJyB8fCB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbiAgaWYodHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJykge1xuICAgIHJldHVybiBOdW1iZXIuaXNGaW5pdGUodmFsdWUpO1xuICB9XG4gIGlmKHR5cGVvZiB2YWx1ZSAhPT0gJ29iamVjdCcgfHwgc2Vlbi5oYXModmFsdWUpKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIGlmKCFBcnJheS5pc0FycmF5KHZhbHVlKSAmJiBPYmplY3QuZ2V0UHJvdG90eXBlT2YodmFsdWUpICE9PSBPYmplY3QucHJvdG90eXBlKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIHNlZW4uYWRkKHZhbHVlKTtcbiAgY29uc3QgdmFsaWQgPSBPYmplY3QudmFsdWVzKHZhbHVlKS5ldmVyeSgoaXRlbSkgPT4gdmFsaWRKc29uKGl0ZW0sIHNlZW4pKTtcbiAgc2Vlbi5kZWxldGUodmFsdWUpO1xuICByZXR1cm4gdmFsaWQ7XG59O1xuXG5leHBvcnQgY29uc3QgYnVpbGROYXRpdmVQdXNoUGF5bG9hZCA9IChcbiAgcGxhdGZvcm06IE5hdGl2ZVBsYXRmb3JtLFxuICBhcG5zRW52aXJvbm1lbnQ6ICdwcm9kdWN0aW9uJyB8ICdzYW5kYm94JyB8IHVuZGVmaW5lZCxcbiAgZW52ZWxvcGU6IE5hdGl2ZVB1c2hFbnZlbG9wZSxcbiAgb3B0aW9uczogTmF0aXZlUHVzaE9wdGlvbnMgPSB7fSxcbiAgbm93OiBEYXRlID0gbmV3IERhdGUoKVxuKTogTmF0aXZlUHVzaFBheWxvYWQgPT4ge1xuICBpZighdmFsaWRKc29uKGVudmVsb3BlKSB8fCBlbnZlbG9wZS5ub3RpZmljYXRpb24/LnZlcnNpb24gIT09IDEgfHxcbiAgICAhZW52ZWxvcGUuc2NvcGU/LmFwcElkIHx8ICFlbnZlbG9wZS5zY29wZT8uZW52aXJvbm1lbnQgfHwgIWVudmVsb3BlLnJlY2lwaWVudFVzZXJJZCB8fFxuICAgICFlbnZlbG9wZS5ub3RpZmljYXRpb24ubm90aWZpY2F0aW9uSWQgfHwgIWVudmVsb3BlLm5vdGlmaWNhdGlvbi5raW5kIHx8XG4gICAgdHlwZW9mIGVudmVsb3BlLm5vdGlmaWNhdGlvbi50aXRsZSAhPT0gJ3N0cmluZycgfHwgdHlwZW9mIGVudmVsb3BlLm5vdGlmaWNhdGlvbi5ib2R5ICE9PSAnc3RyaW5nJyB8fFxuICAgICFOdW1iZXIuaXNGaW5pdGUoRGF0ZS5wYXJzZShlbnZlbG9wZS5ub3RpZmljYXRpb24uY3JlYXRlZEF0KSkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgbmF0aXZlIG5vdGlmaWNhdGlvbiBlbnZlbG9wZScpO1xuICB9XG4gIGlmKG9wdGlvbnMuYmFkZ2UgIT09IHVuZGVmaW5lZCAmJiAoIU51bWJlci5pc0ludGVnZXIob3B0aW9ucy5iYWRnZSkgfHwgb3B0aW9ucy5iYWRnZSA8IDApKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIG5hdGl2ZSBub3RpZmljYXRpb24gYmFkZ2UnKTtcbiAgfVxuICBjb25zdCBleHBpcmF0aW9uID0gb3B0aW9ucy5leHBpcmVzQXQgPT09IHVuZGVmaW5lZCA/IHVuZGVmaW5lZCA6IERhdGUucGFyc2Uob3B0aW9ucy5leHBpcmVzQXQpO1xuICBpZihleHBpcmF0aW9uICE9PSB1bmRlZmluZWQgJiYgKCFOdW1iZXIuaXNGaW5pdGUoZXhwaXJhdGlvbikgfHwgZXhwaXJhdGlvbiA8PSBub3cuZ2V0VGltZSgpKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignTmF0aXZlIG5vdGlmaWNhdGlvbiBleHBpcmVkJyk7XG4gIH1cbiAgY29uc3QgdHRsID0gZXhwaXJhdGlvbiA9PT0gdW5kZWZpbmVkID8gdW5kZWZpbmVkIDogTWF0aC5tYXgoMSwgTWF0aC5jZWlsKChleHBpcmF0aW9uIC0gbm93LmdldFRpbWUoKSkgLyAxMDAwKSk7XG4gIGNvbnN0IHtib2R5LCB0aXRsZX0gPSBlbnZlbG9wZS5ub3RpZmljYXRpb247XG4gIGNvbnN0IGF0dHJpYnV0ZXM6IE5hdGl2ZVB1c2hQYXlsb2FkWydhdHRyaWJ1dGVzJ10gPSB7fTtcbiAgbGV0IGtleTogc3RyaW5nO1xuICBsZXQgY29udGVudDogdW5rbm93bjtcbiAgaWYocGxhdGZvcm0gPT09ICdJT1MnKSB7XG4gICAgaWYoYXBuc0Vudmlyb25tZW50ICE9PSAnc2FuZGJveCcgJiYgYXBuc0Vudmlyb25tZW50ICE9PSAncHJvZHVjdGlvbicpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQVBOcyBlbnZpcm9ubWVudCByZXF1aXJlZCcpO1xuICAgIH1cbiAgICBrZXkgPSBhcG5zRW52aXJvbm1lbnQgPT09ICdzYW5kYm94JyA/ICdBUE5TX1NBTkRCT1gnIDogJ0FQTlMnO1xuICAgIGNvbnRlbnQgPSB7YXBzOiB7YWxlcnQ6IHtib2R5LCB0aXRsZX0sIC4uLihvcHRpb25zLmJhZGdlICE9PSB1bmRlZmluZWQgJiYge2JhZGdlOiBvcHRpb25zLmJhZGdlfSksIHNvdW5kOiAnZGVmYXVsdCd9LCBlbnZlbG9wZTogSlNPTi5zdHJpbmdpZnkoZW52ZWxvcGUpfTtcbiAgICBhdHRyaWJ1dGVzWydBV1MuU05TLk1PQklMRS5BUE5TLlBVU0hfVFlQRSddID0ge0RhdGFUeXBlOiAnU3RyaW5nJywgU3RyaW5nVmFsdWU6ICdhbGVydCd9O1xuICAgIGlmKHR0bCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBhdHRyaWJ1dGVzW2BBV1MuU05TLk1PQklMRS4ke2tleX0uVFRMYF0gPSB7RGF0YVR5cGU6ICdOdW1iZXInLCBTdHJpbmdWYWx1ZTogU3RyaW5nKHR0bCl9O1xuICAgIH1cbiAgfSBlbHNlIGlmKHBsYXRmb3JtID09PSAnQU5EUk9JRCcpIHtcbiAgICBrZXkgPSAnR0NNJztcbiAgICBpZih0dGwgIT09IHVuZGVmaW5lZCAmJiB0dGwgPiAyNDE5MjAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZDTSBleHBpcnkgZXhjZWVkcyAyOCBkYXlzJyk7XG4gICAgfVxuICAgIGNvbnRlbnQgPSB7ZmNtVjFNZXNzYWdlOiB7bWVzc2FnZToge1xuICAgICAgLi4uKHR0bCAhPT0gdW5kZWZpbmVkICYmIHthbmRyb2lkOiB7dHRsOiBgJHt0dGx9c2B9fSksXG4gICAgICBkYXRhOiB7ZW52ZWxvcGU6IEpTT04uc3RyaW5naWZ5KGVudmVsb3BlKX0sXG4gICAgICBub3RpZmljYXRpb246IHtib2R5LCB0aXRsZX1cbiAgICB9fX07XG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIG5hdGl2ZSBwbGF0Zm9ybScpO1xuICB9XG4gIGNvbnN0IHNlcmlhbGl6ZWQgPSBKU09OLnN0cmluZ2lmeShjb250ZW50KTtcbiAgaWYoQnVmZmVyLmJ5dGVMZW5ndGgoc2VyaWFsaXplZCwgJ3V0ZjgnKSA+IDQwOTYpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ05hdGl2ZSBub3RpZmljYXRpb24gc2l6ZSBleGNlZWRzIHByb3ZpZGVyIGxpbWl0Jyk7XG4gIH1cbiAgY29uc3QgbWVzc2FnZSA9IEpTT04uc3RyaW5naWZ5KHtkZWZhdWx0OiBib2R5LCBba2V5XTogc2VyaWFsaXplZH0pO1xuICBpZihCdWZmZXIuYnl0ZUxlbmd0aChtZXNzYWdlLCAndXRmOCcpID4gMjYyMTQ0KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdOYXRpdmUgbm90aWZpY2F0aW9uIHNpemUgZXhjZWVkcyBTTlMgbGltaXQnKTtcbiAgfVxuICByZXR1cm4ge2F0dHJpYnV0ZXMsIG1lc3NhZ2V9O1xufTtcbiJdLCJuYW1lcyI6WyJ2YWxpZEpzb24iLCJ2YWx1ZSIsInNlZW4iLCJTZXQiLCJOdW1iZXIiLCJpc0Zpbml0ZSIsImhhcyIsIkFycmF5IiwiaXNBcnJheSIsIk9iamVjdCIsImdldFByb3RvdHlwZU9mIiwicHJvdG90eXBlIiwiYWRkIiwidmFsaWQiLCJ2YWx1ZXMiLCJldmVyeSIsIml0ZW0iLCJkZWxldGUiLCJidWlsZE5hdGl2ZVB1c2hQYXlsb2FkIiwicGxhdGZvcm0iLCJhcG5zRW52aXJvbm1lbnQiLCJlbnZlbG9wZSIsIm9wdGlvbnMiLCJub3ciLCJEYXRlIiwibm90aWZpY2F0aW9uIiwidmVyc2lvbiIsInNjb3BlIiwiYXBwSWQiLCJlbnZpcm9ubWVudCIsInJlY2lwaWVudFVzZXJJZCIsIm5vdGlmaWNhdGlvbklkIiwia2luZCIsInRpdGxlIiwiYm9keSIsInBhcnNlIiwiY3JlYXRlZEF0IiwiRXJyb3IiLCJiYWRnZSIsInVuZGVmaW5lZCIsImlzSW50ZWdlciIsImV4cGlyYXRpb24iLCJleHBpcmVzQXQiLCJnZXRUaW1lIiwidHRsIiwiTWF0aCIsIm1heCIsImNlaWwiLCJhdHRyaWJ1dGVzIiwia2V5IiwiY29udGVudCIsImFwcyIsImFsZXJ0Iiwic291bmQiLCJKU09OIiwic3RyaW5naWZ5IiwiRGF0YVR5cGUiLCJTdHJpbmdWYWx1ZSIsIlN0cmluZyIsImZjbVYxTWVzc2FnZSIsIm1lc3NhZ2UiLCJhbmRyb2lkIiwiZGF0YSIsInNlcmlhbGl6ZWQiLCJCdWZmZXIiLCJieXRlTGVuZ3RoIiwiZGVmYXVsdCJdLCJtYXBwaW5ncyI6IkFBRUEsTUFBTUEsWUFBWSxDQUFDQyxPQUFnQkMsT0FBTyxJQUFJQyxLQUFhO0lBQ3pELElBQUdGLFVBQVUsUUFBUSxPQUFPQSxVQUFVLGFBQWEsT0FBT0EsVUFBVSxVQUFVO1FB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
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Database } from 'arangojs';
|
|
2
|
+
import type { NativePushRepository } from './types.js';
|
|
3
|
+
export type NativePushDatabaseOptions = {
|
|
4
|
+
collectionName?: string;
|
|
5
|
+
databaseFactory?: (databaseName?: string) => Database;
|
|
6
|
+
databaseName: string;
|
|
7
|
+
now?: () => Date;
|
|
8
|
+
};
|
|
9
|
+
export declare const createArangoNativePushRepository: ({ collectionName, databaseFactory, databaseName, now }: NativePushDatabaseOptions) => NativePushRepository;
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { aql } from 'arangojs';
|
|
2
|
+
import { createHash } from 'node:crypto';
|
|
3
|
+
import { useDb } from '../utils/arangodbUtils.js';
|
|
4
|
+
export const createArangoNativePushRepository = ({ collectionName = 'native_push_registrations', databaseFactory = useDb, databaseName, now = ()=>new Date() })=>{
|
|
5
|
+
const db = databaseFactory(databaseName);
|
|
6
|
+
const collection = db.collection(collectionName);
|
|
7
|
+
return {
|
|
8
|
+
disableBinding: async (scope, actor, registrationId, revision)=>{
|
|
9
|
+
const cursor = await db.query(aql`
|
|
10
|
+
FOR r IN ${collection}
|
|
11
|
+
FILTER r.registrationId == ${registrationId} AND r.appId == ${scope.appId}
|
|
12
|
+
AND r.environment == ${scope.environment} AND r.userId == ${actor.userId}
|
|
13
|
+
AND r.sessionId == ${actor.sessionId} AND r.enabled == true
|
|
14
|
+
AND (${revision ?? null} == null OR r.revision == ${revision ?? null})
|
|
15
|
+
UPDATE r WITH {enabled: false, revision: r.revision + 1, updatedAt: ${now().toISOString()}}
|
|
16
|
+
IN ${collection} OPTIONS {exclusive: true}
|
|
17
|
+
RETURN true
|
|
18
|
+
`);
|
|
19
|
+
return await cursor.next() ?? false;
|
|
20
|
+
},
|
|
21
|
+
disableEndpoint: async (scope, endpointArn)=>{
|
|
22
|
+
await db.query(aql`
|
|
23
|
+
FOR r IN ${collection}
|
|
24
|
+
FILTER r.appId == ${scope.appId} AND r.environment == ${scope.environment}
|
|
25
|
+
AND r.endpointArn == ${endpointArn} AND r.enabled == true
|
|
26
|
+
UPDATE r WITH {enabled: false, revision: r.revision + 1, updatedAt: ${now().toISOString()}}
|
|
27
|
+
IN ${collection} OPTIONS {exclusive: true}
|
|
28
|
+
`);
|
|
29
|
+
},
|
|
30
|
+
hasActiveEndpointBinding: async (scope, endpointArn)=>{
|
|
31
|
+
const cursor = await db.query(aql`
|
|
32
|
+
RETURN LENGTH(FOR r IN ${collection}
|
|
33
|
+
FILTER r.appId == ${scope.appId} AND r.environment == ${scope.environment}
|
|
34
|
+
AND r.endpointArn == ${endpointArn} AND r.enabled == true LIMIT 1 RETURN 1) > 0
|
|
35
|
+
`);
|
|
36
|
+
return await cursor.next();
|
|
37
|
+
},
|
|
38
|
+
isCurrent: async (registration)=>{
|
|
39
|
+
const cursor = await db.query(aql`
|
|
40
|
+
RETURN LENGTH(FOR r IN ${collection}
|
|
41
|
+
FILTER r.registrationId == ${registration.registrationId} AND r.appId == ${registration.appId}
|
|
42
|
+
AND r.environment == ${registration.environment} AND r.userId == ${registration.userId}
|
|
43
|
+
AND r.sessionId == ${registration.sessionId} AND r.revision == ${registration.revision}
|
|
44
|
+
AND r.enabled == true LIMIT 1 RETURN 1) > 0
|
|
45
|
+
`);
|
|
46
|
+
return await cursor.next();
|
|
47
|
+
},
|
|
48
|
+
listEnabled: async (scope, userId)=>{
|
|
49
|
+
const cursor = await db.query(aql`
|
|
50
|
+
FOR r IN ${collection}
|
|
51
|
+
FILTER r.appId == ${scope.appId} AND r.environment == ${scope.environment}
|
|
52
|
+
AND r.userId == ${userId} AND r.enabled == true RETURN r
|
|
53
|
+
`);
|
|
54
|
+
return cursor.all();
|
|
55
|
+
},
|
|
56
|
+
replaceBinding: async (scope, actor, input, endpointArn, tokenHash, expectedRevision)=>{
|
|
57
|
+
const key = createHash('sha256').update(JSON.stringify([
|
|
58
|
+
scope.appId,
|
|
59
|
+
scope.environment,
|
|
60
|
+
input.installationId
|
|
61
|
+
])).digest('hex');
|
|
62
|
+
const timestamp = now().toISOString();
|
|
63
|
+
const cursor = await db.query(aql`
|
|
64
|
+
LET prior = DOCUMENT(${collection.name}, ${key})
|
|
65
|
+
FILTER ${expectedRevision ?? null} == null OR (prior.revision == ${expectedRevision ?? null}
|
|
66
|
+
AND prior.userId == ${actor.userId} AND prior.sessionId == ${actor.sessionId}
|
|
67
|
+
AND prior.tokenHash == ${tokenHash} AND prior.enabled == false)
|
|
68
|
+
LET displaced = (FOR r IN ${collection}
|
|
69
|
+
FILTER r.appId == ${scope.appId} AND r.environment == ${scope.environment}
|
|
70
|
+
AND r.platform == ${input.platform} AND r.apnsEnvironment == ${input.apnsEnvironment ?? null}
|
|
71
|
+
AND r.tokenHash == ${tokenHash} AND r.enabled == true AND r._key != ${key}
|
|
72
|
+
RETURN MERGE(r, {enabled: false, revision: r.revision + 1, updatedAt: ${timestamp}}))
|
|
73
|
+
LET current = MERGE(${scope}, ${actor}, ${input}, {
|
|
74
|
+
_key: ${key}, registrationId: ${key}, endpointArn: ${endpointArn}, tokenHash: ${tokenHash},
|
|
75
|
+
enabled: true, revision: prior == null ? 1 : prior.revision + 1,
|
|
76
|
+
createdAt: prior == null ? ${timestamp} : prior.createdAt, updatedAt: ${timestamp}
|
|
77
|
+
})
|
|
78
|
+
FOR next IN APPEND(displaced, [current])
|
|
79
|
+
UPSERT {_key: next._key} INSERT next UPDATE next IN ${collection} OPTIONS {exclusive: true}
|
|
80
|
+
FILTER NEW._key == ${key}
|
|
81
|
+
RETURN NEW
|
|
82
|
+
`);
|
|
83
|
+
const registration = await cursor.next();
|
|
84
|
+
if (!registration) {
|
|
85
|
+
throw new Error('Push registration superseded');
|
|
86
|
+
}
|
|
87
|
+
return registration;
|
|
88
|
+
},
|
|
89
|
+
reserveBinding: async (scope, actor, input, tokenHash)=>{
|
|
90
|
+
const key = createHash('sha256').update(JSON.stringify([
|
|
91
|
+
scope.appId,
|
|
92
|
+
scope.environment,
|
|
93
|
+
input.installationId
|
|
94
|
+
])).digest('hex');
|
|
95
|
+
const timestamp = now().toISOString();
|
|
96
|
+
const document = {
|
|
97
|
+
...scope,
|
|
98
|
+
...actor,
|
|
99
|
+
...input,
|
|
100
|
+
_key: key,
|
|
101
|
+
createdAt: timestamp,
|
|
102
|
+
enabled: false,
|
|
103
|
+
endpointArn: '',
|
|
104
|
+
registrationId: key,
|
|
105
|
+
revision: 1,
|
|
106
|
+
tokenHash,
|
|
107
|
+
updatedAt: timestamp
|
|
108
|
+
};
|
|
109
|
+
const cursor = await db.query(aql`
|
|
110
|
+
UPSERT {_key: ${key}} INSERT ${document}
|
|
111
|
+
UPDATE MERGE(${document}, {revision: OLD.revision + 1, createdAt: OLD.createdAt})
|
|
112
|
+
IN ${collection} OPTIONS {exclusive: true}
|
|
113
|
+
RETURN NEW.revision
|
|
114
|
+
`);
|
|
115
|
+
return await cursor.next();
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9Vc2Vycy9uaXRyb2c3L0RldmVsb3BtZW50L3JlYWt0b3IvcGFja2FnZXMvcmVha3Rvci9zcmMvbmF0aXZlUHVzaC9yZXBvc2l0b3J5LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7YXFsfSBmcm9tICdhcmFuZ29qcyc7XG5pbXBvcnQge2NyZWF0ZUhhc2h9IGZyb20gJ25vZGU6Y3J5cHRvJztcblxuaW1wb3J0IHt1c2VEYn0gZnJvbSAnLi4vdXRpbHMvYXJhbmdvZGJVdGlscy5qcyc7XG5cbmltcG9ydCB0eXBlIHtEYXRhYmFzZX0gZnJvbSAnYXJhbmdvanMnO1xuaW1wb3J0IHR5cGUge05hdGl2ZVB1c2hSZWdpc3RyYXRpb24sIE5hdGl2ZVB1c2hSZXBvc2l0b3J5fSBmcm9tICcuL3R5cGVzLmpzJztcblxuZXhwb3J0IHR5cGUgTmF0aXZlUHVzaERhdGFiYXNlT3B0aW9ucyA9IHtcbiAgY29sbGVjdGlvbk5hbWU/OiBzdHJpbmc7XG4gIGRhdGFiYXNlRmFjdG9yeT86IChkYXRhYmFzZU5hbWU/OiBzdHJpbmcpID0+IERhdGFiYXNlO1xuICBkYXRhYmFzZU5hbWU6IHN0cmluZztcbiAgbm93PzogKCkgPT4gRGF0ZTtcbn07XG5cbmV4cG9ydCBjb25zdCBjcmVhdGVBcmFuZ29OYXRpdmVQdXNoUmVwb3NpdG9yeSA9ICh7XG4gIGNvbGxlY3Rpb25OYW1lID0gJ25hdGl2ZV9wdXNoX3JlZ2lzdHJhdGlvbnMnLCBkYXRhYmFzZUZhY3RvcnkgPSB1c2VEYiwgZGF0YWJhc2VOYW1lLCBub3cgPSAoKSA9PiBuZXcgRGF0ZSgpXG59OiBOYXRpdmVQdXNoRGF0YWJhc2VPcHRpb25zKTogTmF0aXZlUHVzaFJlcG9zaXRvcnkgPT4ge1xuICBjb25zdCBkYiA9IGRhdGFiYXNlRmFjdG9yeShkYXRhYmFzZU5hbWUpO1xuICBjb25zdCBjb2xsZWN0aW9uID0gZGIuY29sbGVjdGlvbihjb2xsZWN0aW9uTmFtZSk7XG4gIHJldHVybiB7XG4gICAgZGlzYWJsZUJpbmRpbmc6IGFzeW5jIChzY29wZSwgYWN0b3IsIHJlZ2lzdHJhdGlvbklkLCByZXZpc2lvbikgPT4ge1xuICAgICAgY29uc3QgY3Vyc29yID0gYXdhaXQgZGIucXVlcnk8Ym9vbGVhbj4oYXFsYFxuICAgICAgICBGT1IgciBJTiAke2NvbGxlY3Rpb259XG4gICAgICAgICAgRklMVEVSIHIucmVnaXN0cmF0aW9uSWQgPT0gJHtyZWdpc3RyYXRpb25JZH0gQU5EIHIuYXBwSWQgPT0gJHtzY29wZS5hcHBJZH1cbiAgICAgICAgICAgIEFORCByLmVudmlyb25tZW50ID09ICR7c2NvcGUuZW52aXJvbm1lbnR9IEFORCByLnVzZXJJZCA9PSAke2FjdG9yLnVzZXJJZH1cbiAgICAgICAgICAgIEFORCByLnNlc3Npb25JZCA9PSAke2FjdG9yLnNlc3Npb25JZH0gQU5EIHIuZW5hYmxlZCA9PSB0cnVlXG4gICAgICAgICAgICBBTkQgKCR7cmV2aXNpb24gPz8gbnVsbH0gPT0gbnVsbCBPUiByLnJldmlzaW9uID09ICR7cmV2aXNpb24gPz8gbnVsbH0pXG4gICAgICAgICAgVVBEQVRFIHIgV0lUSCB7ZW5hYmxlZDogZmFsc2UsIHJldmlzaW9uOiByLnJldmlzaW9uICsgMSwgdXBkYXRlZEF0OiAke25vdygpLnRvSVNPU3RyaW5nKCl9fVxuICAgICAgICAgICAgSU4gJHtjb2xsZWN0aW9ufSBPUFRJT05TIHtleGNsdXNpdmU6IHRydWV9XG4gICAgICAgICAgUkVUVVJOIHRydWVcbiAgICAgIGApO1xuICAgICAgcmV0dXJuIChhd2FpdCBjdXJzb3IubmV4dCgpKSA/PyBmYWxzZTtcbiAgICB9LFxuICAgIGRpc2FibGVFbmRwb2ludDogYXN5bmMgKHNjb3BlLCBlbmRwb2ludEFybikgPT4ge1xuICAgICAgYXdhaXQgZGIucXVlcnkoYXFsYFxuICAgICAgICBGT1IgciBJTiAke2NvbGxlY3Rpb259XG4gICAgICAgICAgRklMVEVSIHIuYXBwSWQgPT0gJHtzY29wZS5hcHBJZH0gQU5EIHIuZW52aXJvbm1lbnQgPT0gJHtzY29wZS5lbnZpcm9ubWVudH1cbiAgICAgICAgICAgIEFORCByLmVuZHBvaW50QXJuID09ICR7ZW5kcG9pbnRBcm59IEFORCByLmVuYWJsZWQgPT0gdHJ1ZVxuICAgICAgICAgIFVQREFURSByIFdJVEgge2VuYWJsZWQ6IGZhbHNlLCByZXZpc2lvbjogci5yZXZpc2lvbiArIDEsIHVwZGF0ZWRBdDogJHtub3coKS50b0lTT1N0cmluZygpfX1cbiAgICAgICAgICAgIElOICR7Y29sbGVjdGlvbn0gT1BUSU9OUyB7ZXhjbHVzaXZlOiB0cnVlfVxuICAgICAgYCk7XG4gICAgfSxcbiAgICBoYXNBY3RpdmVFbmRwb2ludEJpbmRpbmc6IGFzeW5jIChzY29wZSwgZW5kcG9pbnRBcm4pID0+IHtcbiAgICAgIGNvbnN0IGN1cnNvciA9IGF3YWl0IGRiLnF1ZXJ5PGJvb2xlYW4+KGFxbGBcbiAgICAgICAgUkVUVVJOIExFTkdUSChGT1IgciBJTiAke2NvbGxlY3Rpb259XG4gICAgICAgICAgRklMVEVSIHIuYXBwSWQgPT0gJHtzY29wZS5hcHBJZH0gQU5EIHIuZW52aXJvbm1lbnQgPT0gJHtzY29wZS5lbnZpcm9ubWVudH1cbiAgICAgICAgICAgIEFORCByLmVuZHBvaW50QXJuID09ICR7ZW5kcG9pbnRBcm59IEFORCByLmVuYWJsZWQgPT0gdHJ1ZSBMSU1JVCAxIFJFVFVSTiAxKSA+IDBcbiAgICAgIGApO1xuICAgICAgcmV0dXJuIGF3YWl0IGN1cnNvci5uZXh0KCk7XG4gICAgfSxcbiAgICBpc0N1cnJlbnQ6IGFzeW5jIChyZWdpc3RyYXRpb24pID0+IHtcbiAgICAgIGNvbnN0IGN1cnNvciA9IGF3YWl0IGRiLnF1ZXJ5PGJvb2xlYW4+KGFxbGBcbiAgICAgICAgUkVUVVJOIExFTkdUSChGT1IgciBJTiAke2NvbGxlY3Rpb259XG4gICAgICAgICAgRklMVEVSIHIucmVnaXN0cmF0aW9uSWQgPT0gJHtyZWdpc3RyYXRpb24ucmVnaXN0cmF0aW9uSWR9IEFORCByLmFwcElkID09ICR7cmVnaXN0cmF0aW9uLmFwcElkfVxuICAgICAgICAgICAgQU5EIHIuZW52aXJvbm1lbnQgPT0gJHtyZWdpc3RyYXRpb24uZW52aXJvbm1lbnR9IEFORCByLnVzZXJJZCA9PSAke3JlZ2lzdHJhdGlvbi51c2VySWR9XG4gICAgICAgICAgICBBTkQgci5zZXNzaW9uSWQgPT0gJHtyZWdpc3RyYXRpb24uc2Vzc2lvbklkfSBBTkQgci5yZXZpc2lvbiA9PSAke3JlZ2lzdHJhdGlvbi5yZXZpc2lvbn1cbiAgICAgICAgICAgIEFORCByLmVuYWJsZWQgPT0gdHJ1ZSBMSU1JVCAxIFJFVFVSTiAxKSA+IDBcbiAgICAgIGApO1xuICAgICAgcmV0dXJuIGF3YWl0IGN1cnNvci5uZXh0KCk7XG4gICAgfSxcbiAgICBsaXN0RW5hYmxlZDogYXN5bmMgKHNjb3BlLCB1c2VySWQpID0+IHtcbiAgICAgIGNvbnN0IGN1cnNvciA9IGF3YWl0IGRiLnF1ZXJ5PE5hdGl2ZVB1c2hSZWdpc3RyYXRpb24+KGFxbGBcbiAgICAgICAgRk9SIHIgSU4gJHtjb2xsZWN0aW9ufVxuICAgICAgICAgIEZJTFRFUiByLmFwcElkID09ICR7c2NvcGUuYXBwSWR9IEFORCByLmVudmlyb25tZW50ID09ICR7c2NvcGUuZW52aXJvbm1lbnR9XG4gICAgICAgICAgICBBTkQgci51c2VySWQgPT0gJHt1c2VySWR9IEFORCByLmVuYWJsZWQgPT0gdHJ1ZSBSRVRVUk4gclxuICAgICAgYCk7XG4gICAgICByZXR1cm4gY3Vyc29yLmFsbCgpO1xuICAgIH0sXG4gICAgcmVwbGFjZUJpbmRpbmc6IGFzeW5jIChzY29wZSwgYWN0b3IsIGlucHV0LCBlbmRwb2ludEFybiwgdG9rZW5IYXNoLCBleHBlY3RlZFJldmlzaW9uKSA9PiB7XG4gICAgICBjb25zdCBrZXkgPSBjcmVhdGVIYXNoKCdzaGEyNTYnKS51cGRhdGUoSlNPTi5zdHJpbmdpZnkoW3Njb3BlLmFwcElkLCBzY29wZS5lbnZpcm9ubWVudCwgaW5wdXQuaW5zdGFsbGF0aW9uSWRdKSlcbiAgICAgICAgLmRpZ2VzdCgnaGV4Jyk7XG4gICAgICBjb25zdCB0aW1lc3RhbXAgPSBub3coKS50b0lTT1N0cmluZygpO1xuICAgICAgY29uc3QgY3Vyc29yID0gYXdhaXQgZGIucXVlcnk8TmF0aXZlUHVzaFJlZ2lzdHJhdGlvbj4oYXFsYFxuICAgICAgICBMRVQgcHJpb3IgPSBET0NVTUVOVCgke2NvbGxlY3Rpb24ubmFtZX0sICR7a2V5fSlcbiAgICAgICAgRklMVEVSICR7ZXhwZWN0ZWRSZXZpc2lvbiA/PyBudWxsfSA9PSBudWxsIE9SIChwcmlvci5yZXZpc2lvbiA9PSAke2V4cGVjdGVkUmV2aXNpb24gPz8gbnVsbH1cbiAgICAgICAgICBBTkQgcHJpb3IudXNlcklkID09ICR7YWN0b3IudXNlcklkfSBBTkQgcHJpb3Iuc2Vzc2lvbklkID09ICR7YWN0b3Iuc2Vzc2lvbklkfVxuICAgICAgICAgIEFORCBwcmlvci50b2tlbkhhc2ggPT0gJHt0b2tlbkhhc2h9IEFORCBwcmlvci5lbmFibGVkID09IGZhbHNlKVxuICAgICAgICBMRVQgZGlzcGxhY2VkID0gKEZPUiByIElOICR7Y29sbGVjdGlvbn1cbiAgICAgICAgICBGSUxURVIgci5hcHBJZCA9PSAke3Njb3BlLmFwcElkfSBBTkQgci5lbnZpcm9ubWVudCA9PSAke3Njb3BlLmVudmlyb25tZW50fVxuICAgICAgICAgICAgQU5EIHIucGxhdGZvcm0gPT0gJHtpbnB1dC5wbGF0Zm9ybX0gQU5EIHIuYXBuc0Vudmlyb25tZW50ID09ICR7aW5wdXQuYXBuc0Vudmlyb25tZW50ID8/IG51bGx9XG4gICAgICAgICAgICBBTkQgci50b2tlbkhhc2ggPT0gJHt0b2tlbkhhc2h9IEFORCByLmVuYWJsZWQgPT0gdHJ1ZSBBTkQgci5fa2V5ICE9ICR7a2V5fVxuICAgICAgICAgIFJFVFVSTiBNRVJHRShyLCB7ZW5hYmxlZDogZmFsc2UsIHJldmlzaW9uOiByLnJldmlzaW9uICsgMSwgdXBkYXRlZEF0OiAke3RpbWVzdGFtcH19KSlcbiAgICAgICAgTEVUIGN1cnJlbnQgPSBNRVJHRSgke3Njb3BlfSwgJHthY3Rvcn0sICR7aW5wdXR9LCB7XG4gICAgICAgICAgX2tleTogJHtrZXl9LCByZWdpc3RyYXRpb25JZDogJHtrZXl9LCBlbmRwb2ludEFybjogJHtlbmRwb2ludEFybn0sIHRva2VuSGFzaDogJHt0b2tlbkhhc2h9LFxuICAgICAgICAgIGVuYWJsZWQ6IHRydWUsIHJldmlzaW9uOiBwcmlvciA9PSBudWxsID8gMSA6IHByaW9yLnJldmlzaW9uICsgMSxcbiAgICAgICAgICBjcmVhdGVkQXQ6IHByaW9yID09IG51bGwgPyAke3RpbWVzdGFtcH0gOiBwcmlvci5jcmVhdGVkQXQsIHVwZGF0ZWRBdDogJHt0aW1lc3RhbXB9XG4gICAgICAgIH0pXG4gICAgICAgIEZPUiBuZXh0IElOIEFQUEVORChkaXNwbGFjZWQsIFtjdXJyZW50XSlcbiAgICAgICAgICBVUFNFUlQge19rZXk6IG5leHQuX2tleX0gSU5TRVJUIG5leHQgVVBEQVRFIG5leHQgSU4gJHtjb2xsZWN0aW9ufSBPUFRJT05TIHtleGNsdXNpdmU6IHRydWV9XG4gICAgICAgICAgRklMVEVSIE5FVy5fa2V5ID09ICR7a2V5fVxuICAgICAgICAgIFJFVFVSTiBORVdcbiAgICAgIGApO1xuICAgICAgY29uc3QgcmVnaXN0cmF0aW9uID0gYXdhaXQgY3Vyc29yLm5leHQoKTtcbiAgICAgIGlmKCFyZWdpc3RyYXRpb24pIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdQdXNoIHJlZ2lzdHJhdGlvbiBzdXBlcnNlZGVkJyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVnaXN0cmF0aW9uO1xuICAgIH0sXG4gICAgcmVzZXJ2ZUJpbmRpbmc6IGFzeW5jIChzY29wZSwgYWN0b3IsIGlucHV0LCB0b2tlbkhhc2gpID0+IHtcbiAgICAgIGNvbnN0IGtleSA9IGNyZWF0ZUhhc2goJ3NoYTI1NicpLnVwZGF0ZShKU09OLnN0cmluZ2lmeShbc2NvcGUuYXBwSWQsIHNjb3BlLmVudmlyb25tZW50LCBpbnB1dC5pbnN0YWxsYXRpb25JZF0pKVxuICAgICAgICAuZGlnZXN0KCdoZXgnKTtcbiAgICAgIGNvbnN0IHRpbWVzdGFtcCA9IG5vdygpLnRvSVNPU3RyaW5nKCk7XG4gICAgICBjb25zdCBkb2N1bWVudCA9IHsuLi5zY29wZSwgLi4uYWN0b3IsIC4uLmlucHV0LCBfa2V5OiBrZXksIGNyZWF0ZWRBdDogdGltZXN0YW1wLCBlbmFibGVkOiBmYWxzZSxcbiAgICAgICAgZW5kcG9pbnRBcm46ICcnLCByZWdpc3RyYXRpb25JZDoga2V5LCByZXZpc2lvbjogMSwgdG9rZW5IYXNoLCB1cGRhdGVkQXQ6IHRpbWVzdGFtcH07XG4gICAgICBjb25zdCBjdXJzb3IgPSBhd2FpdCBkYi5xdWVyeTxudW1iZXI+KGFxbGBcbiAgICAgICAgVVBTRVJUIHtfa2V5OiAke2tleX19IElOU0VSVCAke2RvY3VtZW50fVxuICAgICAgICAgIFVQREFURSBNRVJHRSgke2RvY3VtZW50fSwge3JldmlzaW9uOiBPTEQucmV2aXNpb24gKyAxLCBjcmVhdGVkQXQ6IE9MRC5jcmVhdGVkQXR9KVxuICAgICAgICAgIElOICR7Y29sbGVjdGlvbn0gT1BUSU9OUyB7ZXhjbHVzaXZlOiB0cnVlfVxuICAgICAgICBSRVRVUk4gTkVXLnJldmlzaW9uXG4gICAgICBgKTtcbiAgICAgIHJldHVybiBhd2FpdCBjdXJzb3IubmV4dCgpO1xuICAgIH1cbiAgfTtcbn07XG4iXSwibmFtZXMiOlsiYXFsIiwiY3JlYXRlSGFzaCIsInVzZURiIiwiY3JlYXRlQXJhbmdvTmF0aXZlUHVzaFJlcG9zaXRvcnkiLCJjb2xsZWN0aW9uTmFtZSIsImRhdGFiYXNlRmFjdG9yeSIsImRhdGFiYXNlTmFtZSIsIm5vdyIsIkRhdGUiLCJkYiIsImNvbGxlY3Rpb24iLCJkaXNhYmxlQmluZGluZyIsInNjb3BlIiwiYWN0b3IiLCJyZWdpc3RyYXRpb25JZCIsInJldmlzaW9uIiwiY3Vyc29yIiwicXVlcnkiLCJhcHBJZCIsImVudmlyb25tZW50IiwidXNlcklkIiwic2Vzc2lvbklkIiwidG9JU09TdHJpbmciLCJuZXh0IiwiZGlzYWJsZUVuZHBvaW50IiwiZW5kcG9pbnRBcm4iLCJoYXNBY3RpdmVFbmRwb2ludEJpbmRpbmciLCJpc0N1cnJlbnQiLCJyZWdpc3RyYXRpb24iLCJsaXN0RW5hYmxlZCIsImFsbCIsInJlcGxhY2VCaW5kaW5nIiwiaW5wdXQiLCJ0b2tlbkhhc2giLCJleHBlY3RlZFJldmlzaW9uIiwia2V5IiwidXBkYXRlIiwiSlNPTiIsInN0cmluZ2lmeSIsImluc3RhbGxhdGlvbklkIiwiZGlnZXN0IiwidGltZXN0YW1wIiwibmFtZSIsInBsYXRmb3JtIiwiYXBuc0Vudmlyb25tZW50IiwiRXJyb3IiLCJyZXNlcnZlQmluZGluZyIsImRvY3VtZW50IiwiX2tleSIsImNyZWF0ZWRBdCIsImVuYWJsZWQiLCJ1cGRhdGVkQXQiXSwibWFwcGluZ3MiOiJBQUFBLFNBQVFBLEdBQUcsUUFBTyxXQUFXO0FBQzdCLFNBQVFDLFVBQVUsUUFBTyxjQUFjO0FBRXZDLFNBQVFDLEtBQUssUUFBTyw0QkFBNEI7QUFZaEQsT0FBTyxNQUFNQyxtQ0FBbUMsQ0FBQyxFQUMvQ0MsaUJBQWlCLDJCQUEyQixFQUFFQyxrQkFBa0JILEtBQUssRUFBRUksWUFBWSxFQUFFQyxNQUFNLElBQU0sSUFBSUMsTUFBTSxFQUNqRjtJQUMxQixNQUFNQyxLQUFLSixnQkFBZ0JDO0lBQzNCLE1BQU1JLGFBQWFELEdBQUdDLFVBQVUsQ0FBQ047SUFDakMsT0FBTztRQUNMTyxnQkFBZ0IsT0FBT0MsT0FBT0MsT0FBT0MsZ0JBQWdCQztZQUNuRCxNQUFNQyxTQUFTLE1BQU1QLEdBQUdRLEtBQUssQ0FBVWpCLEdBQUcsQ0FBQztpQkFDaEMsRUFBRVUsV0FBVztxQ0FDTyxFQUFFSSxlQUFlLGdCQUFnQixFQUFFRixNQUFNTSxLQUFLLENBQUM7aUNBQ25ELEVBQUVOLE1BQU1PLFdBQVcsQ0FBQyxpQkFBaUIsRUFBRU4sTUFBTU8sTUFBTSxDQUFDOytCQUN0RCxFQUFFUCxNQUFNUSxTQUFTLENBQUM7aUJBQ2hDLEVBQUVOLFlBQVksS0FBSywwQkFB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
|