@venizia/ignis-boot 0.4.6 → 0.4.7-1

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 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 and MCP Server |
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` | `generateArtifactIndex`, `checkArtifactIndex`, `ArtifactScanner`, `ArtifactIndexEmitter`, `ArtifactStereotypes`, `ArtifactTypes`, `ArtifactIndexFields` | `typescript` |
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 { checkArtifactIndex } from '@venizia/ignis-boot/generator';
154
+ import { ArtifactIndexGenerator } from '@venizia/ignis-boot/generator';
155
155
 
156
- const { isFresh } = checkArtifactIndex({ root: 'src', out: 'src/generated/artifacts.ts' });
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":"stamp.d.ts","sourceRoot":"","sources":["../../../src/build-info/stamp.ts"],"names":[],"mappings":"AAOA;;;;;;GAMG;AACH,qBAAa,cAAc;IACzB,+EAA+E;IAC/E,MAAM,CAAC,QAAQ,CAAC,WAAW,sBAAsB;IAEjD,yHAAyH;WAC5G,MAAM,CAAC,IAAI,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAK9E;;;;OAIG;WACU,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAUvC"}
1
+ {"version":3,"file":"stamp.d.ts","sourceRoot":"","sources":["../../../src/build-info/stamp.ts"],"names":[],"mappings":"AAOA;;;;;;GAMG;AACH,qBAAa,cAAc;IACzB,+EAA+E;IAC/E,MAAM,CAAC,QAAQ,CAAC,WAAW,sBAAsB;IAEjD,yHAAyH;WAC5G,MAAM,CAAC,IAAI,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAK9E;;;;OAIG;WACU,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAavC"}
@@ -21,9 +21,14 @@ export class BuildInfoStamp {
21
21
  * stay with the application's `getAppInfo()`, which the health reporter reads when they are absent.
22
22
  */
23
23
  static async register() {
24
- const stamp = typeof IGNIS_BUILD_INFO !== 'undefined'
25
- ? IGNIS_BUILD_INFO
26
- : await BuildInfoResolver.getInstance().resolve();
24
+ let stamp;
25
+ if (typeof IGNIS_BUILD_INFO !== 'undefined') {
26
+ stamp = IGNIS_BUILD_INFO;
27
+ }
28
+ else {
29
+ const resolved = await BuildInfoResolver.getInstance().resolve();
30
+ stamp = resolved;
31
+ }
27
32
  BuildInfoRegistry.set({
28
33
  buildInfo: { commit: stamp.commit, branch: stamp.branch, builtAt: stamp.builtAt },
29
34
  });
@@ -1 +1 @@
1
- {"version":3,"file":"stamp.js","sourceRoot":"","sources":["../../../src/build-info/stamp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAyB,MAAM,6BAA6B,CAAC;AACvF,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAM/C;;;;;;GAMG;AACH,MAAM,OAAO,cAAc;IACzB,+EAA+E;aAC/D,gBAAW,GAAG,kBAAkB,CAAC;IAEjD,yHAAyH;IACzH,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAwB;QAC1C,MAAM,KAAK,GAAG,MAAM,iBAAiB,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAClE,OAAO,EAAE,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;IACjE,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,KAAK,CAAC,QAAQ;QACnB,MAAM,KAAK,GACT,OAAO,gBAAgB,KAAK,WAAW;YACrC,CAAC,CAAC,gBAAgB;YAClB,CAAC,CAAC,MAAM,iBAAiB,CAAC,WAAW,EAAE,CAAC,OAAO,EAAE,CAAC;QAEtD,iBAAiB,CAAC,GAAG,CAAC;YACpB,SAAS,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE;SAClF,CAAC,CAAC;IACL,CAAC","sourcesContent":["import { BuildInfoRegistry, type TBuildInfoRecord } from '@venizia/ignis-helpers/core';\nimport { BuildInfoResolver } from './resolver';\n\n// A compile bakes the stamp in under this name (`define`); a run from source has no such name.\n// The identifier below must spell the same as `BuildInfoStamp.GLOBAL_NAME`.\ndeclare const IGNIS_BUILD_INFO: TBuildInfoRecord | undefined;\n\n/**\n * The build stamp, decided where it is cheap: a compile bakes it into the binary, a run from\n * source resolves it from git when the application starts.\n *\n * `define()` is for the compile script, `register()` for the entrypoint. A binary that carries the\n * stamp never runs git; the resolver is the only code here, and it needs no TypeScript scanner.\n */\nexport class BuildInfoStamp {\n /** The identifier `define()` replaces in the bundle and `register()` reads. */\n static readonly GLOBAL_NAME = 'IGNIS_BUILD_INFO';\n\n /** The `define` record for a compile: resolves the stamp now and returns it under {@link BuildInfoStamp.GLOBAL_NAME}. */\n static async define(opts?: { root?: string }): Promise<Record<string, string>> {\n const stamp = await BuildInfoResolver.getInstance().resolve(opts);\n return { [BuildInfoStamp.GLOBAL_NAME]: JSON.stringify(stamp) };\n }\n\n /**\n * Registers the stamp in {@link BuildInfoRegistry}: the baked value when the compile defined it,\n * else the resolver's. Only `commit`, `branch` and `builtAt` are set - `service` and `version`\n * stay with the application's `getAppInfo()`, which the health reporter reads when they are absent.\n */\n static async register(): Promise<void> {\n const stamp =\n typeof IGNIS_BUILD_INFO !== 'undefined'\n ? IGNIS_BUILD_INFO\n : await BuildInfoResolver.getInstance().resolve();\n\n BuildInfoRegistry.set({\n buildInfo: { commit: stamp.commit, branch: stamp.branch, builtAt: stamp.builtAt },\n });\n }\n}\n"]}
1
+ {"version":3,"file":"stamp.js","sourceRoot":"","sources":["../../../src/build-info/stamp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAyB,MAAM,6BAA6B,CAAC;AACvF,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAM/C;;;;;;GAMG;AACH,MAAM,OAAO,cAAc;IACzB,+EAA+E;aAC/D,gBAAW,GAAG,kBAAkB,CAAC;IAEjD,yHAAyH;IACzH,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAwB;QAC1C,MAAM,KAAK,GAAG,MAAM,iBAAiB,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAClE,OAAO,EAAE,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;IACjE,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,KAAK,CAAC,QAAQ;QACnB,IAAI,KAAuB,CAAC;QAC5B,IAAI,OAAO,gBAAgB,KAAK,WAAW,EAAE,CAAC;YAC5C,KAAK,GAAG,gBAAgB,CAAC;QAC3B,CAAC;aAAM,CAAC;YACN,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,WAAW,EAAE,CAAC,OAAO,EAAE,CAAC;YACjE,KAAK,GAAG,QAAQ,CAAC;QACnB,CAAC;QAED,iBAAiB,CAAC,GAAG,CAAC;YACpB,SAAS,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE;SAClF,CAAC,CAAC;IACL,CAAC","sourcesContent":["import { BuildInfoRegistry, type TBuildInfoRecord } from '@venizia/ignis-helpers/core';\nimport { BuildInfoResolver } from './resolver';\n\n// A compile bakes the stamp in under this name (`define`); a run from source has no such name.\n// The identifier below must spell the same as `BuildInfoStamp.GLOBAL_NAME`.\ndeclare const IGNIS_BUILD_INFO: TBuildInfoRecord | undefined;\n\n/**\n * The build stamp, decided where it is cheap: a compile bakes it into the binary, a run from\n * source resolves it from git when the application starts.\n *\n * `define()` is for the compile script, `register()` for the entrypoint. A binary that carries the\n * stamp never runs git; the resolver is the only code here, and it needs no TypeScript scanner.\n */\nexport class BuildInfoStamp {\n /** The identifier `define()` replaces in the bundle and `register()` reads. */\n static readonly GLOBAL_NAME = 'IGNIS_BUILD_INFO';\n\n /** The `define` record for a compile: resolves the stamp now and returns it under {@link BuildInfoStamp.GLOBAL_NAME}. */\n static async define(opts?: { root?: string }): Promise<Record<string, string>> {\n const stamp = await BuildInfoResolver.getInstance().resolve(opts);\n return { [BuildInfoStamp.GLOBAL_NAME]: JSON.stringify(stamp) };\n }\n\n /**\n * Registers the stamp in {@link BuildInfoRegistry}: the baked value when the compile defined it,\n * else the resolver's. Only `commit`, `branch` and `builtAt` are set - `service` and `version`\n * stay with the application's `getAppInfo()`, which the health reporter reads when they are absent.\n */\n static async register(): Promise<void> {\n let stamp: TBuildInfoRecord;\n if (typeof IGNIS_BUILD_INFO !== 'undefined') {\n stamp = IGNIS_BUILD_INFO;\n } else {\n const resolved = await BuildInfoResolver.getInstance().resolve();\n stamp = resolved;\n }\n\n BuildInfoRegistry.set({\n buildInfo: { commit: stamp.commit, branch: stamp.branch, builtAt: stamp.builtAt },\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, checkArtifactIndex, generateArtifactIndex } from '../generator/index.js';
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 = generateArtifactIndex(options);
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 = checkArtifactIndex(options);
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":"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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, checkArtifactIndex, generateArtifactIndex } 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 = generateArtifactIndex(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 = checkArtifactIndex(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"]}
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":"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;AAuBD,0GAA0G;AAC1G,eAAO,MAAM,qBAAqB,GAChC,MAAM,gBAAgB,KACrB;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GAAG,WAa1C,CAAC;AAKF,4GAA4G;AAC5G,eAAO,MAAM,kBAAkB,GAC7B,MAAM,gBAAgB,KACrB;IACD,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,OAAO,EAAE,gBAAgB,EAAE,CAAC;CAQ7B,CAAC;AAEF,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC"}
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":"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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\nconst 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/** Writes the index only when its content changed, so an unchanged tree leaves the file's mtime alone. */\nexport const generateArtifactIndex = (\n opts: IGenerateOptions,\n): { content: string; written: boolean } & IScanReport => {\n const { content, artifacts, ignored, skipped } = 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/** Everything below the first line: the header only records the command, so a flag change alone must not read as drift. */\nconst bodyOf = (content: string): string => content.slice(content.indexOf('\\n') + 1);\n\n/** Renders in memory and compares the body with the committed file - the staleness gate for lint and CI. */\nexport const checkArtifactIndex = (\n opts: IGenerateOptions,\n): {\n isFresh: boolean;\n expected: string;\n actual: string | undefined;\n ignored: IScannedArtifact[];\n} => {\n const { content: expected, ignored } = render(opts);\n const out = resolve(opts.out);\n const actual = existsSync(out) ? readFileSync(out, 'utf8') : undefined;\n const isFresh = actual !== undefined && bodyOf(actual) === bodyOf(expected);\n\n return { isFresh, expected, actual, ignored };\n};\n\nexport * from './common';\nexport * from './emitter';\nexport * from './scanner';\n"]}
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.6",
3
+ "version": "0.4.7-1",
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.6",
84
- "@venizia/ignis-inversion": "0.4.5"
82
+ "@venizia/ignis-helpers": "0.4.7-1",
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.6",
87
+ "@venizia/dev-configs": "0.4.7-1",
89
88
  "eslint": "^10.13.0",
90
89
  "oxlint": "1.89.0",
91
90
  "oxlint-tsgolint": "7.0.2004",