@dokebi/cli 0.4.1 → 0.4.26

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 (188) hide show
  1. package/AI.md +262 -57
  2. package/README.md +35 -10
  3. package/catalog.json +2519 -257
  4. package/describe.schema.json +748 -0
  5. package/dist/api-app.d.ts +2 -0
  6. package/dist/api-app.js +35 -0
  7. package/dist/app-urls.js +3 -2
  8. package/dist/bin.js +527 -35
  9. package/dist/capability-guide.d.ts +30 -0
  10. package/dist/capability-guide.js +122 -0
  11. package/dist/catalog.d.ts +16 -2
  12. package/dist/catalog.js +19 -7
  13. package/dist/check/asset-rules.d.ts +6 -0
  14. package/dist/check/asset-rules.js +163 -0
  15. package/dist/check/browser-sources.d.ts +20 -0
  16. package/dist/check/browser-sources.js +89 -0
  17. package/dist/check/console-rules.d.ts +6 -0
  18. package/dist/check/console-rules.js +40 -0
  19. package/dist/check/error-rules.d.ts +21 -0
  20. package/dist/check/error-rules.js +212 -0
  21. package/dist/check/form-rules.d.ts +12 -0
  22. package/dist/check/form-rules.js +69 -6
  23. package/dist/check/formatter-rules.d.ts +2 -0
  24. package/dist/check/formatter-rules.js +71 -0
  25. package/dist/check/i18n-rules.d.ts +27 -0
  26. package/dist/check/i18n-rules.js +353 -0
  27. package/dist/check/index.d.ts +15 -1
  28. package/dist/check/index.js +89 -11
  29. package/dist/check/mail-rules.d.ts +4 -0
  30. package/dist/check/mail-rules.js +72 -0
  31. package/dist/check/module-rules.d.ts +13 -0
  32. package/dist/check/module-rules.js +104 -0
  33. package/dist/check/packages.d.ts +8 -0
  34. package/dist/check/packages.js +16 -0
  35. package/dist/check/pool-rules.d.ts +8 -0
  36. package/dist/check/pool-rules.js +164 -0
  37. package/dist/check/problems.d.ts +6 -1
  38. package/dist/check/problems.js +100 -2
  39. package/dist/check/project-rules.d.ts +23 -3
  40. package/dist/check/project-rules.js +265 -23
  41. package/dist/check/seal-rules.d.ts +6 -0
  42. package/dist/check/seal-rules.js +68 -0
  43. package/dist/check/security-rules.d.ts +10 -0
  44. package/dist/check/security-rules.js +450 -0
  45. package/dist/check/shared-state-rules.d.ts +2 -0
  46. package/dist/check/shared-state-rules.js +114 -0
  47. package/dist/check/source-rules.d.ts +26 -3
  48. package/dist/check/source-rules.js +249 -28
  49. package/dist/check/structure-rules.d.ts +23 -0
  50. package/dist/check/structure-rules.js +502 -0
  51. package/dist/check/timer-rules.d.ts +7 -0
  52. package/dist/check/timer-rules.js +543 -0
  53. package/dist/check/typescript.d.ts +35 -5
  54. package/dist/check/typescript.js +163 -17
  55. package/dist/check/vite-rules.d.ts +2 -0
  56. package/dist/check/vite-rules.js +136 -0
  57. package/dist/check/wait-rules.d.ts +16 -0
  58. package/dist/check/wait-rules.js +337 -0
  59. package/dist/commands.d.ts +7 -0
  60. package/dist/commands.js +307 -31
  61. package/dist/config-diff.d.ts +42 -0
  62. package/dist/config-diff.js +289 -0
  63. package/dist/config-edit.d.ts +35 -2
  64. package/dist/config-edit.js +145 -13
  65. package/dist/config-init.d.ts +15 -0
  66. package/dist/config-init.js +61 -0
  67. package/dist/config-paths.d.ts +22 -0
  68. package/dist/config-paths.js +82 -0
  69. package/dist/config-show.d.ts +82 -0
  70. package/dist/config-show.js +563 -0
  71. package/dist/config-values.d.ts +8 -0
  72. package/dist/config-values.js +68 -0
  73. package/dist/configuration-scaffold.d.ts +42 -0
  74. package/dist/configuration-scaffold.js +258 -4
  75. package/dist/configuration.d.ts +63 -3
  76. package/dist/configuration.js +178 -4
  77. package/dist/deployment.d.ts +2 -0
  78. package/dist/deployment.js +111 -0
  79. package/dist/describe-db.d.ts +22 -0
  80. package/dist/describe-db.js +176 -0
  81. package/dist/describe.d.ts +92 -0
  82. package/dist/describe.js +417 -0
  83. package/dist/dev-compose.d.ts +20 -0
  84. package/dist/dev-compose.js +154 -0
  85. package/dist/dev-guard.js +44 -0
  86. package/dist/dev-host.d.ts +13 -0
  87. package/dist/dev-host.js +55 -0
  88. package/dist/dev-infra.d.ts +72 -4
  89. package/dist/dev-infra.js +237 -17
  90. package/dist/dev-watch.d.ts +34 -0
  91. package/dist/dev-watch.js +192 -0
  92. package/dist/diagnostics.d.ts +10 -7
  93. package/dist/diagnostics.js +22 -4
  94. package/dist/drift.d.ts +50 -0
  95. package/dist/drift.js +218 -0
  96. package/dist/env-file.d.ts +25 -1
  97. package/dist/env-file.js +64 -6
  98. package/dist/errors.d.ts +7 -1
  99. package/dist/example-config.d.ts +2 -0
  100. package/dist/example-config.js +3 -0
  101. package/dist/first-admin.d.ts +43 -0
  102. package/dist/first-admin.js +175 -0
  103. package/dist/formatter-ignore.d.ts +37 -0
  104. package/dist/formatter-ignore.js +344 -0
  105. package/dist/generator.d.ts +45 -3
  106. package/dist/generator.js +205 -15
  107. package/dist/guide.d.ts +1 -1
  108. package/dist/guide.js +42 -21
  109. package/dist/install-module.d.ts +29 -3
  110. package/dist/install-module.js +142 -13
  111. package/dist/install-plan.js +5 -3
  112. package/dist/layout.d.ts +12 -1
  113. package/dist/layout.js +19 -6
  114. package/dist/log-writer-control.d.ts +2 -0
  115. package/dist/log-writer-control.js +106 -27
  116. package/dist/log-writer.js +43 -10
  117. package/dist/logging-config.d.ts +8 -3
  118. package/dist/logging-config.js +19 -5
  119. package/dist/manifest.d.ts +29 -1
  120. package/dist/manifest.js +84 -6
  121. package/dist/merge-install-defaults.d.ts +0 -1
  122. package/dist/merge-install-defaults.js +13 -47
  123. package/dist/npm-client.d.ts +59 -4
  124. package/dist/npm-client.js +220 -16
  125. package/dist/npm-paths.js +18 -4
  126. package/dist/openapi.d.ts +27 -0
  127. package/dist/openapi.js +649 -0
  128. package/dist/option-fixes.d.ts +39 -0
  129. package/dist/option-fixes.js +130 -0
  130. package/dist/output.d.ts +1 -1
  131. package/dist/output.js +5 -5
  132. package/dist/plugin-lifecycle.d.ts +34 -2
  133. package/dist/plugin-lifecycle.js +206 -20
  134. package/dist/plugin-options.d.ts +19 -4
  135. package/dist/plugin-options.js +138 -6
  136. package/dist/plugins-command.js +44 -7
  137. package/dist/process-group.d.ts +39 -0
  138. package/dist/process-group.js +132 -0
  139. package/dist/project-guide.d.ts +19 -1
  140. package/dist/project-guide.js +119 -20
  141. package/dist/project-inspector.d.ts +15 -0
  142. package/dist/project-inspector.js +481 -33
  143. package/dist/project-state.d.ts +5 -0
  144. package/dist/project-state.js +8 -0
  145. package/dist/project.d.ts +203 -19
  146. package/dist/project.js +3016 -336
  147. package/dist/recipe-facts.d.ts +127 -0
  148. package/dist/recipe-facts.js +563 -0
  149. package/dist/recipe-login.d.ts +63 -0
  150. package/dist/recipe-login.js +464 -0
  151. package/dist/recipe-mail.d.ts +21 -0
  152. package/dist/recipe-mail.js +214 -0
  153. package/dist/recipe-members.d.ts +35 -0
  154. package/dist/recipe-members.js +178 -0
  155. package/dist/recipe-record.d.ts +82 -7
  156. package/dist/recipe-record.js +226 -22
  157. package/dist/recipe-reset.d.ts +2 -0
  158. package/dist/recipe-reset.js +117 -0
  159. package/dist/recipe-site.d.ts +48 -0
  160. package/dist/recipe-site.js +396 -0
  161. package/dist/recipe-step.d.ts +42 -0
  162. package/dist/recipe-step.js +89 -0
  163. package/dist/recipe.d.ts +56 -20
  164. package/dist/recipe.js +703 -131
  165. package/dist/registry.d.ts +98 -2
  166. package/dist/registry.js +171 -5
  167. package/dist/reloadable.d.ts +35 -0
  168. package/dist/reloadable.js +257 -0
  169. package/dist/server.d.ts +50 -4
  170. package/dist/server.js +790 -103
  171. package/dist/settings.d.ts +48 -0
  172. package/dist/settings.js +168 -0
  173. package/dist/site-auth.d.ts +39 -0
  174. package/dist/site-auth.js +195 -0
  175. package/dist/template-fixes.d.ts +26 -0
  176. package/dist/template-fixes.js +285 -0
  177. package/dist/test-reporter.d.ts +49 -0
  178. package/dist/test-reporter.js +190 -0
  179. package/dist/transaction.d.ts +67 -0
  180. package/dist/transaction.js +428 -46
  181. package/dist/verify-tests.d.ts +98 -0
  182. package/dist/verify-tests.js +449 -0
  183. package/dist/verify.d.ts +113 -4
  184. package/dist/verify.js +326 -28
  185. package/dist/view-choice.d.ts +58 -0
  186. package/dist/view-choice.js +131 -0
  187. package/dist/vite-watch.js +4 -2
  188. package/package.json +8 -6
@@ -0,0 +1,131 @@
1
+ // D-0098: the view of an app is a product choice whose default is Inertia + Vue. Outside a recipe
2
+ // it is made by `dokebi app add <name>` (EJS unless --inertia or --view none; none when the
3
+ // project's recipe built no browser screens, the api recipe) and by the first app of
4
+ // `dokebi add <apps host>` (EJS). These commands record it in `.dokebi/recipe.json` (`choices`)
5
+ // with who made it, the same way D-0095 records recipe answers, so verify's tellUser says it.
6
+ import { debug } from './diagnostics.js';
7
+ import { CliError } from './errors.js';
8
+ /**
9
+ * The longest `--ai-reason` text, one line for the user like a catalog defaultReason: of a recipe
10
+ * answer (D-0095) and of the view `app add` records (D-0098). One rule, `aiReasonFits`, for both.
11
+ */
12
+ export const AI_REASON_MAX = 200;
13
+ /** The id `--ai-chose` and `--ai-reason` name on `app add`. */
14
+ export const VIEW_ID = 'view';
15
+ /** The view answer of a project without browser screens (recipe.ts NO_SCREENS), and of `--view none`. */
16
+ export const NO_VIEW = 'none';
17
+ /**
18
+ * The view the project's latest recipe recorded (`view` answer), if any: `none` for the api
19
+ * recipe, so `app add` makes an app without views there unless a flag says otherwise.
20
+ */
21
+ export async function projectView(root) {
22
+ const { readAppliedRecipes } = await import('./recipe-record.js');
23
+ const recipes = await readAppliedRecipes(root);
24
+ for (const recipe of [...recipes].reverse()) {
25
+ const value = recipe.answers[VIEW_ID]?.value;
26
+ if (value !== undefined)
27
+ return value;
28
+ }
29
+ return undefined;
30
+ }
31
+ /** A trimmed `--ai-reason` text is one line of 1 to AI_REASON_MAX characters. */
32
+ export function aiReasonFits(reason) {
33
+ return reason.length > 0 && reason.length <= AI_REASON_MAX && !/[\r\n]/.test(reason);
34
+ }
35
+ /** The value of the view question for an app made with these flags. */
36
+ export function appViewValue(inertia, ssr, none = false) {
37
+ return inertia ? (ssr ? 'inertia-vue-ssr' : 'inertia-vue') : none ? NO_VIEW : 'ejs';
38
+ }
39
+ /**
40
+ * Checks the source flags of `app add` before anything changes: `--ai-chose` names only `view`,
41
+ * `--ai-reason` only an id of `--ai-chose`, and a reason is one line of 1 to 200 characters.
42
+ */
43
+ export function checkViewSource(flags) {
44
+ for (const id of flags.aiChose ?? [])
45
+ if (id !== VIEW_ID)
46
+ throw new CliError('AI_CHOICE_UNKNOWN', `app add records only the view, not ${id}`, {
47
+ details: { aiChose: id, questions: [VIEW_ID], fix: '--ai-chose view' },
48
+ phase: 'arguments',
49
+ });
50
+ for (const [id, text] of Object.entries(flags.aiReasons ?? {})) {
51
+ if (!(flags.aiChose ?? []).includes(id))
52
+ throw new CliError('AI_REASON_WITHOUT_CHOICE', `--ai-reason ${id} is given, but ${id} is not in --ai-chose`, {
53
+ details: {
54
+ question: id,
55
+ aiChose: [...(flags.aiChose ?? [])],
56
+ fix: 'add --ai-chose view if you chose the view because the user left it to you',
57
+ },
58
+ phase: 'arguments',
59
+ });
60
+ const reason = text.trim();
61
+ if (!aiReasonFits(reason))
62
+ throw new CliError('INVALID_AI_REASON', `--ai-reason ${id} must be one line of 1 to ${AI_REASON_MAX} characters`, {
63
+ details: {
64
+ question: id,
65
+ length: reason.length,
66
+ fix: 'give one short line the user reads: why you chose this view',
67
+ },
68
+ phase: 'arguments',
69
+ });
70
+ }
71
+ }
72
+ /**
73
+ * The record of an app's view: `ai` with `--ai-chose view` (or `--answers-from defaults`),
74
+ * `user` with `--answers-from user`, `unstated` for an EJS app or one without views, without
75
+ * either (not the default, so the user hears about it); none for an Inertia app without either
76
+ * (the default), nor for an app without views the project's recipe implied (`inherited`: the
77
+ * recipe's own line already says who chose no screens).
78
+ */
79
+ export function appViewChoice(app, value, flags, now = new Date(), inherited = false) {
80
+ const recordedAt = now.toISOString();
81
+ if ((flags.aiChose ?? []).includes(VIEW_ID) || flags.answersFrom === 'defaults') {
82
+ const reason = flags.aiReasons?.[VIEW_ID]?.trim();
83
+ return {
84
+ app,
85
+ id: VIEW_ID,
86
+ value,
87
+ answeredBy: 'ai',
88
+ ...(reason ? { aiReason: reason } : {}),
89
+ recordedAt,
90
+ };
91
+ }
92
+ if (flags.answersFrom === 'user')
93
+ return { app, id: VIEW_ID, value, answeredBy: 'user', recordedAt };
94
+ if (inherited) {
95
+ debug('app view: no views, as the project recipe built no screens', { app, value });
96
+ return undefined;
97
+ }
98
+ if (value === 'ejs' || value === NO_VIEW) {
99
+ debug('app view: a view other than the default without a stated source', { app, value });
100
+ return { app, id: VIEW_ID, value, answeredBy: 'unstated', recordedAt };
101
+ }
102
+ return undefined;
103
+ }
104
+ /** The warning of an EJS app (or one without views) whose chooser was not stated (D-0098). */
105
+ export function unstatedViewWarning(app, value = 'ejs') {
106
+ const what = value === NO_VIEW ? 'an app without views (--view none)' : 'EJS';
107
+ return {
108
+ code: 'VIEW_SOURCE_UNSTATED',
109
+ path: `src/apps/${app}`,
110
+ hint: `The app ${app} is ${what}, which is not the default view (Inertia + Vue, npx dokebi app add <name> --inertia). verify's tellUser tells the user that nobody recorded who chose it. Next time say it: --answers-from user when the user or the request chose it, --ai-chose view --ai-reason view=<why> when the user left the view to you.`,
111
+ };
112
+ }
113
+ /**
114
+ * After `app add` (or `add` with the first app): records the app's view with its source and adds
115
+ * VIEW_SOURCE_UNSTATED to the result's warnings for an EJS app without a source. A dry run only
116
+ * warns. The result is the command's own; it is returned with the warning added.
117
+ */
118
+ export async function recordAppView(root, result, app, value, flags, dryRun) {
119
+ // app add says what the app really got (an app without views in an api project).
120
+ const actual = result.appView?.value ?? value;
121
+ const choice = appViewChoice(app, actual, flags, new Date(), result.appView?.from === 'recipe');
122
+ if (!choice)
123
+ return result;
124
+ if (!dryRun) {
125
+ const { saveRecordedChoice } = await import('./recipe-record.js');
126
+ await saveRecordedChoice(root, choice);
127
+ }
128
+ if (choice.answeredBy !== 'unstated')
129
+ return result;
130
+ return { ...result, warnings: [...(result.warnings ?? []), unstatedViewWarning(app, actual)] };
131
+ }
@@ -1,6 +1,8 @@
1
1
  // Run by `dokebi dev` (D-0044) for one Vite config: a watch build that never empties its outDir.
2
- // The browser build's `emptyOutDir: true` would otherwise delete dist/ssr/ on every rebuild,
3
- // which is fine for `npm run build` (one build after the other) but not for two watchers.
2
+ // The templates of @dokebi/app write `emptyOutDir: false` (a rolling deploy keeps the previous
3
+ // chunks), but a vite.config of a project created before them still says `true`: the browser
4
+ // build (outDir dist/) would then delete dist/ssr/ on every rebuild, which `npm run build` (one
5
+ // build after the other) survives but two watchers do not. So dev overrides it for every config.
4
6
  // Every finished build is reported to dev over the IPC channel ({ built: true } or
5
7
  // { failed: true }); output goes to the terminal as usual.
6
8
  import { join } from 'node:path';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dokebi/cli",
3
- "version": "0.4.1",
3
+ "version": "0.4.26",
4
4
  "description": "Project scaffolding, plugin catalog, recipes, install and verification CLI for Dokebi.",
5
5
  "keywords": [
6
6
  "dokebi",
@@ -24,17 +24,18 @@
24
24
  "files": [
25
25
  "dist",
26
26
  "AI.md",
27
- "catalog.json"
27
+ "catalog.json",
28
+ "describe.schema.json"
28
29
  ],
29
30
  "scripts": {
30
31
  "build": "tsc -p tsconfig.json",
31
32
  "typecheck": "tsc -p tsconfig.test.json --noEmit",
32
- "test": "node -e \"require('node:fs').rmSync('.tmp/tests',{recursive:true,force:true})\" && tsc -p tsconfig.test.json && node --test \".tmp/tests/tests/*.test.js\""
33
+ "test": "node -e \"require('node:fs').rmSync('.tmp/tests',{recursive:true,force:true})\" && tsc -p tsconfig.test.json && node .tmp/tests/tests/run-suite.js"
33
34
  },
34
35
  "dependencies": {
35
36
  "semver": "7.8.5",
36
- "@dokebi/core": "^0.4.0",
37
- "@dokebi/config": "^0.4.0",
37
+ "@dokebi/core": "^0.4.2",
38
+ "@dokebi/config": "^0.4.2",
38
39
  "yaml": "2.9.1"
39
40
  },
40
41
  "devDependencies": {
@@ -59,7 +60,8 @@
59
60
  ],
60
61
  "recipes": [
61
62
  "api",
62
- "blog"
63
+ "blog",
64
+ "site"
63
65
  ]
64
66
  }
65
67
  }