@theholocron/astromech 5.0.0-alpha.6 → 5.0.0-alpha.8
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/index.d.mts +110 -1
- package/dist/index.mjs +135 -3
- package/package.json +3 -3
package/dist/index.d.mts
CHANGED
|
@@ -546,6 +546,46 @@ declare const CI_ORDER: string[];
|
|
|
546
546
|
/** Ordered (task contexts in {@link CI_ORDER}, then extras), de-duplicated. */
|
|
547
547
|
declare function requiredChecks(config: TasksConfig): string[];
|
|
548
548
|
//#endregion
|
|
549
|
+
//#region src/resolver.d.ts
|
|
550
|
+
/**
|
|
551
|
+
* Resolves the absolute path to a Bucket A tool's shared `@theholocron/*-config`
|
|
552
|
+
* entry point, installed in the consuming repo's own `node_modules` — and the
|
|
553
|
+
* CLI flag(s) to hand it via (`--config`, `--extends`, …). `run.ts` splices the
|
|
554
|
+
* result into the command it builds for a tool/detect runner or a linter-group
|
|
555
|
+
* entry, right after the tool's own args.
|
|
556
|
+
*
|
|
557
|
+
* Every mapped package's resolved entry point already carries a ready-to-use
|
|
558
|
+
* default export (a plain re-export for `prettier`/`commitlint`; an invoked,
|
|
559
|
+
* zero-arg preset for `eslint`/`vitest`/`tsdown` — verified end-to-end against
|
|
560
|
+
* each tool's real `--config`/`--extends` loader, not just the file's shape).
|
|
561
|
+
* A repo doesn't need this package installed at all — every lookup degrades to
|
|
562
|
+
* `[]` (no flag added, the tool falls back to its own auto-discovery of a
|
|
563
|
+
* local file, unchanged from today) rather than throwing, so this is additive
|
|
564
|
+
* and safe to run unconditionally.
|
|
565
|
+
*
|
|
566
|
+
* `semantic-release`, `devmoji`, `editorconfig-checker`, and `knip` are
|
|
567
|
+
* deliberately absent — `semantic-release-config`'s `defineConfig()` needs
|
|
568
|
+
* real per-repo data (branches, npm options) a static `--extends <path>` can't
|
|
569
|
+
* carry; `devmoji` runs through a git hook template, not `holocron run
|
|
570
|
+
* <task>`; `editorconfig-checker` has no shared-config package yet; `knip` is
|
|
571
|
+
* repo-specific by nature, never a shared-config candidate. See
|
|
572
|
+
* `.notes/tech-config-resolution.spec.md` (#676).
|
|
573
|
+
*/
|
|
574
|
+
interface ResolverDeps {
|
|
575
|
+
readFile: (path: string) => string;
|
|
576
|
+
fileExists: (path: string) => boolean;
|
|
577
|
+
}
|
|
578
|
+
/** Every tool name the resolver knows how to point at a shared config. */
|
|
579
|
+
declare const RESOLVABLE_TOOLS: ReadonlySet<string>;
|
|
580
|
+
/**
|
|
581
|
+
* `<flag> <absolute path>` for `tool`, resolved against `cwd`'s
|
|
582
|
+
* `node_modules` — or `[]` when the tool isn't mapped, the package isn't
|
|
583
|
+
* installed, its `package.json` doesn't declare the export subpath this
|
|
584
|
+
* needs, or the resolved file doesn't actually exist on disk (a stale
|
|
585
|
+
* install, or a package version that predates the export existing).
|
|
586
|
+
*/
|
|
587
|
+
declare function resolveToolConfig(tool: string, cwd: string, deps: ResolverDeps): string[];
|
|
588
|
+
//#endregion
|
|
549
589
|
//#region src/reusable.d.ts
|
|
550
590
|
/**
|
|
551
591
|
* The **reusable** GitHub Actions surface pushed to `theholocron/.github` by
|
|
@@ -573,4 +613,73 @@ declare const WORKFLOW_TEMPLATE_PROPERTIES: Record<string, string>;
|
|
|
573
613
|
*/
|
|
574
614
|
declare function reusableTemplates(): Map<string, string>;
|
|
575
615
|
//#endregion
|
|
576
|
-
|
|
616
|
+
//#region src/tsconfig.d.ts
|
|
617
|
+
/**
|
|
618
|
+
* `tsconfig.json` generation — Bucket B (config-resolution workstream, #676):
|
|
619
|
+
* the file must stay committed (the TypeScript language server discovers it
|
|
620
|
+
* directly from disk, no `--config` override mechanism to hand it a path
|
|
621
|
+
* instead), but its content is fully derivable, so it's generated rather
|
|
622
|
+
* than hand-authored — the same category as `.editorconfig`
|
|
623
|
+
* ({@link "./templates/configs/editorconfig/create-config.js" createConfig})
|
|
624
|
+
* and {@link codecovConfig}.
|
|
625
|
+
*
|
|
626
|
+
* Surveyed every package-level `tsconfig.json` across the org (`holocron`,
|
|
627
|
+
* `clients`, `utils` — 20+ packages). `extends: "@theholocron/tsconfig/
|
|
628
|
+
* node-lts"`, `compilerOptions.baseUrl: "./"`, `compilerOptions.outDir:
|
|
629
|
+
* "./dist"`, `include: ["src/**\/*.ts"]`, and `exclude: ["node_modules",
|
|
630
|
+
* "dist"]` are uniform in every one — safe defaults here. `paths` (a `@/*`
|
|
631
|
+
* → `./src/*` import alias) is a real per-package choice, present in
|
|
632
|
+
* roughly 40% of packages checked — an opt-in parameter, not a default.
|
|
633
|
+
*
|
|
634
|
+
* Two fields checked and deliberately *not* absorbed as defaults, unlike
|
|
635
|
+
* `eslint-config`'s `tsconfigRootDir`/`settings.node` (which turned out
|
|
636
|
+
* redundant with the shared package's own behavior, `configs`#461):
|
|
637
|
+
* `compilerOptions.module`/`moduleResolution` (only `@theholocron/cli`
|
|
638
|
+
* overrides these, to `esnext`/`bundler` — a genuine deviation from the
|
|
639
|
+
* shared `node-lts` preset's `nodenext`/`nodenext`, needed for its bundler
|
|
640
|
+
* tooling, not something every package should inherit) and
|
|
641
|
+
* `compilerOptions.rootDir` (present in exactly two packages, always the
|
|
642
|
+
* same value `./src` that `include` already implies — an unnecessary
|
|
643
|
+
* override wherever it appears, not a pattern worth generalizing).
|
|
644
|
+
*
|
|
645
|
+
* Monorepo *root* `tsconfig.json` (a TS project-references "solution
|
|
646
|
+
* file" — `holocron`'s own root is `{ files: [], references: [...] }`,
|
|
647
|
+
* listing which packages to build) is a structurally different, genuinely
|
|
648
|
+
* per-repo document — out of scope here, same as Bucket C content.
|
|
649
|
+
*
|
|
650
|
+
* Not yet wired into `holocron setup`'s per-package write loop (every
|
|
651
|
+
* other Bucket B file there is a single repo-root file, safely
|
|
652
|
+
* overwritten every run — `tsconfig.json` is per-package, and most
|
|
653
|
+
* packages' files still carry real hand-authored content today, not yet
|
|
654
|
+
* migrated to a fully-generated state). That per-package iteration +
|
|
655
|
+
* safe-migration design is `#680`'s job, not duplicated here — this is
|
|
656
|
+
* the generator itself, ready for it to call.
|
|
657
|
+
*/
|
|
658
|
+
interface TsconfigOptions {
|
|
659
|
+
/** Human-readable name for the `display` field — the package's own name is the usual choice. */
|
|
660
|
+
display: string;
|
|
661
|
+
/**
|
|
662
|
+
* `@theholocron/tsconfig` variant. Defaults to `"node-lts"` — every
|
|
663
|
+
* checked package uses it; the other three (`astro`, `nextjs`, `react`)
|
|
664
|
+
* exist for a template repo's app-shaped packages, not the plain
|
|
665
|
+
* Node.js library packages this org's currently-migrated repos ship.
|
|
666
|
+
*/
|
|
667
|
+
variant?: "astro" | "nextjs" | "node-lts" | "react";
|
|
668
|
+
/**
|
|
669
|
+
* Add a `@/*` → `./src/*` path alias. A real per-package choice, not a
|
|
670
|
+
* default — roughly 40% of packages checked use one, the rest don't.
|
|
671
|
+
*/
|
|
672
|
+
paths?: boolean;
|
|
673
|
+
}
|
|
674
|
+
/**
|
|
675
|
+
* A package-level `tsconfig.json` — the uniform shape confirmed across
|
|
676
|
+
* every package checked, parameterized only by the two fields that
|
|
677
|
+
* genuinely vary (`display`, `paths`). No scaffold/workflow header (matches
|
|
678
|
+
* `.alexrc.json`'s existing precedent for a strict-JSON Bucket B file —
|
|
679
|
+
* JSON has no comment syntax to carry one, and TypeScript's own tolerance
|
|
680
|
+
* for JSONC comments in `tsconfig.json` isn't worth relying on for a file
|
|
681
|
+
* this thin).
|
|
682
|
+
*/
|
|
683
|
+
declare function createTsconfig(options: TsconfigOptions): string;
|
|
684
|
+
//#endregion
|
|
685
|
+
export { type Astromech, type AstromechOptions, CI_ORDER, type CiJobReport, type CiOptions, type CiReport, type ExecFn, type JobDef, KNOWN_TASKS, KNOWN_WORKFLOWS, LINTERS, LINTER_NAMES, type LinterDef, type LocalRunner, type OrgContext, type PreviewConfig, RESOLVABLE_TOOLS, REUSABLE_ACTIONS, REUSABLE_WORKFLOWS, type ResolverDeps, type RunLogger, type RunOptions, type RunTaskInput, type RunTaskReport, TASKS, type TaskDef, type TsconfigOptions, WORKFLOW_CHECK_CONTEXTS, WORKFLOW_TEMPLATES, WORKFLOW_TEMPLATE_PROPERTIES, type WorkspacePackage, codecovComponentBlock, codecovConfig, createAstromech, createCodecovConfig, createTsconfig, deriveDeployPaths, ensureIfNotFound, extractPreviewConfig, generateCombinedDeployContent, generateThinCallerContent, mergeCodecovComponents, normalizeWorkflowWith, readWorkspacePackages, requiredChecks, resolveLinters, resolveToolConfig, reusableTemplates, runCi, runTask };
|
package/dist/index.mjs
CHANGED
|
@@ -327,6 +327,98 @@ function resolveLinters(opts) {
|
|
|
327
327
|
}));
|
|
328
328
|
}
|
|
329
329
|
//#endregion
|
|
330
|
+
//#region src/resolver.ts
|
|
331
|
+
/**
|
|
332
|
+
* `library` is every mapped tool's org-wide default variant today — every
|
|
333
|
+
* currently-migrated repo (`holocron`, `clients`, `utils`, `configs`,
|
|
334
|
+
* `themes`, `observability`, `skills`) is a publishable library package, and
|
|
335
|
+
* `eslint-config`/`vitest-config`/`tsdown-config` all name their
|
|
336
|
+
* general-purpose preset exactly that. Picking a different variant per repo
|
|
337
|
+
* (an app-type template, say) needs new `holocron.config.ts` surface this
|
|
338
|
+
* doesn't add yet — deliberately out of scope until a real consumer needs it.
|
|
339
|
+
*/
|
|
340
|
+
const TOOL_CONFIGS = {
|
|
341
|
+
eslint: {
|
|
342
|
+
package: "@theholocron/eslint-config",
|
|
343
|
+
exportPath: "./bundles/library",
|
|
344
|
+
flag: ["--config"]
|
|
345
|
+
},
|
|
346
|
+
prettier: {
|
|
347
|
+
package: "@theholocron/prettier-config",
|
|
348
|
+
exportPath: ".",
|
|
349
|
+
flag: ["--config"]
|
|
350
|
+
},
|
|
351
|
+
vitest: {
|
|
352
|
+
package: "@theholocron/vitest-config",
|
|
353
|
+
exportPath: "./bundles/library",
|
|
354
|
+
flag: ["--config"]
|
|
355
|
+
},
|
|
356
|
+
tsdown: {
|
|
357
|
+
package: "@theholocron/tsdown-config",
|
|
358
|
+
exportPath: "./presets/library",
|
|
359
|
+
flag: ["--config"]
|
|
360
|
+
},
|
|
361
|
+
commitlint: {
|
|
362
|
+
package: "@theholocron/commitlint-config",
|
|
363
|
+
exportPath: ".",
|
|
364
|
+
flag: ["--config"]
|
|
365
|
+
}
|
|
366
|
+
};
|
|
367
|
+
/** Every tool name the resolver knows how to point at a shared config. */
|
|
368
|
+
const RESOLVABLE_TOOLS = new Set(Object.keys(TOOL_CONFIGS));
|
|
369
|
+
/**
|
|
370
|
+
* `<flag> <absolute path>` for `tool`, resolved against `cwd`'s
|
|
371
|
+
* `node_modules` — or `[]` when the tool isn't mapped, the package isn't
|
|
372
|
+
* installed, its `package.json` doesn't declare the export subpath this
|
|
373
|
+
* needs, or the resolved file doesn't actually exist on disk (a stale
|
|
374
|
+
* install, or a package version that predates the export existing).
|
|
375
|
+
*/
|
|
376
|
+
function resolveToolConfig(tool, cwd, deps) {
|
|
377
|
+
const spec = TOOL_CONFIGS[tool];
|
|
378
|
+
if (!spec) return [];
|
|
379
|
+
const pkgDir = joinPath(cwd, "node_modules", ...spec.package.split("/"));
|
|
380
|
+
const pkgJsonPath = joinPath(pkgDir, "package.json");
|
|
381
|
+
if (!deps.fileExists(pkgJsonPath)) return [];
|
|
382
|
+
let pkg;
|
|
383
|
+
try {
|
|
384
|
+
pkg = JSON.parse(deps.readFile(pkgJsonPath));
|
|
385
|
+
} catch {
|
|
386
|
+
return [];
|
|
387
|
+
}
|
|
388
|
+
const relative = resolveExportEntry(pkg.exports?.[spec.exportPath]);
|
|
389
|
+
if (!relative) return [];
|
|
390
|
+
const absolute = joinPath(pkgDir, relative.replace(/^\.\//, ""));
|
|
391
|
+
if (!deps.fileExists(absolute)) return [];
|
|
392
|
+
return [...spec.flag, absolute];
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* Unwrap a `package.json#exports` subpath entry down to its file path —
|
|
396
|
+
* either a bare string, or an object with condition keys (`import`,
|
|
397
|
+
* `default`, `require`, …) that may themselves nest one level (`{ import: {
|
|
398
|
+
* types, default } }`, the shape every `@theholocron/*-config` package
|
|
399
|
+
* actually uses). Prefers `import` (this org ships ESM), then `default`,
|
|
400
|
+
* then `require` as a last resort.
|
|
401
|
+
*/
|
|
402
|
+
function resolveExportEntry(entry) {
|
|
403
|
+
if (typeof entry === "string") return entry;
|
|
404
|
+
if (entry === null || typeof entry !== "object") return void 0;
|
|
405
|
+
const conditions = entry;
|
|
406
|
+
const value = conditions.import ?? conditions.default ?? conditions.require;
|
|
407
|
+
if (typeof value === "string") return value;
|
|
408
|
+
if (typeof value === "object" && value !== null) return resolveExportEntry(value);
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* A minimal, POSIX-safe `path.join` — avoids importing `node:path` just for
|
|
412
|
+
* this. Every path in play here is either already POSIX (a `package.json`
|
|
413
|
+
* `exports` value, always forward-slashed regardless of platform) or built
|
|
414
|
+
* from platform-neutral segments (`cwd`, `"node_modules"`, a scoped package
|
|
415
|
+
* name split on `/`), so a manual join is safe and keeps this module
|
|
416
|
+
* dependency-free like the rest of `run.ts`'s helpers.
|
|
417
|
+
*/
|
|
418
|
+
function joinPath(...segments) {
|
|
419
|
+
return segments.map((s, i) => i === 0 ? s.replace(/\/+$/, "") : s.replace(/^\/+|\/+$/g, "")).filter(Boolean).join("/");
|
|
420
|
+
}
|
|
421
|
+
//#endregion
|
|
330
422
|
//#region src/run.ts
|
|
331
423
|
/**
|
|
332
424
|
* `holocron run <task> [job] [-- <passthrough>]` — run a registry task (or one
|
|
@@ -448,8 +540,13 @@ function runTask(input) {
|
|
|
448
540
|
const runner = resolveRunner(def.local, cwd, listDir);
|
|
449
541
|
if (runner) {
|
|
450
542
|
const flags = (def.flags?.[runner.tool] ?? []).filter((f) => !passthrough.includes(f));
|
|
543
|
+
const configFlags = resolveToolConfig(runner.tool, cwd, {
|
|
544
|
+
readFile,
|
|
545
|
+
fileExists
|
|
546
|
+
});
|
|
451
547
|
return run(resolveBin(cwd, runner.tool, fileExists), [
|
|
452
548
|
...runner.args,
|
|
549
|
+
...configFlags,
|
|
453
550
|
...flags,
|
|
454
551
|
...passthrough
|
|
455
552
|
]);
|
|
@@ -582,7 +679,7 @@ function runAllJobs(input, jobs, passthrough) {
|
|
|
582
679
|
* turbo/a package script would have already caught in steps 1–2.
|
|
583
680
|
*/
|
|
584
681
|
function runLinterGroup(input, names, passthrough) {
|
|
585
|
-
const { print, logger, listDir, lookPath, cwd, task } = input;
|
|
682
|
+
const { print, logger, listDir, lookPath, cwd, task, readFile, fileExists } = input;
|
|
586
683
|
const dryRun = input.dryRun ?? false;
|
|
587
684
|
const runOne = makeRunOne(input);
|
|
588
685
|
let rootFiles;
|
|
@@ -609,7 +706,15 @@ function runLinterGroup(input, names, passthrough) {
|
|
|
609
706
|
print(`! ${name} — ${bin} not on PATH${def.installHint ? `. ${def.installHint}` : ""} (enforced in CI)`);
|
|
610
707
|
continue;
|
|
611
708
|
}
|
|
612
|
-
|
|
709
|
+
const configFlags = resolveToolConfig(name, cwd, {
|
|
710
|
+
readFile,
|
|
711
|
+
fileExists
|
|
712
|
+
});
|
|
713
|
+
reports.push(runOne(found, [
|
|
714
|
+
...configFlags,
|
|
715
|
+
...def.localArgs ?? [],
|
|
716
|
+
...passthrough
|
|
717
|
+
]));
|
|
613
718
|
}
|
|
614
719
|
if (reports.length === 0) {
|
|
615
720
|
const required = input.required && anyHasLocalBin;
|
|
@@ -1445,4 +1550,31 @@ function createAstromech(options) {
|
|
|
1445
1550
|
};
|
|
1446
1551
|
}
|
|
1447
1552
|
//#endregion
|
|
1448
|
-
|
|
1553
|
+
//#region src/tsconfig.ts
|
|
1554
|
+
/**
|
|
1555
|
+
* A package-level `tsconfig.json` — the uniform shape confirmed across
|
|
1556
|
+
* every package checked, parameterized only by the two fields that
|
|
1557
|
+
* genuinely vary (`display`, `paths`). No scaffold/workflow header (matches
|
|
1558
|
+
* `.alexrc.json`'s existing precedent for a strict-JSON Bucket B file —
|
|
1559
|
+
* JSON has no comment syntax to carry one, and TypeScript's own tolerance
|
|
1560
|
+
* for JSONC comments in `tsconfig.json` isn't worth relying on for a file
|
|
1561
|
+
* this thin).
|
|
1562
|
+
*/
|
|
1563
|
+
function createTsconfig(options) {
|
|
1564
|
+
const variant = options.variant ?? "node-lts";
|
|
1565
|
+
const compilerOptions = {
|
|
1566
|
+
baseUrl: "./",
|
|
1567
|
+
outDir: "./dist"
|
|
1568
|
+
};
|
|
1569
|
+
if (options.paths) compilerOptions.paths = { "@/*": ["./src/*"] };
|
|
1570
|
+
const config = {
|
|
1571
|
+
display: options.display,
|
|
1572
|
+
extends: `@theholocron/tsconfig/${variant}`,
|
|
1573
|
+
compilerOptions,
|
|
1574
|
+
include: ["src/**/*.ts"],
|
|
1575
|
+
exclude: ["node_modules", "dist"]
|
|
1576
|
+
};
|
|
1577
|
+
return JSON.stringify(config, null, 2) + "\n";
|
|
1578
|
+
}
|
|
1579
|
+
//#endregion
|
|
1580
|
+
export { CI_ORDER, KNOWN_TASKS, KNOWN_WORKFLOWS, LINTERS, LINTER_NAMES, RESOLVABLE_TOOLS, REUSABLE_ACTIONS, REUSABLE_WORKFLOWS, TASKS, WORKFLOW_CHECK_CONTEXTS, WORKFLOW_TEMPLATES, WORKFLOW_TEMPLATE_PROPERTIES, codecovComponentBlock, codecovConfig, createAstromech, createCodecovConfig, createTsconfig, deriveDeployPaths, ensureIfNotFound, extractPreviewConfig, generateCombinedDeployContent, generateThinCallerContent, mergeCodecovComponents, normalizeWorkflowWith, readWorkspacePackages, requiredChecks, resolveLinters, resolveToolConfig, reusableTemplates, runCi, runTask };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@theholocron/astromech",
|
|
3
|
-
"version": "5.0.0-alpha.
|
|
3
|
+
"version": "5.0.0-alpha.8",
|
|
4
4
|
"description": "The Holocron task runner — one task manifest drives `holocron run`, `holocron ci`, the CI workflows, package.json scripts, linters, and required checks.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ci",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"dist"
|
|
38
38
|
],
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@theholocron/datapad": "5.0.0-alpha.
|
|
40
|
+
"@theholocron/datapad": "5.0.0-alpha.8"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@theholocron/eslint-config": "^8.0.0",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"tsdown": "^0.22.14",
|
|
54
54
|
"typescript": "^5.9.3",
|
|
55
55
|
"vitest": "^4.1.11",
|
|
56
|
-
"@theholocron/rollup-plugin-transform-template": "5.0.0-alpha.
|
|
56
|
+
"@theholocron/rollup-plugin-transform-template": "5.0.0-alpha.8"
|
|
57
57
|
},
|
|
58
58
|
"engines": {
|
|
59
59
|
"node": ">=22"
|