@venizia/ignis-boot 0.4.7-0 → 0.4.7-2
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.md +1 -4
- package/README.md +3 -3
- package/dist/esm/bun/scan-cache.d.ts.map +1 -1
- package/dist/esm/bun/scan-cache.js +2 -0
- package/dist/esm/bun/scan-cache.js.map +1 -1
- package/dist/esm/clis/artifacts.js +3 -3
- package/dist/esm/clis/artifacts.js.map +1 -1
- package/dist/esm/generator/generator.d.ts +29 -0
- package/dist/esm/generator/generator.d.ts.map +1 -0
- package/dist/esm/generator/generator.js +52 -0
- package/dist/esm/generator/generator.js.map +1 -0
- package/dist/esm/generator/index.d.ts +1 -22
- package/dist/esm/generator/index.d.ts.map +1 -1
- package/dist/esm/generator/index.js +1 -45
- package/dist/esm/generator/index.js.map +1 -1
- package/package.json +4 -5
package/LICENSE.md
CHANGED
|
@@ -46,9 +46,6 @@ This package uses the following open-source libraries:
|
|
|
46
46
|
|---------|---------|-------------|
|
|
47
47
|
| [@venizia/ignis-helpers](https://github.com/VENIZIA-AI/ignis) | MIT | Ignis utility helpers |
|
|
48
48
|
| [@venizia/ignis-inversion](https://github.com/VENIZIA-AI/ignis) | MIT | Ignis DI/IoC container |
|
|
49
|
-
| [glob](https://github.com/isaacs/node-glob) | ISC | File pattern matching |
|
|
50
|
-
| [reflect-metadata](https://github.com/rbuckton/reflect-metadata) | Apache-2.0 | Metadata reflection API |
|
|
51
|
-
| [zod](https://github.com/colinhacks/zod) | MIT | TypeScript-first schema validation |
|
|
52
49
|
|
|
53
50
|
---
|
|
54
51
|
|
|
@@ -63,7 +60,7 @@ Part of the Ignis monorepo:
|
|
|
63
60
|
| `@venizia/ignis-helpers` | Utility helpers - logging, cron, Redis, queues, storage |
|
|
64
61
|
| `@venizia/ignis-inversion` | Dependency Injection & IoC container |
|
|
65
62
|
| `@venizia/dev-configs` | Shared oxlint, ESLint, TypeScript configurations |
|
|
66
|
-
| `@venizia/ignis-docs` | Documentation
|
|
63
|
+
| `@venizia/ignis-docs` | Documentation site content |
|
|
67
64
|
|
|
68
65
|
---
|
|
69
66
|
|
package/README.md
CHANGED
|
@@ -141,7 +141,7 @@ The resolver reads each field from the environment first (first non-blank key wi
|
|
|
141
141
|
| Subpath | What it gives | Extra peers |
|
|
142
142
|
|---|---|---|
|
|
143
143
|
| `@venizia/ignis-boot` | Everything from the two subpaths below | `typescript` |
|
|
144
|
-
| `@venizia/ignis-boot/generator` | `
|
|
144
|
+
| `@venizia/ignis-boot/generator` | `ArtifactIndexGenerator`, `ArtifactScanner`, `ArtifactIndexEmitter`, `ArtifactStereotypes`, `ArtifactTypes`, `ArtifactIndexFields` | `typescript` |
|
|
145
145
|
| `@venizia/ignis-boot/build-info` | `BuildInfoStamp`, `BuildInfoResolver`, `BuildInfoEnvironmentKeys` | none |
|
|
146
146
|
|
|
147
147
|
| Binary | File |
|
|
@@ -151,9 +151,9 @@ The resolver reads each field from the environment first (first non-blank key wi
|
|
|
151
151
|
The package ships ES modules. The programmatic API mirrors the CLI:
|
|
152
152
|
|
|
153
153
|
```typescript
|
|
154
|
-
import {
|
|
154
|
+
import { ArtifactIndexGenerator } from '@venizia/ignis-boot/generator';
|
|
155
155
|
|
|
156
|
-
const { isFresh } =
|
|
156
|
+
const { isFresh } = ArtifactIndexGenerator.check({ root: 'src', out: 'src/generated/artifacts.ts' });
|
|
157
157
|
```
|
|
158
158
|
|
|
159
159
|
## Where it sits
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scan-cache.d.ts","sourceRoot":"","sources":["../../../src/bun/scan-cache.ts"],"names":[],"mappings":"AAWA,OAAO,EAAuB,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAEjF,oNAAoN;AACpN,qBAAa,iBAAiB;IAC5B,MAAM,CAAC,QAAQ,CAAC,OAAO,KAAK;IAE5B,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM;IAM/C,4KAA4K;IAC5K,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM;IAmClD,iGAAiG;IACjG,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,gBAAgB,EAAE,GAAG,SAAS;
|
|
1
|
+
{"version":3,"file":"scan-cache.d.ts","sourceRoot":"","sources":["../../../src/bun/scan-cache.ts"],"names":[],"mappings":"AAWA,OAAO,EAAuB,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAEjF,oNAAoN;AACpN,qBAAa,iBAAiB;IAC5B,MAAM,CAAC,QAAQ,CAAC,OAAO,KAAK;IAE5B,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM;IAM/C,4KAA4K;IAC5K,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM;IAmClD,iGAAiG;IACjG,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,gBAAgB,EAAE,GAAG,SAAS;IAsBnE,uIAAuI;IACvI,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,gBAAgB,EAAE,CAAA;KAAE,GAAG,OAAO;CAoB7E"}
|
|
@@ -52,6 +52,7 @@ export class ArtifactScanCache {
|
|
|
52
52
|
let stored;
|
|
53
53
|
try {
|
|
54
54
|
stored = JSON.parse(readFileSync(file, 'utf8'));
|
|
55
|
+
// eslint-disable-next-line venizia/no-silent-catch -- a corrupt cache is a miss; the cause is not reported and the only cost is one fresh scan
|
|
55
56
|
}
|
|
56
57
|
catch {
|
|
57
58
|
// A corrupt cache is a miss: the caller scans and rewrites it.
|
|
@@ -75,6 +76,7 @@ export class ArtifactScanCache {
|
|
|
75
76
|
}));
|
|
76
77
|
renameSync(temporary, file);
|
|
77
78
|
return true;
|
|
79
|
+
// eslint-disable-next-line venizia/no-silent-catch -- the `false` returned below is the report; the cause of the failed write is lost and the next start pays one scan
|
|
78
80
|
}
|
|
79
81
|
catch {
|
|
80
82
|
// Caching is an optimisation; reporting `false` lets the caller go on with the scan it already has.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scan-cache.js","sourceRoot":"","sources":["../../../src/bun/scan-cache.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"scan-cache.js","sourceRoot":"","sources":["../../../src/bun/scan-cache.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n existsSync,\n globSync,\n mkdirSync,\n readFileSync,\n renameSync,\n statSync,\n writeFileSync,\n} from 'node:fs';\nimport { createHash } from 'node:crypto';\nimport { dirname, join, resolve } from 'node:path';\nimport { ArtifactStereotypes, type IScannedArtifact } from '../generator/common';\n\n/** The scanner's answer for one `src`, kept under the package's `node_modules/.cache` and valid while no `.ts` file under `src`, the package manifest or the lockfile changed - a hit skips TypeScript entirely. */\nexport class ArtifactScanCache {\n static readonly VERSION = 2;\n\n static location(opts: { root: string }): string {\n const root = resolve(opts.root);\n const key = createHash('sha1').update(root).digest('hex').slice(0, 16);\n return join(dirname(root), 'node_modules', '.cache', 'ignis-artifacts', `${key}.json`);\n }\n\n /** Path, size and mtime of every `.ts`/`.tsx` under `root`, plus the package manifest and the nearest lockfile (a dependency upgrade can change which decorators count). */\n static fingerprint(opts: { root: string }): string {\n const root = resolve(opts.root);\n const entries: string[] = [];\n for (const relativePath of globSync(ArtifactStereotypes.SOURCE_GLOB, { cwd: root })) {\n const stats = statSync(join(root, relativePath));\n entries.push(`${relativePath}:${stats.size}:${stats.mtimeMs}`);\n }\n entries.sort();\n\n const extras = [join(dirname(root), 'package.json')];\n let directory = dirname(root);\n while (true) {\n const lockfile = ['bun.lock', 'bun.lockb', 'package-lock.json']\n .map((name) => join(directory, name))\n .find(existsSync);\n if (lockfile) {\n extras.push(lockfile);\n break;\n }\n const parent = dirname(directory);\n if (parent === directory) {\n break;\n }\n directory = parent;\n }\n for (const file of extras.filter(existsSync)) {\n const stats = statSync(file);\n entries.push(`${file}:${stats.size}:${stats.mtimeMs}`);\n }\n\n return createHash('sha1')\n .update(`${ArtifactScanCache.VERSION}\\n${entries.join('\\n')}`)\n .digest('hex');\n }\n\n /** The cached scan, or `undefined` for a missing, stale or unreadable cache - never an error. */\n static read(opts: { root: string }): IScannedArtifact[] | undefined {\n const file = ArtifactScanCache.location(opts);\n if (!existsSync(file)) {\n return undefined;\n }\n let stored: { fingerprint?: unknown; artifacts?: unknown };\n try {\n stored = JSON.parse(readFileSync(file, 'utf8'));\n // eslint-disable-next-line venizia/no-silent-catch -- a corrupt cache is a miss; the cause is not reported and the only cost is one fresh scan\n } catch {\n // A corrupt cache is a miss: the caller scans and rewrites it.\n return undefined;\n }\n if (\n stored.fingerprint !== ArtifactScanCache.fingerprint(opts) ||\n !Array.isArray(stored.artifacts)\n ) {\n return undefined;\n }\n return stored.artifacts;\n }\n\n /** Stores a scan; `false` when the cache directory cannot be written (a read-only install), which only costs the next start a scan. */\n static write(opts: { root: string; artifacts: IScannedArtifact[] }): boolean {\n const file = ArtifactScanCache.location(opts);\n const temporary = `${file}.${process.pid}.tmp`;\n try {\n mkdirSync(dirname(file), { recursive: true });\n writeFileSync(\n temporary,\n JSON.stringify({\n fingerprint: ArtifactScanCache.fingerprint(opts),\n artifacts: opts.artifacts,\n }),\n );\n renameSync(temporary, file);\n return true;\n // eslint-disable-next-line venizia/no-silent-catch -- the `false` returned below is the report; the cause of the failed write is lost and the next start pays one scan\n } catch {\n // Caching is an optimisation; reporting `false` lets the caller go on with the scan it already has.\n return false;\n }\n }\n}\n"]}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import '../common/install-quiet-logger.js';
|
|
3
3
|
import { relative } from 'node:path';
|
|
4
4
|
import { parseArgs } from 'node:util';
|
|
5
|
-
import { ArtifactIndexEmitter,
|
|
5
|
+
import { ArtifactIndexEmitter, ArtifactIndexGenerator } from '../generator/index.js';
|
|
6
6
|
const USAGE = 'ignis-artifacts <generate|check> [--root src] [--out src/generated/artifacts.ts] [--ignore a,b] [--export GeneratedArtifacts] [--source-module <specifier>]...';
|
|
7
7
|
const { positionals, values } = parseArgs({
|
|
8
8
|
args: process.argv.slice(2),
|
|
@@ -35,13 +35,13 @@ const warnIgnored = (opts) => {
|
|
|
35
35
|
const run = () => {
|
|
36
36
|
switch (positionals[0]) {
|
|
37
37
|
case 'generate': {
|
|
38
|
-
const result =
|
|
38
|
+
const result = ArtifactIndexGenerator.generate(options);
|
|
39
39
|
console.log(`${result.written ? 'wrote' : 'up to date'} ${options.out} | ${result.artifacts.length} artifact(s)`);
|
|
40
40
|
warnIgnored({ ignored: result.ignored, root: options.root });
|
|
41
41
|
return 0;
|
|
42
42
|
}
|
|
43
43
|
case 'check': {
|
|
44
|
-
const result =
|
|
44
|
+
const result = ArtifactIndexGenerator.check(options);
|
|
45
45
|
warnIgnored({ ignored: result.ignored, root: options.root });
|
|
46
46
|
if (result.isFresh) {
|
|
47
47
|
console.log(`fresh ${options.out}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"artifacts.js","sourceRoot":"","sources":["../../../src/clis/artifacts.ts"],"names":[],"mappings":";AACA,OAAO,gCAAgC,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,oBAAoB,EAAE,
|
|
1
|
+
{"version":3,"file":"artifacts.js","sourceRoot":"","sources":["../../../src/clis/artifacts.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env bun\nimport '../common/install-quiet-logger';\nimport { relative } from 'node:path';\nimport { parseArgs } from 'node:util';\nimport { ArtifactIndexEmitter, ArtifactIndexGenerator } from '../generator';\nimport type { IScannedArtifact } from '../generator';\n\nconst USAGE =\n 'ignis-artifacts <generate|check> [--root src] [--out src/generated/artifacts.ts] [--ignore a,b] [--export GeneratedArtifacts] [--source-module <specifier>]...';\n\nconst { positionals, values } = parseArgs({\n args: process.argv.slice(2),\n allowPositionals: true,\n options: {\n root: { type: 'string', default: 'src' },\n out: { type: 'string', default: 'src/generated/artifacts.ts' },\n ignore: { type: 'string' },\n export: { type: 'string', default: 'GeneratedArtifacts' },\n 'source-module': { type: 'string', multiple: true },\n },\n});\n\nconst options = {\n root: values.root,\n out: values.out,\n ignore: values.ignore\n ?.split(',')\n .map((pattern) => pattern.trim())\n .filter(Boolean),\n exportName: values.export,\n sourceModules: values['source-module'],\n};\n\n/** One stderr line per decorated class a user `--ignore` pattern hid; silence when nothing is hidden. */\nconst warnIgnored = (opts: { ignored: IScannedArtifact[]; root: string }): void => {\n for (const artifact of opts.ignored) {\n console.error(\n `warning: ${artifact.className} (${artifact.type}) in ${relative(opts.root, artifact.filePath)} matches --ignore and is left out of the index`,\n );\n }\n};\n\n/** Exit code of the command, so the process exits in exactly one place. */\nconst run = (): number => {\n switch (positionals[0]) {\n case 'generate': {\n const result = ArtifactIndexGenerator.generate(options);\n console.log(\n `${result.written ? 'wrote' : 'up to date'} ${options.out} | ${result.artifacts.length} artifact(s)`,\n );\n warnIgnored({ ignored: result.ignored, root: options.root });\n return 0;\n }\n case 'check': {\n const result = ArtifactIndexGenerator.check(options);\n warnIgnored({ ignored: result.ignored, root: options.root });\n if (result.isFresh) {\n console.log(`fresh ${options.out}`);\n return 0;\n }\n console.error(`stale ${options.out} - run: ${ArtifactIndexEmitter.renderCommand(options)}`);\n return 1;\n }\n default: {\n console.error(USAGE);\n return 2;\n }\n }\n};\n\nprocess.exit(run());\n"]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { IScanReport, IScannedArtifact } from './common/index.js';
|
|
2
|
+
export interface IGenerateOptions {
|
|
3
|
+
root: string;
|
|
4
|
+
out: string;
|
|
5
|
+
ignore?: string[];
|
|
6
|
+
/** Name of the exported constant; default `GeneratedArtifacts`. */
|
|
7
|
+
exportName?: string;
|
|
8
|
+
/** Extra module specifiers whose stereotype imports count; see `IScanOptions.sourceModules`. */
|
|
9
|
+
sourceModules?: string[];
|
|
10
|
+
}
|
|
11
|
+
/** Writes the artifact index, and checks that the committed one is still current. */
|
|
12
|
+
export declare class ArtifactIndexGenerator {
|
|
13
|
+
private static render;
|
|
14
|
+
/** Everything below the first line: the header only records the command, so a flag change alone must not read as drift. */
|
|
15
|
+
private static bodyOf;
|
|
16
|
+
/** Writes the index only when its content changed, so an unchanged tree leaves the file's mtime alone. */
|
|
17
|
+
static generate(opts: IGenerateOptions): {
|
|
18
|
+
content: string;
|
|
19
|
+
written: boolean;
|
|
20
|
+
} & IScanReport;
|
|
21
|
+
/** Renders in memory and compares the body with the committed file - the staleness gate for lint and CI. */
|
|
22
|
+
static check(opts: IGenerateOptions): {
|
|
23
|
+
isFresh: boolean;
|
|
24
|
+
expected: string;
|
|
25
|
+
actual: string | undefined;
|
|
26
|
+
ignored: IScannedArtifact[];
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../../src/generator/generator.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAI9D,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,mEAAmE;IACnE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gGAAgG;IAChG,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,qFAAqF;AACrF,qBAAa,sBAAsB;IACjC,OAAO,CAAC,MAAM,CAAC,MAAM;IAqBrB,2HAA2H;IAC3H,OAAO,CAAC,MAAM,CAAC,MAAM;IAIrB,0GAA0G;IAC1G,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,GAAG;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,GAAG,WAAW;IAe5F,4GAA4G;IAC5G,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,gBAAgB,GAAG;QACpC,OAAO,EAAE,OAAO,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;QAC3B,OAAO,EAAE,gBAAgB,EAAE,CAAC;KAC7B;CAUF"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { dirname, resolve } from 'node:path';
|
|
3
|
+
import { ArtifactIndexEmitter } from './emitter.js';
|
|
4
|
+
import { ArtifactScanner } from './scanner.js';
|
|
5
|
+
/** Writes the artifact index, and checks that the committed one is still current. */
|
|
6
|
+
export class ArtifactIndexGenerator {
|
|
7
|
+
static render(opts) {
|
|
8
|
+
const { artifacts, ignored, skipped } = ArtifactScanner.getInstance().scanWithReport({
|
|
9
|
+
root: opts.root,
|
|
10
|
+
ignore: opts.ignore,
|
|
11
|
+
sourceModules: opts.sourceModules,
|
|
12
|
+
});
|
|
13
|
+
const content = ArtifactIndexEmitter.render({
|
|
14
|
+
artifacts,
|
|
15
|
+
outFile: resolve(opts.out),
|
|
16
|
+
exportName: opts.exportName ?? ArtifactIndexEmitter.DEFAULT_EXPORT_NAME,
|
|
17
|
+
command: {
|
|
18
|
+
root: opts.root,
|
|
19
|
+
out: opts.out,
|
|
20
|
+
ignore: opts.ignore,
|
|
21
|
+
sourceModules: opts.sourceModules,
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
return { content, artifacts, ignored, skipped };
|
|
25
|
+
}
|
|
26
|
+
/** Everything below the first line: the header only records the command, so a flag change alone must not read as drift. */
|
|
27
|
+
static bodyOf(content) {
|
|
28
|
+
return content.slice(content.indexOf('\n') + 1);
|
|
29
|
+
}
|
|
30
|
+
/** Writes the index only when its content changed, so an unchanged tree leaves the file's mtime alone. */
|
|
31
|
+
static generate(opts) {
|
|
32
|
+
const { content, artifacts, ignored, skipped } = ArtifactIndexGenerator.render(opts);
|
|
33
|
+
const out = resolve(opts.out);
|
|
34
|
+
const current = existsSync(out) ? readFileSync(out, 'utf8') : undefined;
|
|
35
|
+
if (current === content) {
|
|
36
|
+
return { content, artifacts, ignored, skipped, written: false };
|
|
37
|
+
}
|
|
38
|
+
mkdirSync(dirname(out), { recursive: true });
|
|
39
|
+
writeFileSync(out, content);
|
|
40
|
+
return { content, artifacts, ignored, skipped, written: true };
|
|
41
|
+
}
|
|
42
|
+
/** Renders in memory and compares the body with the committed file - the staleness gate for lint and CI. */
|
|
43
|
+
static check(opts) {
|
|
44
|
+
const { content: expected, ignored } = ArtifactIndexGenerator.render(opts);
|
|
45
|
+
const out = resolve(opts.out);
|
|
46
|
+
const actual = existsSync(out) ? readFileSync(out, 'utf8') : undefined;
|
|
47
|
+
const isFresh = actual !== undefined &&
|
|
48
|
+
ArtifactIndexGenerator.bodyOf(actual) === ArtifactIndexGenerator.bodyOf(expected);
|
|
49
|
+
return { isFresh, expected, actual, ignored };
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generator.js","sourceRoot":"","sources":["../../../src/generator/generator.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname, resolve } from 'node:path';\nimport type { IScanReport, IScannedArtifact } from './common';\nimport { ArtifactIndexEmitter } from './emitter';\nimport { ArtifactScanner } from './scanner';\n\nexport interface IGenerateOptions {\n root: string;\n out: string;\n ignore?: string[];\n /** Name of the exported constant; default `GeneratedArtifacts`. */\n exportName?: string;\n /** Extra module specifiers whose stereotype imports count; see `IScanOptions.sourceModules`. */\n sourceModules?: string[];\n}\n\n/** Writes the artifact index, and checks that the committed one is still current. */\nexport class ArtifactIndexGenerator {\n private static render(opts: IGenerateOptions): { content: string } & IScanReport {\n const { artifacts, ignored, skipped } = ArtifactScanner.getInstance().scanWithReport({\n root: opts.root,\n ignore: opts.ignore,\n sourceModules: opts.sourceModules,\n });\n const content = ArtifactIndexEmitter.render({\n artifacts,\n outFile: resolve(opts.out),\n exportName: opts.exportName ?? ArtifactIndexEmitter.DEFAULT_EXPORT_NAME,\n command: {\n root: opts.root,\n out: opts.out,\n ignore: opts.ignore,\n sourceModules: opts.sourceModules,\n },\n });\n\n return { content, artifacts, ignored, skipped };\n }\n\n /** Everything below the first line: the header only records the command, so a flag change alone must not read as drift. */\n private static bodyOf(content: string): string {\n return content.slice(content.indexOf('\\n') + 1);\n }\n\n /** Writes the index only when its content changed, so an unchanged tree leaves the file's mtime alone. */\n static generate(opts: IGenerateOptions): { content: string; written: boolean } & IScanReport {\n const { content, artifacts, ignored, skipped } = ArtifactIndexGenerator.render(opts);\n const out = resolve(opts.out);\n const current = existsSync(out) ? readFileSync(out, 'utf8') : undefined;\n\n if (current === content) {\n return { content, artifacts, ignored, skipped, written: false };\n }\n\n mkdirSync(dirname(out), { recursive: true });\n writeFileSync(out, content);\n\n return { content, artifacts, ignored, skipped, written: true };\n }\n\n /** Renders in memory and compares the body with the committed file - the staleness gate for lint and CI. */\n static check(opts: IGenerateOptions): {\n isFresh: boolean;\n expected: string;\n actual: string | undefined;\n ignored: IScannedArtifact[];\n } {\n const { content: expected, ignored } = ArtifactIndexGenerator.render(opts);\n const out = resolve(opts.out);\n const actual = existsSync(out) ? readFileSync(out, 'utf8') : undefined;\n const isFresh =\n actual !== undefined &&\n ArtifactIndexGenerator.bodyOf(actual) === ArtifactIndexGenerator.bodyOf(expected);\n\n return { isFresh, expected, actual, ignored };\n }\n}\n"]}
|
|
@@ -1,26 +1,5 @@
|
|
|
1
|
-
import type { IScanReport, IScannedArtifact } from './common/index.js';
|
|
2
|
-
export interface IGenerateOptions {
|
|
3
|
-
root: string;
|
|
4
|
-
out: string;
|
|
5
|
-
ignore?: string[];
|
|
6
|
-
/** Name of the exported constant; default `GeneratedArtifacts`. */
|
|
7
|
-
exportName?: string;
|
|
8
|
-
/** Extra module specifiers whose stereotype imports count; see `IScanOptions.sourceModules`. */
|
|
9
|
-
sourceModules?: string[];
|
|
10
|
-
}
|
|
11
|
-
/** Writes the index only when its content changed, so an unchanged tree leaves the file's mtime alone. */
|
|
12
|
-
export declare const generateArtifactIndex: (opts: IGenerateOptions) => {
|
|
13
|
-
content: string;
|
|
14
|
-
written: boolean;
|
|
15
|
-
} & IScanReport;
|
|
16
|
-
/** Renders in memory and compares the body with the committed file - the staleness gate for lint and CI. */
|
|
17
|
-
export declare const checkArtifactIndex: (opts: IGenerateOptions) => {
|
|
18
|
-
isFresh: boolean;
|
|
19
|
-
expected: string;
|
|
20
|
-
actual: string | undefined;
|
|
21
|
-
ignored: IScannedArtifact[];
|
|
22
|
-
};
|
|
23
1
|
export * from './common/index.js';
|
|
24
2
|
export * from './emitter.js';
|
|
3
|
+
export * from './generator.js';
|
|
25
4
|
export * from './scanner.js';
|
|
26
5
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/generator/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/generator/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC"}
|
|
@@ -1,49 +1,5 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
-
import { dirname, resolve } from 'node:path';
|
|
3
|
-
import { ArtifactIndexEmitter } from './emitter.js';
|
|
4
|
-
import { ArtifactScanner } from './scanner.js';
|
|
5
|
-
const render = (opts) => {
|
|
6
|
-
const { artifacts, ignored, skipped } = ArtifactScanner.getInstance().scanWithReport({
|
|
7
|
-
root: opts.root,
|
|
8
|
-
ignore: opts.ignore,
|
|
9
|
-
sourceModules: opts.sourceModules,
|
|
10
|
-
});
|
|
11
|
-
const content = ArtifactIndexEmitter.render({
|
|
12
|
-
artifacts,
|
|
13
|
-
outFile: resolve(opts.out),
|
|
14
|
-
exportName: opts.exportName ?? ArtifactIndexEmitter.DEFAULT_EXPORT_NAME,
|
|
15
|
-
command: {
|
|
16
|
-
root: opts.root,
|
|
17
|
-
out: opts.out,
|
|
18
|
-
ignore: opts.ignore,
|
|
19
|
-
sourceModules: opts.sourceModules,
|
|
20
|
-
},
|
|
21
|
-
});
|
|
22
|
-
return { content, artifacts, ignored, skipped };
|
|
23
|
-
};
|
|
24
|
-
/** Writes the index only when its content changed, so an unchanged tree leaves the file's mtime alone. */
|
|
25
|
-
export const generateArtifactIndex = (opts) => {
|
|
26
|
-
const { content, artifacts, ignored, skipped } = render(opts);
|
|
27
|
-
const out = resolve(opts.out);
|
|
28
|
-
const current = existsSync(out) ? readFileSync(out, 'utf8') : undefined;
|
|
29
|
-
if (current === content) {
|
|
30
|
-
return { content, artifacts, ignored, skipped, written: false };
|
|
31
|
-
}
|
|
32
|
-
mkdirSync(dirname(out), { recursive: true });
|
|
33
|
-
writeFileSync(out, content);
|
|
34
|
-
return { content, artifacts, ignored, skipped, written: true };
|
|
35
|
-
};
|
|
36
|
-
/** Everything below the first line: the header only records the command, so a flag change alone must not read as drift. */
|
|
37
|
-
const bodyOf = (content) => content.slice(content.indexOf('\n') + 1);
|
|
38
|
-
/** Renders in memory and compares the body with the committed file - the staleness gate for lint and CI. */
|
|
39
|
-
export const checkArtifactIndex = (opts) => {
|
|
40
|
-
const { content: expected, ignored } = render(opts);
|
|
41
|
-
const out = resolve(opts.out);
|
|
42
|
-
const actual = existsSync(out) ? readFileSync(out, 'utf8') : undefined;
|
|
43
|
-
const isFresh = actual !== undefined && bodyOf(actual) === bodyOf(expected);
|
|
44
|
-
return { isFresh, expected, actual, ignored };
|
|
45
|
-
};
|
|
46
1
|
export * from './common/index.js';
|
|
47
2
|
export * from './emitter.js';
|
|
3
|
+
export * from './generator.js';
|
|
48
4
|
export * from './scanner.js';
|
|
49
5
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/generator/index.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/generator/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC","sourcesContent":["export * from './common';\nexport * from './emitter';\nexport * from './generator';\nexport * from './scanner';\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@venizia/ignis-boot",
|
|
3
|
-
"version": "0.4.7-
|
|
3
|
+
"version": "0.4.7-2",
|
|
4
4
|
"description": "Build-time artifact index generator for IGNIS applications: scans decorated classes with the TypeScript AST and emits one static registration file per package, so bun build --compile sees plain imports.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"artifact-index",
|
|
@@ -76,16 +76,15 @@
|
|
|
76
76
|
},
|
|
77
77
|
"scripts": {
|
|
78
78
|
"force-update": "sh ../../scripts/build/force-update.sh",
|
|
79
|
-
"prepublishOnly": "make rebuild",
|
|
80
79
|
"test": "bun test ./src"
|
|
81
80
|
},
|
|
82
81
|
"dependencies": {
|
|
83
|
-
"@venizia/ignis-helpers": "0.4.7-
|
|
84
|
-
"@venizia/ignis-inversion": "0.4.6-
|
|
82
|
+
"@venizia/ignis-helpers": "0.4.7-2",
|
|
83
|
+
"@venizia/ignis-inversion": "0.4.6-1"
|
|
85
84
|
},
|
|
86
85
|
"devDependencies": {
|
|
87
86
|
"@types/bun": "^1.4.3",
|
|
88
|
-
"@venizia/dev-configs": "0.4.7-
|
|
87
|
+
"@venizia/dev-configs": "0.4.7-2",
|
|
89
88
|
"eslint": "^10.13.0",
|
|
90
89
|
"oxlint": "1.89.0",
|
|
91
90
|
"oxlint-tsgolint": "7.0.2004",
|