@dokebi/cli 0.2.4 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AI.md +181 -87
- package/README.md +55 -24
- package/catalog.json +2199 -0
- package/dist/app-urls.d.ts +21 -0
- package/dist/app-urls.js +94 -0
- package/dist/banner-art.d.ts +4 -0
- package/dist/banner-art.js +31 -0
- package/dist/banner.d.ts +25 -0
- package/dist/banner.js +202 -0
- package/dist/bin.d.ts +2 -1
- package/dist/bin.js +475 -46
- package/dist/catalog.d.ts +161 -0
- package/dist/catalog.js +110 -0
- package/dist/check/form-rules.d.ts +13 -0
- package/dist/check/form-rules.js +224 -0
- package/dist/check/index.d.ts +23 -0
- package/dist/check/index.js +70 -0
- package/dist/check/packages.d.ts +17 -0
- package/dist/check/packages.js +161 -0
- package/dist/check/problems.d.ts +19 -0
- package/dist/check/problems.js +22 -0
- package/dist/check/project-rules.d.ts +10 -0
- package/dist/check/project-rules.js +142 -0
- package/dist/check/source-rules.d.ts +28 -0
- package/dist/check/source-rules.js +273 -0
- package/dist/check/typescript.d.ts +46 -0
- package/dist/check/typescript.js +168 -0
- package/dist/commands.d.ts +18 -0
- package/dist/commands.js +372 -0
- package/dist/config-edit.d.ts +7 -0
- package/dist/config-edit.js +17 -0
- package/dist/configuration.d.ts +1 -0
- package/dist/configuration.js +2 -1
- package/dist/dev-infra.d.ts +62 -0
- package/dist/dev-infra.js +215 -0
- package/dist/env-file.d.ts +24 -0
- package/dist/env-file.js +100 -0
- package/dist/generator.d.ts +24 -1
- package/dist/generator.js +57 -47
- package/dist/guide.d.ts +29 -0
- package/dist/guide.js +90 -0
- package/dist/install-plan.d.ts +8 -0
- package/dist/install-plan.js +21 -4
- package/dist/layout.d.ts +5 -4
- package/dist/layout.js +8 -7
- package/dist/log-writer-control.d.ts +55 -0
- package/dist/log-writer-control.js +327 -0
- package/dist/log-writer.js +53 -12
- package/dist/manifest.d.ts +28 -0
- package/dist/manifest.js +77 -2
- package/dist/npm-client.d.ts +49 -0
- package/dist/npm-client.js +162 -41
- package/dist/output.d.ts +1 -1
- package/dist/output.js +14 -8
- package/dist/plugin-lifecycle.d.ts +7 -0
- package/dist/plugin-lifecycle.js +21 -3
- package/dist/plugins-command.d.ts +47 -0
- package/dist/plugins-command.js +189 -0
- package/dist/project-guide.d.ts +36 -1
- package/dist/project-guide.js +141 -18
- package/dist/project-inspector.d.ts +10 -0
- package/dist/project-inspector.js +51 -2
- package/dist/project-state.d.ts +13 -2
- package/dist/project-state.js +8 -6
- package/dist/project.d.ts +89 -7
- package/dist/project.js +856 -85
- package/dist/recipe-record.d.ts +24 -0
- package/dist/recipe-record.js +67 -0
- package/dist/recipe.d.ts +120 -0
- package/dist/recipe.js +793 -0
- package/dist/registry.d.ts +79 -0
- package/dist/registry.js +212 -0
- package/dist/rotating-log.d.ts +12 -0
- package/dist/rotating-log.js +19 -0
- package/dist/server.d.ts +94 -4
- package/dist/server.js +624 -64
- package/dist/verify.d.ts +62 -0
- package/dist/verify.js +380 -0
- package/dist/vite-host-process.d.ts +20 -0
- package/dist/vite-host-process.js +117 -0
- package/package.json +30 -6
package/dist/project-state.d.ts
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
|
+
import { type FileOwner } from './install-plan.js';
|
|
1
2
|
import { type PluginManifest } from './manifest.js';
|
|
2
3
|
export interface OwnedFile {
|
|
3
4
|
hash: string;
|
|
5
|
+
/** The plugins that installed the file (ids). */
|
|
4
6
|
owners: string[];
|
|
7
|
+
/**
|
|
8
|
+
* Who edits it (D-0065 §11): `user` (a scaffold to change; doctor stays silent) or `cli`
|
|
9
|
+
* (regenerated; an edit is MODIFIED_TEMPLATE). States written before this field read as `user`.
|
|
10
|
+
*/
|
|
11
|
+
owner: FileOwner;
|
|
5
12
|
}
|
|
6
13
|
/** Per-plugin results of the install lifecycle that are not part of the package manifest. */
|
|
7
14
|
export interface Installation {
|
|
@@ -15,9 +22,13 @@ export interface ProjectState {
|
|
|
15
22
|
installations: Record<string, Installation>;
|
|
16
23
|
files: Record<string, OwnedFile>;
|
|
17
24
|
generatedHash: string;
|
|
18
|
-
/**
|
|
25
|
+
/**
|
|
26
|
+
* Apps in registration order (src/apps/<name>/app.ts), D-0030, for the plugin that hosts apps
|
|
27
|
+
* (D-0070). That a host is installed is checked where the apps are used (generation, app
|
|
28
|
+
* commands): a state written before the manifests declared roles still loads, so upgrade works.
|
|
29
|
+
*/
|
|
19
30
|
apps?: string[];
|
|
20
|
-
/** Modules
|
|
31
|
+
/** Modules in registration order (src/shared/modules/<name>), D-0032, for the modules host. */
|
|
21
32
|
modules?: string[];
|
|
22
33
|
}
|
|
23
34
|
/** App and template names: lower-case letters, digits and hyphens, starting with a letter. */
|
package/dist/project-state.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { CliError } from './errors.js';
|
|
2
2
|
import { object, templateTarget } from './filesystem.js';
|
|
3
|
+
import { FILE_OWNERS } from './install-plan.js';
|
|
3
4
|
import { ID, readStoredManifest } from './manifest.js';
|
|
4
5
|
/** App and template names: lower-case letters, digits and hyphens, starting with a letter. */
|
|
5
6
|
export const APP_NAME = /^[a-z][a-z0-9-]{0,31}$/;
|
|
@@ -47,9 +48,14 @@ export function readState(value) {
|
|
|
47
48
|
!Array.isArray(file.owners) ||
|
|
48
49
|
!file.owners.length ||
|
|
49
50
|
!file.owners.every((owner) => typeof owner === 'string' && plugins.some((plugin) => plugin.id === owner)) ||
|
|
50
|
-
new Set(file.owners).size !== file.owners.length
|
|
51
|
+
new Set(file.owners).size !== file.owners.length ||
|
|
52
|
+
(file.owner !== undefined && !FILE_OWNERS.includes(file.owner)))
|
|
51
53
|
throw new CliError('INVALID_STATE', 'Invalid file ownership');
|
|
52
|
-
files[path] = {
|
|
54
|
+
files[path] = {
|
|
55
|
+
hash: file.hash,
|
|
56
|
+
owners: file.owners,
|
|
57
|
+
owner: file.owner === undefined ? 'user' : file.owner,
|
|
58
|
+
};
|
|
53
59
|
}
|
|
54
60
|
const installations = Object.create(null);
|
|
55
61
|
if (input.schemaVersion === 1) {
|
|
@@ -89,8 +95,6 @@ export function readState(value) {
|
|
|
89
95
|
if (!APP_NAME.test(name))
|
|
90
96
|
throw new CliError('INVALID_STATE', 'Invalid app name');
|
|
91
97
|
});
|
|
92
|
-
if (apps.length && !plugins.some((plugin) => plugin.id === 'dokebi-app'))
|
|
93
|
-
throw new CliError('INVALID_STATE', 'Apps need the dokebi-app plugin');
|
|
94
98
|
}
|
|
95
99
|
let modules;
|
|
96
100
|
if (input.modules !== undefined) {
|
|
@@ -98,8 +102,6 @@ export function readState(value) {
|
|
|
98
102
|
if (!APP_NAME.test(name))
|
|
99
103
|
throw new CliError('INVALID_STATE', 'Invalid module name');
|
|
100
104
|
});
|
|
101
|
-
if (modules.length && !plugins.some((plugin) => plugin.id === 'dokebi-module'))
|
|
102
|
-
throw new CliError('INVALID_STATE', 'Modules need the dokebi-module plugin');
|
|
103
105
|
}
|
|
104
106
|
return {
|
|
105
107
|
schemaVersion: 2,
|
package/dist/project.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type SetOption, type Warning } from './config-edit.js';
|
|
2
2
|
import { NpmClient } from './npm-client.js';
|
|
3
|
+
import { type Resolution } from './registry.js';
|
|
3
4
|
export interface ConfigRequirement {
|
|
4
5
|
plugin: string;
|
|
5
6
|
errors: Array<{
|
|
@@ -27,28 +28,109 @@ export interface OperationResult {
|
|
|
27
28
|
warnings?: Array<Warning & {
|
|
28
29
|
plugin?: string;
|
|
29
30
|
}>;
|
|
30
|
-
/**
|
|
31
|
-
nextSteps?:
|
|
31
|
+
/** What to do after this command: a command (or an edit) and why (D-0065). */
|
|
32
|
+
nextSteps?: NextStep[];
|
|
33
|
+
/** The version `add` picked when none was given: highest one compatible with the core. */
|
|
34
|
+
resolved?: Resolution;
|
|
32
35
|
from?: string;
|
|
33
36
|
to?: string;
|
|
34
37
|
/** Why an upgrade to the same version was applied: the installed manifest differs (D-0037). */
|
|
35
38
|
reason?: 'MANIFEST_CHANGED';
|
|
36
39
|
/** npm workspace root where `npm install` ran (or, in a dry run, would run) (D-0035). */
|
|
37
40
|
workspaceInstall?: string;
|
|
41
|
+
/**
|
|
42
|
+
* Secrets `add` generated into .env for the plugins it installed (D-0073): variable names only,
|
|
43
|
+
* the values are never shown. A variable already set in the environment or .env is kept.
|
|
44
|
+
*/
|
|
45
|
+
generatedSecrets?: GeneratedSecret[];
|
|
46
|
+
}
|
|
47
|
+
/** One generated secret of `add` (D-0073). */
|
|
48
|
+
export interface GeneratedSecret {
|
|
49
|
+
readonly variable: string;
|
|
50
|
+
readonly file: string;
|
|
51
|
+
readonly plugin: string;
|
|
52
|
+
}
|
|
53
|
+
/** `dokebi add` choices beyond the package (D-0065). */
|
|
54
|
+
export interface AddOptions {
|
|
55
|
+
/** @dokebi/db: write this adapter (pg, mysql2, mariadb, mongodb), its connection and driver. */
|
|
56
|
+
adapter?: string;
|
|
57
|
+
/** The plugin that hosts apps (D-0070): false skips the first `main` app (`--no-first-app`). */
|
|
58
|
+
firstApp?: boolean;
|
|
38
59
|
}
|
|
60
|
+
/** One follow-up of a command (init, add, app, module, recipe): a command to run and why. */
|
|
61
|
+
export interface NextStep {
|
|
62
|
+
command: string;
|
|
63
|
+
why: string;
|
|
64
|
+
}
|
|
65
|
+
/** `dokebi init`: the created folder, plus what to do next (machine-readable). */
|
|
66
|
+
export interface InitResult extends OperationResult {
|
|
67
|
+
nextSteps: NextStep[];
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Follow-ups after init (D-0065): read the guide, pick a recipe and ask its questions, find
|
|
71
|
+
* plugins, read the core contract, and verify before saying done.
|
|
72
|
+
*/
|
|
73
|
+
export declare function initNextSteps(target: string): NextStep[];
|
|
74
|
+
/**
|
|
75
|
+
* Entries `dokebi init` leaves in an existing folder (D-0065 §11, AI-M02: agents are often handed
|
|
76
|
+
* an empty work folder, sometimes with npm or editor files in it). Nothing here is written by init
|
|
77
|
+
* or is part of a Node project; `.npmrc` is also used for init's own npm install.
|
|
78
|
+
*/
|
|
79
|
+
export declare const INIT_HARMLESS: readonly string[];
|
|
80
|
+
/**
|
|
81
|
+
* Whether `dokebi init` may use `target`: absent (created), or a folder that is empty or holds
|
|
82
|
+
* only INIT_HARMLESS entries (`kept`). Anything else (a file, other entries) is PROJECT_EXISTS.
|
|
83
|
+
*/
|
|
84
|
+
export declare function initFolder(target: string,
|
|
85
|
+
/** init's own staging folder inside `target` (checked again before the move). */
|
|
86
|
+
staging?: string): Promise<{
|
|
87
|
+
exists: boolean;
|
|
88
|
+
kept: string[];
|
|
89
|
+
}>;
|
|
39
90
|
export declare class Project {
|
|
40
91
|
#private;
|
|
41
92
|
private readonly npm;
|
|
42
93
|
constructor(npm?: NpmClient);
|
|
43
|
-
init(target: string, core?: string): Promise<
|
|
94
|
+
init(target: string, core?: string, dryRun?: boolean): Promise<InitResult>;
|
|
44
95
|
migrate(root: string, dryRun?: boolean): Promise<OperationResult>;
|
|
45
|
-
add(root: string, spec: string, dryRun?: boolean, sets?: readonly SetOption[]): Promise<OperationResult>;
|
|
96
|
+
add(root: string, spec: string, dryRun?: boolean, sets?: readonly SetOption[], options?: AddOptions): Promise<OperationResult>;
|
|
46
97
|
remove(root: string, id: string, dryRun?: boolean): Promise<OperationResult>;
|
|
47
98
|
upgrade(root: string, id: string, to?: string, dryRun?: boolean): Promise<OperationResult>;
|
|
99
|
+
/**
|
|
100
|
+
* `dokebi config set <plugin>.<path>=<value>…`: non-secret options in dokebi.yaml, checked
|
|
101
|
+
* against that plugin's schema (only missing required values are tolerated and reported).
|
|
102
|
+
*/
|
|
103
|
+
configSet(root: string, assignments: readonly {
|
|
104
|
+
plugin: string;
|
|
105
|
+
set: SetOption;
|
|
106
|
+
}[], dryRun?: boolean): Promise<OperationResult>;
|
|
107
|
+
/**
|
|
108
|
+
* `dokebi dev-infra` (D-0065): compose.yaml for the database of connection `main`, a generated
|
|
109
|
+
* password in .env (git-ignored) and the matching URL in dokebi.yaml. An existing compose.yaml
|
|
110
|
+
* with a `db` service and an existing password are kept; nothing is started here.
|
|
111
|
+
*/
|
|
112
|
+
devInfra(root: string, options?: {
|
|
113
|
+
dbPort?: number;
|
|
114
|
+
dryRun?: boolean;
|
|
115
|
+
}): Promise<OperationResult & {
|
|
116
|
+
service?: Record<string, unknown>;
|
|
117
|
+
}>;
|
|
118
|
+
/**
|
|
119
|
+
* `dokebi config secret <plugin>.<path>`: a generated random secret (32 bytes, base64url) in
|
|
120
|
+
* dokebi.yaml, as a one-item list when the schema wants a list. The value is never returned or
|
|
121
|
+
* logged; an existing value is kept (SECRET_KEPT). Secrets never pass the command line.
|
|
122
|
+
*/
|
|
123
|
+
configSecret(root: string, id: string, path: readonly string[], dryRun?: boolean): Promise<OperationResult & {
|
|
124
|
+
secret: {
|
|
125
|
+
path: string;
|
|
126
|
+
list: boolean;
|
|
127
|
+
generated: boolean;
|
|
128
|
+
};
|
|
129
|
+
}>;
|
|
48
130
|
private coreVersion;
|
|
49
131
|
/**
|
|
50
|
-
* `dokebi app add <name>`: copies the app skeleton of
|
|
51
|
-
* given domains to it in dokebi.yaml and registers it in the generated code (D-0030 §7).
|
|
132
|
+
* `dokebi app add <name>`: copies the app skeleton of the apps host (D-0070) to src/apps/<name>,
|
|
133
|
+
* maps the given domains to it in dokebi.yaml and registers it in the generated code (D-0030 §7).
|
|
52
134
|
*/
|
|
53
135
|
appAdd(root: string, name: string, options?: {
|
|
54
136
|
domains?: readonly string[];
|
|
@@ -78,7 +160,7 @@ export declare class Project {
|
|
|
78
160
|
}[];
|
|
79
161
|
}>;
|
|
80
162
|
/**
|
|
81
|
-
* `dokebi module add <name>` (D-0032): copies the module skeleton of
|
|
163
|
+
* `dokebi module add <name>` (D-0032): copies the module skeleton of the modules host to
|
|
82
164
|
* src/shared/modules/<name> and registers it in the generated code. `views: false` copies the
|
|
83
165
|
* skeleton without views (routes answer JSON).
|
|
84
166
|
*/
|