@atls/code-schematics 2.0.22 → 2.0.23
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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
|
|
2
2
|
|
|
3
|
+
## [2.0.23](https://github.com/atls/raijin/compare/@atls/code-schematics@2.0.22...@atls/code-schematics@2.0.23) (2026-04-30)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
* **code-schematics:** restore schematic smoke helper ([b76a85b](https://github.com/atls/raijin/commit/b76a85bdccfe82b1b33e6f5064f27902adabd3b2))
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
3
15
|
## [2.0.22](https://github.com/atls/raijin/compare/@atls/code-schematics@2.0.21...@atls/code-schematics@2.0.22) (2026-04-29)
|
|
4
16
|
|
|
5
17
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import os from 'node:os';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { prepareTmpDir } from '../helpers/index.js';
|
|
5
|
+
import { runSchematicHelper } from '../helpers/index.js';
|
|
6
|
+
import { writeTmpSchematicHelper } from '../helpers/index.js';
|
|
7
|
+
const helperScanRoots = [
|
|
8
|
+
'package.json',
|
|
9
|
+
'scripts/raijin',
|
|
10
|
+
'README.md',
|
|
11
|
+
'README_EN.md',
|
|
12
|
+
'code/code-schematics/src/scripts/schematic-smoke.script.ts',
|
|
13
|
+
'docs/README.md',
|
|
14
|
+
'docs/README.ru.md',
|
|
15
|
+
'docs/raijin/README.md',
|
|
16
|
+
'docs/raijin/README.ru.md',
|
|
17
|
+
'docs/raijin/quickstart.md',
|
|
18
|
+
'docs/raijin/quickstart.ru.md',
|
|
19
|
+
'docs/raijin/commands.md',
|
|
20
|
+
'docs/raijin/commands.ru.md',
|
|
21
|
+
];
|
|
22
|
+
const requiredGeneratedFiles = [
|
|
23
|
+
'.gitignore',
|
|
24
|
+
'.prettierrc.mjs',
|
|
25
|
+
'.github/workflows/checks.yaml',
|
|
26
|
+
'.github/workflows/preview.yaml',
|
|
27
|
+
'.github/workflows/release.yaml',
|
|
28
|
+
'tsconfig.json',
|
|
29
|
+
];
|
|
30
|
+
const readJson = async (filePath) => JSON.parse(await fs.readFile(filePath, 'utf8'));
|
|
31
|
+
const pathExists = async (filePath) => {
|
|
32
|
+
try {
|
|
33
|
+
await fs.access(filePath);
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
const findRepoRoot = async (startDir) => {
|
|
41
|
+
let currentDir = startDir;
|
|
42
|
+
while (currentDir !== path.dirname(currentDir)) {
|
|
43
|
+
if (await pathExists(path.join(currentDir, 'docs/raijin/index.v1.json'))) {
|
|
44
|
+
return currentDir;
|
|
45
|
+
}
|
|
46
|
+
currentDir = path.dirname(currentDir);
|
|
47
|
+
}
|
|
48
|
+
throw new Error('Cannot find repository root with docs/raijin/index.v1.json');
|
|
49
|
+
};
|
|
50
|
+
const walkFiles = async (entryPath) => {
|
|
51
|
+
if (!(await pathExists(entryPath)))
|
|
52
|
+
return [];
|
|
53
|
+
const stat = await fs.stat(entryPath);
|
|
54
|
+
if (stat.isFile())
|
|
55
|
+
return [entryPath];
|
|
56
|
+
const entries = await fs.readdir(entryPath, { withFileTypes: true });
|
|
57
|
+
const nested = await Promise.all(entries.map(async (entry) => walkFiles(path.join(entryPath, entry.name))));
|
|
58
|
+
return nested.flat();
|
|
59
|
+
};
|
|
60
|
+
const assertInactiveCommandsAreNotInvoked = async (repoRoot) => {
|
|
61
|
+
const index = await readJson(path.join(repoRoot, 'docs/raijin/index.v1.json'));
|
|
62
|
+
const inactiveCommands = index.commands
|
|
63
|
+
.filter((command) => command.status === 'inactive')
|
|
64
|
+
.map((command) => command.command);
|
|
65
|
+
const scanFiles = (await Promise.all(helperScanRoots.map(async (scanRoot) => walkFiles(path.join(repoRoot, scanRoot)))))
|
|
66
|
+
.flat()
|
|
67
|
+
.filter((filePath) => ['.json', '.js', '.mjs', '.ts', '.tsx', '.md'].includes(path.extname(filePath)));
|
|
68
|
+
const violations = [];
|
|
69
|
+
for (const filePath of scanFiles) {
|
|
70
|
+
const content = await fs.readFile(filePath, 'utf8');
|
|
71
|
+
const relativePath = path.relative(repoRoot, filePath);
|
|
72
|
+
for (const command of inactiveCommands) {
|
|
73
|
+
const invocation = ['yarn', command].join(' ');
|
|
74
|
+
if (content.includes(invocation)) {
|
|
75
|
+
violations.push(`${relativePath}: uses inactive command "${invocation}"`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (violations.length > 0) {
|
|
80
|
+
throw new Error(`Inactive command invocations found:\n${violations.join('\n')}`);
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
const writeFixturePackage = async (fixtureDir) => {
|
|
84
|
+
const packageJson = {
|
|
85
|
+
name: 'raijin-schematic-smoke-fixture',
|
|
86
|
+
private: true,
|
|
87
|
+
type: 'module',
|
|
88
|
+
};
|
|
89
|
+
await fs.writeFile(path.join(fixtureDir, 'package.json'), `${JSON.stringify(packageJson, null, 2)}\n`);
|
|
90
|
+
await fs.writeFile(path.join(fixtureDir, 'tsconfig.json'), `${JSON.stringify({}, null, 2)}\n`);
|
|
91
|
+
};
|
|
92
|
+
const prepareCollectionDir = async (repoRoot, collectionDir) => {
|
|
93
|
+
const previousCwd = process.cwd();
|
|
94
|
+
const collectionPortablePath = collectionDir;
|
|
95
|
+
try {
|
|
96
|
+
process.chdir(repoRoot);
|
|
97
|
+
await prepareTmpDir(collectionPortablePath);
|
|
98
|
+
}
|
|
99
|
+
finally {
|
|
100
|
+
process.chdir(previousCwd);
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
const runProjectSchematic = async ({ collectionPath, fixtureDir, }) => {
|
|
104
|
+
const previousCwd = process.cwd();
|
|
105
|
+
try {
|
|
106
|
+
process.chdir(fixtureDir);
|
|
107
|
+
const exitCode = await runSchematicHelper('project', {
|
|
108
|
+
type: 'project',
|
|
109
|
+
cwd: fixtureDir,
|
|
110
|
+
}, collectionPath);
|
|
111
|
+
if (exitCode !== 0) {
|
|
112
|
+
throw new Error(`Schematic workflow failed with exit code ${exitCode}`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
finally {
|
|
116
|
+
process.chdir(previousCwd);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
const assertGeneratedFixture = async (fixtureDir) => {
|
|
120
|
+
const missingFiles = [];
|
|
121
|
+
for (const relativePath of requiredGeneratedFiles) {
|
|
122
|
+
if (!(await pathExists(path.join(fixtureDir, relativePath)))) {
|
|
123
|
+
missingFiles.push(relativePath);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
if (missingFiles.length > 0) {
|
|
127
|
+
throw new Error(`Schematic smoke did not generate required files:\n${missingFiles.join('\n')}`);
|
|
128
|
+
}
|
|
129
|
+
const gitignore = await fs.readFile(path.join(fixtureDir, '.gitignore'), 'utf8');
|
|
130
|
+
if (!gitignore.includes('node_modules') || !gitignore.includes('dist/')) {
|
|
131
|
+
throw new Error('Generated .gitignore does not contain expected baseline entries');
|
|
132
|
+
}
|
|
133
|
+
const tsconfig = await readJson(path.join(fixtureDir, 'tsconfig.json'));
|
|
134
|
+
if (!tsconfig.compilerOptions || typeof tsconfig.compilerOptions !== 'object') {
|
|
135
|
+
throw new Error('Generated tsconfig.json does not contain compilerOptions');
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
const runSchematicSmoke = async () => {
|
|
139
|
+
const repoRoot = await findRepoRoot(process.cwd());
|
|
140
|
+
await assertInactiveCommandsAreNotInvoked(repoRoot);
|
|
141
|
+
const tmpRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'raijin-schematic-smoke-'));
|
|
142
|
+
const collectionDir = path.join(tmpRoot, 'collection');
|
|
143
|
+
const fixtureDir = path.join(tmpRoot, 'fixture');
|
|
144
|
+
try {
|
|
145
|
+
await fs.mkdir(collectionDir, { recursive: true });
|
|
146
|
+
await fs.mkdir(fixtureDir, { recursive: true });
|
|
147
|
+
await writeFixturePackage(fixtureDir);
|
|
148
|
+
await writeTmpSchematicHelper(collectionDir);
|
|
149
|
+
await prepareCollectionDir(repoRoot, collectionDir);
|
|
150
|
+
await runProjectSchematic({
|
|
151
|
+
collectionPath: path.join(collectionDir, 'collection.json'),
|
|
152
|
+
fixtureDir,
|
|
153
|
+
});
|
|
154
|
+
await assertGeneratedFixture(fixtureDir);
|
|
155
|
+
}
|
|
156
|
+
finally {
|
|
157
|
+
await fs.rm(tmpRoot, { recursive: true, force: true });
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
try {
|
|
161
|
+
await runSchematicSmoke();
|
|
162
|
+
console.log('Schematic smoke passed');
|
|
163
|
+
}
|
|
164
|
+
catch (error) {
|
|
165
|
+
if (error instanceof Error) {
|
|
166
|
+
console.error(error.message);
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
console.error(error);
|
|
170
|
+
}
|
|
171
|
+
process.exitCode = 1;
|
|
172
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atls/code-schematics",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.23",
|
|
4
4
|
"license": "BSD-3-Clause",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -19,7 +19,8 @@
|
|
|
19
19
|
"build:library": "yarn library build",
|
|
20
20
|
"build:schematic-factory": "yarn node ./src/scripts/schematic-factory-build.script.ts",
|
|
21
21
|
"prepack": "yarn run build",
|
|
22
|
-
"postpack": "rm -rf dist"
|
|
22
|
+
"postpack": "rm -rf dist",
|
|
23
|
+
"smoke:schematic": "yarn node ./src/scripts/schematic-smoke.script.ts"
|
|
23
24
|
},
|
|
24
25
|
"dependencies": {
|
|
25
26
|
"@angular-devkit/core": "19.1.5",
|
|
@@ -28,7 +29,7 @@
|
|
|
28
29
|
"strip-json-comments": "3.1.1"
|
|
29
30
|
},
|
|
30
31
|
"devDependencies": {
|
|
31
|
-
"@atls/code-runtime": "2.1.
|
|
32
|
+
"@atls/code-runtime": "2.1.28",
|
|
32
33
|
"@types/node": "24.12.2",
|
|
33
34
|
"@yarnpkg/cli": "4.14.1",
|
|
34
35
|
"@yarnpkg/core": "4.7.0",
|