@objectstack/cli 9.2.0 → 9.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/dist/adr-0048-app-split.test.d.ts +2 -0
- package/dist/adr-0048-app-split.test.d.ts.map +1 -0
- package/dist/adr-0048-app-split.test.js +61 -0
- package/dist/adr-0048-app-split.test.js.map +1 -0
- package/dist/commands/compile.d.ts.map +1 -1
- package/dist/commands/compile.js +34 -0
- package/dist/commands/compile.js.map +1 -1
- package/dist/commands/explain.js +1 -1
- package/dist/commands/generate.js +1 -1
- package/dist/commands/lint.d.ts.map +1 -1
- package/dist/commands/lint.js +49 -0
- package/dist/commands/lint.js.map +1 -1
- package/dist/commands/package/install.d.ts +19 -0
- package/dist/commands/package/install.d.ts.map +1 -0
- package/dist/commands/package/install.js +221 -0
- package/dist/commands/package/install.js.map +1 -0
- package/dist/commands/serve.d.ts.map +1 -1
- package/dist/commands/serve.js +53 -2
- package/dist/commands/serve.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/utils/collect-docs.d.ts +38 -0
- package/dist/utils/collect-docs.d.ts.map +1 -0
- package/dist/utils/collect-docs.js +214 -0
- package/dist/utils/collect-docs.js.map +1 -0
- package/dist/utils/collect-docs.test.d.ts +2 -0
- package/dist/utils/collect-docs.test.d.ts.map +1 -0
- package/dist/utils/collect-docs.test.js +118 -0
- package/dist/utils/collect-docs.test.js.map +1 -0
- package/dist/utils/console.d.ts +30 -1
- package/dist/utils/console.d.ts.map +1 -1
- package/dist/utils/console.js +84 -29
- package/dist/utils/console.js.map +1 -1
- package/package.json +46 -43
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
|
|
2
|
+
/**
|
|
3
|
+
* Package documentation collection + lint (ADR-0046).
|
|
4
|
+
*
|
|
5
|
+
* `os build` compiles every Markdown file in the package's flat
|
|
6
|
+
* `src/docs/` directory into a `doc` metadata item on the stack
|
|
7
|
+
* (`docs: DocSchema[]`). This module owns both halves of that contract:
|
|
8
|
+
*
|
|
9
|
+
* - **Collection**: filename stem → `name`, frontmatter `title:` or the
|
|
10
|
+
* first `#` heading → `label`, body → `content`. Subdirectories are a
|
|
11
|
+
* build error — flatness is the contract that keeps cross-references
|
|
12
|
+
* stable (a link is `[text](./<name>.md)`; resolution is a basename
|
|
13
|
+
* lookup with zero path arithmetic).
|
|
14
|
+
* - **Lint**: namespace-prefix naming (doc uniqueness is logical — the
|
|
15
|
+
* metadata registry key carries no package coordinate, so a bare-name
|
|
16
|
+
* collision silently overwrites across packages), the v1 syntax bans
|
|
17
|
+
* (no MDX, no images), and same-package link resolution.
|
|
18
|
+
*
|
|
19
|
+
* Cross-package links (a target whose prefix is not this package's
|
|
20
|
+
* namespace) are deliberately not checked here: they resolve against
|
|
21
|
+
* dependency docs at publish time, and render-side they degrade to a
|
|
22
|
+
* "doc not found" notice rather than coupling into dependency resolution.
|
|
23
|
+
*/
|
|
24
|
+
import fs from 'fs';
|
|
25
|
+
import path from 'path';
|
|
26
|
+
const DOC_NAME_RE = /^[a-z][a-z0-9_]*$/;
|
|
27
|
+
/** Extract a single-line scalar `key: value` from a frontmatter block. */
|
|
28
|
+
function frontmatterScalar(block, key) {
|
|
29
|
+
const re = new RegExp(`^${key}\\s*:`, 'i');
|
|
30
|
+
const line = block.split(/\r?\n/).find((l) => re.test(l));
|
|
31
|
+
if (!line)
|
|
32
|
+
return undefined;
|
|
33
|
+
const value = line.replace(re, '').trim().replace(/^['"]|['"]$/g, '');
|
|
34
|
+
return value || undefined;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Strip a leading `---` frontmatter block; extract `title:` and
|
|
38
|
+
* `description:` if present (both optional, single-line scalars).
|
|
39
|
+
*/
|
|
40
|
+
function parseFrontmatter(raw) {
|
|
41
|
+
if (!raw.startsWith('---\n') && !raw.startsWith('---\r\n'))
|
|
42
|
+
return { body: raw };
|
|
43
|
+
const end = raw.indexOf('\n---', 3);
|
|
44
|
+
if (end === -1)
|
|
45
|
+
return { body: raw };
|
|
46
|
+
const block = raw.slice(raw.indexOf('\n') + 1, end);
|
|
47
|
+
const bodyStart = raw.indexOf('\n', end + 1);
|
|
48
|
+
const body = bodyStart === -1 ? '' : raw.slice(bodyStart + 1);
|
|
49
|
+
return {
|
|
50
|
+
title: frontmatterScalar(block, 'title'),
|
|
51
|
+
description: frontmatterScalar(block, 'description'),
|
|
52
|
+
body,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
/** Remove fenced code blocks and inline code spans before content scans. */
|
|
56
|
+
function stripCode(markdown) {
|
|
57
|
+
return markdown
|
|
58
|
+
.replace(/^(```|~~~)[\s\S]*?^\1\s*$/gm, '')
|
|
59
|
+
.replace(/`[^`\n]*`/g, '');
|
|
60
|
+
}
|
|
61
|
+
function firstHeading(markdown) {
|
|
62
|
+
const m = stripCode(markdown).match(/^#\s+(.+)$/m);
|
|
63
|
+
return m ? m[1].trim() : undefined;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Read `src/docs/*.md` (flat) next to the given config file and compile
|
|
67
|
+
* each file into a `DocItem`. Structural problems (subdirectories, bad
|
|
68
|
+
* filename stems) are reported as error issues; offending files are
|
|
69
|
+
* skipped rather than partially collected.
|
|
70
|
+
*/
|
|
71
|
+
export function collectDocsFromSrc(configPath) {
|
|
72
|
+
const docsDir = path.join(path.dirname(configPath), 'src', 'docs');
|
|
73
|
+
const docs = [];
|
|
74
|
+
const issues = [];
|
|
75
|
+
if (!fs.existsSync(docsDir))
|
|
76
|
+
return { docs, issues };
|
|
77
|
+
for (const entry of fs.readdirSync(docsDir, { withFileTypes: true })) {
|
|
78
|
+
const rel = `src/docs/${entry.name}`;
|
|
79
|
+
if (entry.isDirectory()) {
|
|
80
|
+
issues.push({
|
|
81
|
+
severity: 'error',
|
|
82
|
+
rule: 'docs/flat-directory',
|
|
83
|
+
message: `Subdirectory "${entry.name}" under src/docs/ is not allowed (ADR-0046 §3.2). Flatten all .md files directly into src/docs/.`,
|
|
84
|
+
path: rel,
|
|
85
|
+
});
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (!entry.isFile() || !entry.name.endsWith('.md'))
|
|
89
|
+
continue;
|
|
90
|
+
const stem = entry.name.slice(0, -3);
|
|
91
|
+
if (!DOC_NAME_RE.test(stem)) {
|
|
92
|
+
issues.push({
|
|
93
|
+
severity: 'error',
|
|
94
|
+
rule: 'docs/filename',
|
|
95
|
+
message: `Doc filename "${entry.name}" must be snake_case (e.g. crm_lead_guide.md); the stem becomes the doc name.`,
|
|
96
|
+
path: rel,
|
|
97
|
+
});
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
const raw = fs.readFileSync(path.join(docsDir, entry.name), 'utf-8');
|
|
101
|
+
const { title, description, body } = parseFrontmatter(raw);
|
|
102
|
+
docs.push({
|
|
103
|
+
name: stem,
|
|
104
|
+
label: title ?? firstHeading(body),
|
|
105
|
+
...(description ? { description } : {}),
|
|
106
|
+
content: body,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
return { docs, issues };
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Content + naming lint over the package's full doc set (collected files
|
|
113
|
+
* plus any inline `defineStack({ docs })` items).
|
|
114
|
+
*/
|
|
115
|
+
export function lintDocs(docs, namespace) {
|
|
116
|
+
const issues = [];
|
|
117
|
+
if (docs.length === 0)
|
|
118
|
+
return issues;
|
|
119
|
+
if (!namespace) {
|
|
120
|
+
issues.push({
|
|
121
|
+
severity: 'error',
|
|
122
|
+
rule: 'docs/namespace-required',
|
|
123
|
+
message: 'A package that ships docs must declare manifest.namespace (ADR-0046 §3.2) — doc names are namespace-prefixed.',
|
|
124
|
+
path: 'manifest.namespace',
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
const names = new Set();
|
|
128
|
+
for (const doc of docs) {
|
|
129
|
+
const where = `docs/${doc.name}`;
|
|
130
|
+
if (names.has(doc.name)) {
|
|
131
|
+
issues.push({
|
|
132
|
+
severity: 'error',
|
|
133
|
+
rule: 'docs/duplicate-name',
|
|
134
|
+
message: `Duplicate doc name "${doc.name}" (inline defineStack docs and src/docs/*.md files share one namespace).`,
|
|
135
|
+
path: where,
|
|
136
|
+
});
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
names.add(doc.name);
|
|
140
|
+
if (namespace && !doc.name.startsWith(`${namespace}_`)) {
|
|
141
|
+
issues.push({
|
|
142
|
+
severity: 'error',
|
|
143
|
+
rule: 'docs/namespace-prefix',
|
|
144
|
+
message: `Doc name "${doc.name}" must carry the package namespace prefix: rename to "${namespace}_${doc.name}" (file ${namespace}_${doc.name}.md).`,
|
|
145
|
+
path: where,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
const scannable = stripCode(doc.content);
|
|
149
|
+
// v1 image ban (ADR-0046 §3.4): binaries bloat artifacts; external
|
|
150
|
+
// URLs break version immutability.
|
|
151
|
+
if (/!\[[^\]]*\]\(/.test(scannable) || /<img[\s>]/i.test(scannable)) {
|
|
152
|
+
issues.push({
|
|
153
|
+
severity: 'error',
|
|
154
|
+
rule: 'docs/no-images',
|
|
155
|
+
message: `Doc "${doc.name}" contains an image reference — not allowed in v1 (ADR-0046 §3.4).`,
|
|
156
|
+
path: where,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
// MDX ban (ADR-0046 §3.4): MDX is code crossing the ADR-0025 trust
|
|
160
|
+
// boundary. Heuristics are conservative — ESM import/export statement
|
|
161
|
+
// shapes and capitalized JSX component tags outside code — so prose
|
|
162
|
+
// like "import the data first" never trips them.
|
|
163
|
+
if (/^\s*import\s+.+\s+from\s+['"]/m.test(scannable) ||
|
|
164
|
+
/^\s*export\s+(default|const|function)\s/m.test(scannable) ||
|
|
165
|
+
/<[A-Z][A-Za-z0-9]*[\s/>]/.test(scannable)) {
|
|
166
|
+
issues.push({
|
|
167
|
+
severity: 'error',
|
|
168
|
+
rule: 'docs/no-mdx',
|
|
169
|
+
message: `Doc "${doc.name}" appears to contain MDX/JSX — only CommonMark + GFM Markdown is allowed (ADR-0046 §3.3/§3.4).`,
|
|
170
|
+
path: where,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
// Same-package link resolution: `[text](./<name>.md#anchor)` where the
|
|
175
|
+
// target carries OUR namespace prefix must resolve to a doc in this
|
|
176
|
+
// package. Targets with a different prefix are cross-package links,
|
|
177
|
+
// verified at publish time against dependency docs.
|
|
178
|
+
for (const doc of docs) {
|
|
179
|
+
const linkRe = /\]\((?:\.\/)?([a-zA-Z0-9_.-]+\.md)(#[^)]*)?\)/g;
|
|
180
|
+
const scannable = stripCode(doc.content);
|
|
181
|
+
let m;
|
|
182
|
+
while ((m = linkRe.exec(scannable)) !== null) {
|
|
183
|
+
const target = m[1].slice(0, -3);
|
|
184
|
+
if (m[1].includes('/'))
|
|
185
|
+
continue; // path-shaped link; flatness rule already errs on real subdirs
|
|
186
|
+
if (namespace && !target.startsWith(`${namespace}_`))
|
|
187
|
+
continue;
|
|
188
|
+
if (!names.has(target)) {
|
|
189
|
+
issues.push({
|
|
190
|
+
severity: 'error',
|
|
191
|
+
rule: 'docs/broken-link',
|
|
192
|
+
message: `Doc "${doc.name}" links to "./${m[1]}" but no doc named "${target}" exists in this package.`,
|
|
193
|
+
path: `docs/${doc.name}`,
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
return issues;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* One-call entry for `os build`: collect `src/docs/*.md`, merge with the
|
|
202
|
+
* stack's inline `docs`, and lint the combined set. Returns the merged
|
|
203
|
+
* doc array (inline items first — they were already schema-validated) and
|
|
204
|
+
* every issue found.
|
|
205
|
+
*/
|
|
206
|
+
export function collectAndLintDocs(configPath, stack) {
|
|
207
|
+
const inline = Array.isArray(stack.docs) ? stack.docs : [];
|
|
208
|
+
const collected = collectDocsFromSrc(configPath);
|
|
209
|
+
const namespace = stack.manifest?.namespace;
|
|
210
|
+
const docs = [...inline, ...collected.docs];
|
|
211
|
+
const issues = [...collected.issues, ...lintDocs(docs, namespace)];
|
|
212
|
+
return { docs, issues };
|
|
213
|
+
}
|
|
214
|
+
//# sourceMappingURL=collect-docs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collect-docs.js","sourceRoot":"","sources":["../../src/utils/collect-docs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collect-docs.test.d.ts","sourceRoot":"","sources":["../../src/utils/collect-docs.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
|
|
2
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import os from 'os';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
import { collectDocsFromSrc, lintDocs, collectAndLintDocs } from './collect-docs.js';
|
|
7
|
+
let tmp;
|
|
8
|
+
let configPath;
|
|
9
|
+
let docsDir;
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'os-docs-'));
|
|
12
|
+
configPath = path.join(tmp, 'objectstack.config.ts');
|
|
13
|
+
fs.writeFileSync(configPath, '// stub');
|
|
14
|
+
docsDir = path.join(tmp, 'src', 'docs');
|
|
15
|
+
fs.mkdirSync(docsDir, { recursive: true });
|
|
16
|
+
});
|
|
17
|
+
afterEach(() => {
|
|
18
|
+
fs.rmSync(tmp, { recursive: true, force: true });
|
|
19
|
+
});
|
|
20
|
+
const write = (name, content) => fs.writeFileSync(path.join(docsDir, name), content);
|
|
21
|
+
describe('collectDocsFromSrc (ADR-0046 §3.2)', () => {
|
|
22
|
+
it('compiles each flat .md file into a doc item (stem = name)', () => {
|
|
23
|
+
write('crm_index.md', '# CRM Overview\n\nWhat it is.');
|
|
24
|
+
write('crm_lead_guide.md', '---\ntitle: Lead Guide\n---\n\nBody here.');
|
|
25
|
+
const { docs, issues } = collectDocsFromSrc(configPath);
|
|
26
|
+
expect(issues).toHaveLength(0);
|
|
27
|
+
expect(docs.map((d) => d.name).sort()).toEqual(['crm_index', 'crm_lead_guide']);
|
|
28
|
+
const index = docs.find((d) => d.name === 'crm_index');
|
|
29
|
+
expect(index.label).toBe('CRM Overview'); // first # heading
|
|
30
|
+
const guide = docs.find((d) => d.name === 'crm_lead_guide');
|
|
31
|
+
expect(guide.label).toBe('Lead Guide'); // frontmatter title wins
|
|
32
|
+
expect(guide.content).not.toContain('title:'); // frontmatter stripped
|
|
33
|
+
});
|
|
34
|
+
it('reads optional frontmatter `description:` (and omits it when absent)', () => {
|
|
35
|
+
write('crm_index.md', '---\ntitle: CRM\ndescription: Start here.\n---\n\n# CRM\n\nBody.');
|
|
36
|
+
write('crm_plain.md', '# Plain\n\nNo frontmatter.');
|
|
37
|
+
const { docs, issues } = collectDocsFromSrc(configPath);
|
|
38
|
+
expect(issues).toHaveLength(0);
|
|
39
|
+
const index = docs.find((d) => d.name === 'crm_index');
|
|
40
|
+
expect(index.description).toBe('Start here.');
|
|
41
|
+
expect(index.content).not.toContain('description:'); // frontmatter stripped
|
|
42
|
+
const plain = docs.find((d) => d.name === 'crm_plain');
|
|
43
|
+
expect(plain.description).toBeUndefined(); // absent → omitted, not ''
|
|
44
|
+
});
|
|
45
|
+
it('errors on subdirectories — flatness is the contract', () => {
|
|
46
|
+
fs.mkdirSync(path.join(docsDir, 'user'));
|
|
47
|
+
write('crm_index.md', '# x');
|
|
48
|
+
const { docs, issues } = collectDocsFromSrc(configPath);
|
|
49
|
+
expect(issues.some((i) => i.rule === 'docs/flat-directory' && i.severity === 'error')).toBe(true);
|
|
50
|
+
expect(docs).toHaveLength(1); // the valid file still collects
|
|
51
|
+
});
|
|
52
|
+
it('errors on non-snake_case filename stems', () => {
|
|
53
|
+
write('Lead-Guide.md', '# x');
|
|
54
|
+
const { docs, issues } = collectDocsFromSrc(configPath);
|
|
55
|
+
expect(issues.some((i) => i.rule === 'docs/filename')).toBe(true);
|
|
56
|
+
expect(docs).toHaveLength(0);
|
|
57
|
+
});
|
|
58
|
+
it('ignores non-markdown files and returns empty when src/docs is absent', () => {
|
|
59
|
+
write('notes.txt', 'not a doc');
|
|
60
|
+
expect(collectDocsFromSrc(configPath).docs).toHaveLength(0);
|
|
61
|
+
fs.rmSync(docsDir, { recursive: true });
|
|
62
|
+
expect(collectDocsFromSrc(configPath).docs).toHaveLength(0);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
describe('lintDocs (ADR-0046 §3.2–§3.4)', () => {
|
|
66
|
+
const doc = (name, content) => ({ name, content });
|
|
67
|
+
it('requires manifest.namespace when docs ship', () => {
|
|
68
|
+
const issues = lintDocs([doc('crm_index', 'x')], undefined);
|
|
69
|
+
expect(issues.some((i) => i.rule === 'docs/namespace-required')).toBe(true);
|
|
70
|
+
});
|
|
71
|
+
it('requires the namespace prefix on every doc name', () => {
|
|
72
|
+
const issues = lintDocs([doc('lead_guide', 'x')], 'crm');
|
|
73
|
+
const hit = issues.find((i) => i.rule === 'docs/namespace-prefix');
|
|
74
|
+
expect(hit?.severity).toBe('error');
|
|
75
|
+
expect(hit?.message).toContain('crm_lead_guide');
|
|
76
|
+
});
|
|
77
|
+
it('rejects duplicate names across inline + collected docs', () => {
|
|
78
|
+
const issues = lintDocs([doc('crm_index', 'a'), doc('crm_index', 'b')], 'crm');
|
|
79
|
+
expect(issues.some((i) => i.rule === 'docs/duplicate-name')).toBe(true);
|
|
80
|
+
});
|
|
81
|
+
it('bans image references (v1 text-only)', () => {
|
|
82
|
+
const issues = lintDocs([doc('crm_index', 'See ')], 'crm');
|
|
83
|
+
expect(issues.some((i) => i.rule === 'docs/no-images')).toBe(true);
|
|
84
|
+
});
|
|
85
|
+
it('bans MDX/JSX but tolerates code blocks that mention it', () => {
|
|
86
|
+
expect(lintDocs([doc('crm_a', 'Use <Tabs items={x}> here')], 'crm')
|
|
87
|
+
.some((i) => i.rule === 'docs/no-mdx')).toBe(true);
|
|
88
|
+
expect(lintDocs([doc('crm_b', 'Example:\n\n```jsx\n<Tabs items={x} />\n```\n\nplain prose')], 'crm')
|
|
89
|
+
.some((i) => i.rule === 'docs/no-mdx')).toBe(false);
|
|
90
|
+
});
|
|
91
|
+
it('resolves same-package relative links and flags broken ones', () => {
|
|
92
|
+
const docs = [
|
|
93
|
+
doc('crm_index', 'See the [guide](./crm_lead_guide.md#start) and [missing](./crm_nope.md).'),
|
|
94
|
+
doc('crm_lead_guide', 'Back to [index](crm_index.md).'),
|
|
95
|
+
];
|
|
96
|
+
const issues = lintDocs(docs, 'crm');
|
|
97
|
+
const broken = issues.filter((i) => i.rule === 'docs/broken-link');
|
|
98
|
+
expect(broken).toHaveLength(1);
|
|
99
|
+
expect(broken[0].message).toContain('crm_nope');
|
|
100
|
+
});
|
|
101
|
+
it('leaves cross-package links (foreign prefix) to publish-time checks', () => {
|
|
102
|
+
const issues = lintDocs([doc('crm_index', 'See [billing](./billing_setup.md).')], 'crm');
|
|
103
|
+
expect(issues.some((i) => i.rule === 'docs/broken-link')).toBe(false);
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
describe('collectAndLintDocs', () => {
|
|
107
|
+
it('merges inline stack docs with collected files and lints the union', () => {
|
|
108
|
+
write('crm_admin_setup.md', '# Admin Setup\n\nSee [index](./crm_index.md).');
|
|
109
|
+
const stack = {
|
|
110
|
+
manifest: { namespace: 'crm' },
|
|
111
|
+
docs: [{ name: 'crm_index', content: '# CRM' }],
|
|
112
|
+
};
|
|
113
|
+
const { docs, issues } = collectAndLintDocs(configPath, stack);
|
|
114
|
+
expect(docs.map((d) => d.name).sort()).toEqual(['crm_admin_setup', 'crm_index']);
|
|
115
|
+
expect(issues).toHaveLength(0);
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
//# sourceMappingURL=collect-docs.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collect-docs.test.js","sourceRoot":"","sources":["../../src/utils/collect-docs.test.ts"],"names":[],"mappings":"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"}
|
package/dist/utils/console.d.ts
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
/** URL mount path for the Console portal inside the ObjectStack server */
|
|
2
2
|
export declare const CONSOLE_PATH = "/_console";
|
|
3
|
+
/**
|
|
4
|
+
* The vendored `@objectstack/console` package is version-locked to the
|
|
5
|
+
* framework release, so a healthy install always carries the same major
|
|
6
|
+
* as the CLI. Node module resolution from the consumer cwd, however,
|
|
7
|
+
* climbs `node_modules` directories all the way up the filesystem — a
|
|
8
|
+
* stray install outside the workspace (e.g. a leftover
|
|
9
|
+
* `~/node_modules/@objectstack/console` from an old npm experiment) can
|
|
10
|
+
* shadow the bundled build and silently serve a stale Console.
|
|
11
|
+
*
|
|
12
|
+
* Guard: skip any candidate whose major version differs from the CLI's
|
|
13
|
+
* own, and warn so the stray install is discoverable.
|
|
14
|
+
*/
|
|
15
|
+
export declare function isConsoleVersionCompatible(candidateVersion: unknown, cliVersion: string): boolean;
|
|
3
16
|
/**
|
|
4
17
|
* Resolve the filesystem path to a Console SPA package.
|
|
5
18
|
*
|
|
@@ -23,8 +36,24 @@ export declare const CONSOLE_PATH = "/_console";
|
|
|
23
36
|
* 3. Sibling-repo dev fallback — `../objectui/apps/console` — matched
|
|
24
37
|
* by the package name on disk so an unrelated `apps/console`
|
|
25
38
|
* doesn't get picked up by accident.
|
|
39
|
+
*
|
|
40
|
+
* Strategies 1 and 2 additionally require the candidate's major version
|
|
41
|
+
* to match the CLI's own (see `isConsoleVersionCompatible`) — node
|
|
42
|
+
* resolution climbs past the workspace root, so a stale install higher
|
|
43
|
+
* up the filesystem must not shadow the version-locked bundle.
|
|
44
|
+
* Mismatches are skipped with a warning. The sibling-repo fallback is
|
|
45
|
+
* exempt: the objectui workspace versions independently and is an
|
|
46
|
+
* explicit dev opt-in.
|
|
26
47
|
*/
|
|
27
|
-
export
|
|
48
|
+
export interface ResolveConsoleOptions {
|
|
49
|
+
/** Resolution origin; defaults to `process.cwd()`. */
|
|
50
|
+
cwd?: string;
|
|
51
|
+
/** Override the CLI's own version (tests). */
|
|
52
|
+
cliVersion?: string;
|
|
53
|
+
/** Warning sink; defaults to `console.warn`. */
|
|
54
|
+
warn?: (message: string) => void;
|
|
55
|
+
}
|
|
56
|
+
export declare function resolveConsolePath(options?: ResolveConsoleOptions): string | null;
|
|
28
57
|
/**
|
|
29
58
|
* Check whether the Console portal has a pre-built `dist/` directory.
|
|
30
59
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"console.d.ts","sourceRoot":"","sources":["../../src/utils/console.ts"],"names":[],"mappings":"AAyCA,0EAA0E;AAC1E,eAAO,MAAM,YAAY,cAAc,CAAC;AAOxC
|
|
1
|
+
{"version":3,"file":"console.d.ts","sourceRoot":"","sources":["../../src/utils/console.ts"],"names":[],"mappings":"AAyCA,0EAA0E;AAC1E,eAAO,MAAM,YAAY,cAAc,CAAC;AAOxC;;;;;;;;;;;GAWG;AACH,wBAAgB,0BAA0B,CACxC,gBAAgB,EAAE,OAAO,EACzB,UAAU,EAAE,MAAM,GACjB,OAAO,CAKT;AAwCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,WAAW,qBAAqB;IACpC,sDAAsD;IACtD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,8CAA8C;IAC9C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gDAAgD;IAChD,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC;AAED,wBAAgB,kBAAkB,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,MAAM,GAAG,IAAI,CAmGjF;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAE3D;AAID;;;;;;;;;;;GAWG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,YAAY,CAAC,EAAE,OAAO,CAAA;CAAE;;;iBAM1F,GAAG;EAmFzB"}
|
package/dist/utils/console.js
CHANGED
|
@@ -34,39 +34,84 @@
|
|
|
34
34
|
import path from 'path';
|
|
35
35
|
import fs from 'fs';
|
|
36
36
|
import { createRequire } from 'module';
|
|
37
|
-
import { pathToFileURL } from 'url';
|
|
37
|
+
import { pathToFileURL, fileURLToPath } from 'url';
|
|
38
38
|
// ─── Constants ──────────────────────────────────────────────────────
|
|
39
39
|
/** URL mount path for the Console portal inside the ObjectStack server */
|
|
40
40
|
export const CONSOLE_PATH = '/_console';
|
|
41
41
|
/** Canonical npm package name that ships the Console SPA. */
|
|
42
42
|
const CONSOLE_PACKAGE = '@objectstack/console';
|
|
43
|
-
// ───
|
|
43
|
+
// ─── Version Guard ──────────────────────────────────────────────────
|
|
44
44
|
/**
|
|
45
|
-
*
|
|
45
|
+
* The vendored `@objectstack/console` package is version-locked to the
|
|
46
|
+
* framework release, so a healthy install always carries the same major
|
|
47
|
+
* as the CLI. Node module resolution from the consumer cwd, however,
|
|
48
|
+
* climbs `node_modules` directories all the way up the filesystem — a
|
|
49
|
+
* stray install outside the workspace (e.g. a leftover
|
|
50
|
+
* `~/node_modules/@objectstack/console` from an old npm experiment) can
|
|
51
|
+
* shadow the bundled build and silently serve a stale Console.
|
|
46
52
|
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
53
|
+
* Guard: skip any candidate whose major version differs from the CLI's
|
|
54
|
+
* own, and warn so the stray install is discoverable.
|
|
55
|
+
*/
|
|
56
|
+
export function isConsoleVersionCompatible(candidateVersion, cliVersion) {
|
|
57
|
+
if (typeof candidateVersion !== 'string')
|
|
58
|
+
return false;
|
|
59
|
+
const candidateMajor = majorOf(candidateVersion);
|
|
60
|
+
const cliMajor = majorOf(cliVersion);
|
|
61
|
+
return candidateMajor !== null && candidateMajor === cliMajor;
|
|
62
|
+
}
|
|
63
|
+
function majorOf(version) {
|
|
64
|
+
const match = /^v?(\d+)[.-]/.exec(version.trim()) ?? /^v?(\d+)$/.exec(version.trim());
|
|
65
|
+
return match ? Number(match[1]) : null;
|
|
66
|
+
}
|
|
67
|
+
let cachedCliVersion;
|
|
68
|
+
/**
|
|
69
|
+
* Read this CLI's own version by walking up from the compiled module to
|
|
70
|
+
* the nearest `package.json`. Returns null (guard disabled, fail open)
|
|
71
|
+
* if it can't be determined — never let the version check break
|
|
72
|
+
* resolution outright.
|
|
67
73
|
*/
|
|
68
|
-
|
|
69
|
-
|
|
74
|
+
function getCliVersion() {
|
|
75
|
+
if (cachedCliVersion !== undefined)
|
|
76
|
+
return cachedCliVersion;
|
|
77
|
+
let version = null;
|
|
78
|
+
try {
|
|
79
|
+
let dir = path.dirname(fileURLToPath(import.meta.url));
|
|
80
|
+
for (let depth = 0; depth < 6; depth++) {
|
|
81
|
+
const pkgPath = path.join(dir, 'package.json');
|
|
82
|
+
if (fs.existsSync(pkgPath)) {
|
|
83
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
84
|
+
if (typeof pkg.version === 'string')
|
|
85
|
+
version = pkg.version;
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
const parent = path.dirname(dir);
|
|
89
|
+
if (parent === dir)
|
|
90
|
+
break;
|
|
91
|
+
dir = parent;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
// Unreadable own package.json — leave the guard disabled.
|
|
96
|
+
}
|
|
97
|
+
cachedCliVersion = version;
|
|
98
|
+
return version;
|
|
99
|
+
}
|
|
100
|
+
export function resolveConsolePath(options) {
|
|
101
|
+
const cwd = options?.cwd ?? process.cwd();
|
|
102
|
+
const cliVersion = options?.cliVersion ?? getCliVersion();
|
|
103
|
+
const warn = options?.warn ?? ((message) => console.warn(message));
|
|
104
|
+
/** Version guard for vendored-package candidates (strategies 1 & 2). */
|
|
105
|
+
const versionOk = (dir, candidateVersion) => {
|
|
106
|
+
if (!cliVersion)
|
|
107
|
+
return true; // own version unknown — fail open
|
|
108
|
+
if (isConsoleVersionCompatible(candidateVersion, cliVersion))
|
|
109
|
+
return true;
|
|
110
|
+
const shown = typeof candidateVersion === 'string' ? candidateVersion : 'unknown';
|
|
111
|
+
warn(` ⚠ Ignoring ${CONSOLE_PACKAGE}@${shown} at ${dir} — major version does not match this CLI (${cliVersion}). ` +
|
|
112
|
+
`This is usually a stale install outside your workspace (e.g. a leftover ~/node_modules); remove it or install a matching version.`);
|
|
113
|
+
return false;
|
|
114
|
+
};
|
|
70
115
|
const resolutionBases = [
|
|
71
116
|
pathToFileURL(path.join(cwd, 'package.json')).href, // consumer workspace
|
|
72
117
|
import.meta.url, // CLI package itself
|
|
@@ -82,7 +127,9 @@ export function resolveConsolePath() {
|
|
|
82
127
|
const dir = path.dirname(resolvedPkgJson);
|
|
83
128
|
try {
|
|
84
129
|
const pkg = JSON.parse(fs.readFileSync(resolvedPkgJson, 'utf-8'));
|
|
85
|
-
if (pkg.name === CONSOLE_PACKAGE &&
|
|
130
|
+
if (pkg.name === CONSOLE_PACKAGE &&
|
|
131
|
+
versionOk(dir, pkg.version) &&
|
|
132
|
+
!candidates.includes(dir)) {
|
|
86
133
|
candidates.push(dir);
|
|
87
134
|
}
|
|
88
135
|
}
|
|
@@ -96,9 +143,17 @@ export function resolveConsolePath() {
|
|
|
96
143
|
}
|
|
97
144
|
// 2: direct filesystem check in cwd/node_modules.
|
|
98
145
|
const directPath = path.join(cwd, 'node_modules', ...CONSOLE_PACKAGE.split('/'));
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
146
|
+
const directPkgJson = path.join(directPath, 'package.json');
|
|
147
|
+
if (fs.existsSync(directPkgJson) && !candidates.includes(directPath)) {
|
|
148
|
+
try {
|
|
149
|
+
const pkg = JSON.parse(fs.readFileSync(directPkgJson, 'utf-8'));
|
|
150
|
+
if (pkg.name === CONSOLE_PACKAGE && versionOk(directPath, pkg.version)) {
|
|
151
|
+
candidates.push(directPath);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
// Skip invalid package.json
|
|
156
|
+
}
|
|
102
157
|
}
|
|
103
158
|
// 3: sibling-repo dev fallback. Useful when iterating on the Console
|
|
104
159
|
// source inside `objectui` while running the framework CLI here.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"console.js","sourceRoot":"","sources":["../../src/utils/console.ts"],"names":[],"mappings":"AAAA,yEAAyE;AAEzE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"console.js","sourceRoot":"","sources":["../../src/utils/console.ts"],"names":[],"mappings":"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"}
|