@jskit-ai/google-rewarded-core 0.1.1

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 (42) hide show
  1. package/README.md +98 -0
  2. package/docs/protecting-server-actions.md +190 -0
  3. package/package.descriptor.mjs +186 -0
  4. package/package.json +10 -0
  5. package/src/server/GoogleRewardedCoreProvider.js +51 -0
  6. package/src/server/actions.js +102 -0
  7. package/src/server/inputSchemas.js +394 -0
  8. package/src/server/providerConfigs/GoogleRewardedProviderConfigsProvider.js +98 -0
  9. package/src/server/providerConfigs/actions.js +157 -0
  10. package/src/server/providerConfigs/registerRoutes.js +176 -0
  11. package/src/server/providerConfigs/repository.js +107 -0
  12. package/src/server/providerConfigs/service.js +61 -0
  13. package/src/server/registerRoutes.js +169 -0
  14. package/src/server/rules/GoogleRewardedRulesProvider.js +98 -0
  15. package/src/server/rules/actions.js +157 -0
  16. package/src/server/rules/registerRoutes.js +176 -0
  17. package/src/server/rules/repository.js +107 -0
  18. package/src/server/rules/service.js +61 -0
  19. package/src/server/service.js +552 -0
  20. package/src/server/support/requireGoogleRewardedUnlock.js +142 -0
  21. package/src/server/unlockReceipts/GoogleRewardedUnlockReceiptsProvider.js +98 -0
  22. package/src/server/unlockReceipts/actions.js +157 -0
  23. package/src/server/unlockReceipts/registerRoutes.js +176 -0
  24. package/src/server/unlockReceipts/repository.js +107 -0
  25. package/src/server/unlockReceipts/service.js +61 -0
  26. package/src/server/watchSessions/GoogleRewardedWatchSessionsProvider.js +98 -0
  27. package/src/server/watchSessions/actions.js +157 -0
  28. package/src/server/watchSessions/registerRoutes.js +176 -0
  29. package/src/server/watchSessions/repository.js +107 -0
  30. package/src/server/watchSessions/service.js +61 -0
  31. package/src/shared/googleRewardedProviderConfigResource.js +94 -0
  32. package/src/shared/googleRewardedRuleResource.js +136 -0
  33. package/src/shared/googleRewardedUnlockReceiptResource.js +113 -0
  34. package/src/shared/googleRewardedWatchSessionResource.js +139 -0
  35. package/src/shared/index.js +12 -0
  36. package/templates/migrations/google_rewarded_provider_configs_initial.cjs +27 -0
  37. package/templates/migrations/google_rewarded_rules_initial.cjs +31 -0
  38. package/templates/migrations/google_rewarded_unlock_receipts_initial.cjs +35 -0
  39. package/templates/migrations/google_rewarded_watch_sessions_initial.cjs +36 -0
  40. package/test/requireGoogleRewardedUnlock.test.js +274 -0
  41. package/test/routes.test.js +248 -0
  42. package/test/service.test.js +315 -0
@@ -0,0 +1,157 @@
1
+ import {
2
+ composeSchemaDefinitions,
3
+ recordIdParamsValidator
4
+ } from "@jskit-ai/kernel/shared/validators";
5
+ import {
6
+ createCrudCursorPaginationQueryValidator,
7
+ listSearchQueryValidator,
8
+ lookupIncludeQueryValidator,
9
+ createCrudParentFilterQueryValidator
10
+ } from "@jskit-ai/crud-core/server/listQueryValidators";
11
+ import { resource } from "../../shared/googleRewardedRuleResource.js";
12
+ import { workspaceSlugParamsValidator } from "@jskit-ai/workspaces-core/server/validators/routeParamsValidator";
13
+
14
+ const listCursorPaginationQueryValidator = createCrudCursorPaginationQueryValidator({
15
+ orderBy: resource.defaultSort
16
+ });
17
+ const listParentFilterQueryValidator = createCrudParentFilterQueryValidator(resource);
18
+ const actionPermissions = Object.freeze({
19
+ list: "crud.google_rewarded_rules.list",
20
+ view: "crud.google_rewarded_rules.view",
21
+ create: "crud.google_rewarded_rules.create",
22
+ update: "crud.google_rewarded_rules.update",
23
+ delete: "crud.google_rewarded_rules.delete"
24
+ });
25
+
26
+ function createActions({ surface } = {}) {
27
+ return Object.freeze([
28
+ {
29
+ id: "crud.google_rewarded_rules.list",
30
+ version: 1,
31
+ kind: "query",
32
+ channels: ["api", "automation", "internal"],
33
+ surfaces: [surface],
34
+ permission: { require: "all", permissions: [actionPermissions.list] },
35
+ input: composeSchemaDefinitions([
36
+ workspaceSlugParamsValidator,
37
+ listCursorPaginationQueryValidator,
38
+ listSearchQueryValidator,
39
+ listParentFilterQueryValidator,
40
+ lookupIncludeQueryValidator,
41
+ ]),
42
+ output: null,
43
+ idempotency: "none",
44
+ audit: {
45
+ actionName: "crud.google_rewarded_rules.list"
46
+ },
47
+ observability: {},
48
+ async execute(input, context, deps) {
49
+ const { workspaceSlug, ...query } = input || {};
50
+ return deps.googleRewardedRulesService.queryDocuments(query, {
51
+ context
52
+ });
53
+ }
54
+ },
55
+ {
56
+ id: "crud.google_rewarded_rules.view",
57
+ version: 1,
58
+ kind: "query",
59
+ channels: ["api", "automation", "internal"],
60
+ surfaces: [surface],
61
+ permission: { require: "all", permissions: [actionPermissions.view] },
62
+ input: composeSchemaDefinitions([
63
+ workspaceSlugParamsValidator,
64
+ recordIdParamsValidator,
65
+ lookupIncludeQueryValidator,
66
+ ]),
67
+ output: null,
68
+ idempotency: "none",
69
+ audit: {
70
+ actionName: "crud.google_rewarded_rules.view"
71
+ },
72
+ observability: {},
73
+ async execute(input, context, deps) {
74
+ return deps.googleRewardedRulesService.getDocumentById(input.recordId, {
75
+ context,
76
+ include: input.include
77
+ });
78
+ }
79
+ },
80
+ {
81
+ id: "crud.google_rewarded_rules.create",
82
+ version: 1,
83
+ kind: "command",
84
+ channels: ["api", "automation", "internal"],
85
+ surfaces: [surface],
86
+ permission: { require: "all", permissions: [actionPermissions.create] },
87
+ input: composeSchemaDefinitions([
88
+ workspaceSlugParamsValidator,
89
+ resource.operations.create.body,
90
+ ], {
91
+ mode: "create"
92
+ }),
93
+ output: null,
94
+ idempotency: "optional",
95
+ audit: {
96
+ actionName: "crud.google_rewarded_rules.create"
97
+ },
98
+ observability: {},
99
+ async execute(input, context, deps) {
100
+ const { workspaceSlug, ...payload } = input || {};
101
+ return deps.googleRewardedRulesService.createDocument(payload, {
102
+ context
103
+ });
104
+ }
105
+ },
106
+ {
107
+ id: "crud.google_rewarded_rules.update",
108
+ version: 1,
109
+ kind: "command",
110
+ channels: ["api", "automation", "internal"],
111
+ surfaces: [surface],
112
+ permission: { require: "all", permissions: [actionPermissions.update] },
113
+ input: composeSchemaDefinitions([
114
+ workspaceSlugParamsValidator,
115
+ recordIdParamsValidator,
116
+ resource.operations.patch.body,
117
+ ]),
118
+ output: null,
119
+ idempotency: "optional",
120
+ audit: {
121
+ actionName: "crud.google_rewarded_rules.update"
122
+ },
123
+ observability: {},
124
+ async execute(input, context, deps) {
125
+ const { workspaceSlug, recordId, ...patch } = input || {};
126
+ return deps.googleRewardedRulesService.patchDocumentById(recordId, patch, {
127
+ context
128
+ });
129
+ }
130
+ },
131
+ {
132
+ id: "crud.google_rewarded_rules.delete",
133
+ version: 1,
134
+ kind: "command",
135
+ channels: ["api", "automation", "internal"],
136
+ surfaces: [surface],
137
+ permission: { require: "all", permissions: [actionPermissions.delete] },
138
+ input: composeSchemaDefinitions([
139
+ workspaceSlugParamsValidator,
140
+ recordIdParamsValidator,
141
+ ]),
142
+ output: null,
143
+ idempotency: "optional",
144
+ audit: {
145
+ actionName: "crud.google_rewarded_rules.delete"
146
+ },
147
+ observability: {},
148
+ async execute(input, context, deps) {
149
+ return deps.googleRewardedRulesService.deleteDocumentById(input.recordId, {
150
+ context
151
+ });
152
+ }
153
+ }
154
+ ]);
155
+ }
156
+
157
+ export { createActions };
@@ -0,0 +1,176 @@
1
+ import { normalizeSurfaceId } from "@jskit-ai/kernel/shared/surface/registry";
2
+ import { createCrudJsonApiRouteContracts } from "@jskit-ai/crud-core/server/routeContracts";
3
+ import { checkRouteVisibility } from "@jskit-ai/kernel/shared/support/visibility";
4
+ import { resolveScopedApiBasePath } from "@jskit-ai/kernel/shared/surface";
5
+ import { resource } from "../../shared/googleRewardedRuleResource.js";
6
+ import { routeParamsValidator } from "@jskit-ai/workspaces-core/server/validators/routeParamsValidator";
7
+ import { buildWorkspaceInputFromRouteParams } from "@jskit-ai/workspaces-core/server/support/workspaceRouteInput";
8
+
9
+ const {
10
+ listRouteContract,
11
+ viewRouteContract,
12
+ createRouteContract,
13
+ updateRouteContract,
14
+ deleteRouteContract,
15
+ recordRouteParamsValidator
16
+ } = createCrudJsonApiRouteContracts({
17
+ resource,
18
+ routeParamsValidator
19
+ });
20
+
21
+ function registerRoutes(
22
+ app,
23
+ {
24
+ routeOwnershipFilter = "public",
25
+ routeSurface = "",
26
+ routeRelativePath = ""
27
+ } = {}
28
+ ) {
29
+ const router = app.make("jskit.http.router");
30
+ const normalizedRouteSurface = normalizeSurfaceId(routeSurface);
31
+ const routeBase = resolveScopedApiBasePath({
32
+ routeBase: "/w/:workspaceSlug",
33
+ relativePath: routeRelativePath,
34
+ strictParams: false
35
+ });
36
+
37
+ router.register(
38
+ "GET",
39
+ routeBase,
40
+ {
41
+ auth: "required",
42
+ surface: normalizedRouteSurface,
43
+ internal: true,
44
+ visibility: checkRouteVisibility(routeOwnershipFilter),
45
+ meta: {
46
+ tags: ["crud"],
47
+ summary: "List records."
48
+ },
49
+ ...listRouteContract,
50
+ params: routeParamsValidator,
51
+ },
52
+ async function (request, reply) {
53
+ const listInput = {
54
+ ...buildWorkspaceInputFromRouteParams(request.input.params),
55
+ ...(request.input.query || {})
56
+ };
57
+ const response = await request.executeAction({
58
+ actionId: "crud.google_rewarded_rules.list",
59
+ input: listInput
60
+ });
61
+ reply.code(200).send(response);
62
+ }
63
+ );
64
+
65
+ router.register(
66
+ "GET",
67
+ `${routeBase}/:recordId`,
68
+ {
69
+ auth: "required",
70
+ surface: normalizedRouteSurface,
71
+ internal: true,
72
+ visibility: checkRouteVisibility(routeOwnershipFilter),
73
+ meta: {
74
+ tags: ["crud"],
75
+ summary: "View a record."
76
+ },
77
+ ...viewRouteContract,
78
+ params: recordRouteParamsValidator,
79
+ },
80
+ async function (request, reply) {
81
+ const response = await request.executeAction({
82
+ actionId: "crud.google_rewarded_rules.view",
83
+ input: {
84
+ ...buildWorkspaceInputFromRouteParams(request.input.params),
85
+ recordId: request.input.params.recordId,
86
+ ...(request.input.query || {})
87
+ }
88
+ });
89
+ reply.code(200).send(response);
90
+ }
91
+ );
92
+
93
+ router.register(
94
+ "POST",
95
+ routeBase,
96
+ {
97
+ auth: "required",
98
+ surface: normalizedRouteSurface,
99
+ internal: true,
100
+ visibility: checkRouteVisibility(routeOwnershipFilter),
101
+ meta: {
102
+ tags: ["crud"],
103
+ summary: "Create a record."
104
+ },
105
+ ...createRouteContract,
106
+ params: routeParamsValidator,
107
+ },
108
+ async function (request, reply) {
109
+ const response = await request.executeAction({
110
+ actionId: "crud.google_rewarded_rules.create",
111
+ input: {
112
+ ...buildWorkspaceInputFromRouteParams(request.input.params),
113
+ ...(request.input.body || {})
114
+ }
115
+ });
116
+ reply.code(201).send(response);
117
+ }
118
+ );
119
+
120
+ router.register(
121
+ "PATCH",
122
+ `${routeBase}/:recordId`,
123
+ {
124
+ auth: "required",
125
+ surface: normalizedRouteSurface,
126
+ internal: true,
127
+ visibility: checkRouteVisibility(routeOwnershipFilter),
128
+ meta: {
129
+ tags: ["crud"],
130
+ summary: "Update a record."
131
+ },
132
+ ...updateRouteContract,
133
+ params: recordRouteParamsValidator,
134
+ },
135
+ async function (request, reply) {
136
+ const response = await request.executeAction({
137
+ actionId: "crud.google_rewarded_rules.update",
138
+ input: {
139
+ ...buildWorkspaceInputFromRouteParams(request.input.params),
140
+ recordId: request.input.params.recordId,
141
+ ...(request.input.body || {})
142
+ }
143
+ });
144
+ reply.code(200).send(response);
145
+ }
146
+ );
147
+
148
+ router.register(
149
+ "DELETE",
150
+ `${routeBase}/:recordId`,
151
+ {
152
+ auth: "required",
153
+ surface: normalizedRouteSurface,
154
+ internal: true,
155
+ visibility: checkRouteVisibility(routeOwnershipFilter),
156
+ meta: {
157
+ tags: ["crud"],
158
+ summary: "Delete a record."
159
+ },
160
+ ...deleteRouteContract,
161
+ params: recordRouteParamsValidator,
162
+ },
163
+ async function (request, reply) {
164
+ const response = await request.executeAction({
165
+ actionId: "crud.google_rewarded_rules.delete",
166
+ input: {
167
+ ...buildWorkspaceInputFromRouteParams(request.input.params),
168
+ recordId: request.input.params.recordId
169
+ }
170
+ });
171
+ reply.code(204).send(response);
172
+ }
173
+ );
174
+ }
175
+
176
+ export { registerRoutes };
@@ -0,0 +1,107 @@
1
+ import { createWithTransaction } from "@jskit-ai/database-runtime/shared";
2
+ import {
3
+ buildJsonRestQueryParams,
4
+ createJsonApiInputRecord,
5
+ createJsonRestContext,
6
+ returnNullWhenJsonRestResourceMissing
7
+ } from "@jskit-ai/json-rest-api-core/server/jsonRestApiHost";
8
+ import { resource } from "../../shared/googleRewardedRuleResource.js";
9
+ const JSON_REST_SCOPE_NAME = "googleRewardedRules";
10
+
11
+ function createRepository({ api, knex } = {}) {
12
+ const withTransaction = createWithTransaction(knex);
13
+
14
+ async function queryDocuments(query = {}, options = {}) {
15
+ return api.resources.googleRewardedRules.query(
16
+ {
17
+ queryParams: buildJsonRestQueryParams(JSON_REST_SCOPE_NAME, query),
18
+ transaction: options?.trx || null,
19
+ simplified: false
20
+ },
21
+ createJsonRestContext(options?.context || null)
22
+ );
23
+ }
24
+
25
+ async function getDocumentById(recordId, options = {}) {
26
+ return returnNullWhenJsonRestResourceMissing(() =>
27
+ api.resources.googleRewardedRules.get(
28
+ {
29
+ id: recordId,
30
+ queryParams: buildJsonRestQueryParams(JSON_REST_SCOPE_NAME, {}, {
31
+ include: options?.include
32
+ }),
33
+ transaction: options?.trx || null,
34
+ simplified: false
35
+ },
36
+ createJsonRestContext(options?.context || null)
37
+ )
38
+ );
39
+ }
40
+
41
+ async function createDocument(payload = {}, options = {}) {
42
+ return api.resources.googleRewardedRules.post(
43
+ {
44
+ inputRecord: createJsonApiInputRecord(JSON_REST_SCOPE_NAME, payload, {
45
+ resource
46
+ }),
47
+ transaction: options?.trx || null,
48
+ simplified: false
49
+ },
50
+ createJsonRestContext(options?.context || null)
51
+ );
52
+ }
53
+
54
+ async function patchDocumentById(recordId, patch = {}, options = {}) {
55
+ const sourcePatch = patch && typeof patch === "object" && !Array.isArray(patch) ? patch : {};
56
+ if (Object.keys(sourcePatch).length < 1) {
57
+ return getDocumentById(recordId, options);
58
+ }
59
+
60
+ return returnNullWhenJsonRestResourceMissing(() =>
61
+ api.resources.googleRewardedRules.patch(
62
+ {
63
+ id: recordId,
64
+ inputRecord: createJsonApiInputRecord(
65
+ JSON_REST_SCOPE_NAME,
66
+ {
67
+ ...sourcePatch,
68
+ updatedAt: new Date()
69
+ },
70
+ {
71
+ resource
72
+ }
73
+ ),
74
+ transaction: options?.trx || null,
75
+ simplified: false
76
+ },
77
+ createJsonRestContext(options?.context || null)
78
+ )
79
+ );
80
+ }
81
+
82
+ async function deleteDocumentById(recordId, options = {}) {
83
+ return returnNullWhenJsonRestResourceMissing(async () => {
84
+ await api.resources.googleRewardedRules.delete(
85
+ {
86
+ id: recordId,
87
+ transaction: options?.trx || null,
88
+ simplified: false
89
+ },
90
+ createJsonRestContext(options?.context || null)
91
+ );
92
+
93
+ return null;
94
+ });
95
+ }
96
+
97
+ return Object.freeze({
98
+ withTransaction,
99
+ queryDocuments,
100
+ getDocumentById,
101
+ createDocument,
102
+ patchDocumentById,
103
+ deleteDocumentById
104
+ });
105
+ }
106
+
107
+ export { createRepository };
@@ -0,0 +1,61 @@
1
+ import { AppError } from "@jskit-ai/kernel/server/runtime/errors";
2
+ import { returnJsonApiDocument } from "@jskit-ai/http-runtime/shared";
3
+
4
+ function return404IfNotFound(document = null) {
5
+ if (!document) {
6
+ throw new AppError(404, "Document not found.");
7
+ }
8
+ return document;
9
+ }
10
+
11
+ function createService({ googleRewardedRulesRepository } = {}) {
12
+ if (!googleRewardedRulesRepository) {
13
+ throw new TypeError("createService requires googleRewardedRulesRepository.");
14
+ }
15
+
16
+ async function queryDocuments(query = {}, options = {}) {
17
+ return returnJsonApiDocument(await googleRewardedRulesRepository.queryDocuments(query, {
18
+ trx: options?.trx || null,
19
+ context: options?.context || null
20
+ }));
21
+ }
22
+
23
+ async function getDocumentById(recordId, options = {}) {
24
+ return returnJsonApiDocument(return404IfNotFound(await googleRewardedRulesRepository.getDocumentById(recordId, {
25
+ trx: options?.trx || null,
26
+ context: options?.context || null,
27
+ include: options?.include
28
+ })));
29
+ }
30
+
31
+ async function createDocument(payload = {}, options = {}) {
32
+ return returnJsonApiDocument(await googleRewardedRulesRepository.createDocument(payload, {
33
+ trx: options?.trx || null,
34
+ context: options?.context || null
35
+ }));
36
+ }
37
+
38
+ async function patchDocumentById(recordId, payload = {}, options = {}) {
39
+ return returnJsonApiDocument(return404IfNotFound(await googleRewardedRulesRepository.patchDocumentById(recordId, payload, {
40
+ trx: options?.trx || null,
41
+ context: options?.context || null
42
+ })));
43
+ }
44
+
45
+ async function deleteDocumentById(recordId, options = {}) {
46
+ return googleRewardedRulesRepository.deleteDocumentById(recordId, {
47
+ trx: options?.trx || null,
48
+ context: options?.context || null
49
+ });
50
+ }
51
+
52
+ return Object.freeze({
53
+ queryDocuments,
54
+ getDocumentById,
55
+ createDocument,
56
+ patchDocumentById,
57
+ deleteDocumentById
58
+ });
59
+ }
60
+
61
+ export { createService };