-
-
Notifications
You must be signed in to change notification settings - Fork 929
Expand file tree
/
Copy pathvalidate-aiox-core-namespace.js
More file actions
executable file
·96 lines (86 loc) · 3.29 KB
/
Copy pathvalidate-aiox-core-namespace.js
File metadata and controls
executable file
·96 lines (86 loc) · 3.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#!/usr/bin/env node
/**
* .aiox-core/package.json namespace + version sync validator
*
* Story #739 (Bug 2 follow-up): the internal `.aiox-core/package.json`
* manifest drifted to the legacy `@aiox-fullstack/[email protected]` namespace
* while the surface package moved to `@aiox-squads/[email protected]`. Several
* releases shipped stale internal metadata that confused tooling and
* misled operators investigating upgrade issues.
*
* This validator runs in the pre-publish surface to catch the drift
* before it ships again.
*
* Validation rules:
* 1. `.aiox-core/package.json` MUST exist.
* 2. `name` MUST end with `-internal` (it is NOT a published package on
* its own — `private: true` + suffix avoids npm registry confusion
* with the parent surface).
* 3. `private` MUST be true.
* 4. `version` MUST equal the root `package.json` version (single source
* of truth: the parent surface drives the framework version).
* 5. No `peerDependencies` referencing the legacy `@aiox-fullstack/*`
* namespace.
*
* Exit codes: 0 = PASS, 1 = FAIL
* Usage: node scripts/validate-aiox-core-namespace.js
*/
'use strict';
const fs = require('fs');
const path = require('path');
const ROOT = path.resolve(__dirname, '..');
const INTERNAL_PKG = path.join(ROOT, '.aiox-core', 'package.json');
const ROOT_PKG = path.join(ROOT, 'package.json');
function fail(msg) {
console.error(`FAIL: ${msg}`);
process.exit(1);
}
function main() {
if (!fs.existsSync(INTERNAL_PKG)) {
fail('.aiox-core/package.json not found');
}
if (!fs.existsSync(ROOT_PKG)) {
fail('root package.json not found');
}
const internal = JSON.parse(fs.readFileSync(INTERNAL_PKG, 'utf8'));
const root = JSON.parse(fs.readFileSync(ROOT_PKG, 'utf8'));
if (!internal.name) {
fail('.aiox-core/package.json missing `name` field');
}
const EXPECTED_SCOPE = '@aiox-squads/';
if (!internal.name.startsWith(EXPECTED_SCOPE)) {
fail(
`.aiox-core/package.json name "${internal.name}" must start with "${EXPECTED_SCOPE}" ` +
'(current org scope — names like `@aiox-fullstack/*` are legacy, see Story #739)',
);
}
if (!internal.name.endsWith('-internal')) {
fail(
`.aiox-core/package.json name "${internal.name}" must end with "-internal" ` +
'(internal manifest, not a separately-published package — see Story #739)',
);
}
if (internal.private !== true) {
fail('.aiox-core/package.json must declare `"private": true` (internal-only)');
}
if (internal.version !== root.version) {
fail(
`version drift: .aiox-core/package.json version "${internal.version}" ` +
`does not match root package.json version "${root.version}". ` +
'They must move in lockstep — root is SOT.',
);
}
const peerDeps = internal.peerDependencies || {};
const legacyPeers = Object.keys(peerDeps).filter((d) => d.startsWith('@aiox-fullstack/'));
if (legacyPeers.length > 0) {
fail(
`legacy @aiox-fullstack/* peerDependencies in .aiox-core/package.json: ${legacyPeers.join(', ')}. ` +
'These packages do not exist; drop the peerDependencies block or rename to the current namespace.',
);
}
console.log(
`PASS: .aiox-core/package.json is in sync with root (name=${internal.name}, version=${internal.version})`,
);
process.exit(0);
}
main();