@nlabs/reaktor 1.17.0 → 1.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (320) hide show
  1. package/README.md +182 -0
  2. package/docs/ASSISTANT.md +138 -0
  3. package/docs/GENERATION.md +42 -5
  4. package/docs/NATIVE_PUSH.md +56 -0
  5. package/lib/actions/alfredFaq.d.ts +80 -0
  6. package/lib/actions/alfredFaq.js +206 -0
  7. package/lib/actions/analytics.js +1 -1
  8. package/lib/actions/apps.js +1 -1
  9. package/lib/actions/connections.js +1 -1
  10. package/lib/actions/content.js +1 -1
  11. package/lib/actions/contentGeneration.d.ts +4 -0
  12. package/lib/actions/contentGeneration.js +82 -10
  13. package/lib/actions/contentGenerationErrors.js +1 -1
  14. package/lib/actions/conversations.d.ts +1 -1
  15. package/lib/actions/conversations.js +19 -9
  16. package/lib/actions/crm.js +1 -1
  17. package/lib/actions/crud.js +26 -1
  18. package/lib/actions/databaseAccounts.js +1 -1
  19. package/lib/actions/databaseProvisioningLease.js +1 -1
  20. package/lib/actions/dynamodb.js +1 -1
  21. package/lib/actions/email.js +1 -1
  22. package/lib/actions/files.js +1 -1
  23. package/lib/actions/flags.js +1 -1
  24. package/lib/actions/geminiVideo.js +1 -1
  25. package/lib/actions/groups.js +1 -1
  26. package/lib/actions/higgsfield.js +1 -1
  27. package/lib/actions/imageGeneration.js +1 -1
  28. package/lib/actions/images.js +1 -1
  29. package/lib/actions/index.d.ts +1 -0
  30. package/lib/actions/index.js +2 -1
  31. package/lib/actions/ios.js +1 -1
  32. package/lib/actions/locations.js +1 -1
  33. package/lib/actions/messages.js +23 -7
  34. package/lib/actions/notifications.js +1 -1
  35. package/lib/actions/ollamaGeneration.js +1 -1
  36. package/lib/actions/openaiResponseSession.js +1 -1
  37. package/lib/actions/payments.js +1 -1
  38. package/lib/actions/personas.js +1 -1
  39. package/lib/actions/phoneSupport.js +1 -1
  40. package/lib/actions/posts.js +1 -1
  41. package/lib/actions/query.js +1 -1
  42. package/lib/actions/reactions.js +1 -1
  43. package/lib/actions/rum.js +1 -1
  44. package/lib/actions/s3.js +1 -1
  45. package/lib/actions/search.js +1 -1
  46. package/lib/actions/sms.js +1 -1
  47. package/lib/actions/statistics.js +1 -1
  48. package/lib/actions/subscriptions.js +1 -1
  49. package/lib/actions/tags.js +1 -1
  50. package/lib/actions/users.js +57 -4
  51. package/lib/actions/videoGeneration.js +1 -1
  52. package/lib/actions/videos.js +1 -1
  53. package/lib/adapters/arangoAdapter.js +1 -1
  54. package/lib/adapters/contentAdapter.js +1 -1
  55. package/lib/adapters/fileAdapter.js +1 -1
  56. package/lib/adapters/geminiGenerationAdapter.js +1 -1
  57. package/lib/adapters/higgsfieldAdapter.js +1 -1
  58. package/lib/adapters/higgsfieldModelCatalog.js +1 -1
  59. package/lib/adapters/higgsfieldModels.js +1 -1
  60. package/lib/adapters/imageAdapter.js +1 -1
  61. package/lib/adapters/imageGenerationAdapter.js +1 -1
  62. package/lib/adapters/index.js +1 -1
  63. package/lib/adapters/messageAdapter.js +1 -1
  64. package/lib/adapters/postAdapter.js +1 -1
  65. package/lib/adapters/reaktorAdapter.js +1 -1
  66. package/lib/adapters/tagAdapter.js +1 -1
  67. package/lib/adapters/userAdapter.js +1 -1
  68. package/lib/assistant/core.d.ts +53 -0
  69. package/lib/assistant/core.js +123 -0
  70. package/lib/assistant/faq.d.ts +26 -0
  71. package/lib/assistant/faq.js +238 -0
  72. package/lib/assistant/faqCore.d.ts +23 -0
  73. package/lib/assistant/faqCore.js +20 -0
  74. package/lib/assistant/index.d.ts +7 -0
  75. package/lib/assistant/index.js +5 -0
  76. package/lib/assistant/service.d.ts +35 -0
  77. package/lib/assistant/service.js +201 -0
  78. package/lib/config.js +1 -1
  79. package/lib/constants/collections.js +1 -1
  80. package/lib/durableChat/conversations.d.ts +62 -0
  81. package/lib/durableChat/conversations.js +729 -0
  82. package/lib/durableChat/errors.d.ts +6 -0
  83. package/lib/durableChat/errors.js +11 -0
  84. package/lib/durableChat/events.d.ts +22 -0
  85. package/lib/durableChat/events.js +50 -0
  86. package/lib/durableChat/index.d.ts +8 -0
  87. package/lib/durableChat/index.js +10 -0
  88. package/lib/durableChat/membership.d.ts +24 -0
  89. package/lib/durableChat/membership.js +85 -0
  90. package/lib/durableChat/messageTypes.d.ts +76 -0
  91. package/lib/durableChat/messageTypes.js +3 -0
  92. package/lib/durableChat/messages.d.ts +16 -0
  93. package/lib/durableChat/messages.js +257 -0
  94. package/lib/durableChat/transaction.d.ts +10 -0
  95. package/lib/durableChat/transaction.js +53 -0
  96. package/lib/durableChat/types.d.ts +81 -0
  97. package/lib/durableChat/types.js +3 -0
  98. package/lib/handlers/graphqlHandler.js +1 -1
  99. package/lib/index.d.ts +4 -4
  100. package/lib/index.js +5 -3
  101. package/lib/lambdas/actions/websockets.js +4 -4
  102. package/lib/lambdas/authorizer.js +1 -1
  103. package/lib/lambdas/connection.js +1 -1
  104. package/lib/lambdas/utils/message.js +1 -1
  105. package/lib/lambdas/utils/websocket.js +1 -1
  106. package/lib/mocks/conversation.js +1 -1
  107. package/lib/mocks/file.js +1 -1
  108. package/lib/mocks/group.js +1 -1
  109. package/lib/mocks/image.js +1 -1
  110. package/lib/mocks/post.js +1 -1
  111. package/lib/mocks/tag.js +1 -1
  112. package/lib/mocks/user.js +1 -1
  113. package/lib/mocks/video.js +1 -1
  114. package/lib/mutations/analytics/analytics.js +1 -1
  115. package/lib/mutations/content/content.js +1 -1
  116. package/lib/mutations/crm/crm.js +1 -1
  117. package/lib/mutations/events/events.js +1 -1
  118. package/lib/mutations/flags/flags.js +1 -1
  119. package/lib/mutations/groups/groups.js +1 -1
  120. package/lib/mutations/higgsfield/higgsfield.js +1 -1
  121. package/lib/mutations/images/images.js +1 -1
  122. package/lib/mutations/index.js +1 -1
  123. package/lib/mutations/locations/locations.js +1 -1
  124. package/lib/mutations/messages/messages.js +1 -1
  125. package/lib/mutations/personas/personas.js +1 -1
  126. package/lib/mutations/posts/posts.js +1 -1
  127. package/lib/mutations/reactions/reactions.js +1 -1
  128. package/lib/mutations/rum/rum.js +1 -1
  129. package/lib/mutations/statistics/statistics.js +1 -1
  130. package/lib/mutations/subscriptions/subscriptions.js +1 -1
  131. package/lib/mutations/tags/tags.js +1 -1
  132. package/lib/mutations/users/users.js +1 -1
  133. package/lib/mutations/videos/videos.js +1 -1
  134. package/lib/nativePush/graphql.d.ts +14 -0
  135. package/lib/nativePush/graphql.js +105 -0
  136. package/lib/nativePush/index.d.ts +7 -0
  137. package/lib/nativePush/index.js +9 -0
  138. package/lib/nativePush/migrations.d.ts +2 -0
  139. package/lib/nativePush/migrations.js +36 -0
  140. package/lib/nativePush/nativePushContract.fixture.d.ts +22 -0
  141. package/lib/nativePush/nativePushContract.fixture.js +27 -0
  142. package/lib/nativePush/payload.d.ts +2 -0
  143. package/lib/nativePush/payload.js +106 -0
  144. package/lib/nativePush/repository.d.ts +9 -0
  145. package/lib/nativePush/repository.js +120 -0
  146. package/lib/nativePush/service.d.ts +2 -0
  147. package/lib/nativePush/service.js +110 -0
  148. package/lib/nativePush/snsProvider.d.ts +17 -0
  149. package/lib/nativePush/snsProvider.js +165 -0
  150. package/lib/nativePush/types.d.ts +89 -0
  151. package/lib/nativePush/types.js +3 -0
  152. package/lib/objectTypes/analytics.js +1 -1
  153. package/lib/objectTypes/app.js +1 -1
  154. package/lib/objectTypes/bankAccount.js +1 -1
  155. package/lib/objectTypes/connection.js +1 -1
  156. package/lib/objectTypes/content.js +1 -1
  157. package/lib/objectTypes/contentGeneration.js +1 -1
  158. package/lib/objectTypes/conversation.js +1 -1
  159. package/lib/objectTypes/creditCard.js +1 -1
  160. package/lib/objectTypes/crm.js +1 -1
  161. package/lib/objectTypes/document.js +1 -1
  162. package/lib/objectTypes/error.js +1 -1
  163. package/lib/objectTypes/event.js +1 -1
  164. package/lib/objectTypes/external.js +1 -1
  165. package/lib/objectTypes/file.js +1 -1
  166. package/lib/objectTypes/filter.js +1 -1
  167. package/lib/objectTypes/flag.js +1 -1
  168. package/lib/objectTypes/group.js +1 -1
  169. package/lib/objectTypes/higgsfield.js +1 -1
  170. package/lib/objectTypes/iapSubscription.js +1 -1
  171. package/lib/objectTypes/image.js +1 -1
  172. package/lib/objectTypes/imageGeneration.js +1 -1
  173. package/lib/objectTypes/index.js +1 -1
  174. package/lib/objectTypes/location.js +1 -1
  175. package/lib/objectTypes/message.js +1 -1
  176. package/lib/objectTypes/passcode.js +1 -1
  177. package/lib/objectTypes/persona.js +1 -1
  178. package/lib/objectTypes/plan.js +1 -1
  179. package/lib/objectTypes/post.js +1 -1
  180. package/lib/objectTypes/query.js +1 -1
  181. package/lib/objectTypes/reaction.js +1 -1
  182. package/lib/objectTypes/relation.js +1 -1
  183. package/lib/objectTypes/rum.js +1 -1
  184. package/lib/objectTypes/search.js +1 -1
  185. package/lib/objectTypes/statistics.js +1 -1
  186. package/lib/objectTypes/subscription.js +1 -1
  187. package/lib/objectTypes/tag.js +1 -1
  188. package/lib/objectTypes/user.js +1 -1
  189. package/lib/objectTypes/video.js +1 -1
  190. package/lib/objectTypes/videoGeneration.js +1 -1
  191. package/lib/organizations/accountLifecycle.d.ts +7 -0
  192. package/lib/organizations/accountLifecycle.js +106 -0
  193. package/lib/organizations/authorization.d.ts +9 -0
  194. package/lib/organizations/authorization.js +40 -0
  195. package/lib/organizations/billing.d.ts +38 -0
  196. package/lib/organizations/billing.js +277 -0
  197. package/lib/organizations/billingProvider.d.ts +4 -0
  198. package/lib/organizations/billingProvider.js +287 -0
  199. package/lib/organizations/billingUpdates.d.ts +9 -0
  200. package/lib/organizations/billingUpdates.js +388 -0
  201. package/lib/organizations/index.d.ts +10 -0
  202. package/lib/organizations/index.js +12 -0
  203. package/lib/organizations/mail.d.ts +10 -0
  204. package/lib/organizations/mail.js +60 -0
  205. package/lib/organizations/memberDirectory.d.ts +15 -0
  206. package/lib/organizations/memberDirectory.js +28 -0
  207. package/lib/organizations/membership.d.ts +19 -0
  208. package/lib/organizations/membership.js +248 -0
  209. package/lib/organizations/passwordRecovery.d.ts +9 -0
  210. package/lib/organizations/passwordRecovery.js +50 -0
  211. package/lib/organizations/plans.d.ts +6 -0
  212. package/lib/organizations/plans.js +40 -0
  213. package/lib/organizations/providerPagination.d.ts +6 -0
  214. package/lib/organizations/providerPagination.js +23 -0
  215. package/lib/organizations/reconciliation.d.ts +11 -0
  216. package/lib/organizations/reconciliation.js +400 -0
  217. package/lib/organizations/signup.d.ts +25 -0
  218. package/lib/organizations/signup.js +169 -0
  219. package/lib/organizations/store.d.ts +25 -0
  220. package/lib/organizations/store.js +167 -0
  221. package/lib/organizations/types.d.ts +138 -0
  222. package/lib/organizations/types.js +3 -0
  223. package/lib/organizations/verification.d.ts +3 -0
  224. package/lib/organizations/verification.js +51 -0
  225. package/lib/queries/analytics/analytics.js +1 -1
  226. package/lib/queries/content/content.js +1 -1
  227. package/lib/queries/crm/crm.js +1 -1
  228. package/lib/queries/events/events.js +1 -1
  229. package/lib/queries/flags/flags.js +1 -1
  230. package/lib/queries/groups/groups.js +1 -1
  231. package/lib/queries/higgsfield/higgsfield.js +1 -1
  232. package/lib/queries/images/images.js +1 -1
  233. package/lib/queries/index.js +1 -1
  234. package/lib/queries/locations/locations.js +1 -1
  235. package/lib/queries/messages/messages.js +1 -1
  236. package/lib/queries/personas/personas.js +1 -1
  237. package/lib/queries/posts/posts.js +1 -1
  238. package/lib/queries/query/query.js +1 -1
  239. package/lib/queries/reactions/reactions.js +1 -1
  240. package/lib/queries/statistics/statistics.js +1 -1
  241. package/lib/queries/subscriptions/subscriptions.js +1 -1
  242. package/lib/queries/tags/tags.js +1 -1
  243. package/lib/queries/users/users.js +1 -1
  244. package/lib/queries/videos/videos.js +1 -1
  245. package/lib/templates/email/layout.js +1 -1
  246. package/lib/templates/email/passwordForgot.js +1 -1
  247. package/lib/templates/email/passwordRecovery.js +1 -1
  248. package/lib/templates/email/verifyEmail.js +1 -1
  249. package/lib/templates/email/welcome.js +1 -1
  250. package/lib/templates/sms/passwordForgot.js +1 -1
  251. package/lib/templates/sms/passwordRecovery.js +1 -1
  252. package/lib/templates/sms/verifyEmail.js +1 -1
  253. package/lib/templates/sms/verifyPhone.js +1 -1
  254. package/lib/templates/sms/welcome.js +1 -1
  255. package/lib/types/analytics.types.js +1 -1
  256. package/lib/types/apps.types.js +1 -1
  257. package/lib/types/arangodb.types.js +1 -1
  258. package/lib/types/auth.types.js +1 -1
  259. package/lib/types/connections.types.js +1 -1
  260. package/lib/types/content.types.js +1 -1
  261. package/lib/types/conversations.types.js +1 -1
  262. package/lib/types/crm.types.js +1 -1
  263. package/lib/types/databaseCredentials.types.js +1 -1
  264. package/lib/types/email.types.js +1 -1
  265. package/lib/types/error.types.js +1 -1
  266. package/lib/types/files.types.js +1 -1
  267. package/lib/types/flags.types.js +1 -1
  268. package/lib/types/google.types.js +1 -1
  269. package/lib/types/groups.types.js +1 -1
  270. package/lib/types/images.types.js +1 -1
  271. package/lib/types/index.js +1 -1
  272. package/lib/types/locations.types.js +1 -1
  273. package/lib/types/messages.types.js +1 -1
  274. package/lib/types/notifications.types.js +1 -1
  275. package/lib/types/payments.types.js +1 -1
  276. package/lib/types/personas.types.js +1 -1
  277. package/lib/types/posts.types.js +1 -1
  278. package/lib/types/rum.types.js +1 -1
  279. package/lib/types/statistics.types.js +1 -1
  280. package/lib/types/tags.types.js +1 -1
  281. package/lib/types/users.types.js +1 -1
  282. package/lib/types/videos.types.js +1 -1
  283. package/lib/types/websockets.types.js +1 -1
  284. package/lib/upload.js +1 -1
  285. package/lib/utils/adapterUtils.js +1 -1
  286. package/lib/utils/analyticsUtils.js +1 -1
  287. package/lib/utils/appContext.js +1 -1
  288. package/lib/utils/aqlHelpers.js +1 -1
  289. package/lib/utils/arangodbUtils.js +1 -1
  290. package/lib/utils/authUtils.js +1 -1
  291. package/lib/utils/awsUtils.js +1 -1
  292. package/lib/utils/collectionRegistry.js +1 -1
  293. package/lib/utils/contextUtils.js +1 -1
  294. package/lib/utils/databaseCredentials.js +1 -1
  295. package/lib/utils/dbI18n.example.js +1 -1
  296. package/lib/utils/dbI18n.js +1 -1
  297. package/lib/utils/generationCallback.js +1 -1
  298. package/lib/utils/googleTranslate.js +1 -1
  299. package/lib/utils/graphqlUtils.js +1 -1
  300. package/lib/utils/imageUtils.js +1 -1
  301. package/lib/utils/index.js +1 -1
  302. package/lib/utils/languageDetection.js +1 -1
  303. package/lib/utils/localeUtils.example.js +1 -1
  304. package/lib/utils/localeUtils.js +1 -1
  305. package/lib/utils/mediaAccess.js +1 -1
  306. package/lib/utils/middlewareUtils.js +1 -1
  307. package/lib/utils/nodeRealtime.js +1 -1
  308. package/lib/utils/opaqueToken.js +1 -1
  309. package/lib/utils/queryBuilder.js +1 -1
  310. package/lib/utils/schemaUtils.js +1 -1
  311. package/lib/utils/secretDatabase.js +1 -1
  312. package/lib/utils/sessionUtils.js +1 -1
  313. package/lib/utils/stripeUtils.js +1 -1
  314. package/lib/utils/stripeUtils.ts.bak +1 -1
  315. package/lib/utils/templateUtils.js +1 -1
  316. package/lib/utils/testUtils.js +1 -1
  317. package/lib/utils/translationQueue.example.js +1 -1
  318. package/lib/utils/translationQueue.js +1 -1
  319. package/lib/videoProcessing.js +1 -1
  320. package/package.json +16 -3
@@ -0,0 +1,6 @@
1
+ export type ChatErrorCode = 'conflict' | 'forbidden' | 'invalid_request' | 'rate_limited' | 'unavailable';
2
+ export declare class DurableChatError extends Error {
3
+ readonly code: ChatErrorCode;
4
+ constructor(code: ChatErrorCode);
5
+ }
6
+ export { DurableChatError as ChatError };
@@ -0,0 +1,11 @@
1
+ export class DurableChatError extends Error {
2
+ code;
3
+ constructor(code){
4
+ super(code);
5
+ this.code = code;
6
+ this.name = 'ChatError';
7
+ }
8
+ }
9
+ export { DurableChatError as ChatError };
10
+
11
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9wcml2YXRlL3RtcC92YXVsdC1yZWFrdG9yLWNvbXBsZXRpb24vcGFja2FnZXMvcmVha3Rvci9zcmMvZHVyYWJsZUNoYXQvZXJyb3JzLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCB0eXBlIENoYXRFcnJvckNvZGUgPSAnY29uZmxpY3QnIHwgJ2ZvcmJpZGRlbicgfCAnaW52YWxpZF9yZXF1ZXN0JyB8ICdyYXRlX2xpbWl0ZWQnIHwgJ3VuYXZhaWxhYmxlJztcblxuZXhwb3J0IGNsYXNzIER1cmFibGVDaGF0RXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIHJlYWRvbmx5IGNvZGU6IENoYXRFcnJvckNvZGU7XG5cbiAgY29uc3RydWN0b3IoY29kZTogQ2hhdEVycm9yQ29kZSkge1xuICAgIHN1cGVyKGNvZGUpO1xuICAgIHRoaXMuY29kZSA9IGNvZGU7XG4gICAgdGhpcy5uYW1lID0gJ0NoYXRFcnJvcic7XG4gIH1cbn1cblxuZXhwb3J0IHtEdXJhYmxlQ2hhdEVycm9yIGFzIENoYXRFcnJvcn07XG4iXSwibmFtZXMiOlsiRHVyYWJsZUNoYXRFcnJvciIsIkVycm9yIiwiY29kZSIsIm5hbWUiLCJDaGF0RXJyb3IiXSwibWFwcGluZ3MiOiJBQUVBLE9BQU8sTUFBTUEseUJBQXlCQztJQUMzQkMsS0FBb0I7SUFFN0IsWUFBWUEsSUFBbUIsQ0FBRTtRQUMvQixLQUFLLENBQUNBO1FBQ04sSUFBSSxDQUFDQSxJQUFJLEdBQUdBO1FBQ1osSUFBSSxDQUFDQyxJQUFJLEdBQUc7SUFDZDtBQUNGO0FBRUEsU0FBUUgsb0JBQW9CSSxTQUFTLEdBQUUifQ==
@@ -0,0 +1,22 @@
1
+ import type { ChatQuery } from './membership.js';
2
+ import type { ChatEvent } from './types.js';
3
+ export interface AppendChatEventInput {
4
+ readonly actorPersonaId: string;
5
+ readonly conversationId: string;
6
+ readonly kind: ChatEvent['kind'];
7
+ readonly membershipEpoch?: string;
8
+ readonly resourceId: string;
9
+ readonly revision: number;
10
+ }
11
+ export interface StoredChatEvent extends ChatEvent {
12
+ readonly _key: string;
13
+ readonly actorPersonaId: string;
14
+ readonly createdAt: number;
15
+ readonly leaseUntil: number;
16
+ readonly membershipEpoch?: string;
17
+ readonly nextAttemptAt: number;
18
+ readonly status: 'pending';
19
+ readonly type: ChatEvent['kind'];
20
+ }
21
+ /** Requires the caller's exclusive conversations/chatOutbox locks; never commits independently. */
22
+ export declare const appendChatEvent: (read: ChatQuery, input: AppendChatEventInput) => Promise<StoredChatEvent>;
@@ -0,0 +1,50 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { ChatError } from './errors.js';
3
+ import { isChatIdentifier } from './membership.js';
4
+ /** Requires the caller's exclusive conversations/chatOutbox locks; never commits independently. */ export const appendChatEvent = async (read, input)=>{
5
+ if (!input || !isChatIdentifier(input.actorPersonaId) || !isChatIdentifier(input.conversationId) || !isChatIdentifier(input.resourceId) || !Number.isSafeInteger(input.revision) || input.revision < 1 || input.membershipEpoch !== undefined && !isChatIdentifier(input.membershipEpoch) || ![
6
+ 'membership.changed',
7
+ 'message.changed',
8
+ 'receipt.changed'
9
+ ].includes(input.kind)) {
10
+ throw new ChatError('invalid_request');
11
+ }
12
+ const sequence = await read(`LET conversation = DOCUMENT('conversations', @id)
13
+ FILTER conversation != null AND conversation.chatSchemaVersion == 1
14
+ AND (conversation.lastEventSequence == null OR
15
+ (IS_NUMBER(conversation.lastEventSequence) AND conversation.lastEventSequence >= 0
16
+ AND FLOOR(conversation.lastEventSequence) == conversation.lastEventSequence
17
+ AND conversation.lastEventSequence < 9007199254740991))
18
+ UPDATE @id WITH {lastEventSequence: (conversation.lastEventSequence == null ? 0 : conversation.lastEventSequence) + 1}
19
+ IN conversations RETURN NEW.lastEventSequence`, {
20
+ id: input.conversationId
21
+ });
22
+ if (!Number.isSafeInteger(sequence) || Number(sequence) < 1) {
23
+ throw new ChatError('unavailable');
24
+ }
25
+ const id = randomUUID();
26
+ const record = {
27
+ _key: id,
28
+ actorPersonaId: input.actorPersonaId,
29
+ conversationId: input.conversationId,
30
+ createdAt: Date.now(),
31
+ eventId: id,
32
+ eventSequence: sequence,
33
+ kind: input.kind,
34
+ leaseUntil: 0,
35
+ membershipEpoch: input.membershipEpoch,
36
+ nextAttemptAt: 0,
37
+ resourceId: input.resourceId,
38
+ revision: input.revision,
39
+ status: 'pending',
40
+ type: input.kind
41
+ };
42
+ if (await read('INSERT @record IN chatOutbox RETURN true', {
43
+ record
44
+ }) !== true) {
45
+ throw new ChatError('unavailable');
46
+ }
47
+ return record;
48
+ };
49
+
50
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9wcml2YXRlL3RtcC92YXVsdC1yZWFrdG9yLWNvbXBsZXRpb24vcGFja2FnZXMvcmVha3Rvci9zcmMvZHVyYWJsZUNoYXQvZXZlbnRzLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7cmFuZG9tVVVJRH0gZnJvbSAnbm9kZTpjcnlwdG8nO1xuXG5pbXBvcnQge0NoYXRFcnJvcn0gZnJvbSAnLi9lcnJvcnMuanMnO1xuaW1wb3J0IHtpc0NoYXRJZGVudGlmaWVyfSBmcm9tICcuL21lbWJlcnNoaXAuanMnO1xuXG5pbXBvcnQgdHlwZSB7Q2hhdFF1ZXJ5fSBmcm9tICcuL21lbWJlcnNoaXAuanMnO1xuaW1wb3J0IHR5cGUge0NoYXRFdmVudH0gZnJvbSAnLi90eXBlcy5qcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgQXBwZW5kQ2hhdEV2ZW50SW5wdXQge1xuICByZWFkb25seSBhY3RvclBlcnNvbmFJZDogc3RyaW5nO1xuICByZWFkb25seSBjb252ZXJzYXRpb25JZDogc3RyaW5nO1xuICByZWFkb25seSBraW5kOiBDaGF0RXZlbnRbJ2tpbmQnXTtcbiAgcmVhZG9ubHkgbWVtYmVyc2hpcEVwb2NoPzogc3RyaW5nO1xuICByZWFkb25seSByZXNvdXJjZUlkOiBzdHJpbmc7XG4gIHJlYWRvbmx5IHJldmlzaW9uOiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3RvcmVkQ2hhdEV2ZW50IGV4dGVuZHMgQ2hhdEV2ZW50IHtcbiAgcmVhZG9ubHkgX2tleTogc3RyaW5nO1xuICByZWFkb25seSBhY3RvclBlcnNvbmFJZDogc3RyaW5nO1xuICByZWFkb25seSBjcmVhdGVkQXQ6IG51bWJlcjtcbiAgcmVhZG9ubHkgbGVhc2VVbnRpbDogbnVtYmVyO1xuICByZWFkb25seSBtZW1iZXJzaGlwRXBvY2g/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IG5leHRBdHRlbXB0QXQ6IG51bWJlcjtcbiAgcmVhZG9ubHkgc3RhdHVzOiAncGVuZGluZyc7XG4gIHJlYWRvbmx5IHR5cGU6IENoYXRFdmVudFsna2luZCddO1xufVxuXG4vKiogUmVxdWlyZXMgdGhlIGNhbGxlcidzIGV4Y2x1c2l2ZSBjb252ZXJzYXRpb25zL2NoYXRPdXRib3ggbG9ja3M7IG5ldmVyIGNvbW1pdHMgaW5kZXBlbmRlbnRseS4gKi9cbmV4cG9ydCBjb25zdCBhcHBlbmRDaGF0RXZlbnQgPSBhc3luYyAocmVhZDogQ2hhdFF1ZXJ5LCBpbnB1dDogQXBwZW5kQ2hhdEV2ZW50SW5wdXQpOiBQcm9taXNlPFN0b3JlZENoYXRFdmVudD4gPT4ge1xuICBpZighaW5wdXQgfHwgIWlzQ2hhdElkZW50aWZpZXIoaW5wdXQuYWN0b3JQZXJzb25hSWQpIHx8ICFpc0NoYXRJZGVudGlmaWVyKGlucHV0LmNvbnZlcnNhdGlvbklkKVxuICAgIHx8ICFpc0NoYXRJZGVudGlmaWVyKGlucHV0LnJlc291cmNlSWQpIHx8ICFOdW1iZXIuaXNTYWZlSW50ZWdlcihpbnB1dC5yZXZpc2lvbikgfHwgaW5wdXQucmV2aXNpb24gPCAxXG4gICAgfHwgKGlucHV0Lm1lbWJlcnNoaXBFcG9jaCAhPT0gdW5kZWZpbmVkICYmICFpc0NoYXRJZGVudGlmaWVyKGlucHV0Lm1lbWJlcnNoaXBFcG9jaCkpXG4gICAgfHwgIVsnbWVtYmVyc2hpcC5jaGFuZ2VkJywgJ21lc3NhZ2UuY2hhbmdlZCcsICdyZWNlaXB0LmNoYW5nZWQnXS5pbmNsdWRlcyhpbnB1dC5raW5kKSkge1xuICAgIHRocm93IG5ldyBDaGF0RXJyb3IoJ2ludmFsaWRfcmVxdWVzdCcpO1xuICB9XG4gIGNvbnN0IHNlcXVlbmNlID0gYXdhaXQgcmVhZDxudW1iZXI+KGBMRVQgY29udmVyc2F0aW9uID0gRE9DVU1FTlQoJ2NvbnZlcnNhdGlvbnMnLCBAaWQpXG4gICAgRklMVEVSIGNvbnZlcnNhdGlvbiAhPSBudWxsIEFORCBjb252ZXJzYXRpb24uY2hhdFNjaGVtYVZlcnNpb24gPT0gMVxuICAgICAgQU5EIChjb252ZXJzYXRpb24ubGFzdEV2ZW50U2VxdWVuY2UgPT0gbnVsbCBPUlxuICAgICAgICAoSVNfTlVNQkVSKGNvbnZlcnNhdGlvbi5sYXN0RXZlbnRTZXF1ZW5jZSkgQU5EIGNvbnZlcnNhdGlvbi5sYXN0RXZlbnRTZXF1ZW5jZSA+PSAwXG4gICAgICAgICAgQU5EIEZMT09SKGNvbnZlcnNhdGlvbi5sYXN0RXZlbnRTZXF1ZW5jZSkgPT0gY29udmVyc2F0aW9uLmxhc3RFdmVudFNlcXVlbmNlXG4gICAgICAgICAgQU5EIGNvbnZlcnNhdGlvbi5sYXN0RXZlbnRTZXF1ZW5jZSA8IDkwMDcxOTkyNTQ3NDA5OTEpKVxuICAgIFVQREFURSBAaWQgV0lUSCB7bGFzdEV2ZW50U2VxdWVuY2U6IChjb252ZXJzYXRpb24ubGFzdEV2ZW50U2VxdWVuY2UgPT0gbnVsbCA/IDAgOiBjb252ZXJzYXRpb24ubGFzdEV2ZW50U2VxdWVuY2UpICsgMX1cbiAgICAgIElOIGNvbnZlcnNhdGlvbnMgUkVUVVJOIE5FVy5sYXN0RXZlbnRTZXF1ZW5jZWAsIHtpZDogaW5wdXQuY29udmVyc2F0aW9uSWR9KTtcbiAgaWYoIU51bWJlci5pc1NhZmVJbnRlZ2VyKHNlcXVlbmNlKSB8fCBOdW1iZXIoc2VxdWVuY2UpIDwgMSkge1xuICAgIHRocm93IG5ldyBDaGF0RXJyb3IoJ3VuYXZhaWxhYmxlJyk7XG4gIH1cbiAgY29uc3QgaWQgPSByYW5kb21VVUlEKCk7XG4gIGNvbnN0IHJlY29yZDogU3RvcmVkQ2hhdEV2ZW50ID0ge1xuICAgIF9rZXk6IGlkLCBhY3RvclBlcnNvbmFJZDogaW5wdXQuYWN0b3JQZXJzb25hSWQsIGNvbnZlcnNhdGlvbklkOiBpbnB1dC5jb252ZXJzYXRpb25JZCwgY3JlYXRlZEF0OiBEYXRlLm5vdygpLFxuICAgIGV2ZW50SWQ6IGlkLCBldmVudFNlcXVlbmNlOiBzZXF1ZW5jZSEsIGtpbmQ6IGlucHV0LmtpbmQsIGxlYXNlVW50aWw6IDAsXG4gICAgbWVtYmVyc2hpcEVwb2NoOiBpbnB1dC5tZW1iZXJzaGlwRXBvY2gsIG5leHRBdHRlbXB0QXQ6IDAsIHJlc291cmNlSWQ6IGlucHV0LnJlc291cmNlSWQsXG4gICAgcmV2aXNpb246IGlucHV0LnJldmlzaW9uLCBzdGF0dXM6ICdwZW5kaW5nJywgdHlwZTogaW5wdXQua2luZFxuICB9O1xuICBpZihhd2FpdCByZWFkPGJvb2xlYW4+KCdJTlNFUlQgQHJlY29yZCBJTiBjaGF0T3V0Ym94IFJFVFVSTiB0cnVlJywge3JlY29yZH0pICE9PSB0cnVlKSB7XG4gICAgdGhyb3cgbmV3IENoYXRFcnJvcigndW5hdmFpbGFibGUnKTtcbiAgfVxuICByZXR1cm4gcmVjb3JkO1xufTtcbiJdLCJuYW1lcyI6WyJyYW5kb21VVUlEIiwiQ2hhdEVycm9yIiwiaXNDaGF0SWRlbnRpZmllciIsImFwcGVuZENoYXRFdmVudCIsInJlYWQiLCJpbnB1dCIsImFjdG9yUGVyc29uYUlkIiwiY29udmVyc2F0aW9uSWQiLCJyZXNvdXJjZUlkIiwiTnVtYmVyIiwiaXNTYWZlSW50ZWdlciIsInJldmlzaW9uIiwibWVtYmVyc2hpcEVwb2NoIiwidW5kZWZpbmVkIiwiaW5jbHVkZXMiLCJraW5kIiwic2VxdWVuY2UiLCJpZCIsInJlY29yZCIsIl9rZXkiLCJjcmVhdGVkQXQiLCJEYXRlIiwibm93IiwiZXZlbnRJZCIsImV2ZW50U2VxdWVuY2UiLCJsZWFzZVVudGlsIiwibmV4dEF0dGVtcHRBdCIsInN0YXR1cyIsInR5cGUiXSwibWFwcGluZ3MiOiJBQUFBLFNBQVFBLFVBQVUsUUFBTyxjQUFjO0FBRXZDLFNBQVFDLFNBQVMsUUFBTyxjQUFjO0FBQ3RDLFNBQVFDLGdCQUFnQixRQUFPLGtCQUFrQjtBQXlCakQsaUdBQWlHLEdBQ2pHLE9BQU8sTUFBTUMsa0JBQWtCLE9BQU9DLE1BQWlCQztJQUNyRCxJQUFHLENBQUNBLFNBQVMsQ0FBQ0gsaUJBQWlCRyxNQUFNQyxjQUFjLEtBQUssQ0FBQ0osaUJBQWlCRyxNQUFNRSxjQUFjLEtBQ3pGLENBQUNMLGlCQUFpQkcsTUFBTUcsVUFBVSxLQUFLLENBQUNDLE9BQU9DLGFBQWEsQ0FBQ0wsTUFBTU0sUUFBUSxLQUFLTixNQUFNTSxRQUFRLEdBQUcsS0FDaEdOLE1BQU1PLGVBQWUsS0FBS0MsYUFBYSxDQUFDWCxpQkFBaUJHLE1BQU1PLGVBQWUsS0FDL0UsQ0FBQztRQUFDO1FBQXNCO1FBQW1CO0tBQWtCLENBQUNFLFFBQVEsQ0FBQ1QsTUFBTVUsSUFBSSxHQUFHO1FBQ3ZGLE1BQU0sSUFBSWQsVUFBVTtJQUN0QjtJQUNBLE1BQU1lLFdBQVcsTUFBTVosS0FBYSxDQUFDOzs7Ozs7O21EQU9ZLENBQUMsRUFBRTtRQUFDYSxJQUFJWixNQUFNRSxjQUFjO0lBQUE7SUFDN0UsSUFBRyxDQUFDRSxPQUFPQyxhQUFhLENBQUNNLGFBQWFQLE9BQU9PLFlBQVksR0FBRztRQUMxRCxNQUFNLElBQUlmLFVBQVU7SUFDdEI7SUFDQSxNQUFNZ0IsS0FBS2pCO0lBQ1gsTUFBTWtCLFNBQTBCO1FBQzlCQyxNQUFNRjtRQUFJWCxnQkFBZ0JELE1BQU1DLGNBQWM7UUFBRUMsZ0JBQWdCRixNQUFNRSxjQUFjO1FBQUVhLFdBQVdDLEtBQUtDLEdBQUc7UUFDekdDLFNBQVNOO1FBQUlPLGVBQWVSO1FBQVdELE1BQU1WLE1BQU1VLElBQUk7UUFBRVUsWUFBWTtRQUNyRWIsaUJBQWlCUCxNQUFNTyxlQUFlO1FBQUVjLGVBQWU7UUFBR2xCLFlBQVlILE1BQU1HLFVBQVU7UUFDdEZHLFVBQVVOLE1BQU1NLFFBQVE7UUFBRWdCLFFBQVE7UUFBV0MsTUFBTXZCLE1BQU1VLElBQUk7SUFDL0Q7SUFDQSxJQUFHLE1BQU1YLEtBQWMsNENBQTRDO1FBQUNjO0lBQU0sT0FBTyxNQUFNO1FBQ3JGLE1BQU0sSUFBSWpCLFVBQVU7SUFDdEI7SUFDQSxPQUFPaUI7QUFDVCxFQUFFIn0=
@@ -0,0 +1,8 @@
1
+ export * from './conversations.js';
2
+ export * from './errors.js';
3
+ export * from './events.js';
4
+ export * from './membership.js';
5
+ export * from './transaction.js';
6
+ export * from './types.js';
7
+ export * from './messages.js';
8
+ export * from './messageTypes.js';
@@ -0,0 +1,10 @@
1
+ export * from './conversations.js';
2
+ export * from './errors.js';
3
+ export * from './events.js';
4
+ export * from './membership.js';
5
+ export * from './transaction.js';
6
+ export * from './types.js';
7
+ export * from './messages.js';
8
+ export * from './messageTypes.js';
9
+
10
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9wcml2YXRlL3RtcC92YXVsdC1yZWFrdG9yLWNvbXBsZXRpb24vcGFja2FnZXMvcmVha3Rvci9zcmMvZHVyYWJsZUNoYXQvaW5kZXgudHMiXSwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0ICogZnJvbSAnLi9jb252ZXJzYXRpb25zLmpzJztcbmV4cG9ydCAqIGZyb20gJy4vZXJyb3JzLmpzJztcbmV4cG9ydCAqIGZyb20gJy4vZXZlbnRzLmpzJztcbmV4cG9ydCAqIGZyb20gJy4vbWVtYmVyc2hpcC5qcyc7XG5leHBvcnQgKiBmcm9tICcuL3RyYW5zYWN0aW9uLmpzJztcbmV4cG9ydCAqIGZyb20gJy4vdHlwZXMuanMnO1xuZXhwb3J0ICogZnJvbSAnLi9tZXNzYWdlcy5qcyc7XG5leHBvcnQgKiBmcm9tICcuL21lc3NhZ2VUeXBlcy5qcyc7XG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsY0FBYyxxQkFBcUI7QUFDbkMsY0FBYyxjQUFjO0FBQzVCLGNBQWMsY0FBYztBQUM1QixjQUFjLGtCQUFrQjtBQUNoQyxjQUFjLG1CQUFtQjtBQUNqQyxjQUFjLGFBQWE7QUFDM0IsY0FBYyxnQkFBZ0I7QUFDOUIsY0FBYyxvQkFBb0IifQ==
@@ -0,0 +1,24 @@
1
+ import type { ApiContext } from '../types/auth.types.js';
2
+ import type { ConversationKind, ConversationMembership, ConversationState } from './types.js';
3
+ export interface ChatIdentity {
4
+ readonly personaId: string;
5
+ readonly userId: string;
6
+ }
7
+ export interface MembershipAccessInput {
8
+ readonly conversationId: string;
9
+ readonly membershipEpoch?: string;
10
+ readonly messageSequence?: number;
11
+ readonly purpose: 'history' | 'invite' | 'participants' | 'report' | 'send' | 'socket';
12
+ }
13
+ export interface AuthorizedMembership extends ConversationMembership {
14
+ readonly activeMemberCount: number;
15
+ readonly conversationState: ConversationState;
16
+ readonly kind: ConversationKind;
17
+ readonly lastSequence: number;
18
+ readonly membershipRevision: number;
19
+ }
20
+ /** Inject the transaction's query adapter when this check guards a write. */
21
+ export type ChatQuery = <T>(query: string, bindVars: Record<string, unknown>) => Promise<T | undefined>;
22
+ export declare const isChatIdentifier: (value: unknown) => value is string;
23
+ export declare const createMembershipAuthorizer: (read: ChatQuery) => (identity: ChatIdentity, input: MembershipAccessInput) => Promise<AuthorizedMembership>;
24
+ export declare const authorizeConversationAccess: (context: ApiContext, identity: ChatIdentity, input: MembershipAccessInput) => Promise<AuthorizedMembership>;
@@ -0,0 +1,85 @@
1
+ import { ChatError } from './errors.js';
2
+ import { createDurableQuery } from './transaction.js';
3
+ export const isChatIdentifier = (value)=>typeof value === 'string' && /^[a-zA-Z0-9_-]{1,128}$/.test(value);
4
+ const purposes = [
5
+ 'history',
6
+ 'invite',
7
+ 'participants',
8
+ 'report',
9
+ 'send',
10
+ 'socket'
11
+ ];
12
+ export const createMembershipAuthorizer = (read)=>async (identity, input)=>{
13
+ if (!identity || !isChatIdentifier(identity.userId) || !isChatIdentifier(identity.personaId)) {
14
+ throw new ChatError('forbidden');
15
+ }
16
+ if (!input || !isChatIdentifier(input.conversationId) || !purposes.includes(input.purpose) || input.membershipEpoch !== undefined && !isChatIdentifier(input.membershipEpoch) || input.messageSequence !== undefined && (!Number.isSafeInteger(input.messageSequence) || input.messageSequence < 1) || input.purpose === 'report' && input.messageSequence === undefined) {
17
+ throw new ChatError('invalid_request');
18
+ }
19
+ const result = await read(`
20
+ LET user = DOCUMENT('users', @userId)
21
+ LET persona = DOCUMENT('personas', @personaId)
22
+ LET conversation = DOCUMENT('conversations', @conversationId)
23
+ FILTER user != null AND user.active != false AND persona != null AND persona.active != false
24
+ AND persona.userId == @userId AND conversation != null AND conversation.chatSchemaVersion == 1
25
+ AND conversation.kind IN ['direct', 'group'] AND conversation.state IN ['active', 'forming', 'closed']
26
+ LET membership = FIRST(FOR member IN hasChatMembership
27
+ FILTER member.conversationId == @conversationId AND member.personaId == @personaId
28
+ AND member.userId == @userId AND member._from == CONCAT('personas/', @personaId)
29
+ AND member._to == CONCAT('conversations/', @conversationId)
30
+ AND (@epoch == null OR member.epoch == @epoch)
31
+ AND (@purpose == 'report' ? member.state IN ['active', 'left', 'removed'] : member.state == 'active')
32
+ AND (@sequence == null OR (IS_NUMBER(member.joinSequence) AND @sequence >= member.joinSequence
33
+ AND @sequence <= conversation.lastSequence
34
+ AND (member.state == 'active' OR (IS_NUMBER(member.leftSequence) AND @sequence <= member.leftSequence))))
35
+ SORT member.acceptedAt DESC, member._key DESC LIMIT 1 RETURN member)
36
+ FILTER membership != null
37
+ LET peers = (FOR member IN hasChatMembership
38
+ FILTER member.conversationId == @conversationId AND member.state == 'active'
39
+ AND member.personaId != @personaId RETURN member)
40
+ LET peer = FIRST(peers)
41
+ LET peerPersona = peer == null ? null : DOCUMENT('personas', peer.personaId)
42
+ LET peerUser = peer == null ? null : DOCUMENT('users', peer.userId)
43
+ LET blocked = peer == null ? false : FIRST(FOR edge IN hasConnection FILTER edge.type == 'block'
44
+ AND ((edge._from IN [CONCAT('personas/', @personaId), CONCAT('users/', @userId)]
45
+ AND edge._to IN [CONCAT('personas/', peer.personaId), CONCAT('users/', peer.userId)])
46
+ OR (edge._to IN [CONCAT('personas/', @personaId), CONCAT('users/', @userId)]
47
+ AND edge._from IN [CONCAT('personas/', peer.personaId), CONCAT('users/', peer.userId)])) LIMIT 1 RETURN true)
48
+ LET following = peer == null ? false : FIRST(FOR edge IN hasConnection
49
+ FILTER edge.type == 'follow' AND edge.active != false AND edge._from == CONCAT('personas/', @personaId)
50
+ AND edge._to == CONCAT('personas/', peer.personaId) LIMIT 1 RETURN true)
51
+ LET followed = peer == null ? false : FIRST(FOR edge IN hasConnection
52
+ FILTER edge.type == 'follow' AND edge.active != false AND edge._to == CONCAT('personas/', @personaId)
53
+ AND edge._from == CONCAT('personas/', peer.personaId) LIMIT 1 RETURN true)
54
+ FILTER @purpose NOT IN ['send', 'socket'] OR (conversation.state == 'active'
55
+ AND (conversation.kind != 'direct' OR (LENGTH(peers) == 1 AND peerPersona != null AND peerUser != null
56
+ AND peerPersona.active != false AND peerUser.active != false AND peerPersona.userId == peer.userId
57
+ AND blocked != true AND following == true AND followed == true)))
58
+ FILTER @purpose != 'invite' OR (conversation.kind == 'group' AND conversation.state != 'closed'
59
+ AND membership.role IN ['owner', 'admin'])
60
+ FILTER @purpose == 'report' OR conversation.state != 'closed'
61
+ RETURN {activeMemberCount: conversation.activeMemberCount, conversationId: @conversationId,
62
+ conversationState: conversation.state, epoch: membership.epoch, joinSequence: membership.joinSequence,
63
+ kind: conversation.kind, lastSequence: conversation.lastSequence, leftSequence: membership.leftSequence,
64
+ membershipRevision: conversation.membershipRevision, personaId: @personaId, revision: membership.revision,
65
+ role: membership.role, state: membership.state}
66
+ `, {
67
+ conversationId: input.conversationId,
68
+ epoch: input.membershipEpoch ?? null,
69
+ personaId: identity.personaId,
70
+ purpose: input.purpose,
71
+ sequence: input.messageSequence ?? null,
72
+ userId: identity.userId
73
+ });
74
+ if (!result || !isChatIdentifier(result.epoch) || !Number.isSafeInteger(result.joinSequence) || result.joinSequence < 0 || !Number.isSafeInteger(result.lastSequence) || result.lastSequence < 0 || !Number.isSafeInteger(result.revision) || result.revision < 1 || !Number.isSafeInteger(result.membershipRevision) || result.membershipRevision < 1 || !Number.isSafeInteger(result.activeMemberCount) || result.activeMemberCount < 0 || result.activeMemberCount > 25 || ![
75
+ 'owner',
76
+ 'admin',
77
+ 'member'
78
+ ].includes(result.role)) {
79
+ throw new ChatError('forbidden');
80
+ }
81
+ return result;
82
+ };
83
+ export const authorizeConversationAccess = (context, identity, input)=>createMembershipAuthorizer(createDurableQuery(context))(identity, input);
84
+
85
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9wcml2YXRlL3RtcC92YXVsdC1yZWFrdG9yLWNvbXBsZXRpb24vcGFja2FnZXMvcmVha3Rvci9zcmMvZHVyYWJsZUNoYXQvbWVtYmVyc2hpcC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge0NoYXRFcnJvcn0gZnJvbSAnLi9lcnJvcnMuanMnO1xuaW1wb3J0IHtjcmVhdGVEdXJhYmxlUXVlcnl9IGZyb20gJy4vdHJhbnNhY3Rpb24uanMnO1xuXG5pbXBvcnQgdHlwZSB7QXBpQ29udGV4dH0gZnJvbSAnLi4vdHlwZXMvYXV0aC50eXBlcy5qcyc7XG5pbXBvcnQgdHlwZSB7Q29udmVyc2F0aW9uS2luZCwgQ29udmVyc2F0aW9uTWVtYmVyc2hpcCwgQ29udmVyc2F0aW9uU3RhdGV9IGZyb20gJy4vdHlwZXMuanMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIENoYXRJZGVudGl0eSB7XG4gIHJlYWRvbmx5IHBlcnNvbmFJZDogc3RyaW5nO1xuICByZWFkb25seSB1c2VySWQ6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBNZW1iZXJzaGlwQWNjZXNzSW5wdXQge1xuICByZWFkb25seSBjb252ZXJzYXRpb25JZDogc3RyaW5nO1xuICByZWFkb25seSBtZW1iZXJzaGlwRXBvY2g/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IG1lc3NhZ2VTZXF1ZW5jZT86IG51bWJlcjtcbiAgcmVhZG9ubHkgcHVycG9zZTogJ2hpc3RvcnknIHwgJ2ludml0ZScgfCAncGFydGljaXBhbnRzJyB8ICdyZXBvcnQnIHwgJ3NlbmQnIHwgJ3NvY2tldCc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQXV0aG9yaXplZE1lbWJlcnNoaXAgZXh0ZW5kcyBDb252ZXJzYXRpb25NZW1iZXJzaGlwIHtcbiAgcmVhZG9ubHkgYWN0aXZlTWVtYmVyQ291bnQ6IG51bWJlcjtcbiAgcmVhZG9ubHkgY29udmVyc2F0aW9uU3RhdGU6IENvbnZlcnNhdGlvblN0YXRlO1xuICByZWFkb25seSBraW5kOiBDb252ZXJzYXRpb25LaW5kO1xuICByZWFkb25seSBsYXN0U2VxdWVuY2U6IG51bWJlcjtcbiAgcmVhZG9ubHkgbWVtYmVyc2hpcFJldmlzaW9uOiBudW1iZXI7XG59XG5cbi8qKiBJbmplY3QgdGhlIHRyYW5zYWN0aW9uJ3MgcXVlcnkgYWRhcHRlciB3aGVuIHRoaXMgY2hlY2sgZ3VhcmRzIGEgd3JpdGUuICovXG5leHBvcnQgdHlwZSBDaGF0UXVlcnkgPSA8VD4ocXVlcnk6IHN0cmluZywgYmluZFZhcnM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KSA9PiBQcm9taXNlPFQgfCB1bmRlZmluZWQ+O1xuXG5leHBvcnQgY29uc3QgaXNDaGF0SWRlbnRpZmllciA9ICh2YWx1ZTogdW5rbm93bik6IHZhbHVlIGlzIHN0cmluZyA9PlxuICB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnICYmIC9eW2EtekEtWjAtOV8tXXsxLDEyOH0kLy50ZXN0KHZhbHVlKTtcblxuY29uc3QgcHVycG9zZXM6IHJlYWRvbmx5IE1lbWJlcnNoaXBBY2Nlc3NJbnB1dFsncHVycG9zZSddW10gPSBbJ2hpc3RvcnknLCAnaW52aXRlJywgJ3BhcnRpY2lwYW50cycsICdyZXBvcnQnLCAnc2VuZCcsICdzb2NrZXQnXTtcblxuZXhwb3J0IGNvbnN0IGNyZWF0ZU1lbWJlcnNoaXBBdXRob3JpemVyID0gKHJlYWQ6IENoYXRRdWVyeSkgPT4gYXN5bmMgKFxuICBpZGVudGl0eTogQ2hhdElkZW50aXR5LCBpbnB1dDogTWVtYmVyc2hpcEFjY2Vzc0lucHV0XG4pOiBQcm9taXNlPEF1dGhvcml6ZWRNZW1iZXJzaGlwPiA9PiB7XG4gIGlmKCFpZGVudGl0eSB8fCAhaXNDaGF0SWRlbnRpZmllcihpZGVudGl0eS51c2VySWQpIHx8ICFpc0NoYXRJZGVudGlmaWVyKGlkZW50aXR5LnBlcnNvbmFJZCkpIHtcbiAgICB0aHJvdyBuZXcgQ2hhdEVycm9yKCdmb3JiaWRkZW4nKTtcbiAgfVxuICBpZighaW5wdXQgfHwgIWlzQ2hhdElkZW50aWZpZXIoaW5wdXQuY29udmVyc2F0aW9uSWQpIHx8ICFwdXJwb3Nlcy5pbmNsdWRlcyhpbnB1dC5wdXJwb3NlKVxuICAgIHx8IChpbnB1dC5tZW1iZXJzaGlwRXBvY2ggIT09IHVuZGVmaW5lZCAmJiAhaXNDaGF0SWRlbnRpZmllcihpbnB1dC5tZW1iZXJzaGlwRXBvY2gpKVxuICAgIHx8IChpbnB1dC5tZXNzYWdlU2VxdWVuY2UgIT09IHVuZGVmaW5lZFxuICAgICAgJiYgKCFOdW1iZXIuaXNTYWZlSW50ZWdlcihpbnB1dC5tZXNzYWdlU2VxdWVuY2UpIHx8IGlucHV0Lm1lc3NhZ2VTZXF1ZW5jZSA8IDEpKVxuICAgIHx8IChpbnB1dC5wdXJwb3NlID09PSAncmVwb3J0JyAmJiBpbnB1dC5tZXNzYWdlU2VxdWVuY2UgPT09IHVuZGVmaW5lZCkpIHtcbiAgICB0aHJvdyBuZXcgQ2hhdEVycm9yKCdpbnZhbGlkX3JlcXVlc3QnKTtcbiAgfVxuICBjb25zdCByZXN1bHQgPSBhd2FpdCByZWFkPEF1dGhvcml6ZWRNZW1iZXJzaGlwPihgXG4gICAgTEVUIHVzZXIgPSBET0NVTUVOVCgndXNlcnMnLCBAdXNlcklkKVxuICAgIExFVCBwZXJzb25hID0gRE9DVU1FTlQoJ3BlcnNvbmFzJywgQHBlcnNvbmFJZClcbiAgICBMRVQgY29udmVyc2F0aW9uID0gRE9DVU1FTlQoJ2NvbnZlcnNhdGlvbnMnLCBAY29udmVyc2F0aW9uSWQpXG4gICAgRklMVEVSIHVzZXIgIT0gbnVsbCBBTkQgdXNlci5hY3RpdmUgIT0gZmFsc2UgQU5EIHBlcnNvbmEgIT0gbnVsbCBBTkQgcGVyc29uYS5hY3RpdmUgIT0gZmFsc2VcbiAgICAgIEFORCBwZXJzb25hLnVzZXJJZCA9PSBAdXNlcklkIEFORCBjb252ZXJzYXRpb24gIT0gbnVsbCBBTkQgY29udmVyc2F0aW9uLmNoYXRTY2hlbWFWZXJzaW9uID09IDFcbiAgICAgIEFORCBjb252ZXJzYXRpb24ua2luZCBJTiBbJ2RpcmVjdCcsICdncm91cCddIEFORCBjb252ZXJzYXRpb24uc3RhdGUgSU4gWydhY3RpdmUnLCAnZm9ybWluZycsICdjbG9zZWQnXVxuICAgIExFVCBtZW1iZXJzaGlwID0gRklSU1QoRk9SIG1lbWJlciBJTiBoYXNDaGF0TWVtYmVyc2hpcFxuICAgICAgRklMVEVSIG1lbWJlci5jb252ZXJzYXRpb25JZCA9PSBAY29udmVyc2F0aW9uSWQgQU5EIG1lbWJlci5wZXJzb25hSWQgPT0gQHBlcnNvbmFJZFxuICAgICAgICBBTkQgbWVtYmVyLnVzZXJJZCA9PSBAdXNlcklkIEFORCBtZW1iZXIuX2Zyb20gPT0gQ09OQ0FUKCdwZXJzb25hcy8nLCBAcGVyc29uYUlkKVxuICAgICAgICBBTkQgbWVtYmVyLl90byA9PSBDT05DQVQoJ2NvbnZlcnNhdGlvbnMvJywgQGNvbnZlcnNhdGlvbklkKVxuICAgICAgICBBTkQgKEBlcG9jaCA9PSBudWxsIE9SIG1lbWJlci5lcG9jaCA9PSBAZXBvY2gpXG4gICAgICAgIEFORCAoQHB1cnBvc2UgPT0gJ3JlcG9ydCcgPyBtZW1iZXIuc3RhdGUgSU4gWydhY3RpdmUnLCAnbGVmdCcsICdyZW1vdmVkJ10gOiBtZW1iZXIuc3RhdGUgPT0gJ2FjdGl2ZScpXG4gICAgICAgIEFORCAoQHNlcXVlbmNlID09IG51bGwgT1IgKElTX05VTUJFUihtZW1iZXIuam9pblNlcXVlbmNlKSBBTkQgQHNlcXVlbmNlID49IG1lbWJlci5qb2luU2VxdWVuY2VcbiAgICAgICAgICBBTkQgQHNlcXVlbmNlIDw9IGNvbnZlcnNhdGlvbi5sYXN0U2VxdWVuY2VcbiAgICAgICAgICBBTkQgKG1lbWJlci5zdGF0ZSA9PSAnYWN0aXZlJyBPUiAoSVNfTlVNQkVSKG1lbWJlci5sZWZ0U2VxdWVuY2UpIEFORCBAc2VxdWVuY2UgPD0gbWVtYmVyLmxlZnRTZXF1ZW5jZSkpKSlcbiAgICAgIFNPUlQgbWVtYmVyLmFjY2VwdGVkQXQgREVTQywgbWVtYmVyLl9rZXkgREVTQyBMSU1JVCAxIFJFVFVSTiBtZW1iZXIpXG4gICAgRklMVEVSIG1lbWJlcnNoaXAgIT0gbnVsbFxuICAgIExFVCBwZWVycyA9IChGT1IgbWVtYmVyIElOIGhhc0NoYXRNZW1iZXJzaGlwXG4gICAgICBGSUxURVIgbWVtYmVyLmNvbnZlcnNhdGlvbklkID09IEBjb252ZXJzYXRpb25JZCBBTkQgbWVtYmVyLnN0YXRlID09ICdhY3RpdmUnXG4gICAgICAgIEFORCBtZW1iZXIucGVyc29uYUlkICE9IEBwZXJzb25hSWQgUkVUVVJOIG1lbWJlcilcbiAgICBMRVQgcGVlciA9IEZJUlNUKHBlZXJzKVxuICAgIExFVCBwZWVyUGVyc29uYSA9IHBlZXIgPT0gbnVsbCA/IG51bGwgOiBET0NVTUVOVCgncGVyc29uYXMnLCBwZWVyLnBlcnNvbmFJZClcbiAgICBMRVQgcGVlclVzZXIgPSBwZWVyID09IG51bGwgPyBudWxsIDogRE9DVU1FTlQoJ3VzZXJzJywgcGVlci51c2VySWQpXG4gICAgTEVUIGJsb2NrZWQgPSBwZWVyID09IG51bGwgPyBmYWxzZSA6IEZJUlNUKEZPUiBlZGdlIElOIGhhc0Nvbm5lY3Rpb24gRklMVEVSIGVkZ2UudHlwZSA9PSAnYmxvY2snXG4gICAgICBBTkQgKChlZGdlLl9mcm9tIElOIFtDT05DQVQoJ3BlcnNvbmFzLycsIEBwZXJzb25hSWQpLCBDT05DQVQoJ3VzZXJzLycsIEB1c2VySWQpXVxuICAgICAgICBBTkQgZWRnZS5fdG8gSU4gW0NPTkNBVCgncGVyc29uYXMvJywgcGVlci5wZXJzb25hSWQpLCBDT05DQVQoJ3VzZXJzLycsIHBlZXIudXNlcklkKV0pXG4gICAgICAgIE9SIChlZGdlLl90byBJTiBbQ09OQ0FUKCdwZXJzb25hcy8nLCBAcGVyc29uYUlkKSwgQ09OQ0FUKCd1c2Vycy8nLCBAdXNlcklkKV1cbiAgICAgICAgQU5EIGVkZ2UuX2Zyb20gSU4gW0NPTkNBVCgncGVyc29uYXMvJywgcGVlci5wZXJzb25hSWQpLCBDT05DQVQoJ3VzZXJzLycsIHBlZXIudXNlcklkKV0pKSBMSU1JVCAxIFJFVFVSTiB0cnVlKVxuICAgIExFVCBmb2xsb3dpbmcgPSBwZWVyID09IG51bGwgPyBmYWxzZSA6IEZJUlNUKEZPUiBlZGdlIElOIGhhc0Nvbm5lY3Rpb25cbiAgICAgIEZJTFRFUiBlZGdlLnR5cGUgPT0gJ2ZvbGxvdycgQU5EIGVkZ2UuYWN0aXZlICE9IGZhbHNlIEFORCBlZGdlLl9mcm9tID09IENPTkNBVCgncGVyc29uYXMvJywgQHBlcnNvbmFJZClcbiAgICAgICAgQU5EIGVkZ2UuX3RvID09IENPTkNBVCgncGVyc29uYXMvJywgcGVlci5wZXJzb25hSWQpIExJTUlUIDEgUkVUVVJOIHRydWUpXG4gICAgTEVUIGZvbGxvd2VkID0gcGVlciA9PSBudWxsID8gZmFsc2UgOiBGSVJTVChGT1IgZWRnZSBJTiBoYXNDb25uZWN0aW9uXG4gICAgICBGSUxURVIgZWRnZS50eXBlID09ICdmb2xsb3cnIEFORCBlZGdlLmFjdGl2ZSAhPSBmYWxzZSBBTkQgZWRnZS5fdG8gPT0gQ09OQ0FUKCdwZXJzb25hcy8nLCBAcGVyc29uYUlkKVxuICAgICAgICBBTkQgZWRnZS5fZnJvbSA9PSBDT05DQVQoJ3BlcnNvbmFzLycsIHBlZXIucGVyc29uYUlkKSBMSU1JVCAxIFJFVFVSTiB0cnVlKVxuICAgIEZJTFRFUiBAcHVycG9zZSBOT1QgSU4gWydzZW5kJywgJ3NvY2tldCddIE9SIChjb252ZXJzYXRpb24uc3RhdGUgPT0gJ2FjdGl2ZSdcbiAgICAgIEFORCAoY29udmVyc2F0aW9uLmtpbmQgIT0gJ2RpcmVjdCcgT1IgKExFTkdUSChwZWVycykgPT0gMSBBTkQgcGVlclBlcnNvbmEgIT0gbnVsbCBBTkQgcGVlclVzZXIgIT0gbnVsbFxuICAgICAgICBBTkQgcGVlclBlcnNvbmEuYWN0aXZlICE9IGZhbHNlIEFORCBwZWVyVXNlci5hY3RpdmUgIT0gZmFsc2UgQU5EIHBlZXJQZXJzb25hLnVzZXJJZCA9PSBwZWVyLnVzZXJJZFxuICAgICAgICBBTkQgYmxvY2tlZCAhPSB0cnVlIEFORCBmb2xsb3dpbmcgPT0gdHJ1ZSBBTkQgZm9sbG93ZWQgPT0gdHJ1ZSkpKVxuICAgIEZJTFRFUiBAcHVycG9zZSAhPSAnaW52aXRlJyBPUiAoY29udmVyc2F0aW9uLmtpbmQgPT0gJ2dyb3VwJyBBTkQgY29udmVyc2F0aW9uLnN0YXRlICE9ICdjbG9zZWQnXG4gICAgICBBTkQgbWVtYmVyc2hpcC5yb2xlIElOIFsnb3duZXInLCAnYWRtaW4nXSlcbiAgICBGSUxURVIgQHB1cnBvc2UgPT0gJ3JlcG9ydCcgT1IgY29udmVyc2F0aW9uLnN0YXRlICE9ICdjbG9zZWQnXG4gICAgUkVUVVJOIHthY3RpdmVNZW1iZXJDb3VudDogY29udmVyc2F0aW9uLmFjdGl2ZU1lbWJlckNvdW50LCBjb252ZXJzYXRpb25JZDogQGNvbnZlcnNhdGlvbklkLFxuICAgICAgY29udmVyc2F0aW9uU3RhdGU6IGNvbnZlcnNhdGlvbi5zdGF0ZSwgZXBvY2g6IG1lbWJlcnNoaXAuZXBvY2gsIGpvaW5TZXF1ZW5jZTogbWVtYmVyc2hpcC5qb2luU2VxdWVuY2UsXG4gICAgICBraW5kOiBjb252ZXJzYXRpb24ua2luZCwgbGFzdFNlcXVlbmNlOiBjb252ZXJzYXRpb24ubGFzdFNlcXVlbmNlLCBsZWZ0U2VxdWVuY2U6IG1lbWJlcnNoaXAubGVmdFNlcXVlbmNlLFxuICAgICAgbWVtYmVyc2hpcFJldmlzaW9uOiBjb252ZXJzYXRpb24ubWVtYmVyc2hpcFJldmlzaW9uLCBwZXJzb25hSWQ6IEBwZXJzb25hSWQsIHJldmlzaW9uOiBtZW1iZXJzaGlwLnJldmlzaW9uLFxuICAgICAgcm9sZTogbWVtYmVyc2hpcC5yb2xlLCBzdGF0ZTogbWVtYmVyc2hpcC5zdGF0ZX1cbiAgYCwge1xuICAgIGNvbnZlcnNhdGlvbklkOiBpbnB1dC5jb252ZXJzYXRpb25JZCwgZXBvY2g6IGlucHV0Lm1lbWJlcnNoaXBFcG9jaCA/PyBudWxsLCBwZXJzb25hSWQ6IGlkZW50aXR5LnBlcnNvbmFJZCxcbiAgICBwdXJwb3NlOiBpbnB1dC5wdXJwb3NlLCBzZXF1ZW5jZTogaW5wdXQubWVzc2FnZVNlcXVlbmNlID8/IG51bGwsIHVzZXJJZDogaWRlbnRpdHkudXNlcklkXG4gIH0pO1xuICBpZighcmVzdWx0IHx8ICFpc0NoYXRJZGVudGlmaWVyKHJlc3VsdC5lcG9jaCkgfHwgIU51bWJlci5pc1NhZmVJbnRlZ2VyKHJlc3VsdC5qb2luU2VxdWVuY2UpXG4gICAgfHwgcmVzdWx0LmpvaW5TZXF1ZW5jZSA8IDAgfHwgIU51bWJlci5pc1NhZmVJbnRlZ2VyKHJlc3VsdC5sYXN0U2VxdWVuY2UpIHx8IHJlc3VsdC5sYXN0U2VxdWVuY2UgPCAwXG4gICAgfHwgIU51bWJlci5pc1NhZmVJbnRlZ2VyKHJlc3VsdC5yZXZpc2lvbikgfHwgcmVzdWx0LnJldmlzaW9uIDwgMVxuICAgIHx8ICFOdW1iZXIuaXNTYWZlSW50ZWdlcihyZXN1bHQubWVtYmVyc2hpcFJldmlzaW9uKSB8fCByZXN1bHQubWVtYmVyc2hpcFJldmlzaW9uIDwgMVxuICAgIHx8ICFOdW1iZXIuaXNTYWZlSW50ZWdlcihyZXN1bHQuYWN0aXZlTWVtYmVyQ291bnQpIHx8IHJlc3VsdC5hY3RpdmVNZW1iZXJDb3VudCA8IDBcbiAgICB8fCByZXN1bHQuYWN0aXZlTWVtYmVyQ291bnQgPiAyNSB8fCAhWydvd25lcicsICdhZG1pbicsICdtZW1iZXInXS5pbmNsdWRlcyhyZXN1bHQucm9sZSkpIHtcbiAgICB0aHJvdyBuZXcgQ2hhdEVycm9yKCdmb3JiaWRkZW4nKTtcbiAgfVxuICByZXR1cm4gcmVzdWx0O1xufTtcblxuZXhwb3J0IGNvbnN0IGF1dGhvcml6ZUNvbnZlcnNhdGlvbkFjY2VzcyA9IChcbiAgY29udGV4dDogQXBpQ29udGV4dCwgaWRlbnRpdHk6IENoYXRJZGVudGl0eSwgaW5wdXQ6IE1lbWJlcnNoaXBBY2Nlc3NJbnB1dFxuKTogUHJvbWlzZTxBdXRob3JpemVkTWVtYmVyc2hpcD4gPT4gY3JlYXRlTWVtYmVyc2hpcEF1dGhvcml6ZXIoXG4gIGNyZWF0ZUR1cmFibGVRdWVyeShjb250ZXh0KVxuKShpZGVudGl0eSwgaW5wdXQpO1xuIl0sIm5hbWVzIjpbIkNoYXRFcnJvciIsImNyZWF0ZUR1cmFibGVRdWVyeSIsImlzQ2hhdElkZW50aWZpZXIiLCJ2YWx1ZSIsInRlc3QiLCJwdXJwb3NlcyIsImNyZWF0ZU1lbWJlcnNoaXBBdXRob3JpemVyIiwicmVhZCIsImlkZW50aXR5IiwiaW5wdXQiLCJ1c2VySWQiLCJwZXJzb25hSWQiLCJjb252ZXJzYXRpb25JZCIsImluY2x1ZGVzIiwicHVycG9zZSIsIm1lbWJlcnNoaXBFcG9jaCIsInVuZGVmaW5lZCIsIm1lc3NhZ2VTZXF1ZW5jZSIsIk51bWJlciIsImlzU2FmZUludGVnZXIiLCJyZXN1bHQiLCJlcG9jaCIsInNlcXVlbmNlIiwiam9pblNlcXVlbmNlIiwibGFzdFNlcXVlbmNlIiwicmV2aXNpb24iLCJtZW1iZXJzaGlwUmV2aXNpb24iLCJhY3RpdmVNZW1iZXJDb3VudCIsInJvbGUiLCJhdXRob3JpemVDb252ZXJzYXRpb25BY2Nlc3MiLCJjb250ZXh0Il0sIm1hcHBpbmdzIjoiQUFBQSxTQUFRQSxTQUFTLFFBQU8sY0FBYztBQUN0QyxTQUFRQyxrQkFBa0IsUUFBTyxtQkFBbUI7QUE0QnBELE9BQU8sTUFBTUMsbUJBQW1CLENBQUNDLFFBQy9CLE9BQU9BLFVBQVUsWUFBWSx5QkFBeUJDLElBQUksQ0FBQ0QsT0FBTztBQUVwRSxNQUFNRSxXQUF3RDtJQUFDO0lBQVc7SUFBVTtJQUFnQjtJQUFVO0lBQVE7Q0FBUztBQUUvSCxPQUFPLE1BQU1DLDZCQUE2QixDQUFDQyxPQUFvQixPQUM3REMsVUFBd0JDO1FBRXhCLElBQUcsQ0FBQ0QsWUFBWSxDQUFDTixpQkFBaUJNLFNBQVNFLE1BQU0sS0FBSyxDQUFDUixpQkFBaUJNLFNBQVNHLFNBQVMsR0FBRztZQUMzRixNQUFNLElBQUlYLFVBQVU7UUFDdEI7UUFDQSxJQUFHLENBQUNTLFNBQVMsQ0FBQ1AsaUJBQWlCTyxNQUFNRyxjQUFjLEtBQUssQ0FBQ1AsU0FBU1EsUUFBUSxDQUFDSixNQUFNSyxPQUFPLEtBQ2xGTCxNQUFNTSxlQUFlLEtBQUtDLGFBQWEsQ0FBQ2QsaUJBQWlCTyxNQUFNTSxlQUFlLEtBQzlFTixNQUFNUSxlQUFlLEtBQUtELGFBQ3hCLENBQUEsQ0FBQ0UsT0FBT0MsYUFBYSxDQUFDVixNQUFNUSxlQUFlLEtBQUtSLE1BQU1RLGVBQWUsR0FBRyxDQUFBLEtBQzFFUixNQUFNSyxPQUFPLEtBQUssWUFBWUwsTUFBTVEsZUFBZSxLQUFLRCxXQUFZO1lBQ3hFLE1BQU0sSUFBSWhCLFVBQVU7UUFDdEI7UUFDQSxNQUFNb0IsU0FBUyxNQUFNYixLQUEyQixDQUFDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztFQStDakQsQ0FBQyxFQUFFO1lBQ0RLLGdCQUFnQkgsTUFBTUcsY0FBYztZQUFFUyxPQUFPWixNQUFNTSxlQUFlLElBQUk7WUFBTUosV0FBV0gsU0FBU0csU0FBUztZQUN6R0csU0FBU0wsTUFBTUssT0FBTztZQUFFUSxVQUFVYixNQUFNUSxlQUFlLElBQUk7WUFBTVAsUUFBUUYsU0FBU0UsTUFBTTtRQUMxRjtRQUNBLElBQUcsQ0FBQ1UsVUFBVSxDQUFDbEIsaUJBQWlCa0IsT0FBT0MsS0FBSyxLQUFLLENBQUNILE9BQU9DLGFBQWEsQ0FBQ0MsT0FBT0csWUFBWSxLQUNyRkgsT0FBT0csWUFBWSxHQUFHLEtBQUssQ0FBQ0wsT0FBT0MsYUFBYSxDQUFDQyxPQUFPSSxZQUFZLEtBQUtKLE9BQU9JLFlBQVksR0FBRyxLQUMvRixDQUFDTixPQUFPQyxhQUFhLENBQUNDLE9BQU9LLFFBQVEsS0FBS0wsT0FBT0ssUUFBUSxHQUFHLEtBQzVELENBQUNQLE9BQU9DLGFBQWEsQ0FBQ0MsT0FBT00sa0JBQWtCLEtBQUtOLE9BQU9NLGtCQUFrQixHQUFHLEtBQ2hGLENBQUNSLE9BQU9DLGFBQWEsQ0FBQ0MsT0FBT08saUJBQWlCLEtBQUtQLE9BQU9PLGlCQUFpQixHQUFHLEtBQzlFUCxPQUFPTyxpQkFBaUIsR0FBRyxNQUFNLENBQUM7WUFBQztZQUFTO1lBQVM7U0FBUyxDQUFDZCxRQUFRLENBQUNPLE9BQU9RLElBQUksR0FBRztZQUN6RixNQUFNLElBQUk1QixVQUFVO1FBQ3RCO1FBQ0EsT0FBT29CO0lBQ1QsRUFBRTtBQUVGLE9BQU8sTUFBTVMsOEJBQThCLENBQ3pDQyxTQUFxQnRCLFVBQXdCQyxRQUNYSCwyQkFDbENMLG1CQUFtQjZCLFVBQ25CdEIsVUFBVUMsT0FBTyJ9
@@ -0,0 +1,76 @@
1
+ import type { AppendChatEventInput } from './events.js';
2
+ import type { AuthorizedMembership, ChatIdentity, ChatQuery } from './membership.js';
3
+ export interface DurableChatAttachment {
4
+ readonly contentVersion: string;
5
+ readonly imageId: string;
6
+ }
7
+ export interface DurableChatMessage<TDecision = unknown> {
8
+ readonly _key: string;
9
+ readonly added: number;
10
+ readonly attachmentIds: readonly string[];
11
+ readonly attachments: readonly DurableChatAttachment[];
12
+ readonly chatSchemaVersion: 1;
13
+ readonly clientMessageId: string;
14
+ readonly content: string;
15
+ readonly contentRevision: number;
16
+ readonly conversationId: string;
17
+ readonly deleted: boolean;
18
+ readonly deletedAuthorProofId?: string;
19
+ readonly mobileContentVersion: string;
20
+ readonly mobileDecision: TDecision;
21
+ readonly mobilePlatformDisposition: string;
22
+ readonly modified: number;
23
+ readonly replyToMessageId?: string;
24
+ readonly revision: number;
25
+ readonly senderPersonaId: string;
26
+ readonly sequence: number;
27
+ readonly userId: string;
28
+ }
29
+ export interface DurableSendMessageInput {
30
+ readonly attachmentIds: readonly string[];
31
+ readonly clientMessageId: string;
32
+ readonly content: string;
33
+ readonly conversationId: string;
34
+ readonly replyToMessageId?: string;
35
+ readonly senderPersonaId: string;
36
+ }
37
+ export interface DurableEditMessageInput {
38
+ readonly content: string;
39
+ readonly conversationId: string;
40
+ readonly expectedRevision: number;
41
+ readonly idempotencyKey: string;
42
+ readonly messageId: string;
43
+ }
44
+ export type DurableDeleteMessageInput = Omit<DurableEditMessageInput, 'content'>;
45
+ export interface DurableMessageAcknowledgement {
46
+ readonly clientMessageId: string;
47
+ readonly messageId: string;
48
+ readonly revision: number;
49
+ readonly sequence: number;
50
+ }
51
+ export interface DurableMessageMutationResult {
52
+ readonly messageId: string;
53
+ readonly revision: number;
54
+ readonly sequence: number;
55
+ }
56
+ export interface DurableContentProjection<TDecision> {
57
+ readonly decision: TDecision;
58
+ readonly platformDisposition?: string;
59
+ }
60
+ export type DurableMessageRun = <T>(operation: (read: ChatQuery) => Promise<T>, write?: boolean) => Promise<T>;
61
+ export interface DurableMessageHooks<TDecision> {
62
+ readonly appendEvent: (read: ChatQuery, input: AppendChatEventInput) => Promise<unknown>;
63
+ readonly authorizeAttachment: (read: ChatQuery, imageId: string) => Promise<DurableChatAttachment>;
64
+ readonly authorizeIdentity: (read: ChatQuery, identity: ChatIdentity) => Promise<void>;
65
+ readonly authorizeMembership: (read: ChatQuery, identity: ChatIdentity, conversationId: string, purpose: 'history' | 'send') => Promise<AuthorizedMembership>;
66
+ readonly authorizeMessageVisible: (read: ChatQuery, identity: ChatIdentity, message: DurableChatMessage<TDecision>, membership: AuthorizedMembership) => Promise<void>;
67
+ readonly classifyContent: (input: {
68
+ readonly content: string;
69
+ readonly contentVersion: string;
70
+ }) => DurableContentProjection<TDecision> | Promise<DurableContentProjection<TDecision>>;
71
+ readonly hash?: (value: unknown) => string;
72
+ readonly identity: ChatIdentity;
73
+ readonly now?: () => number;
74
+ readonly run: DurableMessageRun;
75
+ readonly uuid?: () => string;
76
+ }
@@ -0,0 +1,3 @@
1
+ export { };
2
+
3
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9wcml2YXRlL3RtcC92YXVsdC1yZWFrdG9yLWNvbXBsZXRpb24vcGFja2FnZXMvcmVha3Rvci9zcmMvZHVyYWJsZUNoYXQvbWVzc2FnZVR5cGVzLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlIHtBcHBlbmRDaGF0RXZlbnRJbnB1dH0gZnJvbSAnLi9ldmVudHMuanMnO1xuaW1wb3J0IHR5cGUge0F1dGhvcml6ZWRNZW1iZXJzaGlwLCBDaGF0SWRlbnRpdHksIENoYXRRdWVyeX0gZnJvbSAnLi9tZW1iZXJzaGlwLmpzJztcblxuZXhwb3J0IGludGVyZmFjZSBEdXJhYmxlQ2hhdEF0dGFjaG1lbnQge1xuICByZWFkb25seSBjb250ZW50VmVyc2lvbjogc3RyaW5nO1xuICByZWFkb25seSBpbWFnZUlkOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRHVyYWJsZUNoYXRNZXNzYWdlPFREZWNpc2lvbiA9IHVua25vd24+IHtcbiAgcmVhZG9ubHkgX2tleTogc3RyaW5nO1xuICByZWFkb25seSBhZGRlZDogbnVtYmVyO1xuICByZWFkb25seSBhdHRhY2htZW50SWRzOiByZWFkb25seSBzdHJpbmdbXTtcbiAgcmVhZG9ubHkgYXR0YWNobWVudHM6IHJlYWRvbmx5IER1cmFibGVDaGF0QXR0YWNobWVudFtdO1xuICByZWFkb25seSBjaGF0U2NoZW1hVmVyc2lvbjogMTtcbiAgcmVhZG9ubHkgY2xpZW50TWVzc2FnZUlkOiBzdHJpbmc7XG4gIHJlYWRvbmx5IGNvbnRlbnQ6IHN0cmluZztcbiAgcmVhZG9ubHkgY29udGVudFJldmlzaW9uOiBudW1iZXI7XG4gIHJlYWRvbmx5IGNvbnZlcnNhdGlvbklkOiBzdHJpbmc7XG4gIHJlYWRvbmx5IGRlbGV0ZWQ6IGJvb2xlYW47XG4gIHJlYWRvbmx5IGRlbGV0ZWRBdXRob3JQcm9vZklkPzogc3RyaW5nO1xuICByZWFkb25seSBtb2JpbGVDb250ZW50VmVyc2lvbjogc3RyaW5nO1xuICByZWFkb25seSBtb2JpbGVEZWNpc2lvbjogVERlY2lzaW9uO1xuICByZWFkb25seSBtb2JpbGVQbGF0Zm9ybURpc3Bvc2l0aW9uOiBzdHJpbmc7XG4gIHJlYWRvbmx5IG1vZGlmaWVkOiBudW1iZXI7XG4gIHJlYWRvbmx5IHJlcGx5VG9NZXNzYWdlSWQ/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IHJldmlzaW9uOiBudW1iZXI7XG4gIHJlYWRvbmx5IHNlbmRlclBlcnNvbmFJZDogc3RyaW5nO1xuICByZWFkb25seSBzZXF1ZW5jZTogbnVtYmVyO1xuICByZWFkb25seSB1c2VySWQ6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBEdXJhYmxlU2VuZE1lc3NhZ2VJbnB1dCB7XG4gIHJlYWRvbmx5IGF0dGFjaG1lbnRJZHM6IHJlYWRvbmx5IHN0cmluZ1tdO1xuICByZWFkb25seSBjbGllbnRNZXNzYWdlSWQ6IHN0cmluZztcbiAgcmVhZG9ubHkgY29udGVudDogc3RyaW5nO1xuICByZWFkb25seSBjb252ZXJzYXRpb25JZDogc3RyaW5nO1xuICByZWFkb25seSByZXBseVRvTWVzc2FnZUlkPzogc3RyaW5nO1xuICByZWFkb25seSBzZW5kZXJQZXJzb25hSWQ6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBEdXJhYmxlRWRpdE1lc3NhZ2VJbnB1dCB7XG4gIHJlYWRvbmx5IGNvbnRlbnQ6IHN0cmluZztcbiAgcmVhZG9ubHkgY29udmVyc2F0aW9uSWQ6IHN0cmluZztcbiAgcmVhZG9ubHkgZXhwZWN0ZWRSZXZpc2lvbjogbnVtYmVyO1xuICByZWFkb25seSBpZGVtcG90ZW5jeUtleTogc3RyaW5nO1xuICByZWFkb25seSBtZXNzYWdlSWQ6IHN0cmluZztcbn1cblxuZXhwb3J0IHR5cGUgRHVyYWJsZURlbGV0ZU1lc3NhZ2VJbnB1dCA9IE9taXQ8RHVyYWJsZUVkaXRNZXNzYWdlSW5wdXQsICdjb250ZW50Jz47XG5cbmV4cG9ydCBpbnRlcmZhY2UgRHVyYWJsZU1lc3NhZ2VBY2tub3dsZWRnZW1lbnQge1xuICByZWFkb25seSBjbGllbnRNZXNzYWdlSWQ6IHN0cmluZztcbiAgcmVhZG9ubHkgbWVzc2FnZUlkOiBzdHJpbmc7XG4gIHJlYWRvbmx5IHJldmlzaW9uOiBudW1iZXI7XG4gIHJlYWRvbmx5IHNlcXVlbmNlOiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRHVyYWJsZU1lc3NhZ2VNdXRhdGlvblJlc3VsdCB7XG4gIHJlYWRvbmx5IG1lc3NhZ2VJZDogc3RyaW5nO1xuICByZWFkb25seSByZXZpc2lvbjogbnVtYmVyO1xuICByZWFkb25seSBzZXF1ZW5jZTogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIER1cmFibGVDb250ZW50UHJvamVjdGlvbjxURGVjaXNpb24+IHtcbiAgcmVhZG9ubHkgZGVjaXNpb246IFREZWNpc2lvbjtcbiAgcmVhZG9ubHkgcGxhdGZvcm1EaXNwb3NpdGlvbj86IHN0cmluZztcbn1cblxuZXhwb3J0IHR5cGUgRHVyYWJsZU1lc3NhZ2VSdW4gPSA8VD4ob3BlcmF0aW9uOiAocmVhZDogQ2hhdFF1ZXJ5KSA9PiBQcm9taXNlPFQ+LCB3cml0ZT86IGJvb2xlYW4pID0+IFByb21pc2U8VD47XG5cbmV4cG9ydCBpbnRlcmZhY2UgRHVyYWJsZU1lc3NhZ2VIb29rczxURGVjaXNpb24+IHtcbiAgcmVhZG9ubHkgYXBwZW5kRXZlbnQ6IChyZWFkOiBDaGF0UXVlcnksIGlucHV0OiBBcHBlbmRDaGF0RXZlbnRJbnB1dCkgPT4gUHJvbWlzZTx1bmtub3duPjtcbiAgcmVhZG9ubHkgYXV0aG9yaXplQXR0YWNobWVudDogKHJlYWQ6IENoYXRRdWVyeSwgaW1hZ2VJZDogc3RyaW5nKSA9PiBQcm9taXNlPER1cmFibGVDaGF0QXR0YWNobWVudD47XG4gIHJlYWRvbmx5IGF1dGhvcml6ZUlkZW50aXR5OiAocmVhZDogQ2hhdFF1ZXJ5LCBpZGVudGl0eTogQ2hhdElkZW50aXR5KSA9PiBQcm9taXNlPHZvaWQ+O1xuICByZWFkb25seSBhdXRob3JpemVNZW1iZXJzaGlwOiAoXG4gICAgcmVhZDogQ2hhdFF1ZXJ5LCBpZGVudGl0eTogQ2hhdElkZW50aXR5LCBjb252ZXJzYXRpb25JZDogc3RyaW5nLCBwdXJwb3NlOiAnaGlzdG9yeScgfCAnc2VuZCdcbiAgKSA9PiBQcm9taXNlPEF1dGhvcml6ZWRNZW1iZXJzaGlwPjtcbiAgcmVhZG9ubHkgYXV0aG9yaXplTWVzc2FnZVZpc2libGU6IChcbiAgICByZWFkOiBDaGF0UXVlcnksIGlkZW50aXR5OiBDaGF0SWRlbnRpdHksIG1lc3NhZ2U6IER1cmFibGVDaGF0TWVzc2FnZTxURGVjaXNpb24+LCBtZW1iZXJzaGlwOiBBdXRob3JpemVkTWVtYmVyc2hpcFxuICApID0+IFByb21pc2U8dm9pZD47XG4gIHJlYWRvbmx5IGNsYXNzaWZ5Q29udGVudDogKGlucHV0OiB7XG4gICAgcmVhZG9ubHkgY29udGVudDogc3RyaW5nO1xuICAgIHJlYWRvbmx5IGNvbnRlbnRWZXJzaW9uOiBzdHJpbmc7XG4gIH0pID0+IER1cmFibGVDb250ZW50UHJvamVjdGlvbjxURGVjaXNpb24+IHwgUHJvbWlzZTxEdXJhYmxlQ29udGVudFByb2plY3Rpb248VERlY2lzaW9uPj47XG4gIHJlYWRvbmx5IGhhc2g/OiAodmFsdWU6IHVua25vd24pID0+IHN0cmluZztcbiAgcmVhZG9ubHkgaWRlbnRpdHk6IENoYXRJZGVudGl0eTtcbiAgcmVhZG9ubHkgbm93PzogKCkgPT4gbnVtYmVyO1xuICByZWFkb25seSBydW46IER1cmFibGVNZXNzYWdlUnVuO1xuICByZWFkb25seSB1dWlkPzogKCkgPT4gc3RyaW5nO1xufVxuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQXNFQSxXQW1CQyJ9
@@ -0,0 +1,16 @@
1
+ import type { ChatQuery } from './membership.js';
2
+ import type { DurableChatMessage, DurableDeleteMessageInput, DurableEditMessageInput, DurableMessageAcknowledgement, DurableMessageHooks, DurableMessageMutationResult, DurableSendMessageInput } from './messageTypes.js';
3
+ export declare const readDurableMessage: <TDecision>(read: ChatQuery, conversationId: string, messageId: string) => Promise<DurableChatMessage<TDecision>>;
4
+ export declare const createDurableMessagePersistence: <TDecision>(hooks: DurableMessageHooks<TDecision>) => {
5
+ authorize: (read: ChatQuery, conversationId: string, purpose?: 'history' | 'send') => Promise<import("./membership.js").AuthorizedMembership>;
6
+ deleteMessage: (input: DurableDeleteMessageInput) => Promise<DurableMessageMutationResult>;
7
+ editMessage: (input: DurableEditMessageInput) => Promise<DurableMessageMutationResult>;
8
+ rateLimit: (read: ChatQuery, action: string, limit: number, interval?: number) => Promise<void>;
9
+ receipt: <T>(read: ChatQuery, action: string, conversationId: string, key: string, payload: unknown) => Promise<{
10
+ prior: T;
11
+ save: (result: T) => Promise<boolean>;
12
+ }>;
13
+ run: <T>(operation: (read: ChatQuery) => Promise<T>, write?: boolean) => Promise<T>;
14
+ sendMessage: (input: DurableSendMessageInput) => Promise<DurableMessageAcknowledgement>;
15
+ };
16
+ export type DurableMessagePersistence<TDecision = unknown> = ReturnType<typeof createDurableMessagePersistence<TDecision>>;