@jskit-ai/agent-docs 0.1.148 → 0.1.150

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 (232) hide show
  1. package/guide/agent/app-setup/existing-application-migration.md +8 -6
  2. package/guide/agent/app-setup/initial-scaffolding.md +26 -7
  3. package/guide/agent/app-setup/quickstart.md +9 -6
  4. package/guide/agent/framework/application-operations.md +91 -0
  5. package/guide/agent/framework/crud-operations.md +83 -0
  6. package/guide/agent/framework/material-3.md +112 -0
  7. package/guide/agent/framework/ui-operations.md +78 -0
  8. package/guide/agent/index.md +13 -3
  9. package/package.json +1 -1
  10. package/patterns/feature-package/example/booking-engine/package.json +1 -1
  11. package/patterns/minimal-foundation/PATTERN.md +5 -0
  12. package/patterns/minimal-foundation/example/AGENTS.md +8 -8
  13. package/patterns/minimal-foundation/example/package.json +4 -5
  14. package/patterns/minimal-foundation/example/vite.config.mjs +0 -1
  15. package/patterns/shell-foundation/PATTERN.md +5 -0
  16. package/patterns/shell-foundation/example/AGENTS.md +8 -8
  17. package/patterns/shell-foundation/example/package.json +5 -6
  18. package/patterns/shell-foundation/example/packages/main/package.json +1 -1
  19. package/patterns/shell-foundation/example/vite.config.mjs +0 -1
  20. package/reference/autogen/PATTERN_INDEX.md +61 -61
  21. package/reference/autogen/tooling/testUtils.md +1 -1
  22. package/skills/jskit/SKILL.md +8 -5
  23. package/skills/jskit/references/app-operations.md +12 -11
  24. package/skills/jskit/references/crud-operations.md +10 -6
  25. package/skills/jskit/references/existing-application-migration.md +9 -12
  26. package/skills/jskit/references/material-3.md +2 -0
  27. package/skills/jskit/references/pattern-index.md +61 -61
  28. package/skills/jskit/references/patterns/app/minimal-foundation/PATTERN.md +105 -0
  29. package/skills/jskit/references/patterns/app/minimal-foundation/example/.nvmrc +1 -0
  30. package/skills/jskit/references/patterns/app/minimal-foundation/example/AGENTS.md +17 -0
  31. package/skills/jskit/references/patterns/app/minimal-foundation/example/Procfile +2 -0
  32. package/skills/jskit/references/patterns/app/minimal-foundation/example/app.json +14 -0
  33. package/skills/jskit/references/patterns/app/minimal-foundation/example/bin/develop.js +71 -0
  34. package/skills/jskit/references/patterns/app/minimal-foundation/example/bin/server.js +8 -0
  35. package/skills/jskit/references/patterns/app/minimal-foundation/example/config/public.js +40 -0
  36. package/skills/jskit/references/patterns/app/minimal-foundation/example/config/server.js +1 -0
  37. package/skills/jskit/references/patterns/app/minimal-foundation/example/config/surfaceAccessPolicies.js +3 -0
  38. package/skills/jskit/references/patterns/app/minimal-foundation/example/eslint.config.mjs +19 -0
  39. package/skills/jskit/references/patterns/app/minimal-foundation/example/favicon.svg +7 -0
  40. package/skills/jskit/references/patterns/app/minimal-foundation/example/gitignore +9 -0
  41. package/skills/jskit/references/patterns/app/minimal-foundation/example/index.html +13 -0
  42. package/skills/jskit/references/patterns/app/minimal-foundation/example/jsconfig.json +8 -0
  43. package/skills/jskit/references/patterns/app/minimal-foundation/example/package.json +62 -0
  44. package/skills/jskit/references/patterns/app/minimal-foundation/example/packages/main/package.json +42 -0
  45. package/skills/jskit/references/patterns/app/minimal-foundation/example/packages/main/src/shared/index.js +10 -0
  46. package/skills/jskit/references/patterns/app/minimal-foundation/example/packages/main/src/shared/schemas/index.js +22 -0
  47. package/skills/jskit/references/patterns/app/minimal-foundation/example/playwright.config.mjs +31 -0
  48. package/skills/jskit/references/patterns/app/minimal-foundation/example/server/lib/runtimeEnv.js +45 -0
  49. package/skills/jskit/references/patterns/app/minimal-foundation/example/server/lib/surfaceRuntime.js +10 -0
  50. package/skills/jskit/references/patterns/app/minimal-foundation/example/server.js +195 -0
  51. package/skills/jskit/references/patterns/app/minimal-foundation/example/src/App.vue +13 -0
  52. package/skills/jskit/references/patterns/app/minimal-foundation/example/src/main.js +85 -0
  53. package/skills/jskit/references/patterns/app/minimal-foundation/example/src/pages/home/index.vue +48 -0
  54. package/skills/jskit/references/patterns/app/minimal-foundation/example/src/pages/home.vue +13 -0
  55. package/skills/jskit/references/patterns/app/minimal-foundation/example/src/views/NotFound.vue +13 -0
  56. package/skills/jskit/references/patterns/app/minimal-foundation/example/tests/client/smoke.vitest.js +7 -0
  57. package/skills/jskit/references/patterns/app/minimal-foundation/example/tests/e2e/base-shell.spec.ts +23 -0
  58. package/skills/jskit/references/patterns/app/minimal-foundation/example/tests/server/smoke.test.js +16 -0
  59. package/skills/jskit/references/patterns/app/minimal-foundation/example/vite.config.mjs +80 -0
  60. package/skills/jskit/references/patterns/app/shell-foundation/PATTERN.md +111 -0
  61. package/skills/jskit/references/patterns/app/shell-foundation/example/.nvmrc +1 -0
  62. package/skills/jskit/references/patterns/app/shell-foundation/example/AGENTS.md +17 -0
  63. package/skills/jskit/references/patterns/app/shell-foundation/example/Procfile +2 -0
  64. package/skills/jskit/references/patterns/app/shell-foundation/example/app.json +14 -0
  65. package/skills/jskit/references/patterns/app/shell-foundation/example/bin/develop.js +71 -0
  66. package/skills/jskit/references/patterns/app/shell-foundation/example/bin/server.js +8 -0
  67. package/skills/jskit/references/patterns/app/shell-foundation/example/config/public.js +40 -0
  68. package/skills/jskit/references/patterns/app/shell-foundation/example/config/server.js +1 -0
  69. package/skills/jskit/references/patterns/app/shell-foundation/example/config/surfaceAccessPolicies.js +3 -0
  70. package/skills/jskit/references/patterns/app/shell-foundation/example/eslint.config.mjs +19 -0
  71. package/skills/jskit/references/patterns/app/shell-foundation/example/favicon.svg +7 -0
  72. package/skills/jskit/references/patterns/app/shell-foundation/example/gitignore +9 -0
  73. package/skills/jskit/references/patterns/app/shell-foundation/example/index.html +13 -0
  74. package/skills/jskit/references/patterns/app/shell-foundation/example/jsconfig.json +8 -0
  75. package/skills/jskit/references/patterns/app/shell-foundation/example/package.json +64 -0
  76. package/skills/jskit/references/patterns/app/shell-foundation/example/packages/main/package.json +56 -0
  77. package/skills/jskit/references/patterns/app/shell-foundation/example/packages/main/src/client/index.js +9 -0
  78. package/skills/jskit/references/patterns/app/shell-foundation/example/packages/main/src/client/providers/MainClientProvider.js +18 -0
  79. package/skills/jskit/references/patterns/app/shell-foundation/example/packages/main/src/shared/index.js +10 -0
  80. package/skills/jskit/references/patterns/app/shell-foundation/example/packages/main/src/shared/schemas/index.js +22 -0
  81. package/skills/jskit/references/patterns/app/shell-foundation/example/playwright.config.mjs +31 -0
  82. package/skills/jskit/references/patterns/app/shell-foundation/example/server/lib/runtimeEnv.js +45 -0
  83. package/skills/jskit/references/patterns/app/shell-foundation/example/server/lib/surfaceRuntime.js +10 -0
  84. package/skills/jskit/references/patterns/app/shell-foundation/example/server.js +195 -0
  85. package/skills/jskit/references/patterns/app/shell-foundation/example/src/App.vue +11 -0
  86. package/skills/jskit/references/patterns/app/shell-foundation/example/src/components/ShellLayout.vue +12 -0
  87. package/skills/jskit/references/patterns/app/shell-foundation/example/src/components/menus/MenuLinkItem.vue +30 -0
  88. package/skills/jskit/references/patterns/app/shell-foundation/example/src/components/menus/SurfaceAwareMenuLinkItem.vue +42 -0
  89. package/skills/jskit/references/patterns/app/shell-foundation/example/src/components/menus/TabLinkItem.vue +42 -0
  90. package/skills/jskit/references/patterns/app/shell-foundation/example/src/error.js +19 -0
  91. package/skills/jskit/references/patterns/app/shell-foundation/example/src/main.js +85 -0
  92. package/skills/jskit/references/patterns/app/shell-foundation/example/src/pages/home/index.vue +116 -0
  93. package/skills/jskit/references/patterns/app/shell-foundation/example/src/pages/home/settings/general/index.vue +40 -0
  94. package/skills/jskit/references/patterns/app/shell-foundation/example/src/pages/home/settings/index.vue +7 -0
  95. package/skills/jskit/references/patterns/app/shell-foundation/example/src/pages/home/settings.vue +109 -0
  96. package/skills/jskit/references/patterns/app/shell-foundation/example/src/pages/home.vue +20 -0
  97. package/skills/jskit/references/patterns/app/shell-foundation/example/src/placement.js +56 -0
  98. package/skills/jskit/references/patterns/app/shell-foundation/example/src/placementTopology.js +149 -0
  99. package/skills/jskit/references/patterns/app/shell-foundation/example/src/views/NotFound.vue +13 -0
  100. package/skills/jskit/references/patterns/app/shell-foundation/example/tests/client/smoke.vitest.js +7 -0
  101. package/skills/jskit/references/patterns/app/shell-foundation/example/tests/e2e/adaptive-shell.spec.ts +10 -0
  102. package/skills/jskit/references/patterns/app/shell-foundation/example/tests/e2e/base-shell.spec.ts +23 -0
  103. package/skills/jskit/references/patterns/app/shell-foundation/example/tests/server/smoke.test.js +16 -0
  104. package/skills/jskit/references/patterns/app/shell-foundation/example/vite.config.mjs +80 -0
  105. package/skills/jskit/references/patterns/assistant/assistant-surface/PATTERN.md +77 -0
  106. package/skills/jskit/references/patterns/assistant/assistant-surface/example/config/public.js +19 -0
  107. package/skills/jskit/references/patterns/assistant/assistant-surface/example/config/server.js +9 -0
  108. package/skills/jskit/references/patterns/assistant/assistant-surface/example/src/pages/admin/assistant/index.vue +7 -0
  109. package/skills/jskit/references/patterns/assistant/assistant-surface/example/src/pages/admin/settings/assistant/index.vue +7 -0
  110. package/skills/jskit/references/patterns/assistant/assistant-surface/example/src/placement.js +38 -0
  111. package/skills/jskit/references/patterns/auth/auth-surface/PATTERN.md +90 -0
  112. package/skills/jskit/references/patterns/auth/auth-surface/example/src/pages/auth/login.vue +17 -0
  113. package/skills/jskit/references/patterns/auth/auth-surface/example/src/pages/auth/reset-password.vue +17 -0
  114. package/skills/jskit/references/patterns/auth/auth-surface/example/src/pages/auth/signout.vue +17 -0
  115. package/skills/jskit/references/patterns/auth/auth-surface/example/src/runtime/authGuardRuntime.js +7 -0
  116. package/skills/jskit/references/patterns/auth/auth-surface/example/src/runtime/authHttpClient.js +1 -0
  117. package/skills/jskit/references/patterns/auth/auth-surface/example/src/runtime/useSignOut.js +1 -0
  118. package/skills/jskit/references/patterns/auth/auth-surface/example/src/views/auth/LoginView.vue +7 -0
  119. package/skills/jskit/references/patterns/auth/auth-surface/example/src/views/auth/ResetPasswordView.vue +7 -0
  120. package/skills/jskit/references/patterns/auth/auth-surface/example/src/views/auth/SignOutView.vue +7 -0
  121. package/skills/jskit/references/patterns/auth/auth-surface/example/tools/preview-identity +5 -0
  122. package/skills/jskit/references/patterns/auth/supabase-auth/PATTERN.md +67 -0
  123. package/skills/jskit/references/patterns/auth/supabase-auth/example/.env.example +4 -0
  124. package/skills/jskit/references/patterns/auth/supabase-auth/example/config/server.js +11 -0
  125. package/skills/jskit/references/patterns/auth/supabase-auth/example/package.json +7 -0
  126. package/skills/jskit/references/patterns/console/console-surface/PATTERN.md +58 -0
  127. package/skills/jskit/references/patterns/console/console-surface/example/src/pages/console/index.vue +62 -0
  128. package/skills/jskit/references/patterns/console/console-surface/example/src/pages/console/settings/index.vue +17 -0
  129. package/skills/jskit/references/patterns/console/console-surface/example/src/pages/console/settings.vue +95 -0
  130. package/skills/jskit/references/patterns/console/console-surface/example/src/pages/console.vue +20 -0
  131. package/skills/jskit/references/patterns/crud/crud-screen-set/PATTERN.md +88 -0
  132. package/skills/jskit/references/patterns/crud/crud-screen-set/example/books/BookEditPage.vue +54 -0
  133. package/skills/jskit/references/patterns/crud/crud-screen-set/example/books/BookFormFields.vue +52 -0
  134. package/skills/jskit/references/patterns/crud/crud-screen-set/example/books/BookListPage.vue +54 -0
  135. package/skills/jskit/references/patterns/crud/crud-screen-set/example/books/BookNewPage.vue +45 -0
  136. package/skills/jskit/references/patterns/crud/crud-screen-set/example/books/BookViewPage.vue +50 -0
  137. package/skills/jskit/references/patterns/crud/crud-screen-set/example/books/formFields.js +31 -0
  138. package/skills/jskit/references/patterns/crud/crud-screen-set/example/books/listExtensions.js +9 -0
  139. package/skills/jskit/references/patterns/crud/json-api-resource-package/PATTERN.md +160 -0
  140. package/skills/jskit/references/patterns/crud/json-api-resource-package/example/migrations/20260815000000_books.cjs +22 -0
  141. package/skills/jskit/references/patterns/crud/json-api-resource-package/example/packages/books/package.json +41 -0
  142. package/skills/jskit/references/patterns/crud/json-api-resource-package/example/packages/books/src/server/BooksFeature.js +13 -0
  143. package/skills/jskit/references/patterns/crud/json-api-resource-package/example/packages/books/src/shared/bookResource.js +83 -0
  144. package/skills/jskit/references/patterns/crud/json-api-resource-package/example/packages/books/src/shared/index.js +1 -0
  145. package/skills/jskit/references/patterns/crud/resource-contract/PATTERN.md +102 -0
  146. package/skills/jskit/references/patterns/crud/resource-contract/example/bookResource.js +87 -0
  147. package/skills/jskit/references/patterns/database/mysql-application/PATTERN.md +80 -0
  148. package/skills/jskit/references/patterns/database/mysql-application/example/.env.example +5 -0
  149. package/skills/jskit/references/patterns/database/mysql-application/example/.github/workflows/verify.yml +39 -0
  150. package/skills/jskit/references/patterns/database/mysql-application/example/knexfile.js +11 -0
  151. package/skills/jskit/references/patterns/database/mysql-application/example/package.json +13 -0
  152. package/skills/jskit/references/patterns/database/mysql-application/example/scripts/prepare-database.js +3 -0
  153. package/skills/jskit/references/patterns/database/postgres-application/PATTERN.md +80 -0
  154. package/skills/jskit/references/patterns/database/postgres-application/example/.env.example +5 -0
  155. package/skills/jskit/references/patterns/database/postgres-application/example/.github/workflows/verify.yml +38 -0
  156. package/skills/jskit/references/patterns/database/postgres-application/example/knexfile.js +11 -0
  157. package/skills/jskit/references/patterns/database/postgres-application/example/package.json +13 -0
  158. package/skills/jskit/references/patterns/database/postgres-application/example/scripts/prepare-database.js +3 -0
  159. package/skills/jskit/references/patterns/mobile/android-application/PATTERN.md +71 -0
  160. package/skills/jskit/references/patterns/mobile/android-application/example/capacitor.config.json +10 -0
  161. package/skills/jskit/references/patterns/realtime/realtime-application/PATTERN.md +69 -0
  162. package/skills/jskit/references/patterns/realtime/realtime-application/example/.env.example +1 -0
  163. package/skills/jskit/references/patterns/realtime/realtime-application/example/package.json +8 -0
  164. package/skills/jskit/references/patterns/realtime/realtime-application/example/src/placement.js +17 -0
  165. package/skills/jskit/references/patterns/server/feature-package/PATTERN.md +108 -0
  166. package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/package.json +48 -0
  167. package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/src/server/BookingEngineProvider.js +33 -0
  168. package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/src/server/actions.js +26 -0
  169. package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/src/server/inputSchemas.js +19 -0
  170. package/skills/jskit/references/patterns/server/feature-package/example/variations/AvailabilityEngineProvider.js +31 -0
  171. package/skills/jskit/references/patterns/server/feature-package/example/variations/InvoiceRollupProvider.js +36 -0
  172. package/skills/jskit/references/patterns/server/feature-package/example/variations/customKnexRepository.js +34 -0
  173. package/skills/jskit/references/patterns/server/feature-package/example/variations/orchestratorService.js +23 -0
  174. package/skills/jskit/references/patterns/shell/application-shell/PATTERN.md +66 -0
  175. package/skills/jskit/references/patterns/shell/application-shell/example/expected-existing/src/App.vue +13 -0
  176. package/skills/jskit/references/patterns/shell/application-shell/example/expected-existing/src/pages/home/index.vue +48 -0
  177. package/skills/jskit/references/patterns/shell/application-shell/example/expected-existing/src/pages/home.vue +13 -0
  178. package/skills/jskit/references/patterns/shell/application-shell/example/src/App.vue +11 -0
  179. package/skills/jskit/references/patterns/shell/application-shell/example/src/components/ShellLayout.vue +13 -0
  180. package/skills/jskit/references/patterns/shell/application-shell/example/src/components/menus/MenuLinkItem.vue +30 -0
  181. package/skills/jskit/references/patterns/shell/application-shell/example/src/components/menus/SurfaceAwareMenuLinkItem.vue +42 -0
  182. package/skills/jskit/references/patterns/shell/application-shell/example/src/components/menus/TabLinkItem.vue +42 -0
  183. package/skills/jskit/references/patterns/shell/application-shell/example/src/error.js +19 -0
  184. package/skills/jskit/references/patterns/shell/application-shell/example/src/pages/home/index.vue +106 -0
  185. package/skills/jskit/references/patterns/shell/application-shell/example/src/pages/home/settings/general/index.vue +40 -0
  186. package/skills/jskit/references/patterns/shell/application-shell/example/src/pages/home/settings/index.vue +7 -0
  187. package/skills/jskit/references/patterns/shell/application-shell/example/src/pages/home/settings.vue +109 -0
  188. package/skills/jskit/references/patterns/shell/application-shell/example/src/pages/home.vue +20 -0
  189. package/skills/jskit/references/patterns/shell/application-shell/example/src/placement.js +56 -0
  190. package/skills/jskit/references/patterns/shell/application-shell/example/src/placementTopology.js +149 -0
  191. package/skills/jskit/references/patterns/shell/application-shell/example/tests/e2e/adaptive-shell.spec.ts +10 -0
  192. package/skills/jskit/references/patterns/ui/page-and-placement/PATTERN.md +76 -0
  193. package/skills/jskit/references/patterns/ui/page-and-placement/example/packages/main/src/client/providers/MainClientProvider.js +14 -0
  194. package/skills/jskit/references/patterns/ui/page-and-placement/example/src/components/SyncStatusElement.vue +16 -0
  195. package/skills/jskit/references/patterns/ui/page-and-placement/example/src/pages/home/reports/activity.vue +8 -0
  196. package/skills/jskit/references/patterns/ui/page-and-placement/example/src/pages/home/reports/index.vue +7 -0
  197. package/skills/jskit/references/patterns/ui/page-and-placement/example/src/pages/home/reports/overview.vue +8 -0
  198. package/skills/jskit/references/patterns/ui/page-and-placement/example/src/pages/home/reports.vue +33 -0
  199. package/skills/jskit/references/patterns/ui/page-and-placement/example/src/placement.js +52 -0
  200. package/skills/jskit/references/patterns/ui/page-and-placement/example/src/placementTopology.js +29 -0
  201. package/skills/jskit/references/patterns/users/account-settings/PATTERN.md +61 -0
  202. package/skills/jskit/references/patterns/users/account-settings/example/src/components/account/settings/AccountSettingsNotificationsSection.vue +81 -0
  203. package/skills/jskit/references/patterns/users/account-settings/example/src/components/account/settings/AccountSettingsPreferencesSection.vue +151 -0
  204. package/skills/jskit/references/patterns/users/account-settings/example/src/components/account/settings/AccountSettingsProfileSection.vue +120 -0
  205. package/skills/jskit/references/patterns/users/account-settings/example/src/pages/account/index.vue +17 -0
  206. package/skills/jskit/references/patterns/users/user-administration-server/PATTERN.md +64 -0
  207. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users/package.json +42 -0
  208. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users/src/server/UsersFeature.js +13 -0
  209. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users/src/shared/index.js +1 -0
  210. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users/src/shared/userResource.js +69 -0
  211. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users-workspace/package.json +43 -0
  212. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users-workspace/src/server/UsersWorkspaceFeature.js +22 -0
  213. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users-workspace/src/shared/index.js +1 -0
  214. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users-workspace/src/shared/userResource.js +56 -0
  215. package/skills/jskit/references/patterns/workspaces/workspace-server/PATTERN.md +60 -0
  216. package/skills/jskit/references/patterns/workspaces/workspace-server/example/config/roles.js +27 -0
  217. package/skills/jskit/references/patterns/workspaces/workspace-server/example/packages/main/src/server/email/workspaceInviteEmail.js +23 -0
  218. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/PATTERN.md +63 -0
  219. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/packages/main/src/client/components/AccountPendingInvitesCue.vue +106 -0
  220. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/packages/main/src/client/components/AccountSettingsInvitesSection.vue +7 -0
  221. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/src/components/WorkspaceNotFoundCard.vue +53 -0
  222. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/src/composables/useWorkspaceNotFoundState.js +41 -0
  223. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/src/pages/admin/members/index.vue +7 -0
  224. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/src/pages/admin/workspace/settings/index.vue +23 -0
  225. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/src/pages/admin/workspace/settings.vue +95 -0
  226. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/src/pages/invite/[token].vue +7 -0
  227. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/src/surfaces/admin/index.vue +85 -0
  228. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/src/surfaces/admin/root.vue +20 -0
  229. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/src/surfaces/app/index.vue +46 -0
  230. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/src/surfaces/app/root.vue +20 -0
  231. package/skills/jskit/references/ui-operations.md +5 -3
  232. package/templates/app/AGENTS.md +8 -8
@@ -0,0 +1,54 @@
1
+ <script setup>
2
+ import { computed } from "vue";
3
+ import { useRoute } from "vue-router";
4
+ import CrudAddEditScreen from "@jskit-ai/http-web/client/components/CrudAddEditScreen";
5
+ import { useCrudAddEditScreen } from "@jskit-ai/http-web/client/composables/useCrudAddEditScreen";
6
+ import { bookResource } from "@local/books/shared";
7
+ import BookFormFields from "./BookFormFields.vue";
8
+ import { bookFormFields } from "./formFields.js";
9
+
10
+ const route = useRoute();
11
+ const routeRecordId = computed(() => String(route.params.bookId || "").trim());
12
+
13
+ const screen = useCrudAddEditScreen({
14
+ mode: "edit",
15
+ title: "Edit book",
16
+ subtitle: "Update this catalogue entry.",
17
+ saveLabel: "Save changes",
18
+ cancelTo: "/books/:bookId",
19
+ preserveCancelQuery: true,
20
+ resource: bookResource,
21
+ operationName: "patch",
22
+ formFields: bookFormFields,
23
+ addEditOptions: {
24
+ apiUrlTemplate: "/books/:bookId",
25
+ placementSource: "crud.books.edit",
26
+ writeMethod: "PATCH",
27
+ requestRecoveryLabel: "Book",
28
+ fallbackLoadError: "Unable to load this book.",
29
+ fallbackSaveError: "Unable to save this book.",
30
+ recordIdParam: "bookId",
31
+ routeRecordId,
32
+ viewUrlTemplate: "/books/:bookId",
33
+ listUrlTemplate: "/books"
34
+ },
35
+ saveSuccess: {
36
+ invalidateQueryKey: ["crud", "books"],
37
+ listUrlTemplate: "/books"
38
+ }
39
+ });
40
+ </script>
41
+
42
+ <template>
43
+ <CrudAddEditScreen :screen="screen">
44
+ <template #fields="fieldRuntime">
45
+ <BookFormFields
46
+ v-model:title="fieldRuntime.formState.title"
47
+ v-model:author="fieldRuntime.formState.author"
48
+ v-model:notes="fieldRuntime.formState.notes"
49
+ :readonly="fieldRuntime.addEdit.isFieldLocked"
50
+ :resolve-field-errors="fieldRuntime.resolveFieldErrors"
51
+ />
52
+ </template>
53
+ </CrudAddEditScreen>
54
+ </template>
@@ -0,0 +1,52 @@
1
+ <script setup>
2
+ const title = defineModel("title", { type: String, default: "" });
3
+ const author = defineModel("author", { type: String, default: "" });
4
+ const notes = defineModel("notes", { type: String, default: "" });
5
+
6
+ defineProps({
7
+ readonly: {
8
+ type: Boolean,
9
+ default: false
10
+ },
11
+ resolveFieldErrors: {
12
+ type: Function,
13
+ required: true
14
+ }
15
+ });
16
+ </script>
17
+
18
+ <template>
19
+ <v-col cols="12" md="6">
20
+ <v-text-field
21
+ v-model="title"
22
+ label="Title"
23
+ variant="outlined"
24
+ density="comfortable"
25
+ maxlength="255"
26
+ :readonly="readonly"
27
+ :error-messages="resolveFieldErrors('title')"
28
+ />
29
+ </v-col>
30
+ <v-col cols="12" md="6">
31
+ <v-text-field
32
+ v-model="author"
33
+ label="Author"
34
+ variant="outlined"
35
+ density="comfortable"
36
+ maxlength="255"
37
+ :readonly="readonly"
38
+ :error-messages="resolveFieldErrors('author')"
39
+ />
40
+ </v-col>
41
+ <v-col cols="12">
42
+ <v-textarea
43
+ v-model="notes"
44
+ label="Notes"
45
+ variant="outlined"
46
+ density="comfortable"
47
+ auto-grow
48
+ :readonly="readonly"
49
+ :error-messages="resolveFieldErrors('notes')"
50
+ />
51
+ </v-col>
52
+ </template>
@@ -0,0 +1,54 @@
1
+ <script setup>
2
+ import CrudListScreen from "@jskit-ai/http-web/client/components/CrudListScreen";
3
+ import { useCrudListScreen } from "@jskit-ai/http-web/client/composables/useCrudListScreen";
4
+ import { bookResource } from "@local/books/shared";
5
+ import { listBulkActions, listFilters, listRowActions } from "./listExtensions.js";
6
+
7
+ const screen = useCrudListScreen({
8
+ resource: bookResource,
9
+ resourceNamespace: "books",
10
+ apiSuffix: "/books",
11
+ recordIdParam: "bookId",
12
+ recordIdSelector: (book = {}) => book.id,
13
+ titleFallbackFieldKey: "title",
14
+ viewUrlTemplate: "/books/:bookId",
15
+ editUrlTemplate: "/books/:bookId/edit",
16
+ newUrlTemplate: "/books/new",
17
+ listFilters,
18
+ listBulkActions,
19
+ listRowActions,
20
+ requestRecoveryLabel: "Books",
21
+ fallbackLoadError: "Unable to load books."
22
+ });
23
+ </script>
24
+
25
+ <template>
26
+ <CrudListScreen
27
+ :screen="screen"
28
+ title-label="Books"
29
+ heading-title="My books"
30
+ subtitle="Search and maintain your catalogue."
31
+ create-label="Add book"
32
+ empty-title="No books yet"
33
+ empty-body="Add your first book to begin the catalogue."
34
+ >
35
+ <template #card-fields="{ record, formatListCardValue }">
36
+ <dl class="d-grid ga-2 mb-0">
37
+ <div>
38
+ <dt class="text-caption text-medium-emphasis">Author</dt>
39
+ <dd class="text-body-2 mb-0">{{ formatListCardValue(record.author) }}</dd>
40
+ </div>
41
+ </dl>
42
+ </template>
43
+
44
+ <template #table-header>
45
+ <th>Title</th>
46
+ <th>Author</th>
47
+ </template>
48
+
49
+ <template #table-row="{ record }">
50
+ <td>{{ record.title }}</td>
51
+ <td>{{ record.author }}</td>
52
+ </template>
53
+ </CrudListScreen>
54
+ </template>
@@ -0,0 +1,45 @@
1
+ <script setup>
2
+ import CrudAddEditScreen from "@jskit-ai/http-web/client/components/CrudAddEditScreen";
3
+ import { useCrudAddEditScreen } from "@jskit-ai/http-web/client/composables/useCrudAddEditScreen";
4
+ import { bookResource } from "@local/books/shared";
5
+ import BookFormFields from "./BookFormFields.vue";
6
+ import { bookFormFields } from "./formFields.js";
7
+
8
+ const screen = useCrudAddEditScreen({
9
+ mode: "new",
10
+ title: "Add book",
11
+ subtitle: "Add a book to your catalogue.",
12
+ saveLabel: "Save book",
13
+ cancelTo: "/books",
14
+ resource: bookResource,
15
+ operationName: "create",
16
+ formFields: bookFormFields,
17
+ addEditOptions: {
18
+ apiSuffix: "/books",
19
+ placementSource: "crud.books.new",
20
+ readEnabled: false,
21
+ writeMethod: "POST",
22
+ recordIdParam: "bookId",
23
+ viewUrlTemplate: "/books/:bookId",
24
+ listUrlTemplate: "/books"
25
+ },
26
+ saveSuccess: {
27
+ invalidateQueryKey: ["crud", "books"],
28
+ listUrlTemplate: "/books"
29
+ }
30
+ });
31
+ </script>
32
+
33
+ <template>
34
+ <CrudAddEditScreen :screen="screen">
35
+ <template #fields="fieldRuntime">
36
+ <BookFormFields
37
+ v-model:title="fieldRuntime.formState.title"
38
+ v-model:author="fieldRuntime.formState.author"
39
+ v-model:notes="fieldRuntime.formState.notes"
40
+ :readonly="fieldRuntime.addEdit.isFieldLocked"
41
+ :resolve-field-errors="fieldRuntime.resolveFieldErrors"
42
+ />
43
+ </template>
44
+ </CrudAddEditScreen>
45
+ </template>
@@ -0,0 +1,50 @@
1
+ <script setup>
2
+ import CrudDeleteAction from "@jskit-ai/http-web/client/components/CrudDeleteAction";
3
+ import CrudViewScreen from "@jskit-ai/http-web/client/components/CrudViewScreen";
4
+ import { useCrudDeleteAction } from "@jskit-ai/http-web/client/composables/useCrudDeleteAction";
5
+ import { useCrudViewScreen } from "@jskit-ai/http-web/client/composables/useCrudViewScreen";
6
+ import { bookResource } from "@local/books/shared";
7
+
8
+ const screen = useCrudViewScreen({
9
+ resource: bookResource,
10
+ resourceNamespace: "books",
11
+ apiUrlTemplate: "/books/:bookId",
12
+ recordIdParam: "bookId",
13
+ titleFallbackFieldKey: "title",
14
+ listUrlTemplate: "/books",
15
+ editUrlTemplate: "/books/:bookId/edit",
16
+ requestRecoveryLabel: "Book",
17
+ fallbackLoadError: "Unable to load this book."
18
+ });
19
+
20
+ const deleteAction = useCrudDeleteAction({
21
+ screen,
22
+ resource: bookResource,
23
+ resourceNamespace: "books",
24
+ apiUrlTemplate: "/books/:bookId"
25
+ });
26
+ </script>
27
+
28
+ <template>
29
+ <CrudViewScreen
30
+ :screen="screen"
31
+ resource-singular-title="Book"
32
+ resource-plural-title="Books"
33
+ description="Review this catalogue entry."
34
+ >
35
+ <template #actions>
36
+ <CrudDeleteAction :action="deleteAction" resource-singular-title="Book" />
37
+ </template>
38
+
39
+ <template #fields="{ view }">
40
+ <v-col cols="12" md="6">
41
+ <div class="text-caption text-medium-emphasis">Author</div>
42
+ <div class="text-body-1">{{ view.record?.author }}</div>
43
+ </v-col>
44
+ <v-col cols="12">
45
+ <div class="text-caption text-medium-emphasis">Notes</div>
46
+ <div class="text-body-1 text-pre-wrap">{{ view.record?.notes || "No notes" }}</div>
47
+ </v-col>
48
+ </template>
49
+ </CrudViewScreen>
50
+ </template>
@@ -0,0 +1,31 @@
1
+ const bookFormFields = Object.freeze([
2
+ Object.freeze({
3
+ key: "title",
4
+ label: "Title",
5
+ type: "string",
6
+ nullable: false,
7
+ inputType: "text",
8
+ component: "text",
9
+ maxLength: 255
10
+ }),
11
+ Object.freeze({
12
+ key: "author",
13
+ label: "Author",
14
+ type: "string",
15
+ nullable: false,
16
+ inputType: "text",
17
+ component: "text",
18
+ maxLength: 255
19
+ }),
20
+ Object.freeze({
21
+ key: "notes",
22
+ label: "Notes",
23
+ type: "string",
24
+ nullable: true,
25
+ inputType: "textarea",
26
+ component: "textarea",
27
+ maxLength: 65535
28
+ })
29
+ ]);
30
+
31
+ export { bookFormFields };
@@ -0,0 +1,9 @@
1
+ import { defineCrudListBulkActions } from "@jskit-ai/http-web/client/bulkActions";
2
+ import { defineCrudListFilters } from "@jskit-ai/http-web/client/filters";
3
+ import { defineCrudListRowActions } from "@jskit-ai/http-web/client/rowActions";
4
+
5
+ const listFilters = defineCrudListFilters({});
6
+ const listBulkActions = defineCrudListBulkActions([]);
7
+ const listRowActions = defineCrudListRowActions([]);
8
+
9
+ export { listBulkActions, listFilters, listRowActions };
@@ -0,0 +1,160 @@
1
+ ---
2
+ id: crud/json-api-resource-package
3
+ title: JSON API CRUD resource package
4
+ summary: Build a complete application-owned CRUD server package from a migration, resource contract, and one framework module declaration.
5
+ keywords: actions, crud, database, json-api, migration, permissions, provider, repository, routes, service
6
+ requires: @jskit-ai/crud-core, @jskit-ai/resource-crud-core
7
+ ---
8
+
9
+ # JSON API CRUD resource package
10
+
11
+ ## Use when
12
+
13
+ Use this pattern when a product entity needs conventional JSON API list, view,
14
+ create, patch, and delete behavior. JSKIT owns the repeated repository, service,
15
+ action, route, and provider mechanics. The application owns the migration,
16
+ resource contract, access surface, ownership policy, and package composition.
17
+
18
+ ## Do not use when
19
+
20
+ Do not use this pattern for a command-oriented workflow, aggregate, import job,
21
+ multi-resource transaction, or domain with materially different operations.
22
+ Use a feature package and explicit services for those cases.
23
+
24
+ ## Product decisions
25
+
26
+ Decide the entity fields, validation, search, sorting, access surface, ownership,
27
+ enabled operations, route name, permissions, and user-facing messages. Author
28
+ those decisions in normal migration and resource source. Do not derive them
29
+ from a generator questionnaire or treat a live table as the sole contract.
30
+
31
+ ## Invariants
32
+
33
+ - Migration and resource storage metadata describe the same table.
34
+ - `apiAccess`, surface access, and `autofilter` agree.
35
+ - Public routes use public ownership only.
36
+ - Workspace routes receive explicit scope validators and route-to-action input.
37
+ - Application source contains one module declaration, not copied generic CRUD
38
+ repository, service, action, route, and provider files.
39
+ - Current migration/resource/source state is authoritative; there is no receipt,
40
+ provenance marker, generator identity, or field-patching lane.
41
+
42
+ ## Framework APIs
43
+
44
+ Use `defineCrudResource()` from `@jskit-ai/resource-crud-core` and
45
+ `defineCrudJsonApiFeature()` from `@jskit-ai/crud-core`. The latter composes the
46
+ JSON REST resource, repository, service events, standard CRUD actions, route
47
+ contracts, access policy, and HTTP routes.
48
+
49
+ ## Example files
50
+
51
+ `example/` contains a complete books package plus a source-controlled migration.
52
+ `BooksFeature.js` is deliberately tiny: it binds the readable resource contract
53
+ to the framework module and exports the resulting provider.
54
+
55
+ ## Variation points
56
+
57
+ Change the package name, resource fields, table, surface, ownership filter,
58
+ relative route, messages, and migration. Supply explicit permissions when the
59
+ surface uses named policy. For workspace ownership, add the workspace route and
60
+ action validators through the module's `scope` option. The feature exposes the
61
+ operations declared by the resource. Use `operations` only to narrow that
62
+ surface further; do not register unused mutation actions and routes. Use
63
+ `routes: false` only for an internal
64
+ capability/action surface that deliberately has no HTTP API.
65
+
66
+ When otherwise-standard CRUD earns product behavior, name the exact
67
+ capabilities in `requires` and provide `decorateService({ service, repository,
68
+ resource, ...dependencies })`. Retain the standard methods, override only the
69
+ methods whose CRUD behavior changes, and add resource-related domain methods
70
+ such as `confirmBooking()` or `sendReminder()` directly to that service. Those
71
+ additional methods remain available through the resource capability. When the
72
+ product needs only a few additional queries or locking operations, provide
73
+ `decorateRepository({ repository, database, http, jsonRestApi, resource,
74
+ ...dependencies })`; return the standard methods plus only those unique
75
+ persistence operations instead of copying the CRUD repository.
76
+
77
+ Use `operationLifecycle` for behavior surrounding a standard operation. Its
78
+ per-operation `before`, `execute`, and `after` phases share one repository
79
+ transaction for create, update, and delete. An `execute` hook receives
80
+ `standard(nextInput)` so it can retain the framework write while adjusting its
81
+ input or coordinating other repository work. `afterCommit` runs only after the
82
+ mutation transaction succeeds. Put durable external delivery behind an outbox
83
+ written inside the transaction; do not make an email or webhook the arbiter of
84
+ whether an already-committed request appears successful.
85
+
86
+ Declare resource-related non-CRUD commands in `actions`. Each named action has
87
+ a normal JSKIT input, permission, audit, events, and `execute({ input, context,
88
+ service, repository, ...dependencies })` contract. Its optional `route`
89
+ declares an HTTP method, path below the resource base, explicit route contract,
90
+ status code, and optional request-to-action input mapper. This is the normal
91
+ home for `confirm`, `publish`, `cancel`, `reorder`, or `sendReminder`. Move to a
92
+ separate explicit feature only when the operation belongs to another domain or
93
+ the resource is no longer principally CRUD.
94
+
95
+ If a product-specific list filter needs additional transport validation and
96
+ JSON API search mapping, pass its validator as `listFilterQueryValidator` and
97
+ its storage mapping as `searchSchema`; keep that contract next to the feature.
98
+ Use `operationInputs.create` or `operationInputs.update` when a standard CRUD
99
+ operation intentionally accepts a small virtual product field that is handled
100
+ by the service decorator rather than stored on the resource row.
101
+
102
+ ```js
103
+ const BookingsFeature = defineCrudJsonApiFeature({
104
+ resource: bookingResource,
105
+ surface: "app",
106
+ decorateService({ service, repository }) {
107
+ return {
108
+ ...service,
109
+ async confirmBooking(recordId, options) {
110
+ return repository.confirmBooking(recordId, options);
111
+ }
112
+ };
113
+ },
114
+ operationLifecycle: {
115
+ update: {
116
+ async before({ input, service, trx, context }) {
117
+ await service.assertUpdateAllowed(input.recordId, { trx, context });
118
+ },
119
+ async afterCommit({ result, service, context }) {
120
+ await service.recordUpdateCompleted(result.data.id, { context });
121
+ }
122
+ }
123
+ },
124
+ actions: {
125
+ confirm: {
126
+ input: confirmBookingInput,
127
+ permission: { require: "all", permissions: ["bookings.confirm"] },
128
+ execute({ input, context, service }) {
129
+ return service.confirmBooking(input.recordId, { context });
130
+ },
131
+ route: {
132
+ method: "POST",
133
+ path: "/:recordId/confirm",
134
+ contract: confirmBookingRouteContract,
135
+ statusCode: 200
136
+ }
137
+ }
138
+ }
139
+ });
140
+ ```
141
+
142
+ ## Verification
143
+
144
+ - Rebuild the table from migrations in disposable MySQL and PostgreSQL databases
145
+ when both drivers are supported by the application.
146
+ - Validate representative accepted and rejected resource values.
147
+ - Exercise every enabled route and JSON API document shape.
148
+ - Prove positive owner access and negative cross-owner access.
149
+ - Verify public routes require neither identity nor CSRF only when explicitly
150
+ declared public.
151
+ - Run the package tests and application verifier.
152
+
153
+ ## Avoid
154
+
155
+ - copied generic repository/service/action/route/provider boilerplate
156
+ - generator subcommands for adding fields
157
+ - editing an applied baseline migration instead of adding a new migration
158
+ - public access combined with user or workspace ownership
159
+ - implicit workspace route parameters or permissions
160
+ - receipt, replay, provenance, ownership-marker, or scaffold-shape files
@@ -0,0 +1,22 @@
1
+ const TABLE_NAME = "books";
2
+
3
+ exports.up = async function up(knex) {
4
+ if (await knex.schema.hasTable(TABLE_NAME)) {
5
+ return;
6
+ }
7
+
8
+ await knex.schema.createTable(TABLE_NAME, (table) => {
9
+ table.bigIncrements("id").primary();
10
+ table.bigInteger("user_id").unsigned().notNullable().index()
11
+ .references("id").inTable("users").onDelete("CASCADE");
12
+ table.string("title", 255).notNullable();
13
+ table.string("author", 255).notNullable();
14
+ table.text("notes").nullable();
15
+ table.timestamp("created_at", { useTz: false }).notNullable().defaultTo(knex.fn.now());
16
+ table.timestamp("updated_at", { useTz: false }).notNullable().defaultTo(knex.fn.now());
17
+ });
18
+ };
19
+
20
+ exports.down = async function down(knex) {
21
+ await knex.schema.dropTableIfExists(TABLE_NAME);
22
+ };
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@app/books",
3
+ "private": true,
4
+ "version": "0.0.0",
5
+ "type": "module",
6
+ "exports": {
7
+ "./server/BooksFeature": "./src/server/BooksFeature.js",
8
+ "./shared": "./src/shared/index.js"
9
+ },
10
+ "dependencies": {
11
+ "@jskit-ai/crud-core": "0.1.189",
12
+ "@jskit-ai/resource-crud-core": "0.1.120"
13
+ },
14
+ "jskit": {
15
+ "kind": "runtime",
16
+ "capabilities": {
17
+ "provides": [
18
+ "app.books"
19
+ ],
20
+ "requires": [
21
+ "runtime.http",
22
+ "runtime.json-rest-api",
23
+ "runtime.actions",
24
+ "runtime.database"
25
+ ]
26
+ },
27
+ "runtime": {
28
+ "server": {
29
+ "providers": [
30
+ {
31
+ "entrypoint": "src/server/BooksFeature.js",
32
+ "export": "BooksFeature"
33
+ }
34
+ ]
35
+ },
36
+ "client": {
37
+ "providers": []
38
+ }
39
+ }
40
+ }
41
+ }
@@ -0,0 +1,13 @@
1
+ import { defineCrudJsonApiFeature } from "@jskit-ai/crud-core/server/defineCrudJsonApiFeature";
2
+ import { bookResource } from "../shared/bookResource.js";
3
+
4
+ const BooksFeature = defineCrudJsonApiFeature({
5
+ resource: bookResource,
6
+ id: "app.books",
7
+ capability: "app.books",
8
+ surface: "app",
9
+ ownershipFilter: "user",
10
+ relativePath: "/books"
11
+ });
12
+
13
+ export { BooksFeature };
@@ -0,0 +1,83 @@
1
+ import { defineCrudResource } from "@jskit-ai/resource-crud-core/shared/crudResource";
2
+
3
+ const bookResource = defineCrudResource({
4
+ namespace: "books",
5
+ tableName: "books",
6
+ apiAccess: "authenticated",
7
+ autofilter: "user",
8
+ schema: {
9
+ userId: {
10
+ type: "id",
11
+ required: true,
12
+ hidden: true,
13
+ operations: {}
14
+ },
15
+ title: {
16
+ type: "string",
17
+ maxLength: 255,
18
+ required: true,
19
+ search: true,
20
+ operations: {
21
+ output: { required: true },
22
+ create: { required: true },
23
+ patch: { required: false }
24
+ }
25
+ },
26
+ author: {
27
+ type: "string",
28
+ maxLength: 255,
29
+ required: true,
30
+ search: true,
31
+ operations: {
32
+ output: { required: true },
33
+ create: { required: true },
34
+ patch: { required: false }
35
+ }
36
+ },
37
+ notes: {
38
+ type: "string",
39
+ maxLength: 65535,
40
+ nullable: true,
41
+ search: true,
42
+ operations: {
43
+ output: { required: true },
44
+ create: { required: false },
45
+ patch: { required: false }
46
+ }
47
+ },
48
+ createdAt: {
49
+ type: "dateTime",
50
+ temporalPrecision: 0,
51
+ default: "now()",
52
+ storage: { writeSerializer: "datetime-utc" },
53
+ operations: { output: { required: true } }
54
+ },
55
+ updatedAt: {
56
+ type: "dateTime",
57
+ temporalPrecision: 0,
58
+ default: "now()",
59
+ storage: { writeSerializer: "datetime-utc" },
60
+ operations: { output: { required: true } }
61
+ }
62
+ },
63
+ searchSchema: {
64
+ id: { type: "id", actualField: "id" },
65
+ q: {
66
+ type: "string",
67
+ oneOf: ["title", "author", "notes"],
68
+ filterOperator: "like",
69
+ splitBy: " ",
70
+ matchAll: true
71
+ }
72
+ },
73
+ defaultSort: ["-createdAt"],
74
+ messages: {
75
+ validation: "Fix invalid values and try again.",
76
+ saveSuccess: "Book saved.",
77
+ saveError: "Unable to save this book.",
78
+ deleteSuccess: "Book deleted.",
79
+ deleteError: "Unable to delete this book."
80
+ }
81
+ });
82
+
83
+ export { bookResource };
@@ -0,0 +1 @@
1
+ export { bookResource } from "./bookResource.js";