@ouispec/cli 0.1.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/LICENSE +21 -0
- package/README.md +112 -0
- package/dist/analyze.d.ts +282 -0
- package/dist/analyze.d.ts.map +1 -0
- package/dist/analyze.js +1421 -0
- package/dist/analyze.js.map +1 -0
- package/dist/assemble.d.ts +50 -0
- package/dist/assemble.d.ts.map +1 -0
- package/dist/assemble.js +555 -0
- package/dist/assemble.js.map +1 -0
- package/dist/cli.d.ts +12 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +54 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +54 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +126 -0
- package/dist/config.js.map +1 -0
- package/dist/contract.d.ts +10 -0
- package/dist/contract.d.ts.map +1 -0
- package/dist/contract.js +15 -0
- package/dist/contract.js.map +1 -0
- package/dist/generate.d.ts +49 -0
- package/dist/generate.d.ts.map +1 -0
- package/dist/generate.js +178 -0
- package/dist/generate.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/inputs.d.ts +134 -0
- package/dist/inputs.d.ts.map +1 -0
- package/dist/inputs.js +705 -0
- package/dist/inputs.js.map +1 -0
- package/dist/knowledge.d.ts +19 -0
- package/dist/knowledge.d.ts.map +1 -0
- package/dist/knowledge.js +366 -0
- package/dist/knowledge.js.map +1 -0
- package/dist/program.d.ts +60 -0
- package/dist/program.d.ts.map +1 -0
- package/dist/program.js +302 -0
- package/dist/program.js.map +1 -0
- package/dist/recipes.d.ts +17 -0
- package/dist/recipes.d.ts.map +1 -0
- package/dist/recipes.js +48 -0
- package/dist/recipes.js.map +1 -0
- package/dist/tier2.d.ts +74 -0
- package/dist/tier2.d.ts.map +1 -0
- package/dist/tier2.js +303 -0
- package/dist/tier2.js.map +1 -0
- package/package.json +62 -0
package/dist/cli.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* oui (also installed as closure-oui) — the assistant's surfaces and knowledge,
|
|
4
|
+
* generated from the UI's code (ADR-0220, ADR-0226).
|
|
5
|
+
*
|
|
6
|
+
* oui generate write <out>/oui-manifest.json and oui-knowledge.json
|
|
7
|
+
* oui generate --check fail if they are stale, or if any declaration is invalid (CI)
|
|
8
|
+
*
|
|
9
|
+
* Options: --config <path> (default ./oui.config.json)
|
|
10
|
+
*/
|
|
11
|
+
import { basename, resolve } from 'node:path';
|
|
12
|
+
/** The name it was run as: `oui`, or `closure-oui`. */
|
|
13
|
+
const cliName = basename(process.argv[1] ?? 'oui').replace(/\.js$/, '') === 'closure-oui' ? 'closure-oui' : 'oui';
|
|
14
|
+
import { loadConfig } from './config.js';
|
|
15
|
+
import { generate, writeOrCheck } from './generate.js';
|
|
16
|
+
async function main(argv) {
|
|
17
|
+
const [command, ...rest] = argv;
|
|
18
|
+
if (command !== 'generate') {
|
|
19
|
+
console.error(`usage: ${cliName} generate [--check] [--config oui.config.json]`);
|
|
20
|
+
return 2;
|
|
21
|
+
}
|
|
22
|
+
const check = rest.includes('--check');
|
|
23
|
+
const configFlag = rest.indexOf('--config');
|
|
24
|
+
const configPath = resolve(configFlag === -1 ? 'oui.config.json' : rest[configFlag + 1]);
|
|
25
|
+
const config = loadConfig(configPath);
|
|
26
|
+
const result = await generate(config);
|
|
27
|
+
for (const e of result.errors)
|
|
28
|
+
console.error(`${e.file}${e.line ? `:${e.line}` : ''}: ${e.message}`);
|
|
29
|
+
for (const w of result.warnings)
|
|
30
|
+
console.error(`${w.file}${w.line ? `:${w.line}` : ''}: warning: ${w.message}`);
|
|
31
|
+
const stale = writeOrCheck(result, config, check);
|
|
32
|
+
const { pages, actions, rooms, unboundPages, boundModules } = result.stats;
|
|
33
|
+
const summary = `${pages} pages, ${rooms} rooms, ${actions} actions; ${unboundPages} pages not yet bound; ` +
|
|
34
|
+
`${boundModules ? `${boundModules} bound modules; ` : ''}build ${result.manifest.buildId}`;
|
|
35
|
+
if (result.errors.length) {
|
|
36
|
+
console.error(`\n${result.errors.length} problem(s) in the UI's declarations. ${summary}`);
|
|
37
|
+
return 1;
|
|
38
|
+
}
|
|
39
|
+
if (check && stale.length) {
|
|
40
|
+
console.error(`Stale: ${stale.join(', ')}. Run: npx ${cliName} generate\n${summary}`);
|
|
41
|
+
return 1;
|
|
42
|
+
}
|
|
43
|
+
console.log(`${check ? 'Up to date' : 'Generated'}: ${summary}`);
|
|
44
|
+
return 0;
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
process.exitCode = await main(process.argv.slice(2));
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
// A setting or input the generator cannot use: its message names it; a stack would bury it.
|
|
51
|
+
console.error(err.message);
|
|
52
|
+
process.exitCode = 1;
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The generator's configuration: where an app keeps its routes, navigation
|
|
3
|
+
* and output, which design systems its controls come from, where its API is
|
|
4
|
+
* described, and which of its pages are not yet bound (ADR-0220 §2.8,
|
|
5
|
+
* ADR-0226 §2.4).
|
|
6
|
+
*
|
|
7
|
+
* Read from `oui.config.json` at the app's root; paths are relative to it.
|
|
8
|
+
* The file is required and explicit: nothing an app depends on has a default,
|
|
9
|
+
* so a misconfigured app fails here, naming the setting, instead of
|
|
10
|
+
* generating an assistant that can do nothing.
|
|
11
|
+
*/
|
|
12
|
+
import type { ControlTableFile, RoomCatalogData } from '@ouispec/bindings';
|
|
13
|
+
import { type AppCatalogEntry, type OuiConfigFile, type ShellEntry } from '@ouispec/contract';
|
|
14
|
+
export type { AppCatalogEntry, OuiConfigFile, ShellEntry };
|
|
15
|
+
/** Tables and catalogs given directly rather than read from packages: tests, and tools that already hold them. */
|
|
16
|
+
export interface ConfigInjection {
|
|
17
|
+
controlTables?: Readonly<Record<string, ControlTableFile>>;
|
|
18
|
+
catalogs?: readonly {
|
|
19
|
+
package: string;
|
|
20
|
+
hosts: readonly string[];
|
|
21
|
+
catalog: RoomCatalogData;
|
|
22
|
+
}[];
|
|
23
|
+
}
|
|
24
|
+
/** The resolved configuration: every path absolute, every list present. */
|
|
25
|
+
export interface GeneratorConfig extends ConfigInjection {
|
|
26
|
+
/** The app's root: where `oui.config.json` is. */
|
|
27
|
+
root: string;
|
|
28
|
+
tsconfig: string;
|
|
29
|
+
routes: string;
|
|
30
|
+
routeWrappers: readonly string[];
|
|
31
|
+
nav: readonly string[];
|
|
32
|
+
out: string;
|
|
33
|
+
designSystem: readonly string[];
|
|
34
|
+
/** Tier 2 mappings, each absolute (ADR-0226 §2.3). */
|
|
35
|
+
mappings: readonly string[];
|
|
36
|
+
/** As written: a module path or a path relative to the root; resolved when the spec is read. */
|
|
37
|
+
apiSpec: string | null;
|
|
38
|
+
unbound: readonly string[];
|
|
39
|
+
appCatalogs: readonly AppCatalogEntry[];
|
|
40
|
+
shell: readonly ShellEntry[];
|
|
41
|
+
}
|
|
42
|
+
export declare const CONFIG_FILE = "oui.config.json";
|
|
43
|
+
export declare class ConfigError extends Error {
|
|
44
|
+
readonly file: string;
|
|
45
|
+
readonly problems: readonly string[];
|
|
46
|
+
constructor(file: string, problems: readonly string[]);
|
|
47
|
+
}
|
|
48
|
+
export declare function loadConfig(file: string): GeneratorConfig;
|
|
49
|
+
/**
|
|
50
|
+
* Validate the file's settings and resolve their paths against `root`.
|
|
51
|
+
* Throws a `ConfigError` listing every problem.
|
|
52
|
+
*/
|
|
53
|
+
export declare function resolveConfig(root: string, raw: unknown, inject?: ConfigInjection): GeneratorConfig;
|
|
54
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAC3E,OAAO,EAAoB,KAAK,eAAe,EAAE,KAAK,aAAa,EAAE,KAAK,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAIhH,YAAY,EAAE,eAAe,EAAE,aAAa,EAAE,UAAU,EAAE,CAAC;AAE3D,kHAAkH;AAClH,MAAM,WAAW,eAAe;IAC9B,aAAa,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC;IAC3D,QAAQ,CAAC,EAAE,SAAS;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;QAAC,OAAO,EAAE,eAAe,CAAA;KAAE,EAAE,CAAC;CAC/F;AAED,2EAA2E;AAC3E,MAAM,WAAW,eAAgB,SAAQ,eAAe;IACtD,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,GAAG,EAAE,SAAS,MAAM,EAAE,CAAC;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,sDAAsD;IACtD,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,gGAAgG;IAChG,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,WAAW,EAAE,SAAS,eAAe,EAAE,CAAC;IACxC,KAAK,EAAE,SAAS,UAAU,EAAE,CAAC;CAC9B;AAED,eAAO,MAAM,WAAW,oBAAoB,CAAC;AAqB7C,qBAAa,WAAY,SAAQ,KAAK;IAElC,QAAQ,CAAC,IAAI,EAAE,MAAM;IACrB,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE;gBAD3B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,SAAS,MAAM,EAAE;CAKvC;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CAYxD;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,GAAE,eAAoB,GAAG,eAAe,CAqDvG"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The generator's configuration: where an app keeps its routes, navigation
|
|
3
|
+
* and output, which design systems its controls come from, where its API is
|
|
4
|
+
* described, and which of its pages are not yet bound (ADR-0220 §2.8,
|
|
5
|
+
* ADR-0226 §2.4).
|
|
6
|
+
*
|
|
7
|
+
* Read from `oui.config.json` at the app's root; paths are relative to it.
|
|
8
|
+
* The file is required and explicit: nothing an app depends on has a default,
|
|
9
|
+
* so a misconfigured app fails here, naming the setting, instead of
|
|
10
|
+
* generating an assistant that can do nothing.
|
|
11
|
+
*/
|
|
12
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
13
|
+
import { dirname, resolve } from 'node:path';
|
|
14
|
+
import { CONTRACT_SCHEMAS } from '@ouispec/contract';
|
|
15
|
+
import { contractProblems } from '@ouispec/contract/validate';
|
|
16
|
+
export const CONFIG_FILE = 'oui.config.json';
|
|
17
|
+
/** The schema the file is checked against: what is required, what is a setting, and what each is. */
|
|
18
|
+
const SCHEMA = CONTRACT_SCHEMAS['oui-config.json'];
|
|
19
|
+
/** What a setting is, for the message that says it is missing: its description's first sentence. */
|
|
20
|
+
const what = (key) => {
|
|
21
|
+
const sentence = (SCHEMA.properties[key]?.description ?? '').split(/(?<=[.:])\s/)[0].replace(/[.:]$/, '');
|
|
22
|
+
return sentence.charAt(0).toLowerCase() + sentence.slice(1);
|
|
23
|
+
};
|
|
24
|
+
/** Settings an older generator read, and what replaced each. */
|
|
25
|
+
const REPLACED = {
|
|
26
|
+
apiClient: '"apiClient" is replaced by "apiSpec": the module path of the API’s OpenAPI document ' +
|
|
27
|
+
'(e.g. "@closurestudio/api-client/openapi.json"), or null for none',
|
|
28
|
+
};
|
|
29
|
+
export class ConfigError extends Error {
|
|
30
|
+
file;
|
|
31
|
+
problems;
|
|
32
|
+
constructor(file, problems) {
|
|
33
|
+
super(`${file} is not valid:\n${problems.map(p => ` - ${p}`).join('\n')}`);
|
|
34
|
+
this.file = file;
|
|
35
|
+
this.problems = problems;
|
|
36
|
+
this.name = 'ConfigError';
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
export function loadConfig(file) {
|
|
40
|
+
const path = resolve(file);
|
|
41
|
+
if (!existsSync(path)) {
|
|
42
|
+
throw new Error(`No ${CONFIG_FILE} at ${path}: the generator reads every setting from it (ADR-0226 §2.4)`);
|
|
43
|
+
}
|
|
44
|
+
let raw;
|
|
45
|
+
try {
|
|
46
|
+
raw = JSON.parse(readFileSync(path, 'utf8'));
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
throw new Error(`${path} is not JSON: ${err.message}`, { cause: err });
|
|
50
|
+
}
|
|
51
|
+
return resolveConfig(dirname(path), raw);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Validate the file's settings and resolve their paths against `root`.
|
|
55
|
+
* Throws a `ConfigError` listing every problem.
|
|
56
|
+
*/
|
|
57
|
+
export function resolveConfig(root, raw, inject = {}) {
|
|
58
|
+
if (!isRecord(raw))
|
|
59
|
+
throw new ConfigError(CONFIG_FILE, ['it must be a JSON object of settings']);
|
|
60
|
+
const problems = [];
|
|
61
|
+
for (const key of SCHEMA.required) {
|
|
62
|
+
if (!(key in raw))
|
|
63
|
+
problems.push(`"${key}" is required: ${what(key)}`);
|
|
64
|
+
}
|
|
65
|
+
for (const key of Object.keys(raw)) {
|
|
66
|
+
if (key in SCHEMA.properties)
|
|
67
|
+
continue;
|
|
68
|
+
problems.push(REPLACED[key] ?? `"${key}" is not a setting`);
|
|
69
|
+
}
|
|
70
|
+
const path = (key) => {
|
|
71
|
+
if (key in raw && (typeof raw[key] !== 'string' || !raw[key].trim()))
|
|
72
|
+
problems.push(`"${key}" must be a path`);
|
|
73
|
+
};
|
|
74
|
+
const strings = (key, what) => {
|
|
75
|
+
if (key in raw && !(Array.isArray(raw[key]) && raw[key].every(v => typeof v === 'string' && v.trim())))
|
|
76
|
+
problems.push(`"${key}" must be a list of ${what}`);
|
|
77
|
+
};
|
|
78
|
+
path('tsconfig');
|
|
79
|
+
path('routes');
|
|
80
|
+
path('out');
|
|
81
|
+
strings('designSystem', 'package names');
|
|
82
|
+
strings('mappings', 'paths');
|
|
83
|
+
strings('routeWrappers', 'component names');
|
|
84
|
+
strings('nav', 'paths');
|
|
85
|
+
strings('unbound', 'component names');
|
|
86
|
+
if ('apiSpec' in raw && raw.apiSpec !== null && (typeof raw.apiSpec !== 'string' || !raw.apiSpec.trim()))
|
|
87
|
+
problems.push('"apiSpec" must be the module path of an OpenAPI document, or null');
|
|
88
|
+
entries(raw, 'shell', ['module', 'export'], problems);
|
|
89
|
+
entries(raw, 'appCatalogs', ['module', 'export'], problems);
|
|
90
|
+
// The schema is the authority: whatever the checks above put in words, a
|
|
91
|
+
// file it refuses is refused.
|
|
92
|
+
if (!problems.length)
|
|
93
|
+
problems.push(...contractProblems('oui-config.json', raw).map(p => `the contract's oui-config.json: ${p}`));
|
|
94
|
+
if (problems.length)
|
|
95
|
+
throw new ConfigError(CONFIG_FILE, problems);
|
|
96
|
+
const file = raw;
|
|
97
|
+
return {
|
|
98
|
+
...inject,
|
|
99
|
+
root,
|
|
100
|
+
tsconfig: resolve(root, file.tsconfig),
|
|
101
|
+
routes: resolve(root, file.routes),
|
|
102
|
+
routeWrappers: [...(file.routeWrappers ?? [])],
|
|
103
|
+
nav: (file.nav ?? []).map(n => resolve(root, n)),
|
|
104
|
+
out: resolve(root, file.out),
|
|
105
|
+
designSystem: [...file.designSystem],
|
|
106
|
+
mappings: (file.mappings ?? []).map(m => resolve(root, m)),
|
|
107
|
+
apiSpec: file.apiSpec,
|
|
108
|
+
unbound: [...(file.unbound ?? [])].sort(),
|
|
109
|
+
appCatalogs: [...(file.appCatalogs ?? [])],
|
|
110
|
+
shell: (file.shell ?? []).map(s => ({ ...s, module: resolve(root, s.module) })),
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
/** A list of objects each with string settings `required`. */
|
|
114
|
+
function entries(raw, key, required, problems) {
|
|
115
|
+
if (!(key in raw))
|
|
116
|
+
return;
|
|
117
|
+
const value = raw[key];
|
|
118
|
+
const ok = Array.isArray(value) &&
|
|
119
|
+
value.every(v => isRecord(v) && required.every(k => typeof v[k] === 'string' && v[k].trim()));
|
|
120
|
+
if (!ok)
|
|
121
|
+
problems.push(`"${key}" must be a list of { ${required.map(k => `"${k}"`).join(', ')}, … } entries`);
|
|
122
|
+
}
|
|
123
|
+
function isRecord(v) {
|
|
124
|
+
return !!v && typeof v === 'object' && !Array.isArray(v);
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The contract the generator reads and writes (ADR-0226 §3.1): every control
|
|
3
|
+
* table, room catalog, manifest and knowledge it handles is checked against
|
|
4
|
+
* the published schemas, and each way one breaks them is a finding.
|
|
5
|
+
*/
|
|
6
|
+
import { type ContractRef } from '@ouispec/contract/validate';
|
|
7
|
+
import type { Finding } from './analyze.js';
|
|
8
|
+
/** Each way `value` breaks the contract's `ref`, as a finding against `file`, naming `what`. */
|
|
9
|
+
export declare function contractFindings(ref: ContractRef, value: unknown, file: string, what: string): Finding[];
|
|
10
|
+
//# sourceMappingURL=contract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAoB,KAAK,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAEhF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE5C,gGAAgG;AAChG,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,EAAE,CAMxG"}
|
package/dist/contract.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The contract the generator reads and writes (ADR-0226 §3.1): every control
|
|
3
|
+
* table, room catalog, manifest and knowledge it handles is checked against
|
|
4
|
+
* the published schemas, and each way one breaks them is a finding.
|
|
5
|
+
*/
|
|
6
|
+
import { contractProblems } from '@ouispec/contract/validate';
|
|
7
|
+
/** Each way `value` breaks the contract's `ref`, as a finding against `file`, naming `what`. */
|
|
8
|
+
export function contractFindings(ref, value, file, what) {
|
|
9
|
+
return contractProblems(ref, value).map(problem => ({
|
|
10
|
+
file,
|
|
11
|
+
line: 0,
|
|
12
|
+
message: `${what} does not match the OUI contract (${ref}): ${problem}`,
|
|
13
|
+
}));
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=contract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract.js","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,gBAAgB,EAAoB,MAAM,4BAA4B,CAAC;AAIhF,gGAAgG;AAChG,MAAM,UAAU,gBAAgB,CAAC,GAAgB,EAAE,KAAc,EAAE,IAAY,EAAE,IAAY;IAC3F,OAAO,gBAAgB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAClD,IAAI;QACJ,IAAI,EAAE,CAAC;QACP,OAAO,EAAE,GAAG,IAAI,qCAAqC,GAAG,MAAM,OAAO,EAAE;KACxE,CAAC,CAAC,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The generator (ADR-0220 §2.4): reads the app, emits each build's manifest
|
|
3
|
+
* and knowledge, and validates both. Deterministic: no LLM, no network, no
|
|
4
|
+
* clock; the same source always gives the same bytes.
|
|
5
|
+
*/
|
|
6
|
+
import { type GeneratedKnowledge, type OuiManifest } from '@ouispec/bindings';
|
|
7
|
+
import { type Finding } from './analyze.js';
|
|
8
|
+
import { type GeneratorConfig } from './config.js';
|
|
9
|
+
export declare const MANIFEST_FILE = "oui-manifest.json";
|
|
10
|
+
export declare const KNOWLEDGE_FILE = "oui-knowledge.json";
|
|
11
|
+
/** One use of a mapped control, as the conformance kit's `checkTier2` takes it (`Tier2Use`). */
|
|
12
|
+
export interface Tier2Use {
|
|
13
|
+
/** The mapped control's name in its mapping. */
|
|
14
|
+
component: string;
|
|
15
|
+
/** The file, relative to the app root. */
|
|
16
|
+
file: string;
|
|
17
|
+
line: number;
|
|
18
|
+
/** The props the use passes. */
|
|
19
|
+
props: string[];
|
|
20
|
+
}
|
|
21
|
+
export interface GenerateResult {
|
|
22
|
+
manifest: OuiManifest;
|
|
23
|
+
knowledge: GeneratedKnowledge;
|
|
24
|
+
errors: Finding[];
|
|
25
|
+
/** What the build reports without failing: each uncontrolled use of a mapped control. */
|
|
26
|
+
warnings: Finding[];
|
|
27
|
+
/** Tier 2 (ADR-0226 §2.3): every use of a mapped control's root, and those that do not pass the prop that shows its value. */
|
|
28
|
+
tier2: {
|
|
29
|
+
uses: Tier2Use[];
|
|
30
|
+
uncontrolled: Tier2Use[];
|
|
31
|
+
};
|
|
32
|
+
files: {
|
|
33
|
+
path: string;
|
|
34
|
+
content: string;
|
|
35
|
+
}[];
|
|
36
|
+
/** Files in `<out>/bound/` no mapping emits any more: stale, and deleted on write. */
|
|
37
|
+
obsolete: string[];
|
|
38
|
+
stats: {
|
|
39
|
+
pages: number;
|
|
40
|
+
actions: number;
|
|
41
|
+
rooms: number;
|
|
42
|
+
unboundPages: number;
|
|
43
|
+
boundModules: number;
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
export declare function generate(config: GeneratorConfig): Promise<GenerateResult>;
|
|
47
|
+
/** Write the files, or (with `check`) list those whose committed content differs. */
|
|
48
|
+
export declare function writeOrCheck(result: GenerateResult, config: GeneratorConfig, check: boolean): string[];
|
|
49
|
+
//# sourceMappingURL=generate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../src/generate.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,OAAO,EAGL,KAAK,kBAAkB,EACvB,KAAK,WAAW,EACjB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAgB,KAAK,OAAO,EAAsC,MAAM,cAAc,CAAC;AAE9F,OAAO,EAAe,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAgBhE,eAAO,MAAM,aAAa,sBAAsB,CAAC;AACjD,eAAO,MAAM,cAAc,uBAAuB,CAAC;AAEnD,gGAAgG;AAChG,MAAM,WAAW,QAAQ;IACvB,gDAAgD;IAChD,SAAS,EAAE,MAAM,CAAC;IAClB,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,gCAAgC;IAChC,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,WAAW,CAAC;IACtB,SAAS,EAAE,kBAAkB,CAAC;IAC9B,MAAM,EAAE,OAAO,EAAE,CAAC;IAClB,yFAAyF;IACzF,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,8HAA8H;IAC9H,KAAK,EAAE;QAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;QAAC,YAAY,EAAE,QAAQ,EAAE,CAAA;KAAE,CAAC;IACtD,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC3C,sFAAsF;IACtF,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC;CACtG;AAED,wBAAsB,QAAQ,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,CA2K/E;AAED,qFAAqF;AACrF,wBAAgB,YAAY,CAAC,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,eAAe,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,CAiBtG"}
|
package/dist/generate.js
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The generator (ADR-0220 §2.4): reads the app, emits each build's manifest
|
|
3
|
+
* and knowledge, and validates both. Deterministic: no LLM, no network, no
|
|
4
|
+
* clock; the same source always gives the same bytes.
|
|
5
|
+
*/
|
|
6
|
+
import { createHash } from 'node:crypto';
|
|
7
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
8
|
+
import { join, relative } from 'node:path';
|
|
9
|
+
import { MANIFEST_VERSION, stableStringify, } from '@ouispec/bindings';
|
|
10
|
+
import { PageAnalyzer } from './analyze.js';
|
|
11
|
+
import { assemble } from './assemble.js';
|
|
12
|
+
import { CONFIG_FILE } from './config.js';
|
|
13
|
+
import { contractFindings } from './contract.js';
|
|
14
|
+
import { loadApiOperations, loadAppCatalogs, loadCatalogs, loadControls, loadNav, loadRoutes, loadShell, personOnlyLookup, } from './inputs.js';
|
|
15
|
+
import { generateKnowledge } from './knowledge.js';
|
|
16
|
+
import { loadSource } from './program.js';
|
|
17
|
+
import { BOUND_DIR, boundModuleSource, boundTableSource, checkMappingTypes, loadMappings } from './tier2.js';
|
|
18
|
+
export const MANIFEST_FILE = 'oui-manifest.json';
|
|
19
|
+
export const KNOWLEDGE_FILE = 'oui-knowledge.json';
|
|
20
|
+
export async function generate(config) {
|
|
21
|
+
// The design systems' tables first: a mapping may use a kind one of them registers.
|
|
22
|
+
const controls = loadControls(config);
|
|
23
|
+
const mappings = loadMappings(config);
|
|
24
|
+
// Each bound module as this run emits it, read by the program in place of what is on disk.
|
|
25
|
+
const bound = mappings.mappings.flatMap(m => [
|
|
26
|
+
{ path: m.module, content: boundModuleSource(m) },
|
|
27
|
+
{ path: m.table, content: boundTableSource(m) },
|
|
28
|
+
]);
|
|
29
|
+
// Only what the routes, navigation and frame reach: every page is imported from the routes file.
|
|
30
|
+
const source = loadSource(config.root, config.tsconfig, [config.routes, ...config.nav, ...config.shell.map(s => s.module)], new Map(bound.map(f => [f.path, f.content])));
|
|
31
|
+
const packageCatalogs = loadCatalogs(config);
|
|
32
|
+
const catalogs = [...packageCatalogs.catalogs, ...(await loadAppCatalogs(config))];
|
|
33
|
+
const api = loadApiOperations(config);
|
|
34
|
+
const nav = loadNav(source, config.nav);
|
|
35
|
+
const routes = loadRoutes(source, config);
|
|
36
|
+
if (routes.pages.length === 0)
|
|
37
|
+
throw new Error(`No routes found in ${source.rel(config.routes)}`);
|
|
38
|
+
const analyzer = new PageAnalyzer(source, controls.controls, catalogs, config.designSystem, controls.loaded, personOnlyLookup(config), mappings.mappings);
|
|
39
|
+
const analyses = new Map();
|
|
40
|
+
const analyze = (decl) => {
|
|
41
|
+
const analysis = analyses.get(decl) ?? analyzer.analyze(decl);
|
|
42
|
+
analyses.set(decl, analysis);
|
|
43
|
+
return analysis;
|
|
44
|
+
};
|
|
45
|
+
const pages = new Map();
|
|
46
|
+
for (const route of routes.pages) {
|
|
47
|
+
let page = pages.get(route.component);
|
|
48
|
+
if (!page) {
|
|
49
|
+
page = { component: route.component, routes: [], analysis: route.declaration ? analyze(route.declaration) : null };
|
|
50
|
+
pages.set(route.component, page);
|
|
51
|
+
}
|
|
52
|
+
page.routes.push(route);
|
|
53
|
+
}
|
|
54
|
+
// The frame around the pages: analysed as a page is, offered wherever it frames.
|
|
55
|
+
const frame = (component, paths, declaration) => {
|
|
56
|
+
if (pages.has(component))
|
|
57
|
+
throw new Error(`${component} is both a page and the frame around pages`);
|
|
58
|
+
pages.set(component, {
|
|
59
|
+
component,
|
|
60
|
+
routes: paths.map(path => ({ path, component, declaration })),
|
|
61
|
+
analysis: declaration ? analyze(declaration) : null,
|
|
62
|
+
frame: true,
|
|
63
|
+
});
|
|
64
|
+
};
|
|
65
|
+
for (const shell of loadShell(source, config))
|
|
66
|
+
frame(shell.component, shell.routes, shell.declaration);
|
|
67
|
+
// A layout route's element frames the pages under it, when it has anything of its own.
|
|
68
|
+
for (const layout of routes.layouts) {
|
|
69
|
+
if (!source.isAppFile(layout.declaration.getSourceFile()))
|
|
70
|
+
continue;
|
|
71
|
+
const analysis = analyze(layout.declaration);
|
|
72
|
+
const empty = !analysis.controls.length &&
|
|
73
|
+
!analysis.displays.length &&
|
|
74
|
+
!analysis.unbound.length &&
|
|
75
|
+
!analysis.errors.length &&
|
|
76
|
+
!analysis.rooms.size;
|
|
77
|
+
if (!empty)
|
|
78
|
+
frame(layout.component, layout.routes, layout.declaration);
|
|
79
|
+
}
|
|
80
|
+
// Every catalog must be what the contract says a room catalog is (`room-catalog-data.json`).
|
|
81
|
+
const catalogFindings = catalogs.flatMap(c => contractFindings('room-catalog-data.json', c.catalog, CONFIG_FILE, `the room catalog of "${c.package}"`));
|
|
82
|
+
const unknownUnbound = config.unbound.filter(name => !pages.has(name));
|
|
83
|
+
const assembled = assemble([...pages.values()], nav, api, routes.pages, new Set(config.unbound));
|
|
84
|
+
const errors = [
|
|
85
|
+
...controls.errors,
|
|
86
|
+
...mappings.errors,
|
|
87
|
+
...checkMappingTypes(source, mappings.mappings),
|
|
88
|
+
...packageCatalogs.errors,
|
|
89
|
+
...catalogFindings,
|
|
90
|
+
...api.errors,
|
|
91
|
+
...routes.errors,
|
|
92
|
+
...assembled.errors,
|
|
93
|
+
...unknownUnbound.map(name => ({
|
|
94
|
+
file: 'oui.config.json',
|
|
95
|
+
line: 0,
|
|
96
|
+
message: `"unbound" lists ${name}, which no route renders`,
|
|
97
|
+
})),
|
|
98
|
+
];
|
|
99
|
+
const knowledgeBody = generateKnowledge(assembled.surfaces, assembled.pages, assembled.frames, catalogs.map(c => c.catalog), nav, api.operations);
|
|
100
|
+
const buildId = createHash('sha256')
|
|
101
|
+
.update(stableStringify({ surfaces: assembled.surfaces, knowledge: knowledgeBody }, 0))
|
|
102
|
+
.digest('hex')
|
|
103
|
+
.slice(0, 16);
|
|
104
|
+
const manifest = { version: MANIFEST_VERSION, buildId, surfaces: assembled.surfaces };
|
|
105
|
+
const knowledge = { version: MANIFEST_VERSION, buildId, ...knowledgeBody };
|
|
106
|
+
// What the generator emits is held to the contract too: a manifest or knowledge
|
|
107
|
+
// the schemas refuse is a defect here, never something to ship.
|
|
108
|
+
errors.push(...contractFindings('oui-manifest.json', manifest, MANIFEST_FILE, 'the generated manifest'), ...contractFindings('generated-knowledge.json', knowledge, KNOWLEDGE_FILE, 'the generated knowledge'));
|
|
109
|
+
// Every use of a mapped control, once each however many pages render it.
|
|
110
|
+
const found = new Map();
|
|
111
|
+
for (const analysis of analyses.values())
|
|
112
|
+
for (const use of analysis.tier2Uses)
|
|
113
|
+
found.set(`${use.file}:${use.line}:${use.tag}`, use);
|
|
114
|
+
const uses = [...found.values()].sort((a, b) => a.file.localeCompare(b.file) || a.line - b.line);
|
|
115
|
+
const asUse = (u) => ({ component: u.component, file: u.file, line: u.line, props: u.props });
|
|
116
|
+
const uncontrolled = uses.filter(u => u.uncontrolled);
|
|
117
|
+
const warnings = uncontrolled.map(u => ({
|
|
118
|
+
file: u.file,
|
|
119
|
+
line: u.line,
|
|
120
|
+
message: `<${u.tag}> does not pass ${u.controlled}, the prop that shows its value: the assistant can set it, ` +
|
|
121
|
+
`but the control will not show what it set. Pass ${u.controlled}, kept in state.` +
|
|
122
|
+
(u.spread ? ' (A spread may carry it, but the build cannot see what a spread holds: write it out.)' : ''),
|
|
123
|
+
}));
|
|
124
|
+
const files = [
|
|
125
|
+
{ path: join(config.out, MANIFEST_FILE), content: `${stableStringify(manifest)}\n` },
|
|
126
|
+
{ path: join(config.out, KNOWLEDGE_FILE), content: `${stableStringify(knowledge)}\n` },
|
|
127
|
+
...bound,
|
|
128
|
+
];
|
|
129
|
+
// A bound module whose mapping is gone is stale: listed, and removed on write.
|
|
130
|
+
const boundDir = join(config.out, BOUND_DIR);
|
|
131
|
+
const emitted = new Set(files.map(f => f.path));
|
|
132
|
+
const obsolete = existsSync(boundDir)
|
|
133
|
+
? readdirSync(boundDir)
|
|
134
|
+
.map(f => join(boundDir, f))
|
|
135
|
+
.filter(f => !emitted.has(f))
|
|
136
|
+
.sort()
|
|
137
|
+
: [];
|
|
138
|
+
return {
|
|
139
|
+
manifest,
|
|
140
|
+
knowledge,
|
|
141
|
+
errors: errors.sort((a, b) => a.file.localeCompare(b.file) || a.line - b.line || a.message.localeCompare(b.message)),
|
|
142
|
+
warnings,
|
|
143
|
+
tier2: { uses: uses.map(asUse), uncontrolled: uncontrolled.map(asUse) },
|
|
144
|
+
files,
|
|
145
|
+
obsolete,
|
|
146
|
+
stats: {
|
|
147
|
+
pages: assembled.pages.length,
|
|
148
|
+
actions: assembled.surfaces.reduce((n, s) => n + s.actions.length, 0),
|
|
149
|
+
rooms: assembled.surfaces.filter(s => s.kind === 'room').length,
|
|
150
|
+
unboundPages: config.unbound.length,
|
|
151
|
+
boundModules: mappings.mappings.length,
|
|
152
|
+
},
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
/** Write the files, or (with `check`) list those whose committed content differs. */
|
|
156
|
+
export function writeOrCheck(result, config, check) {
|
|
157
|
+
const stale = [];
|
|
158
|
+
for (const file of result.files) {
|
|
159
|
+
const current = existsSync(file.path) ? readFileSync(file.path, 'utf8') : null;
|
|
160
|
+
if (current === file.content)
|
|
161
|
+
continue;
|
|
162
|
+
if (check) {
|
|
163
|
+
stale.push(relative(config.root, file.path));
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
mkdirSync(join(file.path, '..'), { recursive: true });
|
|
167
|
+
writeFileSync(file.path, file.content);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
for (const path of result.obsolete) {
|
|
171
|
+
if (check)
|
|
172
|
+
stale.push(`${relative(config.root, path)} (no mapping emits it)`);
|
|
173
|
+
else
|
|
174
|
+
rmSync(path);
|
|
175
|
+
}
|
|
176
|
+
return stale;
|
|
177
|
+
}
|
|
178
|
+
//# sourceMappingURL=generate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate.js","sourceRoot":"","sources":["../src/generate.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @ouispec/cli — the assistant's surfaces and knowledge,
|
|
3
|
+
* generated from a UI's code (ADR-0220).
|
|
4
|
+
*/
|
|
5
|
+
export { CONFIG_FILE, ConfigError, loadConfig, resolveConfig, type AppCatalogEntry, type ConfigInjection, type GeneratorConfig, type OuiConfigFile, type ShellEntry, } from './config.js';
|
|
6
|
+
export { generate, writeOrCheck, MANIFEST_FILE, KNOWLEDGE_FILE, type GenerateResult, type Tier2Use } from './generate.js';
|
|
7
|
+
export { boundModuleSlug, BINDINGS_JSX_MODULE, BINDINGS_REACT_MODULE, BOUND_DIR } from './tier2.js';
|
|
8
|
+
export type { Finding } from './analyze.js';
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,WAAW,EACX,WAAW,EACX,UAAU,EACV,aAAa,EACb,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,UAAU,GAChB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,KAAK,cAAc,EAAE,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC1H,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACpG,YAAY,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @ouispec/cli — the assistant's surfaces and knowledge,
|
|
3
|
+
* generated from a UI's code (ADR-0220).
|
|
4
|
+
*/
|
|
5
|
+
export { CONFIG_FILE, ConfigError, loadConfig, resolveConfig, } from './config.js';
|
|
6
|
+
export { generate, writeOrCheck, MANIFEST_FILE, KNOWLEDGE_FILE } from './generate.js';
|
|
7
|
+
export { boundModuleSlug, BINDINGS_JSX_MODULE, BINDINGS_REACT_MODULE, BOUND_DIR } from './tier2.js';
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,WAAW,EACX,WAAW,EACX,UAAU,EACV,aAAa,GAMd,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,aAAa,EAAE,cAAc,EAAsC,MAAM,eAAe,CAAC;AAC1H,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC"}
|