@jskit-ai/agent-docs 0.1.257 → 0.1.258
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/guide/agent/app-extras/assistant-conversation.md +88 -35
- package/guide/agent/app-extras/assistant.md +28 -28
- package/guide/agent/app-setup/authentication.md +36 -17
- package/guide/agent/app-setup/database-layer.md +116 -17
- package/guide/agent/app-setup/existing-application-migration.md +29 -25
- package/guide/agent/app-setup/multi-homing.md +94 -48
- package/guide/agent/app-setup/run-an-accounts-hub.md +6 -4
- package/guide/agent/framework/client-features.md +496 -0
- package/guide/agent/framework/crud-operations.md +5 -5
- package/guide/agent/framework/translation.md +4 -3
- package/guide/agent/framework/typed-features.md +1104 -0
- package/guide/agent/framework/ui-operations.md +2 -2
- package/guide/agent/index.md +6 -1
- package/package.json +1 -1
- package/patterns/feature-package/PATTERN.md +104 -10
- package/patterns/feature-package/example/booking-engine/package.json +9 -4
- package/patterns/feature-package/example/booking-engine/src/server/BookingEngineFeature.js +24 -0
- package/patterns/feature-package/example/booking-engine/src/server/bookingAvailability.js +10 -0
- package/patterns/feature-package/example/booking-engine/src/server/bookingEngine.js +29 -0
- package/patterns/feature-package/example/booking-engine/src/server/bookingEngineActions.js +26 -0
- package/patterns/feature-package/example/booking-engine/src/server/inputSchemas.js +1 -2
- package/patterns/feature-package/example/booking-engine/src/server/types.js +12 -0
- package/patterns/feature-package/example/variations/AvailabilityEngineFeature.js +19 -0
- package/patterns/feature-package/example/variations/InvoiceRollupFeature.js +23 -0
- package/patterns/feature-package/example/variations/availabilityEngineActions.js +26 -0
- package/patterns/feature-package/example/variations/customKnexRepository.js +32 -26
- package/patterns/feature-package/example/variations/invoiceRollupActions.js +26 -0
- package/patterns/feature-package/example/variations/orchestratorService.js +24 -19
- package/patterns/feature-package/example/variations/types.js +7 -0
- package/patterns/minimal-foundation/PATTERN.md +30 -1
- package/patterns/minimal-foundation/example/AGENTS.md +14 -0
- package/patterns/minimal-foundation/example/bin/develop.js +10 -5
- package/patterns/minimal-foundation/example/eslint.config.mjs +21 -2
- package/patterns/minimal-foundation/example/package.json +5 -4
- package/patterns/minimal-foundation/example/playwright.config.mjs +1 -1
- package/patterns/minimal-foundation/example/server/lib/envFile.js +19 -0
- package/patterns/minimal-foundation/example/server/lib/loggerOptions.js +15 -0
- package/patterns/minimal-foundation/example/server/lib/runtimeEnv.js +17 -17
- package/patterns/minimal-foundation/example/server.js +32 -29
- package/patterns/minimal-foundation/example/tests/server/smoke.test.js +2 -1
- package/patterns/shell-foundation/PATTERN.md +29 -0
- package/patterns/shell-foundation/example/AGENTS.md +14 -0
- package/patterns/shell-foundation/example/bin/develop.js +10 -5
- package/patterns/shell-foundation/example/eslint.config.mjs +21 -2
- package/patterns/shell-foundation/example/package.json +6 -5
- package/patterns/shell-foundation/example/packages/main/package.json +1 -1
- package/patterns/shell-foundation/example/packages/main/src/client/providers/MainClientProvider.js +1 -0
- package/patterns/shell-foundation/example/playwright.config.mjs +1 -1
- package/patterns/shell-foundation/example/server/lib/envFile.js +19 -0
- package/patterns/shell-foundation/example/server/lib/loggerOptions.js +15 -0
- package/patterns/shell-foundation/example/server/lib/runtimeEnv.js +17 -17
- package/patterns/shell-foundation/example/server.js +32 -29
- package/patterns/shell-foundation/example/tests/server/smoke.test.js +2 -1
- package/reference/autogen/KERNEL_MAP.md +14 -8
- package/reference/autogen/PATTERN_INDEX.md +37 -37
- package/reference/autogen/README.md +2 -0
- package/reference/autogen/packages/agent-docs.md +70 -26
- package/reference/autogen/packages/agent-runtime.md +129 -0
- package/reference/autogen/packages/agent.md +149 -0
- package/reference/autogen/packages/architecture-inspector.md +97 -44
- package/reference/autogen/packages/assistant-core.md +786 -292
- package/reference/autogen/packages/assistant-runtime.md +182 -57
- package/reference/autogen/packages/assistant-voice-sherpa.md +4 -0
- package/reference/autogen/packages/assistant-voice.md +54 -8
- package/reference/autogen/packages/auth-core.md +44 -13
- package/reference/autogen/packages/auth-provider-local-core.md +86 -34
- package/reference/autogen/packages/auth-provider-local-db-core.md +1 -2
- package/reference/autogen/packages/auth-provider-oidc-core.md +10 -4
- package/reference/autogen/packages/auth-provider-supabase-core.md +52 -66
- package/reference/autogen/packages/auth-web.md +19 -11
- package/reference/autogen/packages/connectors-catalog.md +71 -43
- package/reference/autogen/packages/connectors-core.md +42 -4
- package/reference/autogen/packages/console-core.md +27 -14
- package/reference/autogen/packages/crud-core.md +178 -170
- package/reference/autogen/packages/database-runtime-mysql.md +0 -2
- package/reference/autogen/packages/database-runtime-postgres.md +0 -2
- package/reference/autogen/packages/database-runtime.md +39 -10
- package/reference/autogen/packages/http-runtime.md +79 -57
- package/reference/autogen/packages/json-rest-api-core.md +11 -8
- package/reference/autogen/packages/kernel.md +144 -83
- package/reference/autogen/packages/oidc-issuer-core.md +49 -20
- package/reference/autogen/packages/payments-core.md +20 -3
- package/reference/autogen/packages/realtime.md +47 -22
- package/reference/autogen/packages/resource-core.md +1 -1
- package/reference/autogen/packages/resource-crud-core.md +64 -26
- package/reference/autogen/packages/rewarded-core.md +47 -36
- package/reference/autogen/packages/shell-web.md +7 -10
- package/reference/autogen/packages/storage-runtime.md +6 -2
- package/reference/autogen/packages/uploads-runtime.md +10 -2
- package/reference/autogen/packages/users-core.md +73 -71
- package/reference/autogen/packages/workspaces-core.md +121 -106
- package/reference/autogen/packages/workspaces-web.md +1 -2
- package/reference/autogen/tooling/config-eslint.md +302 -0
- package/reference/autogen/tooling/jskit-catalog.md +28 -18
- package/reference/autogen/tooling/jskit-release.md +35 -20
- package/reference/autogen/tooling/testUtils.md +3 -1
- package/skills/jskit/SKILL.md +3 -2
- package/skills/jskit/references/app-operations.md +1 -1
- package/skills/jskit/references/client-features.md +491 -0
- package/skills/jskit/references/crud-form-actions.md +1 -1
- package/skills/jskit/references/crud-operations.md +7 -7
- package/skills/jskit/references/existing-application-migration.md +31 -27
- package/skills/jskit/references/heuristics/INDEX.md +5 -1
- package/skills/jskit/references/heuristics/child-cruds.md +1 -1
- package/skills/jskit/references/heuristics/client-features.md +66 -0
- package/skills/jskit/references/heuristics/client-requests.md +1 -1
- package/skills/jskit/references/heuristics/crud-authoring.md +12 -2
- package/skills/jskit/references/heuristics/crud-links.md +1 -1
- package/skills/jskit/references/heuristics/crud-repository-mapping.md +3 -3
- package/skills/jskit/references/heuristics/filters.md +1 -1
- package/skills/jskit/references/heuristics/live-actions.md +1 -1
- package/skills/jskit/references/heuristics/page-redirects.md +1 -1
- package/skills/jskit/references/heuristics/page-scaffolding.md +1 -1
- package/skills/jskit/references/heuristics/placements.md +1 -1
- package/skills/jskit/references/heuristics/row-policies.md +1 -1
- package/skills/jskit/references/heuristics/server-search.md +1 -1
- package/skills/jskit/references/heuristics/surfaces.md +1 -1
- package/skills/jskit/references/heuristics/typed-features.md +100 -0
- package/skills/jskit/references/heuristics/ui-contract.md +1 -1
- package/skills/jskit/references/heuristics/ui-testing.md +4 -4
- package/skills/jskit/references/material-3.md +2 -2
- package/skills/jskit/references/multi-homing.md +96 -50
- package/skills/jskit/references/pattern-index.md +37 -37
- package/skills/jskit/references/patterns/app/minimal-foundation/PATTERN.md +30 -1
- package/skills/jskit/references/patterns/app/minimal-foundation/example/AGENTS.md +14 -0
- package/skills/jskit/references/patterns/app/minimal-foundation/example/bin/develop.js +10 -5
- package/skills/jskit/references/patterns/app/minimal-foundation/example/eslint.config.mjs +21 -2
- package/skills/jskit/references/patterns/app/minimal-foundation/example/package.json +5 -4
- package/skills/jskit/references/patterns/app/minimal-foundation/example/playwright.config.mjs +1 -1
- package/skills/jskit/references/patterns/app/minimal-foundation/example/server/lib/envFile.js +19 -0
- package/skills/jskit/references/patterns/app/minimal-foundation/example/server/lib/loggerOptions.js +15 -0
- package/skills/jskit/references/patterns/app/minimal-foundation/example/server/lib/runtimeEnv.js +17 -17
- package/skills/jskit/references/patterns/app/minimal-foundation/example/server.js +32 -29
- package/skills/jskit/references/patterns/app/minimal-foundation/example/tests/server/smoke.test.js +2 -1
- package/skills/jskit/references/patterns/app/shell-foundation/PATTERN.md +29 -0
- package/skills/jskit/references/patterns/app/shell-foundation/example/AGENTS.md +14 -0
- package/skills/jskit/references/patterns/app/shell-foundation/example/bin/develop.js +10 -5
- package/skills/jskit/references/patterns/app/shell-foundation/example/eslint.config.mjs +21 -2
- package/skills/jskit/references/patterns/app/shell-foundation/example/package.json +6 -5
- package/skills/jskit/references/patterns/app/shell-foundation/example/packages/main/package.json +1 -1
- package/skills/jskit/references/patterns/app/shell-foundation/example/packages/main/src/client/providers/MainClientProvider.js +1 -0
- package/skills/jskit/references/patterns/app/shell-foundation/example/playwright.config.mjs +1 -1
- package/skills/jskit/references/patterns/app/shell-foundation/example/server/lib/envFile.js +19 -0
- package/skills/jskit/references/patterns/app/shell-foundation/example/server/lib/loggerOptions.js +15 -0
- package/skills/jskit/references/patterns/app/shell-foundation/example/server/lib/runtimeEnv.js +17 -17
- package/skills/jskit/references/patterns/app/shell-foundation/example/server.js +32 -29
- package/skills/jskit/references/patterns/app/shell-foundation/example/tests/server/smoke.test.js +2 -1
- package/skills/jskit/references/patterns/assistant/assistant-surface/example/src/ApplicationAiFeature.js +4 -2
- package/skills/jskit/references/patterns/auth/accounts-hub/PATTERN.md +2 -1
- package/skills/jskit/references/patterns/auth/accounts-hub/example/package.json +2 -2
- package/skills/jskit/references/patterns/auth/accounts-hub/example/server/hubPaths.js +9 -3
- package/skills/jskit/references/patterns/auth/auth-surface/PATTERN.md +25 -12
- package/skills/jskit/references/patterns/auth/auth-surface/example/tools/preview-identity +7 -1
- package/skills/jskit/references/patterns/auth/oidc-sign-in/example/package.json +2 -2
- package/skills/jskit/references/patterns/auth/supabase-auth/example/package.json +1 -1
- package/skills/jskit/references/patterns/connectors/ai-connections/PATTERN.md +16 -1
- package/skills/jskit/references/patterns/connectors/ai-connections/example/ai-model.js +12 -3
- package/skills/jskit/references/patterns/connectors/ai-connections/example/perplexity-answer.js +15 -4
- package/skills/jskit/references/patterns/connectors/api-key-connection/PATTERN.md +9 -1
- package/skills/jskit/references/patterns/connectors/api-key-connection/example/connections.js +5 -2
- package/skills/jskit/references/patterns/connectors/aws-storage-queries/PATTERN.md +13 -3
- package/skills/jskit/references/patterns/connectors/aws-storage-queries/example/s3-transfer.js +14 -3
- package/skills/jskit/references/patterns/connectors/calendar-cli/PATTERN.md +8 -0
- package/skills/jskit/references/patterns/connectors/calendar-cli/example/knexfile.js +1 -1
- package/skills/jskit/references/patterns/connectors/calendar-cli/example/package.json +4 -4
- package/skills/jskit/references/patterns/connectors/calendar-cli/example/scripts/calendar.js +8 -4
- package/skills/jskit/references/patterns/connectors/event-delivery/PATTERN.md +1 -1
- package/skills/jskit/references/patterns/connectors/firebase-messaging/PATTERN.md +10 -0
- package/skills/jskit/references/patterns/connectors/firebase-messaging/example/server/notifications.js +8 -0
- package/skills/jskit/references/patterns/connectors/google-ads-search/PATTERN.md +18 -7
- package/skills/jskit/references/patterns/connectors/google-ads-search/example/ads-setup.js +13 -5
- package/skills/jskit/references/patterns/connectors/oauth-connection/PATTERN.md +1 -1
- package/skills/jskit/references/patterns/connectors/paddle-catalogue/PATTERN.md +11 -2
- package/skills/jskit/references/patterns/connectors/paddle-catalogue/example/create-products.js +5 -2
- package/skills/jskit/references/patterns/connectors/public-image/PATTERN.md +10 -1
- package/skills/jskit/references/patterns/connectors/public-image/example/logo-url.js +4 -1
- package/skills/jskit/references/patterns/connectors/redshift-queries/PATTERN.md +1 -1
- package/skills/jskit/references/patterns/connectors/source-scanning/PATTERN.md +13 -2
- package/skills/jskit/references/patterns/connectors/source-scanning/example/source-scanner.js +9 -0
- package/skills/jskit/references/patterns/crud/json-api-resource-package/PATTERN.md +102 -23
- package/skills/jskit/references/patterns/crud/json-api-resource-package/example/packages/books/package.json +3 -2
- package/skills/jskit/references/patterns/crud/json-api-resource-package/example/packages/books/src/server/types.js +5 -0
- package/skills/jskit/references/patterns/crud/resource-contract/PATTERN.md +54 -1
- package/skills/jskit/references/patterns/database/mysql-application/PATTERN.md +16 -5
- package/skills/jskit/references/patterns/database/mysql-application/example/knexfile.js +2 -2
- package/skills/jskit/references/patterns/database/mysql-application/example/package.json +1 -1
- package/skills/jskit/references/patterns/database/mysql-application/example/scripts/prepare-database.js +1 -1
- package/skills/jskit/references/patterns/database/postgres-application/PATTERN.md +16 -5
- package/skills/jskit/references/patterns/database/postgres-application/example/knexfile.js +2 -2
- package/skills/jskit/references/patterns/database/postgres-application/example/package.json +1 -1
- package/skills/jskit/references/patterns/database/postgres-application/example/scripts/prepare-database.js +1 -1
- package/skills/jskit/references/patterns/realtime/realtime-application/example/package.json +2 -2
- package/skills/jskit/references/patterns/rewards/google-rewarded/example/GoogleRewardedDeliveryProvider.js +1 -1
- package/skills/jskit/references/patterns/rewards/google-rewarded/example/googlePublisherTag.js +5 -11
- package/skills/jskit/references/patterns/server/feature-package/PATTERN.md +104 -10
- package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/package.json +9 -4
- package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/src/server/BookingEngineFeature.js +24 -0
- package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/src/server/bookingAvailability.js +10 -0
- package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/src/server/bookingEngine.js +29 -0
- package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/src/server/bookingEngineActions.js +26 -0
- package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/src/server/inputSchemas.js +1 -2
- package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/src/server/types.js +12 -0
- package/skills/jskit/references/patterns/server/feature-package/example/variations/AvailabilityEngineFeature.js +19 -0
- package/skills/jskit/references/patterns/server/feature-package/example/variations/InvoiceRollupFeature.js +23 -0
- package/skills/jskit/references/patterns/server/feature-package/example/variations/availabilityEngineActions.js +26 -0
- package/skills/jskit/references/patterns/server/feature-package/example/variations/customKnexRepository.js +32 -26
- package/skills/jskit/references/patterns/server/feature-package/example/variations/invoiceRollupActions.js +26 -0
- package/skills/jskit/references/patterns/server/feature-package/example/variations/orchestratorService.js +24 -19
- package/skills/jskit/references/patterns/server/feature-package/example/variations/types.js +7 -0
- package/skills/jskit/references/patterns/users/user-administration-server/PATTERN.md +16 -1
- package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users/package.json +3 -2
- package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users/src/server/types.js +5 -0
- package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users-workspace/package.json +4 -3
- package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users-workspace/src/server/UsersWorkspaceFeature.js +2 -9
- package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users-workspace/src/server/types.js +5 -0
- package/skills/jskit/references/patterns/workspaces/workspace-server/PATTERN.md +42 -17
- package/skills/jskit/references/patterns/workspaces/workspace-server/example/packages/main/src/server/WorkspaceInvitationsFeature.js +27 -0
- package/skills/jskit/references/patterns/workspaces/workspace-server/example/packages/main/src/server/email/workspaceInviteEmail.js +11 -10
- package/skills/jskit/references/patterns/workspaces/workspace-server/example/packages/main/src/server/email/workspaceInviteMailer.js +27 -0
- package/skills/jskit/references/translation.md +5 -4
- package/skills/jskit/references/typed-features.md +1099 -0
- package/skills/jskit/references/ui-operations.md +3 -3
- package/patterns/feature-package/example/booking-engine/src/server/BookingEngineProvider.js +0 -33
- package/patterns/feature-package/example/booking-engine/src/server/actions.js +0 -24
- package/patterns/feature-package/example/variations/AvailabilityEngineProvider.js +0 -31
- package/patterns/feature-package/example/variations/InvoiceRollupProvider.js +0 -36
- package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/src/server/BookingEngineProvider.js +0 -33
- package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/src/server/actions.js +0 -24
- package/skills/jskit/references/patterns/server/feature-package/example/variations/AvailabilityEngineProvider.js +0 -31
- package/skills/jskit/references/patterns/server/feature-package/example/variations/InvoiceRollupProvider.js +0 -36
|
@@ -18,7 +18,7 @@ The example wires that library to application-owned authority and snapshot looku
|
|
|
18
18
|
## Do not use when
|
|
19
19
|
|
|
20
20
|
This is not an HTTP application-data connector, user login, a managed gateway,
|
|
21
|
-
or an implementation of
|
|
21
|
+
or an implementation of a hosted editor's coding agents. It does not generate an app.
|
|
22
22
|
Auth0 and native Windows execution are not implemented in the current runner.
|
|
23
23
|
|
|
24
24
|
## Product decisions
|
|
@@ -39,7 +39,15 @@ and whether a blocking verdict prevents a later operation.
|
|
|
39
39
|
- Missing/invalid reports, cancellation and failed scans never become clean scans.
|
|
40
40
|
- Provider credentials are isolated from coding-agent sessions and credentials.
|
|
41
41
|
- The host supplies its own authorized provider credentials; editor edition does
|
|
42
|
-
not select a shared
|
|
42
|
+
not select a shared hosted provider account.
|
|
43
|
+
- Each collaborator the composition receives (`authorize`, `resolveReference`
|
|
44
|
+
and `resolveScanTarget`) is a required parameter typed in a JSDoc `@param` and
|
|
45
|
+
called directly, without a `typeof` probe, a "requires x" guard or a no-op
|
|
46
|
+
default. `authorize` and `resolveReference` are typed with `ConnectorAuthorize`
|
|
47
|
+
and `ResolveReference` from `@jskit-ai/connectors-core/server/types`, and
|
|
48
|
+
`resolveScanTarget` with `WizScanTargetResolver` from
|
|
49
|
+
`@jskit-ai/connectors-catalog/server/types`. A server feature that uses it follows
|
|
50
|
+
[typed features](https://github.com/mobily-enterprises/jskit-ai/blob/main/packages/agent-docs/site/guide/framework/typed-features.md).
|
|
43
51
|
|
|
44
52
|
## Framework APIs
|
|
45
53
|
|
|
@@ -81,3 +89,6 @@ and findings require separately authorised provider acceptance.
|
|
|
81
89
|
Do not infer workspace grants from a shared slot, return raw provider stderr,
|
|
82
90
|
replay scans automatically, pass arbitrary CLI flags, use a mutable working tree
|
|
83
91
|
as if it were a fixed revision, or substitute a generic API reader for source scans.
|
|
92
|
+
|
|
93
|
+
Do not probe a collaborator, default one to `null`, `{}` or a no-op, fill a slot
|
|
94
|
+
with a setter after construction, or keep a module-level registry.
|
package/skills/jskit/references/patterns/connectors/source-scanning/example/source-scanner.js
CHANGED
|
@@ -3,6 +3,15 @@ import { parseIntegrationConfiguration } from "@jskit-ai/connectors-core/shared/
|
|
|
3
3
|
import { wizDefinition } from "@jskit-ai/connectors-catalog/shared";
|
|
4
4
|
import { createWizScanner } from "@jskit-ai/connectors-catalog/server/wiz";
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* @param {object} dependencies
|
|
8
|
+
* @param {string} [dependencies.configFile]
|
|
9
|
+
* @param {string} dependencies.installedWizCliPath
|
|
10
|
+
* @param {import("@jskit-ai/connectors-core/server/types").ConnectorAuthorize} dependencies.authorize The application's access policy.
|
|
11
|
+
* @param {import("@jskit-ai/connectors-core/server/types").ResolveReference} dependencies.resolveReference
|
|
12
|
+
* @param {import("@jskit-ai/connectors-catalog/server/types").WizScanTargetResolver} dependencies.resolveScanTarget
|
|
13
|
+
* @param {Record<string, string>} [dependencies.environment]
|
|
14
|
+
*/
|
|
6
15
|
export async function projectSourceScanner({ configFile = "integrations.json", installedWizCliPath,
|
|
7
16
|
authorize, resolveReference, resolveScanTarget, environment }) {
|
|
8
17
|
const configuration = parseIntegrationConfiguration(await readFile(configFile, "utf8"), {
|
|
@@ -33,18 +33,32 @@ from a generator questionnaire or treat a live table as the sole contract.
|
|
|
33
33
|
- Migration and resource storage metadata describe the same table.
|
|
34
34
|
- `apiAccess`, surface access, and `autofilter` agree.
|
|
35
35
|
- Public routes use public ownership only.
|
|
36
|
-
- Workspace routes receive explicit scope validators and route-to-action input
|
|
36
|
+
- Workspace routes receive explicit scope validators and route-to-action input:
|
|
37
|
+
workspaces-core's `WORKSPACE_CRUD_SCOPE`, never a copied scope literal.
|
|
37
38
|
- Application source contains one module declaration, not copied generic CRUD
|
|
38
39
|
repository, service, action, route, and provider files.
|
|
39
40
|
- Current migration/resource/source state is authoritative; there is no receipt,
|
|
40
41
|
provenance marker, generator identity, or field-patching lane.
|
|
42
|
+
- The package exports the type of the capability it provides:
|
|
43
|
+
`src/server/types.js` declares `AppBooks` (for `app.books`) as crud-core's
|
|
44
|
+
`CrudResourceApi`, exported as `./server/types`. A feature that requires
|
|
45
|
+
`app.books` names that type in a JSDoc `@param`; code given only its service
|
|
46
|
+
or repository names crud-core's `CrudService` or `CrudRepository`.
|
|
47
|
+
- Code the declaration adds follows [typed features](https://github.com/mobily-enterprises/jskit-ai/blob/main/packages/agent-docs/site/guide/framework/typed-features.md):
|
|
48
|
+
`decorateService`, `decorateRepository`, `operationLifecycle` hooks and named
|
|
49
|
+
`actions` call the collaborators they receive directly, with no `typeof`
|
|
50
|
+
probe, optional call, absent default, slot setter or module-level registry.
|
|
51
|
+
Each action's `execute` is one call to one service method with the
|
|
52
|
+
validated input, and its argument is typed as crud-core's
|
|
53
|
+
`CrudCustomActionInvocation`. Keep one copy of each helper per package, files
|
|
54
|
+
under 750 lines and functions under 600.
|
|
41
55
|
|
|
42
56
|
## Framework APIs
|
|
43
57
|
|
|
44
58
|
Use `defineCrudResource()` from `@jskit-ai/resource-crud-core` and
|
|
45
59
|
`defineCrudJsonApiFeature()` from `@jskit-ai/crud-core`. The latter composes the
|
|
46
|
-
JSON REST resource, repository, service
|
|
47
|
-
contracts, access policy, and HTTP routes.
|
|
60
|
+
JSON REST resource, repository, service, standard CRUD actions with their
|
|
61
|
+
record-changed events, route contracts, access policy, and HTTP routes.
|
|
48
62
|
|
|
49
63
|
## Example files
|
|
50
64
|
|
|
@@ -55,6 +69,7 @@ Paths below are relative to this pattern directory:
|
|
|
55
69
|
example/migrations/20260815000000_books.cjs
|
|
56
70
|
example/packages/books/package.json
|
|
57
71
|
example/packages/books/src/server/BooksFeature.js
|
|
72
|
+
example/packages/books/src/server/types.js
|
|
58
73
|
example/packages/books/src/shared/bookResource.js
|
|
59
74
|
example/packages/books/src/shared/index.js
|
|
60
75
|
```
|
|
@@ -67,6 +82,8 @@ guide.
|
|
|
67
82
|
|
|
68
83
|
`BooksFeature.js` is deliberately tiny: it binds the readable resource contract
|
|
69
84
|
to the framework module and exports the resulting provider.
|
|
85
|
+
`types.js` declares the type of the `app.books` capability, for features that
|
|
86
|
+
require it.
|
|
70
87
|
|
|
71
88
|
## List search is part of the initial composition
|
|
72
89
|
|
|
@@ -89,8 +106,15 @@ an unfiltered collection can satisfy a matching-row-only assertion.
|
|
|
89
106
|
|
|
90
107
|
Change the package name, resource fields, table, surface, ownership filter,
|
|
91
108
|
relative route, messages, and migration. Supply explicit permissions when the
|
|
92
|
-
surface uses named policy. For workspace ownership,
|
|
93
|
-
|
|
109
|
+
surface uses named policy. For workspace ownership, pass `scope:
|
|
110
|
+
WORKSPACE_CRUD_SCOPE` (`@jskit-ai/workspaces-core/server/support/workspaceCrud`):
|
|
111
|
+
the `/w/:workspaceSlug` route base, the workspace route and action validators
|
|
112
|
+
and the slug input. A repository method of such a feature reads the workspace
|
|
113
|
+
id with `resolveWorkspaceScopeValue(options.context)`
|
|
114
|
+
(`@jskit-ai/json-rest-api-core/server/jsonRestApiHost`), and a
|
|
115
|
+
hand-written workspace route's path is
|
|
116
|
+
`resolveWorkspaceRoutePath("relative-path")`
|
|
117
|
+
(`@jskit-ai/workspaces-core/server/support/workspaceRoutePaths`). The feature exposes the
|
|
94
118
|
operations declared by the resource. Use `operations` only to narrow that
|
|
95
119
|
surface further; do not register unused mutation actions and routes. Use
|
|
96
120
|
`routes: false` only for an internal
|
|
@@ -108,7 +132,13 @@ capabilities in `requires` and provide `decorateService({ service, repository,
|
|
|
108
132
|
resource, ...dependencies })`. Retain the standard methods, override only the
|
|
109
133
|
methods whose CRUD behavior changes, and add resource-related domain methods
|
|
110
134
|
such as `confirmBooking()` or `sendReminder()` directly to that service. Those
|
|
111
|
-
additional methods remain available through the resource capability.
|
|
135
|
+
additional methods remain available through the resource capability. An
|
|
136
|
+
overridden `createDocument()` returns the created record, with its id, as a
|
|
137
|
+
tagged JSON:API result: a document result (`returnJsonApiDocument`), as the
|
|
138
|
+
standard one does, or a data result (`returnJsonApiData(record)`). The create
|
|
139
|
+
action's created and `record.changed` events read the record's id from it, and
|
|
140
|
+
a create whose service returns an untagged document or record, or a result
|
|
141
|
+
without the record's id, fails in every channel. When the
|
|
112
142
|
product needs only a few additional queries or locking operations, provide
|
|
113
143
|
`decorateRepository({ repository, database, http, jsonRestApi, resource,
|
|
114
144
|
...dependencies })`; return the standard methods plus only those unique
|
|
@@ -118,14 +148,28 @@ Use `operationLifecycle` for behavior surrounding a standard operation. Its
|
|
|
118
148
|
per-operation `before`, `execute`, and `after` phases share one repository
|
|
119
149
|
transaction for create, update, and delete. An `execute` hook receives
|
|
120
150
|
`standard(nextInput)` so it can retain the framework write while adjusting its
|
|
121
|
-
input or coordinating other repository work
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
151
|
+
input or coordinating other repository work, and returns what `standard()`
|
|
152
|
+
returns: the operation's tagged JSON:API result (null for delete). A create's
|
|
153
|
+
`execute` returns the created record with its id, as the document result
|
|
154
|
+
`standard()` returns or as `returnJsonApiData(record)`, because the create's
|
|
155
|
+
events read its id; a create that returns anything else fails inside its
|
|
156
|
+
transaction. `after` and `afterCommit` receive that `result`, so a record id is
|
|
157
|
+
`result.value.data.id` for a document result. `afterCommit` runs only after the
|
|
158
|
+
mutation transaction succeeds. A hook's argument is `CrudLifecycleContext` from
|
|
159
|
+
`@jskit-ai/crud-core/server/types`; type a lifecycle declared apart from its
|
|
160
|
+
feature with `CrudOperationLifecycle`, whose type arguments are the decorated
|
|
161
|
+
service and repository its hooks call. Put durable external delivery behind an
|
|
162
|
+
outbox written inside the transaction; do not make an email or webhook the
|
|
163
|
+
arbiter of whether an already-committed request appears successful.
|
|
125
164
|
|
|
126
165
|
Declare resource-related non-CRUD commands in `actions`. Each named action has
|
|
127
166
|
a normal JSKIT input, permission, audit, events, and `execute({ input, context,
|
|
128
|
-
service, repository, ...dependencies })` contract.
|
|
167
|
+
service, repository, ...dependencies })` contract. Type that argument with
|
|
168
|
+
`CrudCustomActionInvocation` from `@jskit-ai/crud-core/server/types`. Its first
|
|
169
|
+
type argument is the service the action calls, when `decorateService` adds the
|
|
170
|
+
method; its second holds the types of required capabilities the action uses,
|
|
171
|
+
by local name; its third is the repository the action calls, when
|
|
172
|
+
`decorateRepository` adds the method. Its optional `route`
|
|
129
173
|
declares an HTTP method, path below the resource base, explicit route contract,
|
|
130
174
|
status code, and optional request-to-action input mapper. This is the normal
|
|
131
175
|
home for `confirm`, `publish`, `cancel`, `reorder`, or `sendReminder`. Move to a
|
|
@@ -139,25 +183,58 @@ Use `operationInputs.create` or `operationInputs.update` when a standard CRUD
|
|
|
139
183
|
operation intentionally accepts a small virtual product field that is handled
|
|
140
184
|
by the service decorator rather than stored on the resource row.
|
|
141
185
|
|
|
186
|
+
A decorator lives in a module of its own and returns its result frozen, with
|
|
187
|
+
each added method a named function. Spreading belongs here only, over the CRUD
|
|
188
|
+
service or repository, whose members are the contract's. `types.js` names the
|
|
189
|
+
decorated types once:
|
|
190
|
+
|
|
191
|
+
```js
|
|
192
|
+
// bookingsService.js
|
|
193
|
+
import { AppError } from "@jskit-ai/kernel/server/runtime/errors";
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* The bookings service: the CRUD service plus booking confirmation and the
|
|
197
|
+
* checks and history its updates need.
|
|
198
|
+
* @param {object} dependencies
|
|
199
|
+
* @param {import("@jskit-ai/crud-core/server/types").CrudService} dependencies.service
|
|
200
|
+
* @param {import("./types.js").BookingsRepository} dependencies.repository
|
|
201
|
+
*/
|
|
202
|
+
function decorateBookingsService({ service, repository }) {
|
|
203
|
+
async function confirmBooking(recordId, options) {
|
|
204
|
+
return repository.confirmBooking(recordId, options);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
async function assertUpdateAllowed(recordId, options) {
|
|
208
|
+
if (await repository.isBookingLocked(recordId, options)) {
|
|
209
|
+
throw new AppError(409, "This booking is locked.", { code: "bookings.locked" });
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
async function recordUpdateCompleted(recordId, options) {
|
|
214
|
+
return repository.addBookingHistoryEntry(recordId, "updated", options);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
return Object.freeze({ ...service, confirmBooking, assertUpdateAllowed, recordUpdateCompleted });
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// types.js
|
|
221
|
+
/** @typedef {ReturnType<typeof import("./bookingsRepository.js").decorateBookingsRepository>} BookingsRepository */
|
|
222
|
+
/** @typedef {ReturnType<typeof import("./bookingsService.js").decorateBookingsService>} BookingsService */
|
|
223
|
+
```
|
|
224
|
+
|
|
142
225
|
```js
|
|
143
226
|
const BookingsFeature = defineCrudJsonApiFeature({
|
|
144
227
|
resource: bookingResource,
|
|
145
228
|
surface: "app",
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
...service,
|
|
149
|
-
async confirmBooking(recordId, options) {
|
|
150
|
-
return repository.confirmBooking(recordId, options);
|
|
151
|
-
}
|
|
152
|
-
};
|
|
153
|
-
},
|
|
229
|
+
decorateRepository: decorateBookingsRepository,
|
|
230
|
+
decorateService: decorateBookingsService,
|
|
154
231
|
operationLifecycle: {
|
|
155
232
|
update: {
|
|
156
233
|
async before({ input, service, trx, context }) {
|
|
157
234
|
await service.assertUpdateAllowed(input.recordId, { trx, context });
|
|
158
235
|
},
|
|
159
236
|
async afterCommit({ result, service, context }) {
|
|
160
|
-
await service.recordUpdateCompleted(result.data.id, { context });
|
|
237
|
+
await service.recordUpdateCompleted(result.value.data.id, { context });
|
|
161
238
|
}
|
|
162
239
|
}
|
|
163
240
|
},
|
|
@@ -165,9 +242,8 @@ const BookingsFeature = defineCrudJsonApiFeature({
|
|
|
165
242
|
confirm: {
|
|
166
243
|
input: confirmBookingInput,
|
|
167
244
|
permission: { require: "all", permissions: ["bookings.confirm"] },
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
},
|
|
245
|
+
/** @param {import("@jskit-ai/crud-core/server/types").CrudCustomActionInvocation<import("./types.js").BookingsService>} action */
|
|
246
|
+
execute: ({ input, context, service }) => service.confirmBooking(input.recordId, { context }),
|
|
171
247
|
route: {
|
|
172
248
|
method: "POST",
|
|
173
249
|
path: "/:recordId/confirm",
|
|
@@ -203,3 +279,6 @@ const BookingsFeature = defineCrudJsonApiFeature({
|
|
|
203
279
|
- public access combined with user or workspace ownership
|
|
204
280
|
- implicit workspace route parameters or permissions
|
|
205
281
|
- receipt, replay, provenance, ownership-marker, or scaffold-shape files
|
|
282
|
+
- probing a collaborator, defaulting one to `null`, `{}` or a no-op, setters
|
|
283
|
+
that fill a slot after construction, and module-level registries in
|
|
284
|
+
decorators, lifecycle hooks or actions
|
|
@@ -5,11 +5,12 @@
|
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
7
7
|
"./server/BooksFeature": "./src/server/BooksFeature.js",
|
|
8
|
+
"./server/types": "./src/server/types.js",
|
|
8
9
|
"./shared": "./src/shared/index.js"
|
|
9
10
|
},
|
|
10
11
|
"dependencies": {
|
|
11
|
-
"@jskit-ai/crud-core": "0.2.
|
|
12
|
-
"@jskit-ai/resource-crud-core": "0.1.
|
|
12
|
+
"@jskit-ai/crud-core": "0.2.4",
|
|
13
|
+
"@jskit-ai/resource-crud-core": "0.1.195"
|
|
13
14
|
},
|
|
14
15
|
"jskit": {
|
|
15
16
|
"kind": "runtime",
|
|
@@ -44,7 +44,9 @@ not from a JSKIT questionnaire.
|
|
|
44
44
|
- User ownership is represented by a non-null `user_id` column.
|
|
45
45
|
- The resource's hidden `userId` field maps to that ownership column.
|
|
46
46
|
- `autofilter: "user"` is used only for genuine current-user ownership.
|
|
47
|
-
-
|
|
47
|
+
- Each product field's output, create, and patch participation is its
|
|
48
|
+
`operations` block, or the default `defineCrudResource()` gives a field
|
|
49
|
+
without one (see Field operations and lookups below).
|
|
48
50
|
- Temporal database values use the declared storage serializer.
|
|
49
51
|
- The source-controlled migration and resource contract agree.
|
|
50
52
|
- Server policy tests prove that one user cannot read or mutate another user's
|
|
@@ -60,6 +62,57 @@ Higher layers should consume this resource through JSKIT's CRUD service,
|
|
|
60
62
|
repository, route, and UI APIs. They should not rebuild field validators or
|
|
61
63
|
serialize requests independently.
|
|
62
64
|
|
|
65
|
+
## Field operations and lookups
|
|
66
|
+
|
|
67
|
+
A field's `operations` name the operations it takes part in: `output` (the
|
|
68
|
+
record in every response), and `create` and `patch` (the request bodies; an
|
|
69
|
+
enabled `replace` uses the `create` fields unless a field names `replace`). A
|
|
70
|
+
field that leaves `operations` out takes the default:
|
|
71
|
+
|
|
72
|
+
| Field | Default `operations` |
|
|
73
|
+
| --- | --- |
|
|
74
|
+
| `primary: true` | `{}`: no operation; every record output already carries its `id` |
|
|
75
|
+
| `hidden: true` | `{}`: no operation |
|
|
76
|
+
| `readOnly: true` | `{ output: { required: true } }` |
|
|
77
|
+
| any other field | `{ output: { required: true }, create: { required: <the field's required> }, patch: { required: false } }` |
|
|
78
|
+
|
|
79
|
+
So a `required: true` field is required on create, and any other field is
|
|
80
|
+
optional there. An `operations` block you write always wins, for example
|
|
81
|
+
`operations: { output: {}, create: {}, patch: {} }` for a field that is
|
|
82
|
+
optional everywhere. Write the block only where it differs from the default:
|
|
83
|
+
|
|
84
|
+
```js
|
|
85
|
+
schema: {
|
|
86
|
+
userId: { type: "id", required: true, hidden: true },
|
|
87
|
+
title: { type: "string", maxLength: 255, required: true, search: true },
|
|
88
|
+
notes: { type: "string", maxLength: 65535, nullable: true, search: true },
|
|
89
|
+
createdAt: { type: "dateTime", default: "now()", readOnly: true, storage: { writeSerializer: "datetime-utc" } }
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
A field that looks up a record of another resource can name that resource's
|
|
94
|
+
namespace with `lookup`:
|
|
95
|
+
|
|
96
|
+
```js
|
|
97
|
+
shelfId: { type: "id", nullable: true, search: true, lookup: "shelves" }
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
`defineCrudResource()` expands it, where `lookup` stood, to:
|
|
101
|
+
|
|
102
|
+
```js
|
|
103
|
+
relation: { kind: "lookup", namespace: "shelves", valueKey: "id" },
|
|
104
|
+
belongsTo: "shelves", // the namespace's JSON REST resource, camel-cased
|
|
105
|
+
as: "shelf", // the field key without its Id suffix
|
|
106
|
+
ui: { formControl: "autocomplete" }
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Keys you write beside `lookup` win: `belongsTo` and `as` replace the
|
|
110
|
+
filled-in values, and `relation` and `ui` are merged over them, so
|
|
111
|
+
`relation: { labelKey: "name" }` adds a label key and
|
|
112
|
+
`ui: { formControl: "select" }` picks a select. A field whose key has no `Id`
|
|
113
|
+
suffix must write `as`. The built resource equals one that writes the expanded
|
|
114
|
+
keys out.
|
|
115
|
+
|
|
63
116
|
## Example files
|
|
64
117
|
|
|
65
118
|
- `example/bookResource.js` is a complete resource contract for personal book
|
|
@@ -38,7 +38,10 @@ decisions, not framework questions.
|
|
|
38
38
|
## Framework APIs
|
|
39
39
|
|
|
40
40
|
Use `createKnexMigrationConfigFromApp()` from
|
|
41
|
-
`@jskit-ai/database-runtime/server/knexMigrationConfig
|
|
41
|
+
`@jskit-ai/database-runtime/server/knexMigrationConfig`, and
|
|
42
|
+
`prepareDatabaseFromApp()` from `@jskit-ai/database-runtime/server/databaseSetup`.
|
|
43
|
+
Both take the dialect and the application's environment
|
|
44
|
+
(`environment: process.env`), which they never read on their own. The running JSKIT
|
|
42
45
|
application automatically selects the sole installed database driver, while
|
|
43
46
|
Knex discovers package-owned migrations from the installed dependency graph.
|
|
44
47
|
|
|
@@ -50,6 +53,14 @@ Knex discovers package-owned migrations from the installed dependency graph.
|
|
|
50
53
|
entrypoint for managed sessions and deployments. `example/.env.example` names
|
|
51
54
|
the connection values and separate test databases without a secret.
|
|
52
55
|
|
|
56
|
+
`example/.github/workflows/verify.yml` is a normal app-owned CI workflow with
|
|
57
|
+
exactly one database service: `mariadb` (`mariadb:11.4`, `MARIADB_*`
|
|
58
|
+
variables, port `3306`, a `healthcheck.sh` health check). Copy it whole from
|
|
59
|
+
this pattern and adapt it as source rather than generating it from package
|
|
60
|
+
metadata. Do not combine it with the PostgreSQL pattern's workflow: a MySQL
|
|
61
|
+
application's workflow has no `postgres` service, `POSTGRES_*` variables, port
|
|
62
|
+
`5432`, or `pg_isready` option.
|
|
63
|
+
|
|
53
64
|
`example/tests/browser/database.js` is the application-owned browser preparation
|
|
54
65
|
helper. It requires the exact `BROWSER_TEST_DB_NAME`, rejects the ordinary and
|
|
55
66
|
disposable `TEST_DB_NAME` databases,
|
|
@@ -93,10 +104,9 @@ it as `seed` to `prepareDatabaseFromApp()`.
|
|
|
93
104
|
foreign-key checks remain enabled, and the normal database is unchanged.
|
|
94
105
|
Also prove that a new pending migration is applied. Keep this as a regression
|
|
95
106
|
test when adapting the example; reject a harness that recreates the schema.
|
|
96
|
-
|
|
97
|
-
`
|
|
98
|
-
|
|
99
|
-
package metadata.
|
|
107
|
+
- Confirm `.github/workflows/verify.yml` parses as YAML and declares only the
|
|
108
|
+
`mariadb` service. GitHub reports an unparseable workflow only as a failed
|
|
109
|
+
run with "no jobs were run".
|
|
100
110
|
|
|
101
111
|
## Avoid
|
|
102
112
|
|
|
@@ -104,4 +114,5 @@ package metadata.
|
|
|
104
114
|
- generated `.env` secrets
|
|
105
115
|
- depending on a live schema as the source contract
|
|
106
116
|
- a second driver installed “just in case”
|
|
117
|
+
- any file, service, port, or variable copied from the PostgreSQL pattern
|
|
107
118
|
- migration receipts, provenance, replay logs, or generator ownership
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { createKnexMigrationConfigFromApp } from "@jskit-ai/database-runtime/server/knexMigrationConfig";
|
|
2
2
|
|
|
3
3
|
try {
|
|
4
|
-
process.loadEnvFile
|
|
4
|
+
process.loadEnvFile(".env");
|
|
5
5
|
} catch (error) {
|
|
6
6
|
if (error?.code !== "ENOENT") {
|
|
7
7
|
throw error;
|
|
8
8
|
}
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
export default await createKnexMigrationConfigFromApp({ client: "mysql2" });
|
|
11
|
+
export default await createKnexMigrationConfigFromApp({ client: "mysql2", environment: process.env });
|
|
@@ -38,7 +38,10 @@ decisions, not framework questions.
|
|
|
38
38
|
## Framework APIs
|
|
39
39
|
|
|
40
40
|
Use `createKnexMigrationConfigFromApp()` from
|
|
41
|
-
`@jskit-ai/database-runtime/server/knexMigrationConfig
|
|
41
|
+
`@jskit-ai/database-runtime/server/knexMigrationConfig`, and
|
|
42
|
+
`prepareDatabaseFromApp()` from `@jskit-ai/database-runtime/server/databaseSetup`.
|
|
43
|
+
Both take the dialect and the application's environment
|
|
44
|
+
(`environment: process.env`), which they never read on their own. The running JSKIT
|
|
42
45
|
application automatically selects the sole installed database driver, while
|
|
43
46
|
Knex discovers package-owned migrations from the installed dependency graph.
|
|
44
47
|
|
|
@@ -50,6 +53,14 @@ dialect. `example/scripts/prepare-database.js` is the portable
|
|
|
50
53
|
migrate-then-seed entrypoint for managed sessions and deployments.
|
|
51
54
|
`example/.env.example` names the five connection values without a secret.
|
|
52
55
|
|
|
56
|
+
`example/.github/workflows/verify.yml` is a normal app-owned CI workflow with
|
|
57
|
+
exactly one database service: `postgres` (`postgres:17`, `POSTGRES_*`
|
|
58
|
+
variables, port `5432`, a `pg_isready` health check). Copy it whole from this
|
|
59
|
+
pattern and adapt it as source rather than generating it from package metadata.
|
|
60
|
+
Do not combine it with the MySQL pattern's workflow: a PostgreSQL application's
|
|
61
|
+
workflow has no `mariadb` service, `MARIADB_*` variables, port `3306`, or
|
|
62
|
+
`healthcheck.sh` option.
|
|
63
|
+
|
|
53
64
|
## Variation points
|
|
54
65
|
|
|
55
66
|
Change scripts, migration location, connection values, and secret injection to
|
|
@@ -66,10 +77,9 @@ it as `seed` to `prepareDatabaseFromApp()`.
|
|
|
66
77
|
- Run `npm run db:migrate:status` and the application verification command.
|
|
67
78
|
- Exercise one transaction and one negative connection case.
|
|
68
79
|
- When a seed exists, run `db:prepare` twice and require the second run to be safe.
|
|
69
|
-
|
|
70
|
-
`
|
|
71
|
-
|
|
72
|
-
from package metadata.
|
|
80
|
+
- Confirm `.github/workflows/verify.yml` parses as YAML and declares only the
|
|
81
|
+
`postgres` service. GitHub reports an unparseable workflow only as a failed
|
|
82
|
+
run with "no jobs were run".
|
|
73
83
|
|
|
74
84
|
## Avoid
|
|
75
85
|
|
|
@@ -77,4 +87,5 @@ from package metadata.
|
|
|
77
87
|
- generated `.env` secrets
|
|
78
88
|
- depending on a live schema as the source contract
|
|
79
89
|
- a second driver installed “just in case”
|
|
90
|
+
- any file, service, port, or variable copied from the MySQL pattern
|
|
80
91
|
- migration receipts, provenance, replay logs, or generator ownership
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { createKnexMigrationConfigFromApp } from "@jskit-ai/database-runtime/server/knexMigrationConfig";
|
|
2
2
|
|
|
3
3
|
try {
|
|
4
|
-
process.loadEnvFile
|
|
4
|
+
process.loadEnvFile(".env");
|
|
5
5
|
} catch (error) {
|
|
6
6
|
if (error?.code !== "ENOENT") {
|
|
7
7
|
throw error;
|
|
8
8
|
}
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
export default await createKnexMigrationConfigFromApp({ client: "pg" });
|
|
11
|
+
export default await createKnexMigrationConfigFromApp({ client: "pg", environment: process.env });
|
|
@@ -5,7 +5,7 @@ const GoogleRewardedDeliveryProvider = defineProvider({
|
|
|
5
5
|
id: "app.rewarded.google",
|
|
6
6
|
provides: { delivery: "client.rewarded-delivery" },
|
|
7
7
|
setup() {
|
|
8
|
-
return { delivery: { launchReward: launchGoogleRewardedAd } };
|
|
8
|
+
return { delivery: Object.freeze({ launchReward: launchGoogleRewardedAd }) };
|
|
9
9
|
}
|
|
10
10
|
});
|
|
11
11
|
|
package/skills/jskit/references/patterns/rewards/google-rewarded/example/googlePublisherTag.js
CHANGED
|
@@ -71,14 +71,10 @@ function launchGoogleRewardedAd({
|
|
|
71
71
|
let settled = false;
|
|
72
72
|
|
|
73
73
|
const cleanup = () => {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
79
|
-
if (typeof googletag.destroySlots === "function") {
|
|
80
|
-
googletag.destroySlots([slot]);
|
|
81
|
-
}
|
|
74
|
+
pubads.removeEventListener("rewardedSlotReady", handleReady);
|
|
75
|
+
pubads.removeEventListener("rewardedSlotGranted", handleGranted);
|
|
76
|
+
pubads.removeEventListener("rewardedSlotClosed", handleClosed);
|
|
77
|
+
googletag.destroySlots([slot]);
|
|
82
78
|
};
|
|
83
79
|
|
|
84
80
|
const handleReady = async (event) => {
|
|
@@ -87,9 +83,7 @@ function launchGoogleRewardedAd({
|
|
|
87
83
|
}
|
|
88
84
|
readySeen = true;
|
|
89
85
|
await Promise.resolve(onReady?.());
|
|
90
|
-
|
|
91
|
-
event.makeRewardedVisible();
|
|
92
|
-
}
|
|
86
|
+
event.makeRewardedVisible();
|
|
93
87
|
};
|
|
94
88
|
|
|
95
89
|
const handleGranted = async (event) => {
|