@jskit-ai/rewarded-core 0.1.120

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.
@@ -0,0 +1,69 @@
1
+ import { defineCrudJsonApiFeature } from "@jskit-ai/crud-core/server/defineCrudJsonApiFeature";
2
+ import { routeParamsValidator } from "@jskit-ai/workspaces-core/server/validators/routeParamsValidator";
3
+ import { workspaceSlugParamsValidator } from "@jskit-ai/workspaces-core/server/validators/routeParamsValidator";
4
+ import { buildWorkspaceInputFromRouteParams } from "@jskit-ai/workspaces-core/server/support/workspaceRouteInput";
5
+ import { resource as providerConfigResource } from "../shared/rewardedProviderConfigResource.js";
6
+ import { resource as ruleResource } from "../shared/rewardedRuleResource.js";
7
+ import { resource as unlockReceiptResource } from "../shared/rewardedUnlockReceiptResource.js";
8
+ import { resource as watchSessionResource } from "../shared/rewardedWatchSessionResource.js";
9
+
10
+ function workspaceScope() {
11
+ return {
12
+ routeBase: "/w/:workspaceSlug",
13
+ actionInputValidator: workspaceSlugParamsValidator,
14
+ routeParamsValidator,
15
+ inputKeys: ["workspaceSlug"],
16
+ input: (request) => buildWorkspaceInputFromRouteParams(request.input.params)
17
+ };
18
+ }
19
+
20
+ const RewardedRulesFeature = defineCrudJsonApiFeature({
21
+ id: "rewarded.rules",
22
+ capability: "rewarded.rules",
23
+ resource: ruleResource,
24
+ surface: "admin",
25
+ ownershipFilter: "workspace",
26
+ relativePath: "/rewarded-rules",
27
+ internal: true,
28
+ scope: workspaceScope()
29
+ });
30
+
31
+ const RewardedProviderConfigsFeature = defineCrudJsonApiFeature({
32
+ id: "rewarded.provider-configs",
33
+ capability: "rewarded.provider-configs",
34
+ resource: providerConfigResource,
35
+ surface: "admin",
36
+ ownershipFilter: "workspace",
37
+ relativePath: "/rewarded-provider-configs",
38
+ internal: true,
39
+ scope: workspaceScope()
40
+ });
41
+
42
+ const RewardedWatchSessionsFeature = defineCrudJsonApiFeature({
43
+ id: "rewarded.watch-sessions",
44
+ capability: "rewarded.watch-sessions",
45
+ resource: watchSessionResource,
46
+ surface: "admin",
47
+ ownershipFilter: "workspace_user",
48
+ relativePath: "/rewarded-watch-sessions",
49
+ internal: true,
50
+ scope: workspaceScope()
51
+ });
52
+
53
+ const RewardedUnlockReceiptsFeature = defineCrudJsonApiFeature({
54
+ id: "rewarded.unlock-receipts",
55
+ capability: "rewarded.unlock-receipts",
56
+ resource: unlockReceiptResource,
57
+ surface: "admin",
58
+ ownershipFilter: "workspace_user",
59
+ relativePath: "/rewarded-unlock-receipts",
60
+ internal: true,
61
+ scope: workspaceScope()
62
+ });
63
+
64
+ export {
65
+ RewardedProviderConfigsFeature,
66
+ RewardedRulesFeature,
67
+ RewardedUnlockReceiptsFeature,
68
+ RewardedWatchSessionsFeature
69
+ };
@@ -0,0 +1,152 @@
1
+ import {
2
+ currentQueryInputValidator,
3
+ startCommandInputValidator,
4
+ grantCommandInputValidator,
5
+ closeCommandInputValidator,
6
+ currentStateOutputValidator,
7
+ startGateOutputValidator,
8
+ grantRewardOutputValidator,
9
+ closeSessionOutputValidator
10
+ } from "./inputSchemas.js";
11
+ import { createEntityChangedActionEvent } from "@jskit-ai/kernel/server/actions";
12
+ import { resolveCrudRecordChangedEvent } from "@jskit-ai/resource-crud-core/shared/crudNamespaceSupport";
13
+
14
+ const ACTION_CURRENT = "rewarded.current.read";
15
+ const ACTION_START = "rewarded.start";
16
+ const ACTION_GRANT = "rewarded.grant";
17
+ const ACTION_CLOSE = "rewarded.close";
18
+
19
+ const watchSessionChanged = resolveCrudRecordChangedEvent("rewarded_watch_sessions");
20
+ const unlockReceiptChanged = resolveCrudRecordChangedEvent("rewarded_unlock_receipts");
21
+
22
+ function changedEvent({ entity, operation, entityId, event }) {
23
+ return createEntityChangedActionEvent({
24
+ source: "rewarded",
25
+ entity,
26
+ operation,
27
+ entityId,
28
+ realtime: { event, audience: "event_scope" }
29
+ });
30
+ }
31
+
32
+ function createRewardedActions({ rewarded } = {}) {
33
+ if (!rewarded) {
34
+ throw new TypeError("createRewardedActions requires rewarded.");
35
+ }
36
+ return Object.freeze([
37
+ {
38
+ id: ACTION_CURRENT,
39
+ version: 1,
40
+ kind: "query",
41
+ channels: ["api", "automation", "internal"],
42
+ surfaces: ["app"],
43
+ permission: { require: "authenticated" },
44
+ input: currentQueryInputValidator,
45
+ output: currentStateOutputValidator,
46
+ idempotency: "none",
47
+ audit: {
48
+ actionName: ACTION_CURRENT
49
+ },
50
+ observability: {},
51
+ async execute(input, context) {
52
+ return rewarded.getCurrentState(input, {
53
+ context
54
+ });
55
+ }
56
+ },
57
+ {
58
+ id: ACTION_START,
59
+ version: 1,
60
+ kind: "command",
61
+ channels: ["api", "automation", "internal"],
62
+ surfaces: ["app"],
63
+ permission: { require: "authenticated" },
64
+ input: startCommandInputValidator,
65
+ output: startGateOutputValidator,
66
+ idempotency: "optional",
67
+ audit: {
68
+ actionName: ACTION_START
69
+ },
70
+ observability: {},
71
+ events: [changedEvent({
72
+ entity: "watch-session",
73
+ operation: "created",
74
+ entityId: ({ result }) => result?.session?.id,
75
+ event: watchSessionChanged
76
+ })],
77
+ async execute(input, context) {
78
+ return rewarded.startGate(input, {
79
+ context
80
+ });
81
+ }
82
+ },
83
+ {
84
+ id: ACTION_GRANT,
85
+ version: 1,
86
+ kind: "command",
87
+ channels: ["api", "automation", "internal"],
88
+ surfaces: ["app"],
89
+ permission: { require: "authenticated" },
90
+ input: grantCommandInputValidator,
91
+ output: grantRewardOutputValidator,
92
+ idempotency: "optional",
93
+ audit: {
94
+ actionName: ACTION_GRANT
95
+ },
96
+ observability: {},
97
+ events: [
98
+ changedEvent({
99
+ entity: "watch-session",
100
+ operation: "updated",
101
+ entityId: ({ result }) => result?.session?.id,
102
+ event: watchSessionChanged
103
+ }),
104
+ changedEvent({
105
+ entity: "unlock-receipt",
106
+ operation: "created",
107
+ entityId: ({ result }) => result?.unlock?.id,
108
+ event: unlockReceiptChanged
109
+ })
110
+ ],
111
+ async execute(input, context) {
112
+ return rewarded.grantReward(input, {
113
+ context
114
+ });
115
+ }
116
+ },
117
+ {
118
+ id: ACTION_CLOSE,
119
+ version: 1,
120
+ kind: "command",
121
+ channels: ["api", "automation", "internal"],
122
+ surfaces: ["app"],
123
+ permission: { require: "authenticated" },
124
+ input: closeCommandInputValidator,
125
+ output: closeSessionOutputValidator,
126
+ idempotency: "optional",
127
+ audit: {
128
+ actionName: ACTION_CLOSE
129
+ },
130
+ observability: {},
131
+ events: [changedEvent({
132
+ entity: "watch-session",
133
+ operation: "updated",
134
+ entityId: ({ result }) => result?.session?.id,
135
+ event: watchSessionChanged
136
+ })],
137
+ async execute(input, context) {
138
+ return rewarded.closeSession(input, {
139
+ context
140
+ });
141
+ }
142
+ }
143
+ ]);
144
+ }
145
+
146
+ export {
147
+ ACTION_CURRENT,
148
+ ACTION_START,
149
+ ACTION_GRANT,
150
+ ACTION_CLOSE,
151
+ createRewardedActions
152
+ };
@@ -0,0 +1,394 @@
1
+ import { createSchema } from "json-rest-schema";
2
+ import { deepFreeze } from "@jskit-ai/kernel/shared/support/deepFreeze";
3
+
4
+ const gateQuerySchema = createSchema({
5
+ gateKey: {
6
+ type: "string",
7
+ required: true,
8
+ minLength: 1,
9
+ maxLength: 120
10
+ },
11
+ workspaceSlug: {
12
+ type: "string",
13
+ required: false,
14
+ minLength: 1,
15
+ maxLength: 120
16
+ }
17
+ });
18
+
19
+ const currentQueryInputValidator = deepFreeze({
20
+ schema: gateQuerySchema,
21
+ mode: "patch"
22
+ });
23
+
24
+ const startCommandInputValidator = deepFreeze({
25
+ schema: gateQuerySchema,
26
+ mode: "patch"
27
+ });
28
+
29
+ const grantCommandInputValidator = deepFreeze({
30
+ schema: createSchema({
31
+ sessionId: {
32
+ type: "id",
33
+ required: true
34
+ },
35
+ workspaceSlug: {
36
+ type: "string",
37
+ required: false,
38
+ minLength: 1,
39
+ maxLength: 120
40
+ }
41
+ }),
42
+ mode: "patch"
43
+ });
44
+
45
+ const closeCommandInputValidator = deepFreeze({
46
+ schema: createSchema({
47
+ sessionId: {
48
+ type: "id",
49
+ required: true
50
+ },
51
+ workspaceSlug: {
52
+ type: "string",
53
+ required: false,
54
+ minLength: 1,
55
+ maxLength: 120
56
+ }
57
+ }),
58
+ mode: "patch"
59
+ });
60
+
61
+ const gateRuleOutputSchema = createSchema({
62
+ id: {
63
+ type: "string",
64
+ required: false,
65
+ nullable: true,
66
+ minLength: 1
67
+ },
68
+ gateKey: {
69
+ type: "string",
70
+ required: true,
71
+ minLength: 1,
72
+ maxLength: 120
73
+ },
74
+ surface: {
75
+ type: "string",
76
+ required: true,
77
+ minLength: 1,
78
+ maxLength: 64
79
+ },
80
+ enabled: {
81
+ type: "boolean",
82
+ required: true
83
+ },
84
+ unlockMinutes: {
85
+ type: "integer",
86
+ required: true,
87
+ min: 0
88
+ },
89
+ cooldownMinutes: {
90
+ type: "integer",
91
+ required: true,
92
+ min: 0
93
+ },
94
+ dailyLimit: {
95
+ type: "integer",
96
+ required: false,
97
+ nullable: true,
98
+ min: 0
99
+ },
100
+ title: {
101
+ type: "string",
102
+ required: true
103
+ },
104
+ description: {
105
+ type: "string",
106
+ required: true
107
+ }
108
+ });
109
+
110
+ const providerConfigOutputSchema = createSchema({
111
+ id: {
112
+ type: "string",
113
+ required: false,
114
+ nullable: true,
115
+ minLength: 1
116
+ },
117
+ surface: {
118
+ type: "string",
119
+ required: true,
120
+ minLength: 1,
121
+ maxLength: 64
122
+ },
123
+ enabled: {
124
+ type: "boolean",
125
+ required: true
126
+ },
127
+ placement: {
128
+ type: "string",
129
+ required: true
130
+ },
131
+ provider: {
132
+ type: "string",
133
+ required: true
134
+ }
135
+ });
136
+
137
+ const watchSessionOutputSchema = createSchema({
138
+ id: {
139
+ type: "string",
140
+ required: false,
141
+ nullable: true,
142
+ minLength: 1
143
+ },
144
+ gateKey: {
145
+ type: "string",
146
+ required: true,
147
+ minLength: 1,
148
+ maxLength: 120
149
+ },
150
+ providerConfigId: {
151
+ type: "string",
152
+ required: false,
153
+ nullable: true,
154
+ minLength: 1
155
+ },
156
+ status: {
157
+ type: "string",
158
+ required: true,
159
+ minLength: 1
160
+ },
161
+ startedAt: {
162
+ type: "string",
163
+ required: false,
164
+ nullable: true,
165
+ minLength: 1
166
+ },
167
+ rewardedAt: {
168
+ type: "string",
169
+ required: false,
170
+ nullable: true,
171
+ minLength: 1
172
+ },
173
+ completedAt: {
174
+ type: "string",
175
+ required: false,
176
+ nullable: true,
177
+ minLength: 1
178
+ },
179
+ closedAt: {
180
+ type: "string",
181
+ required: false,
182
+ nullable: true,
183
+ minLength: 1
184
+ }
185
+ });
186
+
187
+ const unlockReceiptOutputSchema = createSchema({
188
+ id: {
189
+ type: "string",
190
+ required: false,
191
+ nullable: true,
192
+ minLength: 1
193
+ },
194
+ gateKey: {
195
+ type: "string",
196
+ required: true,
197
+ minLength: 1,
198
+ maxLength: 120
199
+ },
200
+ providerConfigId: {
201
+ type: "string",
202
+ required: false,
203
+ nullable: true,
204
+ minLength: 1
205
+ },
206
+ watchSessionId: {
207
+ type: "string",
208
+ required: false,
209
+ nullable: true,
210
+ minLength: 1
211
+ },
212
+ grantedAt: {
213
+ type: "string",
214
+ required: false,
215
+ nullable: true,
216
+ minLength: 1
217
+ },
218
+ unlockedUntil: {
219
+ type: "string",
220
+ required: false,
221
+ nullable: true,
222
+ minLength: 1
223
+ }
224
+ });
225
+
226
+ function createGateStateOutputValidator({
227
+ includeSession = false
228
+ } = {}) {
229
+ const fields = {
230
+ gateKey: {
231
+ type: "string",
232
+ required: true,
233
+ minLength: 1,
234
+ maxLength: 120
235
+ },
236
+ workspaceSlug: {
237
+ type: "string",
238
+ required: true,
239
+ minLength: 1,
240
+ maxLength: 120
241
+ },
242
+ surface: {
243
+ type: "string",
244
+ required: true,
245
+ minLength: 1,
246
+ maxLength: 64
247
+ },
248
+ enabled: {
249
+ type: "boolean",
250
+ required: true
251
+ },
252
+ available: {
253
+ type: "boolean",
254
+ required: true
255
+ },
256
+ blocked: {
257
+ type: "boolean",
258
+ required: true
259
+ },
260
+ reason: {
261
+ type: "string",
262
+ required: true,
263
+ minLength: 1
264
+ },
265
+ rule: {
266
+ type: "object",
267
+ required: false,
268
+ nullable: true,
269
+ schema: gateRuleOutputSchema
270
+ },
271
+ providerConfig: {
272
+ type: "object",
273
+ required: false,
274
+ nullable: true,
275
+ schema: providerConfigOutputSchema
276
+ },
277
+ unlock: {
278
+ type: "object",
279
+ required: false,
280
+ nullable: true,
281
+ schema: unlockReceiptOutputSchema
282
+ },
283
+ cooldownUntil: {
284
+ type: "string",
285
+ required: false,
286
+ nullable: true,
287
+ minLength: 1
288
+ },
289
+ dailyLimitRemaining: {
290
+ type: "integer",
291
+ required: false,
292
+ nullable: true,
293
+ min: 0
294
+ }
295
+ };
296
+
297
+ if (includeSession === true) {
298
+ fields.session = {
299
+ type: "object",
300
+ required: false,
301
+ nullable: true,
302
+ schema: watchSessionOutputSchema
303
+ };
304
+ }
305
+
306
+ return deepFreeze({
307
+ schema: createSchema(fields),
308
+ mode: "replace"
309
+ });
310
+ }
311
+
312
+ const currentStateOutputValidator = createGateStateOutputValidator();
313
+ const startGateOutputValidator = createGateStateOutputValidator({
314
+ includeSession: true
315
+ });
316
+
317
+ const grantRewardOutputValidator = deepFreeze({
318
+ schema: createSchema({
319
+ unlocked: {
320
+ type: "boolean",
321
+ required: true
322
+ },
323
+ workspaceSlug: {
324
+ type: "string",
325
+ required: true,
326
+ minLength: 1,
327
+ maxLength: 120
328
+ },
329
+ gateKey: {
330
+ type: "string",
331
+ required: true,
332
+ minLength: 1,
333
+ maxLength: 120
334
+ },
335
+ unlock: {
336
+ type: "object",
337
+ required: false,
338
+ nullable: true,
339
+ schema: unlockReceiptOutputSchema
340
+ },
341
+ session: {
342
+ type: "object",
343
+ required: false,
344
+ nullable: true,
345
+ schema: watchSessionOutputSchema
346
+ }
347
+ }),
348
+ mode: "replace"
349
+ });
350
+
351
+ const closeSessionOutputValidator = deepFreeze({
352
+ schema: createSchema({
353
+ closed: {
354
+ type: "boolean",
355
+ required: true
356
+ },
357
+ workspaceSlug: {
358
+ type: "string",
359
+ required: true,
360
+ minLength: 1,
361
+ maxLength: 120
362
+ },
363
+ gateKey: {
364
+ type: "string",
365
+ required: true,
366
+ minLength: 1,
367
+ maxLength: 120
368
+ },
369
+ session: {
370
+ type: "object",
371
+ required: false,
372
+ nullable: true,
373
+ schema: watchSessionOutputSchema
374
+ },
375
+ reason: {
376
+ type: "string",
377
+ required: false,
378
+ nullable: true,
379
+ minLength: 1
380
+ }
381
+ }),
382
+ mode: "replace"
383
+ });
384
+
385
+ export {
386
+ currentQueryInputValidator,
387
+ startCommandInputValidator,
388
+ grantCommandInputValidator,
389
+ closeCommandInputValidator,
390
+ currentStateOutputValidator,
391
+ startGateOutputValidator,
392
+ grantRewardOutputValidator,
393
+ closeSessionOutputValidator
394
+ };