@jskit-ai/agent-docs 0.1.257 → 0.1.259

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 (230) hide show
  1. package/guide/agent/app-extras/assistant-conversation.md +88 -35
  2. package/guide/agent/app-extras/assistant.md +28 -28
  3. package/guide/agent/app-setup/authentication.md +36 -17
  4. package/guide/agent/app-setup/database-layer.md +116 -17
  5. package/guide/agent/app-setup/existing-application-migration.md +29 -25
  6. package/guide/agent/app-setup/multi-homing.md +94 -48
  7. package/guide/agent/app-setup/run-an-accounts-hub.md +6 -4
  8. package/guide/agent/framework/client-features.md +496 -0
  9. package/guide/agent/framework/crud-operations.md +5 -5
  10. package/guide/agent/framework/translation.md +4 -3
  11. package/guide/agent/framework/typed-features.md +1104 -0
  12. package/guide/agent/framework/ui-operations.md +2 -2
  13. package/guide/agent/index.md +6 -1
  14. package/package.json +1 -1
  15. package/patterns/feature-package/PATTERN.md +104 -10
  16. package/patterns/feature-package/example/booking-engine/package.json +9 -4
  17. package/patterns/feature-package/example/booking-engine/src/server/BookingEngineFeature.js +24 -0
  18. package/patterns/feature-package/example/booking-engine/src/server/bookingAvailability.js +10 -0
  19. package/patterns/feature-package/example/booking-engine/src/server/bookingEngine.js +29 -0
  20. package/patterns/feature-package/example/booking-engine/src/server/bookingEngineActions.js +26 -0
  21. package/patterns/feature-package/example/booking-engine/src/server/inputSchemas.js +1 -2
  22. package/patterns/feature-package/example/booking-engine/src/server/types.js +12 -0
  23. package/patterns/feature-package/example/variations/AvailabilityEngineFeature.js +19 -0
  24. package/patterns/feature-package/example/variations/InvoiceRollupFeature.js +23 -0
  25. package/patterns/feature-package/example/variations/availabilityEngineActions.js +26 -0
  26. package/patterns/feature-package/example/variations/customKnexRepository.js +32 -26
  27. package/patterns/feature-package/example/variations/invoiceRollupActions.js +26 -0
  28. package/patterns/feature-package/example/variations/orchestratorService.js +24 -19
  29. package/patterns/feature-package/example/variations/types.js +7 -0
  30. package/patterns/minimal-foundation/PATTERN.md +30 -1
  31. package/patterns/minimal-foundation/example/AGENTS.md +14 -0
  32. package/patterns/minimal-foundation/example/bin/develop.js +10 -5
  33. package/patterns/minimal-foundation/example/eslint.config.mjs +21 -2
  34. package/patterns/minimal-foundation/example/package.json +5 -4
  35. package/patterns/minimal-foundation/example/playwright.config.mjs +1 -1
  36. package/patterns/minimal-foundation/example/server/lib/envFile.js +19 -0
  37. package/patterns/minimal-foundation/example/server/lib/loggerOptions.js +15 -0
  38. package/patterns/minimal-foundation/example/server/lib/runtimeEnv.js +17 -17
  39. package/patterns/minimal-foundation/example/server.js +32 -29
  40. package/patterns/minimal-foundation/example/tests/server/smoke.test.js +2 -1
  41. package/patterns/shell-foundation/PATTERN.md +29 -0
  42. package/patterns/shell-foundation/example/AGENTS.md +14 -0
  43. package/patterns/shell-foundation/example/bin/develop.js +10 -5
  44. package/patterns/shell-foundation/example/eslint.config.mjs +21 -2
  45. package/patterns/shell-foundation/example/package.json +6 -5
  46. package/patterns/shell-foundation/example/packages/main/package.json +1 -1
  47. package/patterns/shell-foundation/example/packages/main/src/client/providers/MainClientProvider.js +1 -0
  48. package/patterns/shell-foundation/example/playwright.config.mjs +1 -1
  49. package/patterns/shell-foundation/example/server/lib/envFile.js +19 -0
  50. package/patterns/shell-foundation/example/server/lib/loggerOptions.js +15 -0
  51. package/patterns/shell-foundation/example/server/lib/runtimeEnv.js +17 -17
  52. package/patterns/shell-foundation/example/server.js +32 -29
  53. package/patterns/shell-foundation/example/tests/server/smoke.test.js +2 -1
  54. package/reference/autogen/KERNEL_MAP.md +14 -8
  55. package/reference/autogen/PATTERN_INDEX.md +37 -37
  56. package/reference/autogen/README.md +2 -0
  57. package/reference/autogen/packages/agent-docs.md +70 -26
  58. package/reference/autogen/packages/agent-runtime.md +129 -0
  59. package/reference/autogen/packages/agent.md +149 -0
  60. package/reference/autogen/packages/architecture-inspector.md +97 -44
  61. package/reference/autogen/packages/assistant-core.md +786 -292
  62. package/reference/autogen/packages/assistant-runtime.md +182 -57
  63. package/reference/autogen/packages/assistant-voice-sherpa.md +4 -0
  64. package/reference/autogen/packages/assistant-voice.md +54 -8
  65. package/reference/autogen/packages/auth-core.md +44 -13
  66. package/reference/autogen/packages/auth-provider-local-core.md +86 -34
  67. package/reference/autogen/packages/auth-provider-local-db-core.md +1 -2
  68. package/reference/autogen/packages/auth-provider-oidc-core.md +10 -4
  69. package/reference/autogen/packages/auth-provider-supabase-core.md +52 -66
  70. package/reference/autogen/packages/auth-web.md +19 -11
  71. package/reference/autogen/packages/connectors-catalog.md +71 -43
  72. package/reference/autogen/packages/connectors-core.md +42 -4
  73. package/reference/autogen/packages/console-core.md +27 -14
  74. package/reference/autogen/packages/crud-core.md +178 -170
  75. package/reference/autogen/packages/database-runtime-mysql.md +0 -2
  76. package/reference/autogen/packages/database-runtime-postgres.md +0 -2
  77. package/reference/autogen/packages/database-runtime.md +39 -10
  78. package/reference/autogen/packages/http-runtime.md +79 -57
  79. package/reference/autogen/packages/json-rest-api-core.md +11 -8
  80. package/reference/autogen/packages/kernel.md +144 -83
  81. package/reference/autogen/packages/oidc-issuer-core.md +49 -20
  82. package/reference/autogen/packages/payments-core.md +20 -3
  83. package/reference/autogen/packages/realtime.md +47 -22
  84. package/reference/autogen/packages/resource-core.md +1 -1
  85. package/reference/autogen/packages/resource-crud-core.md +64 -26
  86. package/reference/autogen/packages/rewarded-core.md +47 -36
  87. package/reference/autogen/packages/shell-web.md +7 -10
  88. package/reference/autogen/packages/storage-runtime.md +6 -2
  89. package/reference/autogen/packages/uploads-runtime.md +10 -2
  90. package/reference/autogen/packages/users-core.md +73 -71
  91. package/reference/autogen/packages/workspaces-core.md +121 -106
  92. package/reference/autogen/packages/workspaces-web.md +1 -2
  93. package/reference/autogen/tooling/config-eslint.md +302 -0
  94. package/reference/autogen/tooling/jskit-catalog.md +28 -18
  95. package/reference/autogen/tooling/jskit-release.md +35 -20
  96. package/reference/autogen/tooling/testUtils.md +3 -1
  97. package/skills/jskit/SKILL.md +9 -8
  98. package/skills/jskit/references/app-operations.md +1 -1
  99. package/skills/jskit/references/client-features.md +491 -0
  100. package/skills/jskit/references/crud-form-actions.md +1 -1
  101. package/skills/jskit/references/crud-operations.md +7 -7
  102. package/skills/jskit/references/existing-application-migration.md +31 -27
  103. package/skills/jskit/references/heuristics/INDEX.md +5 -1
  104. package/skills/jskit/references/heuristics/child-cruds.md +1 -1
  105. package/skills/jskit/references/heuristics/client-features.md +66 -0
  106. package/skills/jskit/references/heuristics/client-requests.md +1 -1
  107. package/skills/jskit/references/heuristics/crud-authoring.md +12 -2
  108. package/skills/jskit/references/heuristics/crud-links.md +1 -1
  109. package/skills/jskit/references/heuristics/crud-repository-mapping.md +3 -3
  110. package/skills/jskit/references/heuristics/filters.md +1 -1
  111. package/skills/jskit/references/heuristics/live-actions.md +1 -1
  112. package/skills/jskit/references/heuristics/page-redirects.md +1 -1
  113. package/skills/jskit/references/heuristics/page-scaffolding.md +1 -1
  114. package/skills/jskit/references/heuristics/placements.md +1 -1
  115. package/skills/jskit/references/heuristics/row-policies.md +1 -1
  116. package/skills/jskit/references/heuristics/server-search.md +1 -1
  117. package/skills/jskit/references/heuristics/surfaces.md +1 -1
  118. package/skills/jskit/references/heuristics/typed-features.md +100 -0
  119. package/skills/jskit/references/heuristics/ui-contract.md +1 -1
  120. package/skills/jskit/references/heuristics/ui-testing.md +4 -4
  121. package/skills/jskit/references/material-3.md +2 -2
  122. package/skills/jskit/references/multi-homing.md +96 -50
  123. package/skills/jskit/references/pattern-index.md +37 -37
  124. package/skills/jskit/references/patterns/app/minimal-foundation/PATTERN.md +30 -1
  125. package/skills/jskit/references/patterns/app/minimal-foundation/example/AGENTS.md +14 -0
  126. package/skills/jskit/references/patterns/app/minimal-foundation/example/bin/develop.js +10 -5
  127. package/skills/jskit/references/patterns/app/minimal-foundation/example/eslint.config.mjs +21 -2
  128. package/skills/jskit/references/patterns/app/minimal-foundation/example/package.json +5 -4
  129. package/skills/jskit/references/patterns/app/minimal-foundation/example/playwright.config.mjs +1 -1
  130. package/skills/jskit/references/patterns/app/minimal-foundation/example/server/lib/envFile.js +19 -0
  131. package/skills/jskit/references/patterns/app/minimal-foundation/example/server/lib/loggerOptions.js +15 -0
  132. package/skills/jskit/references/patterns/app/minimal-foundation/example/server/lib/runtimeEnv.js +17 -17
  133. package/skills/jskit/references/patterns/app/minimal-foundation/example/server.js +32 -29
  134. package/skills/jskit/references/patterns/app/minimal-foundation/example/tests/server/smoke.test.js +2 -1
  135. package/skills/jskit/references/patterns/app/shell-foundation/PATTERN.md +29 -0
  136. package/skills/jskit/references/patterns/app/shell-foundation/example/AGENTS.md +14 -0
  137. package/skills/jskit/references/patterns/app/shell-foundation/example/bin/develop.js +10 -5
  138. package/skills/jskit/references/patterns/app/shell-foundation/example/eslint.config.mjs +21 -2
  139. package/skills/jskit/references/patterns/app/shell-foundation/example/package.json +6 -5
  140. package/skills/jskit/references/patterns/app/shell-foundation/example/packages/main/package.json +1 -1
  141. package/skills/jskit/references/patterns/app/shell-foundation/example/packages/main/src/client/providers/MainClientProvider.js +1 -0
  142. package/skills/jskit/references/patterns/app/shell-foundation/example/playwright.config.mjs +1 -1
  143. package/skills/jskit/references/patterns/app/shell-foundation/example/server/lib/envFile.js +19 -0
  144. package/skills/jskit/references/patterns/app/shell-foundation/example/server/lib/loggerOptions.js +15 -0
  145. package/skills/jskit/references/patterns/app/shell-foundation/example/server/lib/runtimeEnv.js +17 -17
  146. package/skills/jskit/references/patterns/app/shell-foundation/example/server.js +32 -29
  147. package/skills/jskit/references/patterns/app/shell-foundation/example/tests/server/smoke.test.js +2 -1
  148. package/skills/jskit/references/patterns/assistant/assistant-surface/example/src/ApplicationAiFeature.js +4 -2
  149. package/skills/jskit/references/patterns/auth/accounts-hub/PATTERN.md +2 -1
  150. package/skills/jskit/references/patterns/auth/accounts-hub/example/package.json +2 -2
  151. package/skills/jskit/references/patterns/auth/accounts-hub/example/server/hubPaths.js +9 -3
  152. package/skills/jskit/references/patterns/auth/auth-surface/PATTERN.md +25 -12
  153. package/skills/jskit/references/patterns/auth/auth-surface/example/tools/preview-identity +7 -1
  154. package/skills/jskit/references/patterns/auth/oidc-sign-in/example/package.json +2 -2
  155. package/skills/jskit/references/patterns/auth/supabase-auth/example/package.json +1 -1
  156. package/skills/jskit/references/patterns/connectors/ai-connections/PATTERN.md +16 -1
  157. package/skills/jskit/references/patterns/connectors/ai-connections/example/ai-model.js +12 -3
  158. package/skills/jskit/references/patterns/connectors/ai-connections/example/perplexity-answer.js +15 -4
  159. package/skills/jskit/references/patterns/connectors/api-key-connection/PATTERN.md +9 -1
  160. package/skills/jskit/references/patterns/connectors/api-key-connection/example/connections.js +5 -2
  161. package/skills/jskit/references/patterns/connectors/aws-storage-queries/PATTERN.md +13 -3
  162. package/skills/jskit/references/patterns/connectors/aws-storage-queries/example/s3-transfer.js +14 -3
  163. package/skills/jskit/references/patterns/connectors/calendar-cli/PATTERN.md +8 -0
  164. package/skills/jskit/references/patterns/connectors/calendar-cli/example/knexfile.js +1 -1
  165. package/skills/jskit/references/patterns/connectors/calendar-cli/example/package.json +4 -4
  166. package/skills/jskit/references/patterns/connectors/calendar-cli/example/scripts/calendar.js +8 -4
  167. package/skills/jskit/references/patterns/connectors/event-delivery/PATTERN.md +1 -1
  168. package/skills/jskit/references/patterns/connectors/firebase-messaging/PATTERN.md +10 -0
  169. package/skills/jskit/references/patterns/connectors/firebase-messaging/example/server/notifications.js +8 -0
  170. package/skills/jskit/references/patterns/connectors/google-ads-search/PATTERN.md +18 -7
  171. package/skills/jskit/references/patterns/connectors/google-ads-search/example/ads-setup.js +13 -5
  172. package/skills/jskit/references/patterns/connectors/oauth-connection/PATTERN.md +1 -1
  173. package/skills/jskit/references/patterns/connectors/paddle-catalogue/PATTERN.md +11 -2
  174. package/skills/jskit/references/patterns/connectors/paddle-catalogue/example/create-products.js +5 -2
  175. package/skills/jskit/references/patterns/connectors/public-image/PATTERN.md +10 -1
  176. package/skills/jskit/references/patterns/connectors/public-image/example/logo-url.js +4 -1
  177. package/skills/jskit/references/patterns/connectors/redshift-queries/PATTERN.md +1 -1
  178. package/skills/jskit/references/patterns/connectors/source-scanning/PATTERN.md +13 -2
  179. package/skills/jskit/references/patterns/connectors/source-scanning/example/source-scanner.js +9 -0
  180. package/skills/jskit/references/patterns/crud/json-api-resource-package/PATTERN.md +102 -23
  181. package/skills/jskit/references/patterns/crud/json-api-resource-package/example/packages/books/package.json +3 -2
  182. package/skills/jskit/references/patterns/crud/json-api-resource-package/example/packages/books/src/server/types.js +5 -0
  183. package/skills/jskit/references/patterns/crud/resource-contract/PATTERN.md +54 -1
  184. package/skills/jskit/references/patterns/database/mysql-application/PATTERN.md +16 -5
  185. package/skills/jskit/references/patterns/database/mysql-application/example/knexfile.js +2 -2
  186. package/skills/jskit/references/patterns/database/mysql-application/example/package.json +1 -1
  187. package/skills/jskit/references/patterns/database/mysql-application/example/scripts/prepare-database.js +1 -1
  188. package/skills/jskit/references/patterns/database/postgres-application/PATTERN.md +16 -5
  189. package/skills/jskit/references/patterns/database/postgres-application/example/knexfile.js +2 -2
  190. package/skills/jskit/references/patterns/database/postgres-application/example/package.json +1 -1
  191. package/skills/jskit/references/patterns/database/postgres-application/example/scripts/prepare-database.js +1 -1
  192. package/skills/jskit/references/patterns/realtime/realtime-application/example/package.json +2 -2
  193. package/skills/jskit/references/patterns/rewards/google-rewarded/example/GoogleRewardedDeliveryProvider.js +1 -1
  194. package/skills/jskit/references/patterns/rewards/google-rewarded/example/googlePublisherTag.js +5 -11
  195. package/skills/jskit/references/patterns/server/feature-package/PATTERN.md +104 -10
  196. package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/package.json +9 -4
  197. package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/src/server/BookingEngineFeature.js +24 -0
  198. package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/src/server/bookingAvailability.js +10 -0
  199. package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/src/server/bookingEngine.js +29 -0
  200. package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/src/server/bookingEngineActions.js +26 -0
  201. package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/src/server/inputSchemas.js +1 -2
  202. package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/src/server/types.js +12 -0
  203. package/skills/jskit/references/patterns/server/feature-package/example/variations/AvailabilityEngineFeature.js +19 -0
  204. package/skills/jskit/references/patterns/server/feature-package/example/variations/InvoiceRollupFeature.js +23 -0
  205. package/skills/jskit/references/patterns/server/feature-package/example/variations/availabilityEngineActions.js +26 -0
  206. package/skills/jskit/references/patterns/server/feature-package/example/variations/customKnexRepository.js +32 -26
  207. package/skills/jskit/references/patterns/server/feature-package/example/variations/invoiceRollupActions.js +26 -0
  208. package/skills/jskit/references/patterns/server/feature-package/example/variations/orchestratorService.js +24 -19
  209. package/skills/jskit/references/patterns/server/feature-package/example/variations/types.js +7 -0
  210. package/skills/jskit/references/patterns/users/user-administration-server/PATTERN.md +16 -1
  211. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users/package.json +3 -2
  212. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users/src/server/types.js +5 -0
  213. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users-workspace/package.json +4 -3
  214. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users-workspace/src/server/UsersWorkspaceFeature.js +2 -9
  215. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users-workspace/src/server/types.js +5 -0
  216. package/skills/jskit/references/patterns/workspaces/workspace-server/PATTERN.md +42 -17
  217. package/skills/jskit/references/patterns/workspaces/workspace-server/example/packages/main/src/server/WorkspaceInvitationsFeature.js +27 -0
  218. package/skills/jskit/references/patterns/workspaces/workspace-server/example/packages/main/src/server/email/workspaceInviteEmail.js +11 -10
  219. package/skills/jskit/references/patterns/workspaces/workspace-server/example/packages/main/src/server/email/workspaceInviteMailer.js +27 -0
  220. package/skills/jskit/references/translation.md +5 -4
  221. package/skills/jskit/references/typed-features.md +1099 -0
  222. package/skills/jskit/references/ui-operations.md +3 -3
  223. package/patterns/feature-package/example/booking-engine/src/server/BookingEngineProvider.js +0 -33
  224. package/patterns/feature-package/example/booking-engine/src/server/actions.js +0 -24
  225. package/patterns/feature-package/example/variations/AvailabilityEngineProvider.js +0 -31
  226. package/patterns/feature-package/example/variations/InvoiceRollupProvider.js +0 -36
  227. package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/src/server/BookingEngineProvider.js +0 -33
  228. package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/src/server/actions.js +0 -24
  229. package/skills/jskit/references/patterns/server/feature-package/example/variations/AvailabilityEngineProvider.js +0 -31
  230. package/skills/jskit/references/patterns/server/feature-package/example/variations/InvoiceRollupProvider.js +0 -36
@@ -42,8 +42,43 @@ questionnaire.
42
42
  the feature package.
43
43
  - `defineFeature()` receives only declared capabilities and returns only
44
44
  declared feature APIs.
45
- - Actions define the public operation contract and close over the feature APIs
46
- they need. They never resolve arbitrary dependencies at execution time.
45
+ - Each provided capability exports its type. A named `create<Name>` factory in
46
+ its own module builds the value `setup()` returns, and `types.js` declares
47
+ one `@typedef` per provided token, named after the token in PascalCase
48
+ (`feature.booking-engine` -> `BookingEngine`). A package exports it as
49
+ `./server/types`.
50
+ - Every factory, action creator and hook that receives a collaborator names its
51
+ type in a JSDoc `@param`: `import("./types.js").<Name>` or
52
+ `ReturnType<typeof createX>` inside the package, the owner's `./server/types`
53
+ across packages; a Knex client is database-runtime's `RuntimeKnex`.
54
+ - Collaborators are required. There is no `= null`, `= {}` or no-op default,
55
+ no `typeof` probe, no optional call and no "requires x" guard: the capability
56
+ runtime refuses to start without a required token.
57
+ - An extension point is an `optional` token whose default the package names
58
+ in a module of its own and `setup()` resolves once with `??`, never a setter
59
+ that fills a slot later or a module-level registry. The token is typed
60
+ `X | null` only in `setup()`; what `setup()` builds receives it as required.
61
+ - One `create<Name>Actions({ <api> })` per feature, destructured, in
62
+ `<name>Actions.js`, creates its actions and closes over the feature APIs they
63
+ need. Every definition and the list are frozen. Each definition spreads one
64
+ frozen constant of the fields its kind shares (`version`, `kind`,
65
+ `channels`, `surfaces`) first. Each id is a string literal or a module-level
66
+ constant, and `execute: (input, context) => api.method(input, { context })`
67
+ is one call, without `async`, a body, an envelope or a helper that builds or
68
+ strips it. Actions never resolve arbitrary dependencies at execution time.
69
+ - Methods take the validated input as it is: no `input = {}` default, no
70
+ `input?.x` and no second normalization of fields the input schema already
71
+ checked. An options bag whose fields are optional by contract
72
+ (`options = {}` with `trx`) keeps its default.
73
+ - The package reads the actor from an action context one way, with the
74
+ kernel's `resolveActorId(context)` or `resolveActor(context)`
75
+ (`@jskit-ai/kernel/server/actions/actionContributorHelpers`), and its actions
76
+ pass the context one way.
77
+ - Every `create*` returns `Object.freeze({ … })` of named inner functions, and
78
+ exposes another factory's functions by name, never by spreading it.
79
+ - A description sits inside its `/** */` block, never in a `//` line above it.
80
+ - One copy of each pure helper per package, imported directly. Files stay under
81
+ 750 lines and functions under 600, one concern per factory.
47
82
  - The service orchestrates the feature and does not issue SQL directly.
48
83
  - A repository owns persistence and accepts transaction/context options.
49
84
  - The normal persistence lane uses a public or documented high-level resource
@@ -68,20 +103,65 @@ The custom persistence variation uses `createWithTransaction()` from
68
103
  ## Example files
69
104
 
70
105
  `example/booking-engine/` is a concrete app-local package showing the preferred
71
- small-feature boundary. Its status query is deliberately small: product logic
72
- can grow inside the returned feature API without creating ceremonial layers.
73
-
74
- `example/variations/AvailabilityEngineProvider.js` and
106
+ small-feature boundary:
107
+
108
+ - `src/server/BookingEngineFeature.js` declares the feature, its optional
109
+ `feature.booking-engine.availability` slot and the engine it provides;
110
+ - `src/server/bookingEngine.js` builds the engine with `createBookingEngine()`,
111
+ a frozen object of named functions, and reads who asked with the kernel's
112
+ `resolveActorId(context)`;
113
+ - `src/server/bookingAvailability.js` names the slot's default,
114
+ `everyScopeOpen`;
115
+ - `src/server/bookingEngineActions.js` creates its one-line, frozen actions
116
+ with `createBookingEngineActions({ bookingEngine })`, each spreading the
117
+ shared `BOOKING_QUERY` fields first;
118
+ - `src/server/types.js` declares `BookingEngine` and
119
+ `BookingEngineAvailability`, exported as `./server/types`.
120
+
121
+ Its status query is deliberately small: product logic can grow inside the
122
+ returned feature API without creating ceremonial layers. The feature resolves
123
+ the slot once:
124
+
125
+ ```js
126
+ optional: {
127
+ availability: "feature.booking-engine.availability"
128
+ },
129
+ /** @param {{ availability: import("./types.js").BookingEngineAvailability | null }} capabilities */
130
+ setup({ availability }) {
131
+ return { bookingEngine: createBookingEngine({ availability: availability ?? everyScopeOpen }) };
132
+ },
133
+ ```
134
+
135
+ Another package fills the slot by providing the token, never by calling a
136
+ setter:
137
+
138
+ ```js
139
+ const SeasonalAvailabilityFeature = defineFeature({
140
+ id: "feature.seasonal-availability",
141
+ provides: { availability: "feature.booking-engine.availability" },
142
+ setup: () => ({ availability: isInSeason })
143
+ });
144
+ ```
145
+
146
+ `example/variations/AvailabilityEngineFeature.js`,
147
+ `example/variations/availabilityEngineActions.js` and
75
148
  `example/variations/orchestratorService.js` show the repository-free lane.
76
- `example/variations/InvoiceRollupProvider.js` and
149
+ `example/variations/InvoiceRollupFeature.js`,
150
+ `example/variations/invoiceRollupActions.js` and
77
151
  `example/variations/customKnexRepository.js` show the explicit custom
78
- persistence lane.
152
+ persistence lane. `example/variations/types.js` declares the
153
+ `AvailabilityEngine` and `InvoiceRollup` types.
154
+
155
+ The [typed features guide](https://mobily-enterprises.github.io/jskit-ai/guide/framework/typed-features)
156
+ explains each rule this example follows, with a good and a bad example, and
157
+ `npm run lint` checks the ones a machine can see.
79
158
 
80
159
  ## Variation points
81
160
 
82
161
  Rename the package, capability id, actions, validators, and domain methods.
83
- Select the correct channels and surfaces in `actionDefaults`, overriding them
84
- only for exceptional actions. Add a service when orchestration is shared or
162
+ Select the channels and surfaces in the shared-field constant each definition
163
+ spreads first; a kind of action whose values differ gets a constant of its
164
+ own. Add a service when orchestration is shared or
85
165
  stateful. Add a repository only when the feature owns persistence. Replace the
86
166
  illustrative status query with narrow product language before shipping.
87
167
 
@@ -104,5 +184,19 @@ illustrative status query with narrow product language before shipping.
104
184
  - a repository for an orchestration-only feature
105
185
  - generic `execute(anything)` operations in finished product code
106
186
  - `app.make()`, `scope.make()`, container tokens, or service-location helpers
187
+ - probing a collaborator (`typeof x.method === "function"`, `x?.method?.()`)
188
+ before calling it
189
+ - absent defaults on a collaborator or on the dependencies object (`= null`,
190
+ `= {}`, a no-op)
191
+ - setters that fill a slot after construction, and module-level registries
192
+ - a collaborator accepted in two shapes (`capability.service || capability`)
193
+ - an `async` `execute`, an `execute` with a body, or a helper that builds an
194
+ action or strips its input
195
+ - a hand-written `(...args: any[]) => Promise<any>` type instead of the
196
+ owner's type, and the same `ReturnType<…>` or indexed type spelled out in
197
+ several files
198
+ - spreading an in-package factory's result into a provided value
199
+ - unfrozen `create*` results and inline methods
200
+ - a guard, default or comment that exists for a test double
107
201
  - metadata claiming which authoring tool or pattern created the package
108
202
  - field questionnaires, overwrite switches, or durable operation records
@@ -5,11 +5,12 @@
5
5
  "private": true,
6
6
  "type": "module",
7
7
  "dependencies": {
8
- "@jskit-ai/kernel": "0.2.3",
8
+ "@jskit-ai/kernel": "0.2.4",
9
9
  "json-rest-schema": "^1.0.17"
10
10
  },
11
11
  "exports": {
12
- "./server/actions": "./src/server/actions.js"
12
+ "./server/actions": "./src/server/bookingEngineActions.js",
13
+ "./server/types": "./src/server/types.js"
13
14
  },
14
15
  "jskit": {
15
16
  "kind": "runtime",
@@ -25,8 +26,8 @@
25
26
  "server": {
26
27
  "providers": [
27
28
  {
28
- "entrypoint": "src/server/BookingEngineProvider.js",
29
- "export": "BookingEngineProvider"
29
+ "entrypoint": "src/server/BookingEngineFeature.js",
30
+ "export": "BookingEngineFeature"
30
31
  }
31
32
  ]
32
33
  },
@@ -40,6 +41,10 @@
40
41
  {
41
42
  "subpath": "./server/actions",
42
43
  "summary": "Exports booking-engine action definitions."
44
+ },
45
+ {
46
+ "subpath": "./server/types",
47
+ "summary": "Types of the feature.booking-engine capability and its optional feature.booking-engine.availability slot."
43
48
  }
44
49
  ]
45
50
  }
@@ -0,0 +1,24 @@
1
+ import { defineFeature } from "@jskit-ai/kernel/server/features";
2
+ import { everyScopeOpen } from "./bookingAvailability.js";
3
+ import { createBookingEngine } from "./bookingEngine.js";
4
+ import { createBookingEngineActions } from "./bookingEngineActions.js";
5
+
6
+ const BookingEngineFeature = defineFeature({
7
+ id: "feature.booking-engine",
8
+ domain: "booking",
9
+ optional: {
10
+ availability: "feature.booking-engine.availability"
11
+ },
12
+ provides: {
13
+ bookingEngine: "feature.booking-engine"
14
+ },
15
+ /** @param {{ availability: import("./types.js").BookingEngineAvailability | null }} capabilities */
16
+ setup({ availability }) {
17
+ return { bookingEngine: createBookingEngine({ availability: availability ?? everyScopeOpen }) };
18
+ },
19
+ actions({ bookingEngine }) {
20
+ return createBookingEngineActions({ bookingEngine });
21
+ }
22
+ });
23
+
24
+ export { BookingEngineFeature };
@@ -0,0 +1,10 @@
1
+ /**
2
+ * The `feature.booking-engine.availability` default when no package provides
3
+ * one: every scope takes bookings.
4
+ * @type {import("./types.js").BookingEngineAvailability}
5
+ */
6
+ async function everyScopeOpen() {
7
+ return true;
8
+ }
9
+
10
+ export { everyScopeOpen };
@@ -0,0 +1,29 @@
1
+ import { resolveActorId } from "@jskit-ai/kernel/server/actions/actionContributorHelpers";
2
+
3
+ /**
4
+ * The booking engine the feature provides as `feature.booking-engine`.
5
+ * @param {object} dependencies
6
+ * @param {import("./types.js").BookingEngineAvailability} dependencies.availability
7
+ */
8
+ function createBookingEngine({ availability }) {
9
+ /**
10
+ * Reports, for the validated query, whether its scope takes bookings and who
11
+ * asked.
12
+ * @param {{ scope?: string, verbose?: boolean }} query
13
+ * @param {{ context: object }} options
14
+ */
15
+ async function readStatus({ scope = "default", verbose = false }, { context }) {
16
+ return {
17
+ ok: true,
18
+ feature: "booking-engine",
19
+ scope,
20
+ verbose,
21
+ open: await availability(scope),
22
+ requestedBy: resolveActorId(context)
23
+ };
24
+ }
25
+
26
+ return Object.freeze({ readStatus });
27
+ }
28
+
29
+ export { createBookingEngine };
@@ -0,0 +1,26 @@
1
+ import { statusQueryInputValidator } from "./inputSchemas.js";
2
+
3
+ const ACTION_GET_STATUS = "feature.booking-engine.status.read";
4
+
5
+ /** The fields every booking query shares, spread first into each definition. */
6
+ const BOOKING_QUERY = Object.freeze({
7
+ version: 1,
8
+ kind: "query",
9
+ channels: ["api", "assistant", "internal"],
10
+ surfaces: ["app"]
11
+ });
12
+
13
+ /** @param {{ bookingEngine: import("./types.js").BookingEngine }} dependencies */
14
+ function createBookingEngineActions({ bookingEngine }) {
15
+ return Object.freeze([
16
+ Object.freeze({
17
+ ...BOOKING_QUERY,
18
+ id: ACTION_GET_STATUS,
19
+ input: statusQueryInputValidator,
20
+ output: null,
21
+ execute: (input, context) => bookingEngine.readStatus(input, { context })
22
+ })
23
+ ]);
24
+ }
25
+
26
+ export { ACTION_GET_STATUS, createBookingEngineActions };
@@ -12,8 +12,7 @@ const statusQueryInputValidator = deepFreeze({
12
12
  type: "boolean",
13
13
  required: false
14
14
  }
15
- }),
16
- mode: "patch"
15
+ })
17
16
  });
18
17
 
19
18
  export { statusQueryInputValidator };
@@ -0,0 +1,12 @@
1
+ // The types of the `feature.booking-engine` capability and of its optional
2
+ // `feature.booking-engine.availability` slot.
3
+
4
+ /** @typedef {ReturnType<typeof import("./bookingEngine.js").createBookingEngine>} BookingEngine */
5
+
6
+ /**
7
+ * The `feature.booking-engine.availability` slot: answers whether a scope takes
8
+ * bookings. A package supplies it by providing that token.
9
+ * @typedef {(scope: string) => Promise<boolean>} BookingEngineAvailability
10
+ */
11
+
12
+ export {};
@@ -0,0 +1,19 @@
1
+ import { defineFeature } from "@jskit-ai/kernel/server/features";
2
+ import { createAvailabilityEngineActions } from "./availabilityEngineActions.js";
3
+ import { createAvailabilityEngine } from "./orchestratorService.js";
4
+
5
+ const AvailabilityEngineFeature = defineFeature({
6
+ id: "feature.availability-engine",
7
+ domain: "availability",
8
+ provides: {
9
+ availabilityEngine: "feature.availability-engine"
10
+ },
11
+ setup() {
12
+ return { availabilityEngine: createAvailabilityEngine() };
13
+ },
14
+ actions({ availabilityEngine }) {
15
+ return createAvailabilityEngineActions({ availabilityEngine });
16
+ }
17
+ });
18
+
19
+ export { AvailabilityEngineFeature };
@@ -0,0 +1,23 @@
1
+ import { defineFeature } from "@jskit-ai/kernel/server/features";
2
+ import { createInvoiceRollup } from "./customKnexRepository.js";
3
+ import { createInvoiceRollupActions } from "./invoiceRollupActions.js";
4
+
5
+ const InvoiceRollupFeature = defineFeature({
6
+ id: "feature.invoice-rollup",
7
+ domain: "invoices",
8
+ requires: {
9
+ database: "runtime.database"
10
+ },
11
+ provides: {
12
+ invoiceRollup: "feature.invoice-rollup"
13
+ },
14
+ /** @param {{ database: import("@jskit-ai/database-runtime/server/types").RuntimeDatabase }} capabilities */
15
+ setup({ database }) {
16
+ return { invoiceRollup: createInvoiceRollup({ knex: database.knex }) };
17
+ },
18
+ actions({ invoiceRollup }) {
19
+ return createInvoiceRollupActions({ invoiceRollup });
20
+ }
21
+ });
22
+
23
+ export { InvoiceRollupFeature };
@@ -0,0 +1,26 @@
1
+ import { emptyInputValidator } from "@jskit-ai/kernel/server/actions/actionContributorHelpers";
2
+
3
+ const ACTION_GET_AVAILABILITY_STATUS = "availability.status.read";
4
+
5
+ /** The fields every availability query shares, spread first into each definition. */
6
+ const AVAILABILITY_QUERY = Object.freeze({
7
+ version: 1,
8
+ kind: "query",
9
+ channels: ["api", "assistant", "internal"],
10
+ surfaces: ["app"]
11
+ });
12
+
13
+ /** @param {{ availabilityEngine: import("./types.js").AvailabilityEngine }} dependencies */
14
+ function createAvailabilityEngineActions({ availabilityEngine }) {
15
+ return Object.freeze([
16
+ Object.freeze({
17
+ ...AVAILABILITY_QUERY,
18
+ id: ACTION_GET_AVAILABILITY_STATUS,
19
+ input: emptyInputValidator,
20
+ output: null,
21
+ execute: (input) => availabilityEngine.getStatus(input)
22
+ })
23
+ ]);
24
+ }
25
+
26
+ export { ACTION_GET_AVAILABILITY_STATUS, createAvailabilityEngineActions };
@@ -1,34 +1,40 @@
1
1
  import { createWithTransaction } from "@jskit-ai/database-runtime/shared";
2
2
 
3
- function createRepository({ knex } = {}) {
4
- if (!knex) {
5
- throw new TypeError("createRepository requires knex.");
3
+ /**
4
+ * The invoice rollup's persistence: a reviewed custom Knex repository.
5
+ * @param {{ knex: import("@jskit-ai/database-runtime/server/types").RuntimeKnex }} dependencies
6
+ */
7
+ function createInvoiceRollup({ knex }) {
8
+ const withTransaction = createWithTransaction(knex);
9
+
10
+ async function getStatus(input, options = {}) {
11
+ return {
12
+ ok: true,
13
+ feature: "invoice-rollup",
14
+ persistence: "custom-knex",
15
+ tableName: "invoice_rollups",
16
+ hasTransaction: Boolean(options.trx),
17
+ input
18
+ };
19
+ }
20
+
21
+ async function execute(input, options = {}) {
22
+ return {
23
+ accepted: false,
24
+ feature: "invoice-rollup",
25
+ persistence: "custom-knex",
26
+ tableName: "invoice_rollups",
27
+ hasTransaction: Boolean(options.trx),
28
+ input,
29
+ message: "Replace this example with the reviewed domain-specific query."
30
+ };
6
31
  }
7
32
 
8
33
  return Object.freeze({
9
- withTransaction: createWithTransaction(knex),
10
- async getStatus(input = {}, options = {}) {
11
- return {
12
- ok: true,
13
- feature: "invoice-rollup",
14
- persistence: "custom-knex",
15
- tableName: "invoice_rollups",
16
- hasTransaction: Boolean(options.trx),
17
- input
18
- };
19
- },
20
- async execute(input = {}, options = {}) {
21
- return {
22
- accepted: false,
23
- feature: "invoice-rollup",
24
- persistence: "custom-knex",
25
- tableName: "invoice_rollups",
26
- hasTransaction: Boolean(options.trx),
27
- input,
28
- message: "Replace this example with the reviewed domain-specific query."
29
- };
30
- }
34
+ withTransaction,
35
+ getStatus,
36
+ execute
31
37
  });
32
38
  }
33
39
 
34
- export { createRepository };
40
+ export { createInvoiceRollup };
@@ -0,0 +1,26 @@
1
+ import { emptyInputValidator } from "@jskit-ai/kernel/server/actions/actionContributorHelpers";
2
+
3
+ const ACTION_GET_ROLLUP_STATUS = "invoices.rollup.status.read";
4
+
5
+ /** The fields every invoice rollup query shares, spread first into each definition: they run on the admin surface. */
6
+ const ROLLUP_QUERY = Object.freeze({
7
+ version: 1,
8
+ kind: "query",
9
+ channels: ["api", "assistant", "internal"],
10
+ surfaces: ["admin"]
11
+ });
12
+
13
+ /** @param {{ invoiceRollup: import("./types.js").InvoiceRollup }} dependencies */
14
+ function createInvoiceRollupActions({ invoiceRollup }) {
15
+ return Object.freeze([
16
+ Object.freeze({
17
+ ...ROLLUP_QUERY,
18
+ id: ACTION_GET_ROLLUP_STATUS,
19
+ input: emptyInputValidator,
20
+ output: null,
21
+ execute: (input, context) => invoiceRollup.getStatus(input, { context })
22
+ })
23
+ ]);
24
+ }
25
+
26
+ export { ACTION_GET_ROLLUP_STATUS, createInvoiceRollupActions };
@@ -1,23 +1,28 @@
1
- function createService() {
1
+ /** The availability engine: orchestration with no persistence of its own. */
2
+ function createAvailabilityEngine() {
3
+ async function getStatus(input) {
4
+ return {
5
+ ok: true,
6
+ feature: "availability-engine",
7
+ mode: "orchestrator",
8
+ input
9
+ };
10
+ }
11
+
12
+ async function execute(input) {
13
+ return {
14
+ accepted: false,
15
+ feature: "availability-engine",
16
+ mode: "orchestrator",
17
+ input,
18
+ message: "Replace this example with calls to the feature's injected collaborators."
19
+ };
20
+ }
21
+
2
22
  return Object.freeze({
3
- async getStatus(input = {}) {
4
- return {
5
- ok: true,
6
- feature: "availability-engine",
7
- mode: "orchestrator",
8
- input
9
- };
10
- },
11
- async execute(input = {}) {
12
- return {
13
- accepted: false,
14
- feature: "availability-engine",
15
- mode: "orchestrator",
16
- input,
17
- message: "Replace this example with calls to the feature's injected collaborators."
18
- };
19
- }
23
+ getStatus,
24
+ execute
20
25
  });
21
26
  }
22
27
 
23
- export { createService };
28
+ export { createAvailabilityEngine };
@@ -0,0 +1,7 @@
1
+ // The types of the `feature.availability-engine` and `feature.invoice-rollup`
2
+ // capabilities, for features that require them.
3
+
4
+ /** @typedef {ReturnType<typeof import("./orchestratorService.js").createAvailabilityEngine>} AvailabilityEngine */
5
+ /** @typedef {ReturnType<typeof import("./customKnexRepository.js").createInvoiceRollup>} InvoiceRollup */
6
+
7
+ export {};
@@ -38,12 +38,25 @@ and the resource contracts from `@jskit-ai/resource-crud-core`.
38
38
  - Shared profile persistence remains owned by `@jskit-ai/users-core`.
39
39
  - The resource is the field contract; the feature projects its repository,
40
40
  service, actions, and routes without app-local ceremony.
41
+ - Each package exports the type of the capability it provides:
42
+ `src/server/types.js` declares `AppUsers` (for `app.users`) or
43
+ `AppUsersWorkspace` (for `app.users-workspace`) as crud-core's
44
+ `CrudResourceApi`, exported as `./server/types`. A feature that requires the
45
+ capability names that type in a JSDoc `@param`.
46
+ - Code added to a declaration follows [typed features](https://github.com/mobily-enterprises/jskit-ai/blob/main/packages/agent-docs/site/guide/framework/typed-features.md):
47
+ decorators, lifecycle hooks and named actions call the collaborators they
48
+ receive directly, with no `typeof` probe, optional call, absent default,
49
+ slot setter or module-level registry, and each action's `execute` is one
50
+ call to one service method with the validated input. Keep one copy of each
51
+ helper per package, files under 750 lines and functions under 600.
41
52
 
42
53
  ## Example files
43
54
 
44
55
  `example/packages/users/` is a global administration package.
45
56
  `example/packages/users-workspace/` demonstrates the workspace route/action
46
- boundary while reusing the same service contract. Copy only the composition
57
+ boundary, with workspaces-core's `WORKSPACE_CRUD_SCOPE`, while reusing the same
58
+ service contract. Each package's
59
+ `src/server/types.js` declares the type of the capability it provides. Copy only the composition
47
60
  that matches the product and adapt it as ordinary application source.
48
61
 
49
62
  ## Variation points
@@ -62,3 +75,5 @@ isolation, missing records, null/cleared fields, filtering, and pagination.
62
75
  - trusting route scope without repository scope
63
76
  - adding app-local mechanics already provided by `defineCrudJsonApiFeature()`
64
77
  - generator metadata or field questionnaires
78
+ - probing a collaborator, defaulting one to `null`, `{}` or a no-op, setters
79
+ that fill a slot after construction, and module-level registries
@@ -6,11 +6,12 @@
6
6
  "type": "module",
7
7
  "exports": {
8
8
  "./server/UsersFeature": "./src/server/UsersFeature.js",
9
+ "./server/types": "./src/server/types.js",
9
10
  "./shared": "./src/shared/index.js"
10
11
  },
11
12
  "dependencies": {
12
- "@jskit-ai/crud-core": "0.2.3",
13
- "@jskit-ai/resource-crud-core": "0.1.194"
13
+ "@jskit-ai/crud-core": "0.2.4",
14
+ "@jskit-ai/resource-crud-core": "0.1.195"
14
15
  },
15
16
  "jskit": {
16
17
  "kind": "runtime",
@@ -0,0 +1,5 @@
1
+ // The type of the `app.users` capability, for features that require it.
2
+
3
+ /** @typedef {import("@jskit-ai/crud-core/server/types").CrudResourceApi} AppUsers */
4
+
5
+ export {};
@@ -6,12 +6,13 @@
6
6
  "type": "module",
7
7
  "exports": {
8
8
  "./server/UsersWorkspaceFeature": "./src/server/UsersWorkspaceFeature.js",
9
+ "./server/types": "./src/server/types.js",
9
10
  "./shared": "./src/shared/index.js"
10
11
  },
11
12
  "dependencies": {
12
- "@jskit-ai/crud-core": "0.2.3",
13
- "@jskit-ai/resource-crud-core": "0.1.194",
14
- "@jskit-ai/workspaces-core": "0.2.4"
13
+ "@jskit-ai/crud-core": "0.2.4",
14
+ "@jskit-ai/resource-crud-core": "0.1.195",
15
+ "@jskit-ai/workspaces-core": "0.2.5"
15
16
  },
16
17
  "jskit": {
17
18
  "kind": "runtime",
@@ -1,6 +1,5 @@
1
1
  import { defineCrudJsonApiFeature } from "@jskit-ai/crud-core/server/defineCrudJsonApiFeature";
2
- import { buildWorkspaceInputFromRouteParams } from "@jskit-ai/workspaces-core/server/support/workspaceRouteInput";
3
- import { workspaceSlugParamsValidator } from "@jskit-ai/workspaces-core/server/validators/routeParamsValidator";
2
+ import { WORKSPACE_CRUD_SCOPE } from "@jskit-ai/workspaces-core/server/support/workspaceCrud";
4
3
  import { resource } from "../shared/userResource.js";
5
4
 
6
5
  const UsersWorkspaceFeature = defineCrudJsonApiFeature({
@@ -10,13 +9,7 @@ const UsersWorkspaceFeature = defineCrudJsonApiFeature({
10
9
  surface: "admin",
11
10
  ownershipFilter: "workspace",
12
11
  relativePath: "/users",
13
- scope: {
14
- routeBase: "/w/:workspaceSlug",
15
- actionInputValidator: workspaceSlugParamsValidator,
16
- routeParamsValidator: workspaceSlugParamsValidator,
17
- inputKeys: ["workspaceSlug"],
18
- input: (request) => buildWorkspaceInputFromRouteParams(request.input.params)
19
- }
12
+ scope: WORKSPACE_CRUD_SCOPE
20
13
  });
21
14
 
22
15
  export { UsersWorkspaceFeature };
@@ -0,0 +1,5 @@
1
+ // The type of the `app.users-workspace` capability, for features that require it.
2
+
3
+ /** @typedef {import("@jskit-ai/crud-core/server/types").CrudResourceApi} AppUsersWorkspace */
4
+
5
+ export {};