@ai-plugin-marketplace/core 0.1.0 → 0.3.0
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/config.d.ts +112 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +56 -0
- package/dist/config.js.map +1 -1
- package/dist/core.d.ts +187 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/pipeline/build.d.ts +159 -1
- package/dist/pipeline/build.d.ts.map +1 -1
- package/dist/pipeline/build.js +413 -9
- package/dist/pipeline/build.js.map +1 -1
- package/dist/pipeline/discover.d.ts +20 -13
- package/dist/pipeline/discover.d.ts.map +1 -1
- package/dist/pipeline/discover.js +53 -32
- package/dist/pipeline/discover.js.map +1 -1
- package/dist/pipeline/init-template.d.ts +16 -5
- package/dist/pipeline/init-template.d.ts.map +1 -1
- package/dist/pipeline/init-template.js +65 -21
- package/dist/pipeline/init-template.js.map +1 -1
- package/dist/pipeline/init.d.ts +17 -14
- package/dist/pipeline/init.d.ts.map +1 -1
- package/dist/pipeline/init.js +23 -15
- package/dist/pipeline/init.js.map +1 -1
- package/dist/pipeline/load-config.d.ts +62 -2
- package/dist/pipeline/load-config.d.ts.map +1 -1
- package/dist/pipeline/load-config.js +147 -30
- package/dist/pipeline/load-config.js.map +1 -1
- package/dist/pipeline/operations.d.ts +15 -3
- package/dist/pipeline/operations.d.ts.map +1 -1
- package/dist/pipeline/operations.js +25 -4
- package/dist/pipeline/operations.js.map +1 -1
- package/dist/pipeline/scaffold-refresh.d.ts +80 -0
- package/dist/pipeline/scaffold-refresh.d.ts.map +1 -0
- package/dist/pipeline/scaffold-refresh.js +152 -0
- package/dist/pipeline/scaffold-refresh.js.map +1 -0
- package/dist/pipeline/scaffold.d.ts.map +1 -1
- package/dist/pipeline/scaffold.js +55 -26
- package/dist/pipeline/scaffold.js.map +1 -1
- package/dist/pipeline/types.d.ts +51 -3
- package/dist/pipeline/types.d.ts.map +1 -1
- package/dist/pipeline/types.js +1 -0
- package/dist/pipeline/types.js.map +1 -1
- package/dist/pipeline/validate.d.ts +12 -2
- package/dist/pipeline/validate.d.ts.map +1 -1
- package/dist/pipeline/validate.js +342 -38
- package/dist/pipeline/validate.js.map +1 -1
- package/dist/targets/codex/scaffold.d.ts +31 -0
- package/dist/targets/codex/scaffold.d.ts.map +1 -0
- package/dist/targets/codex/scaffold.js +47 -0
- package/dist/targets/codex/scaffold.js.map +1 -0
- package/dist/targets/codex/schemas.d.ts +70 -0
- package/dist/targets/codex/schemas.d.ts.map +1 -0
- package/dist/targets/codex/schemas.js +153 -0
- package/dist/targets/codex/schemas.js.map +1 -0
- package/dist/targets/codex/validate.d.ts +25 -0
- package/dist/targets/codex/validate.d.ts.map +1 -0
- package/dist/targets/codex/validate.js +117 -0
- package/dist/targets/codex/validate.js.map +1 -0
- package/package.json +1 -1
|
@@ -1,70 +1,91 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Plugin discovery: resolve a `targetPath` (plugin dir or repo root) to the list of plugin
|
|
3
|
-
* directories to operate on plus the
|
|
3
|
+
* directories to operate on plus the dist output root. Shared by the build (§5.2) and
|
|
4
4
|
* validate (§5.3) orchestrators so they detect topology identically.
|
|
5
5
|
*
|
|
6
6
|
* Detection rules (§8.1 "Why one build signature"):
|
|
7
|
-
* - **Repo root** — `targetPath` contains
|
|
8
|
-
*
|
|
7
|
+
* - **Repo root** — `targetPath` contains the configured plugins root (default `plugins/`), or an
|
|
8
|
+
* `aipm.repo.ts`. Every immediate subdirectory of the plugins root that contains an
|
|
9
|
+
* `aipm.config.ts` is a plugin; generated bundles sit at the configured dist root
|
|
10
|
+
* (default `<root>/dist`).
|
|
9
11
|
* - **Single plugin** — otherwise `targetPath` is treated as a single plugin directory. The repo
|
|
10
|
-
* root is the plugin's grandparent (`repoRoot = dirname(dirname(pluginDir))`) and
|
|
11
|
-
*
|
|
12
|
-
* config loader so the validate orchestrator can report it as an
|
|
13
|
-
* (§10.1 step 1) and the build orchestrator can throw a descriptive
|
|
12
|
+
* root is the plugin's grandparent (`repoRoot = dirname(dirname(pluginDir))`) and the dist root
|
|
13
|
+
* is resolved from that repo root's config. A missing `aipm.config.ts` is **not** a discovery
|
|
14
|
+
* error: it is deferred to the config loader so the validate orchestrator can report it as an
|
|
15
|
+
* `envelope-invalid` finding (§10.1 step 1) and the build orchestrator can throw a descriptive
|
|
16
|
+
* error.
|
|
14
17
|
*
|
|
15
18
|
* Repo-root detection is tried first so a real repo root is never misread as a single plugin.
|
|
16
19
|
*
|
|
20
|
+
* The plugins root and dist root are read from an optional `aipm.repo.ts` at the repo root
|
|
21
|
+
* (embedded-marketplace support). Absent that file, they default to `plugins/` and `dist/`, so a
|
|
22
|
+
* repo with no repo config behaves exactly as before.
|
|
23
|
+
*
|
|
17
24
|
* @see docs/specs/architecture.md §8.1, §3.2 (repository topology), §10.1 (validation order)
|
|
18
25
|
*/
|
|
19
26
|
import * as fs from 'node:fs';
|
|
20
27
|
import * as path from 'node:path';
|
|
21
|
-
import { AIPM_CONFIG_FILENAME } from './load-config.js';
|
|
28
|
+
import { AIPM_CONFIG_FILENAME, hasRepoConfig, loadRepoConfig } from './load-config.js';
|
|
22
29
|
/** True iff `dir` contains an `aipm.config.ts`. */
|
|
23
30
|
function hasConfig(dir) {
|
|
24
31
|
return fs.existsSync(path.join(dir, AIPM_CONFIG_FILENAME));
|
|
25
32
|
}
|
|
33
|
+
/** True iff `dir` exists and is a directory. */
|
|
34
|
+
function isDirectory(dir) {
|
|
35
|
+
return fs.existsSync(dir) && fs.statSync(dir).isDirectory();
|
|
36
|
+
}
|
|
26
37
|
/**
|
|
27
|
-
* Resolve `targetPath` to the plugins to build/validate and the
|
|
38
|
+
* Resolve `targetPath` to the plugins to build/validate and the dist root.
|
|
28
39
|
*
|
|
29
40
|
* @param targetPath - Absolute path to a single plugin directory or a repo root.
|
|
30
41
|
* @returns The resolved discovery.
|
|
31
|
-
* @throws {Error} If `targetPath`
|
|
32
|
-
*
|
|
42
|
+
* @throws {Error} If `targetPath` does not exist.
|
|
43
|
+
* @throws {ConfigLoadError} If a present `aipm.repo.ts` cannot be imported or fails validation.
|
|
33
44
|
*/
|
|
34
|
-
export function discoverPlugins(targetPath) {
|
|
45
|
+
export async function discoverPlugins(targetPath) {
|
|
35
46
|
const resolved = path.resolve(targetPath);
|
|
36
47
|
if (!fs.existsSync(resolved)) {
|
|
37
48
|
throw new Error(`Path '${targetPath}' does not exist.`);
|
|
38
49
|
}
|
|
39
50
|
// ── Repo-root input (tried first) ─────────────────────────────────────────
|
|
40
|
-
// A path is a repo root when it does NOT itself carry a config but
|
|
41
|
-
//
|
|
42
|
-
// unlikely and would be a layout error; carrying
|
|
43
|
-
|
|
44
|
-
if (!hasConfig(resolved)
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
51
|
+
// A path is a repo root when it does NOT itself carry a plugin config but either declares an
|
|
52
|
+
// `aipm.repo.ts` or contains the configured plugins root. (A plugin directory that happens to
|
|
53
|
+
// contain a `plugins/` subfolder is vanishingly unlikely and would be a layout error; carrying
|
|
54
|
+
// its own `aipm.config.ts` disambiguates it as a plugin.)
|
|
55
|
+
if (!hasConfig(resolved)) {
|
|
56
|
+
const repoConfig = await loadRepoConfig(resolved);
|
|
57
|
+
const pluginsDir = path.join(resolved, repoConfig.pluginsRoot);
|
|
58
|
+
// An explicit `aipm.repo.ts` marks a repo root even before its plugins dir exists, so a
|
|
59
|
+
// freshly-initialised embedded repo still resolves as a repo root rather than a single plugin.
|
|
60
|
+
if (hasRepoConfig(resolved) || isDirectory(pluginsDir)) {
|
|
61
|
+
const pluginDirs = [];
|
|
62
|
+
if (isDirectory(pluginsDir)) {
|
|
63
|
+
for (const entry of fs.readdirSync(pluginsDir, { withFileTypes: true })) {
|
|
64
|
+
if (!entry.isDirectory())
|
|
65
|
+
continue;
|
|
66
|
+
const candidate = path.join(pluginsDir, entry.name);
|
|
67
|
+
if (hasConfig(candidate)) {
|
|
68
|
+
pluginDirs.push(candidate);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
pluginDirs.sort();
|
|
52
72
|
}
|
|
73
|
+
return {
|
|
74
|
+
repoRoot: resolved,
|
|
75
|
+
distDir: path.join(resolved, repoConfig.distDir),
|
|
76
|
+
pluginDirs,
|
|
77
|
+
};
|
|
53
78
|
}
|
|
54
|
-
pluginDirs.sort();
|
|
55
|
-
return {
|
|
56
|
-
repoRoot: resolved,
|
|
57
|
-
distDir: path.join(resolved, 'dist'),
|
|
58
|
-
pluginDirs,
|
|
59
|
-
};
|
|
60
79
|
}
|
|
61
80
|
// ── Single-plugin input ───────────────────────────────────────────────────
|
|
62
81
|
// Whether or not it carries a config: a missing config is deferred to the loader so validate
|
|
63
|
-
// can emit `envelope-invalid` and build can throw a descriptive error (§10.1 step 1).
|
|
82
|
+
// can emit `envelope-invalid` and build can throw a descriptive error (§10.1 step 1). The dist
|
|
83
|
+
// root is resolved from the repo root's config so a relocated dist root is still honored.
|
|
64
84
|
const grandparent = path.dirname(path.dirname(resolved));
|
|
85
|
+
const repoConfig = await loadRepoConfig(grandparent);
|
|
65
86
|
return {
|
|
66
87
|
repoRoot: grandparent,
|
|
67
|
-
distDir: path.join(grandparent,
|
|
88
|
+
distDir: path.join(grandparent, repoConfig.distDir),
|
|
68
89
|
pluginDirs: [resolved],
|
|
69
90
|
};
|
|
70
91
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discover.js","sourceRoot":"","sources":["../../src/pipeline/discover.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"discover.js","sourceRoot":"","sources":["../../src/pipeline/discover.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAYvF,mDAAmD;AACnD,SAAS,SAAS,CAAC,GAAW;IAC5B,OAAO,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,oBAAoB,CAAC,CAAC,CAAC;AAC7D,CAAC;AAED,gDAAgD;AAChD,SAAS,WAAW,CAAC,GAAW;IAC9B,OAAO,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;AAC9D,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,UAAkB;IACtD,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAE1C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,SAAS,UAAU,mBAAmB,CAAC,CAAC;IAC1D,CAAC;IAED,6EAA6E;IAC7E,6FAA6F;IAC7F,8FAA8F;IAC9F,+FAA+F;IAC/F,0DAA0D;IAC1D,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzB,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,QAAQ,CAAC,CAAC;QAClD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,WAAW,CAAC,CAAC;QAC/D,wFAAwF;QACxF,+FAA+F;QAC/F,IAAI,aAAa,CAAC,QAAQ,CAAC,IAAI,WAAW,CAAC,UAAU,CAAC,EAAE,CAAC;YACvD,MAAM,UAAU,GAAa,EAAE,CAAC;YAChC,IAAI,WAAW,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC5B,KAAK,MAAM,KAAK,IAAI,EAAE,CAAC,WAAW,CAAC,UAAU,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;oBACxE,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE;wBAAE,SAAS;oBACnC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;oBACpD,IAAI,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC;wBACzB,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;oBAC7B,CAAC;gBACH,CAAC;gBACD,UAAU,CAAC,IAAI,EAAE,CAAC;YACpB,CAAC;YACD,OAAO;gBACL,QAAQ,EAAE,QAAQ;gBAClB,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,OAAO,CAAC;gBAChD,UAAU;aACX,CAAC;QACJ,CAAC;IACH,CAAC;IAED,6EAA6E;IAC7E,6FAA6F;IAC7F,+FAA+F;IAC/F,0FAA0F;IAC1F,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;IACzD,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,WAAW,CAAC,CAAC;IACrD,OAAO;QACL,QAAQ,EAAE,WAAW;QACrB,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,OAAO,CAAC;QACnD,UAAU,EAAE,CAAC,QAAQ,CAAC;KACvB,CAAC;AACJ,CAAC"}
|
|
@@ -21,13 +21,24 @@ export interface InitFile {
|
|
|
21
21
|
/** Full file contents, including a trailing newline. */
|
|
22
22
|
content: string;
|
|
23
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* Toolkit-owned **scaffold** files that `aipm init --refresh` keeps in sync with the installed
|
|
26
|
+
* tooling: the CI workflow and `.gitignore`. These are pure tooling recipes — their content is
|
|
27
|
+
* independent of the repo name and the pinned toolkit version, so refresh can re-render them with
|
|
28
|
+
* no inputs and compare byte-for-byte. (Files with repo identity or user content — `package.json`,
|
|
29
|
+
* `aipm.workspace.ts`, `README.md`, plugins, `aipm build` output — are deliberately NOT here.)
|
|
30
|
+
*
|
|
31
|
+
* Output is deterministic and stably ordered.
|
|
32
|
+
*/
|
|
33
|
+
export declare function buildManagedScaffoldFiles(): InitFile[];
|
|
24
34
|
/**
|
|
25
35
|
* Build the complete, deterministic seed file set for a consumer repo named `name`, pinning the
|
|
26
|
-
*
|
|
36
|
+
* `cli`/`core` dev dependencies to carets of `cliVersion`/`coreVersion` respectively.
|
|
27
37
|
*
|
|
28
|
-
* The set mirrors §3.2: `package.json`,
|
|
29
|
-
*
|
|
30
|
-
*
|
|
38
|
+
* The set mirrors §3.2: `package.json`, the {@link buildManagedScaffoldFiles managed scaffold
|
|
39
|
+
* files} (`.gitignore`, CI workflow), `README.md`, both repo-root marketplace registries, and an
|
|
40
|
+
* empty `plugins/` (seeded with `.gitkeep` so the directory is tracked). Output is a pure function
|
|
41
|
+
* of the inputs — stable ordering, no timestamps.
|
|
31
42
|
*/
|
|
32
|
-
export declare function buildInitFiles(name: string,
|
|
43
|
+
export declare function buildInitFiles(name: string, cliVersion: string, coreVersion: string): InitFile[];
|
|
33
44
|
//# sourceMappingURL=init-template.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init-template.d.ts","sourceRoot":"","sources":["../../src/pipeline/init-template.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;
|
|
1
|
+
{"version":3,"file":"init-template.d.ts","sourceRoot":"","sources":["../../src/pipeline/init-template.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAaH,gGAAgG;AAChG,MAAM,WAAW,QAAQ;IACvB,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAC;IACb,wDAAwD;IACxD,OAAO,EAAE,MAAM,CAAC;CACjB;AAqID;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,IAAI,QAAQ,EAAE,CAKtD;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,QAAQ,EAAE,CAShG"}
|
|
@@ -17,33 +17,40 @@
|
|
|
17
17
|
const json = String.raw;
|
|
18
18
|
const md = String.raw;
|
|
19
19
|
const yaml = String.raw;
|
|
20
|
+
/**
|
|
21
|
+
* pnpm version pinned in the generated `package.json#packageManager`. The CI workflow reads the
|
|
22
|
+
* pnpm version from this field (it runs `pnpm/action-setup` without a hard-coded version), so the
|
|
23
|
+
* two stay in sync. Bumped deliberately when the recommended pnpm baseline moves.
|
|
24
|
+
*/
|
|
25
|
+
const PACKAGE_MANAGER = 'pnpm@10.30.3';
|
|
20
26
|
/**
|
|
21
27
|
* The `package.json` for a generated consumer repo.
|
|
22
28
|
*
|
|
23
29
|
* - `private: true` — a plugin repo is never published to npm; only its plugins ship to registries.
|
|
24
30
|
* - `type: 'module'` — the toolkit is ESM-only (§8.1), and `aipm.config.ts` files are ESM.
|
|
31
|
+
* - `packageManager` pins pnpm; the CI workflow reads the pnpm version from here.
|
|
25
32
|
* - `scripts` call `aipm` directly (it is on PATH via the dev dependency's bin).
|
|
26
|
-
* -
|
|
27
|
-
*
|
|
33
|
+
* - `cli` provides the `aipm` binary; `core` provides `defineConfig`/`defineWorkspace` for each
|
|
34
|
+
* plugin's `aipm.config.ts` (§6.1). They ship independently and may differ (`cli 0.1.1` ships
|
|
35
|
+
* with `core 0.2.0`), so each is pinned to a caret of its own version; authors upgrade both via
|
|
36
|
+
* `pnpm up` (§11 contract).
|
|
28
37
|
*
|
|
29
38
|
* Emitted as 2-space JSON with a trailing newline to match the repo's formatting conventions.
|
|
30
39
|
*/
|
|
31
|
-
function renderPackageJson(name,
|
|
40
|
+
function renderPackageJson(name, cliVersion, coreVersion) {
|
|
32
41
|
const pkg = {
|
|
33
42
|
name,
|
|
34
43
|
private: true,
|
|
35
44
|
type: 'module',
|
|
45
|
+
packageManager: PACKAGE_MANAGER,
|
|
36
46
|
scripts: {
|
|
37
47
|
build: 'aipm build',
|
|
38
48
|
check: 'aipm validate',
|
|
39
49
|
scaffold: 'aipm scaffold',
|
|
40
50
|
},
|
|
41
51
|
devDependencies: {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
// version and upgraded together via `pnpm up`.
|
|
45
|
-
'@ai-plugin-marketplace/cli': `^${toolkitVersion}`,
|
|
46
|
-
'@ai-plugin-marketplace/core': `^${toolkitVersion}`,
|
|
52
|
+
'@ai-plugin-marketplace/cli': `^${cliVersion}`,
|
|
53
|
+
'@ai-plugin-marketplace/core': `^${coreVersion}`,
|
|
47
54
|
},
|
|
48
55
|
};
|
|
49
56
|
return `${JSON.stringify(pkg, null, 2)}\n`;
|
|
@@ -95,21 +102,43 @@ function renderCiWorkflow() {
|
|
|
95
102
|
|
|
96
103
|
on:
|
|
97
104
|
push:
|
|
105
|
+
branches: [main]
|
|
98
106
|
pull_request:
|
|
107
|
+
branches: [main]
|
|
99
108
|
|
|
100
109
|
jobs:
|
|
101
|
-
|
|
110
|
+
CI:
|
|
102
111
|
runs-on: ubuntu-latest
|
|
112
|
+
env:
|
|
113
|
+
CI: "true"
|
|
103
114
|
steps:
|
|
104
115
|
- uses: actions/checkout@v4
|
|
116
|
+
|
|
105
117
|
- uses: pnpm/action-setup@v4
|
|
118
|
+
# version is read from package.json#packageManager — do not duplicate here
|
|
119
|
+
|
|
106
120
|
- uses: actions/setup-node@v4
|
|
107
121
|
with:
|
|
108
|
-
node-version:
|
|
122
|
+
node-version: 24
|
|
109
123
|
cache: pnpm
|
|
110
|
-
|
|
111
|
-
-
|
|
112
|
-
|
|
124
|
+
|
|
125
|
+
- name: Install dependencies
|
|
126
|
+
run: pnpm install --frozen-lockfile
|
|
127
|
+
|
|
128
|
+
- name: Build plugins
|
|
129
|
+
run: pnpm exec aipm build
|
|
130
|
+
|
|
131
|
+
- name: Verify the tree is clean after build (freshness)
|
|
132
|
+
run: |
|
|
133
|
+
if [ -n "$(git status --porcelain)" ]; then
|
|
134
|
+
echo "::error::Working tree is dirty after 'aipm build'. Run 'aipm build' locally and commit the regenerated artifacts."
|
|
135
|
+
git status --porcelain
|
|
136
|
+
git --no-pager diff
|
|
137
|
+
exit 1
|
|
138
|
+
fi
|
|
139
|
+
|
|
140
|
+
- name: Validate plugins
|
|
141
|
+
run: pnpm exec aipm validate
|
|
113
142
|
`;
|
|
114
143
|
}
|
|
115
144
|
/** `.gitignore` for a consumer repo: dependencies, build intermediates, OS/local cruft. */
|
|
@@ -121,22 +150,37 @@ function renderGitignore() {
|
|
|
121
150
|
`;
|
|
122
151
|
}
|
|
123
152
|
/**
|
|
124
|
-
*
|
|
125
|
-
*
|
|
153
|
+
* Toolkit-owned **scaffold** files that `aipm init --refresh` keeps in sync with the installed
|
|
154
|
+
* tooling: the CI workflow and `.gitignore`. These are pure tooling recipes — their content is
|
|
155
|
+
* independent of the repo name and the pinned toolkit version, so refresh can re-render them with
|
|
156
|
+
* no inputs and compare byte-for-byte. (Files with repo identity or user content — `package.json`,
|
|
157
|
+
* `aipm.workspace.ts`, `README.md`, plugins, `aipm build` output — are deliberately NOT here.)
|
|
126
158
|
*
|
|
127
|
-
*
|
|
128
|
-
* registries, an empty `plugins/` (seeded with `.gitkeep` so the directory is tracked), and the
|
|
129
|
-
* CI workflow. Output is a pure function of the two inputs — stable ordering, no timestamps.
|
|
159
|
+
* Output is deterministic and stably ordered.
|
|
130
160
|
*/
|
|
131
|
-
export function
|
|
161
|
+
export function buildManagedScaffoldFiles() {
|
|
132
162
|
return [
|
|
133
|
-
{ path: 'package.json', content: renderPackageJson(name, toolkitVersion) },
|
|
134
163
|
{ path: '.gitignore', content: renderGitignore() },
|
|
164
|
+
{ path: '.github/workflows/ci.yml', content: renderCiWorkflow() },
|
|
165
|
+
];
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Build the complete, deterministic seed file set for a consumer repo named `name`, pinning the
|
|
169
|
+
* `cli`/`core` dev dependencies to carets of `cliVersion`/`coreVersion` respectively.
|
|
170
|
+
*
|
|
171
|
+
* The set mirrors §3.2: `package.json`, the {@link buildManagedScaffoldFiles managed scaffold
|
|
172
|
+
* files} (`.gitignore`, CI workflow), `README.md`, both repo-root marketplace registries, and an
|
|
173
|
+
* empty `plugins/` (seeded with `.gitkeep` so the directory is tracked). Output is a pure function
|
|
174
|
+
* of the inputs — stable ordering, no timestamps.
|
|
175
|
+
*/
|
|
176
|
+
export function buildInitFiles(name, cliVersion, coreVersion) {
|
|
177
|
+
return [
|
|
178
|
+
{ path: 'package.json', content: renderPackageJson(name, cliVersion, coreVersion) },
|
|
135
179
|
{ path: 'README.md', content: renderReadme(name) },
|
|
136
180
|
{ path: '.claude-plugin/marketplace.json', content: renderEmptyMarketplace() },
|
|
137
181
|
{ path: '.cursor-plugin/marketplace.json', content: renderEmptyMarketplace() },
|
|
138
182
|
{ path: 'plugins/.gitkeep', content: '' },
|
|
139
|
-
|
|
183
|
+
...buildManagedScaffoldFiles(),
|
|
140
184
|
];
|
|
141
185
|
}
|
|
142
186
|
//# sourceMappingURL=init-template.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init-template.js","sourceRoot":"","sources":["../../src/pipeline/init-template.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC;AACxB,MAAM,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC;AACtB,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"init-template.js","sourceRoot":"","sources":["../../src/pipeline/init-template.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC;AACxB,MAAM,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC;AACtB,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC;AAExB;;;;GAIG;AACH,MAAM,eAAe,GAAG,cAAc,CAAC;AAUvC;;;;;;;;;;;;;GAaG;AACH,SAAS,iBAAiB,CAAC,IAAY,EAAE,UAAkB,EAAE,WAAmB;IAC9E,MAAM,GAAG,GAAG;QACV,IAAI;QACJ,OAAO,EAAE,IAAI;QACb,IAAI,EAAE,QAAQ;QACd,cAAc,EAAE,eAAe;QAC/B,OAAO,EAAE;YACP,KAAK,EAAE,YAAY;YACnB,KAAK,EAAE,eAAe;YACtB,QAAQ,EAAE,eAAe;SAC1B;QACD,eAAe,EAAE;YACf,4BAA4B,EAAE,IAAI,UAAU,EAAE;YAC9C,6BAA6B,EAAE,IAAI,WAAW,EAAE;SACjD;KACF,CAAC;IACF,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC;AAC7C,CAAC;AAED,+FAA+F;AAC/F,SAAS,sBAAsB;IAC7B,OAAO,IAAI,CAAA;;;CAGZ,CAAC;AACF,CAAC;AAED,2EAA2E;AAC3E,SAAS,YAAY,CAAC,IAAY;IAChC,OAAO,EAAE,CAAA,KAAK,IAAI;;;;;;;;;;;;;;;;;;;;;;;;CAwBnB,CAAC;AACF,CAAC;AAED;;;;;;GAMG;AACH,SAAS,gBAAgB;IACvB,OAAO,IAAI,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyCZ,CAAC;AACF,CAAC;AAED,2FAA2F;AAC3F,SAAS,eAAe;IACtB,OAAO;;;;CAIR,CAAC;AACF,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,yBAAyB;IACvC,OAAO;QACL,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,eAAe,EAAE,EAAE;QAClD,EAAE,IAAI,EAAE,0BAA0B,EAAE,OAAO,EAAE,gBAAgB,EAAE,EAAE;KAClE,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,UAAkB,EAAE,WAAmB;IAClF,OAAO;QACL,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,iBAAiB,CAAC,IAAI,EAAE,UAAU,EAAE,WAAW,CAAC,EAAE;QACnF,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,YAAY,CAAC,IAAI,CAAC,EAAE;QAClD,EAAE,IAAI,EAAE,iCAAiC,EAAE,OAAO,EAAE,sBAAsB,EAAE,EAAE;QAC9E,EAAE,IAAI,EAAE,iCAAiC,EAAE,OAAO,EAAE,sBAAsB,EAAE,EAAE;QAC9E,EAAE,IAAI,EAAE,kBAAkB,EAAE,OAAO,EAAE,EAAE,EAAE;QACzC,GAAG,yBAAyB,EAAE;KAC/B,CAAC;AACJ,CAAC"}
|
package/dist/pipeline/init.d.ts
CHANGED
|
@@ -4,35 +4,38 @@
|
|
|
4
4
|
*
|
|
5
5
|
* This is the filesystem-writing orchestrator behind the public `init` operation and the
|
|
6
6
|
* `aipm init [dir]` CLI surface. The generated file *contents* live in `init-template.ts`; this
|
|
7
|
-
* module is the I/O boundary: it resolves the
|
|
8
|
-
*
|
|
7
|
+
* module is the I/O boundary: it resolves the versions to pin, refuses to clobber a non-empty
|
|
8
|
+
* target, writes the seed tree, and seeds the `.aipm/scaffold.json` refresh sidecar.
|
|
9
9
|
*
|
|
10
|
-
* **Version pinning
|
|
11
|
-
*
|
|
12
|
-
* `
|
|
13
|
-
*
|
|
14
|
-
* the
|
|
10
|
+
* **Version pinning.** `cli` and `core` ship independently and may differ (e.g. `cli 0.1.1` ships
|
|
11
|
+
* with `core 0.2.0`), so the generated `package.json` pins each to a caret of its *own* version.
|
|
12
|
+
* `core`'s version is read at runtime from this package's `package.json` (resolved relative to
|
|
13
|
+
* {@link import.meta.url}, exactly as `load-config.ts` resolves the package entrypoint); `cli`'s
|
|
14
|
+
* version is supplied by the cli entrypoint via {@link InitOptions.cliVersion} (it reads its own
|
|
15
|
+
* `package.json`). When `cliVersion` is omitted, it falls back to core's version.
|
|
15
16
|
*
|
|
16
17
|
* @see docs/specs/architecture.md §3.2 (template repo contents)
|
|
17
|
-
* @see docs/specs/architecture.md §9.1 (lockstep release lines)
|
|
18
18
|
* @see docs/specs/architecture.md §11 (template→toolkit dependency contract)
|
|
19
|
+
* @see docs/specs/scaffold-refresh-and-upgrade.md (`aipm init --refresh`)
|
|
19
20
|
*/
|
|
20
21
|
import type { InitOptions } from './types.js';
|
|
21
22
|
/**
|
|
22
23
|
* Scaffold a thin consumer repo at `targetDir` (§3.2).
|
|
23
24
|
*
|
|
24
|
-
* Writes `package.json` (with
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* `aipm
|
|
28
|
-
* `
|
|
25
|
+
* Writes `package.json` (with `cli`/`core` dev dependencies pinned to carets of their respective
|
|
26
|
+
* versions), `.gitignore`, `README.md`, both repo-root marketplace registries (`{ "plugins": [] }`),
|
|
27
|
+
* an empty `plugins/` (tracked via `.gitkeep`), and a CI workflow that runs `aipm build` then
|
|
28
|
+
* `aipm validate` (§10.5 freshness). It also seeds `.aipm/scaffold.json` so a later
|
|
29
|
+
* `aipm init --refresh` can tell pristine toolkit-owned files from user edits. The repo name
|
|
30
|
+
* defaults to `basename(targetDir)`; override it with `opts.name`.
|
|
29
31
|
*
|
|
30
32
|
* **Refuses to clobber.** If `targetDir` exists and is a non-empty directory (or exists as a
|
|
31
33
|
* non-directory), the function throws and writes nothing. Creating into a fresh or empty directory
|
|
32
34
|
* is fine.
|
|
33
35
|
*
|
|
34
36
|
* @param targetDir - Absolute or relative path to the directory to scaffold into.
|
|
35
|
-
* @param opts - Init options; `name` overrides the derived repo name
|
|
37
|
+
* @param opts - Init options; `name` overrides the derived repo name, `cliVersion` the pinned cli
|
|
38
|
+
* dependency version (defaults to core's version).
|
|
36
39
|
* @throws {Error} When `targetDir` exists and is non-empty (or is not a directory).
|
|
37
40
|
*/
|
|
38
41
|
export declare function runInit(targetDir: string, opts?: InitOptions): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/pipeline/init.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/pipeline/init.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAQH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AA6B9C;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,GAAE,WAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CA0BtF"}
|
package/dist/pipeline/init.js
CHANGED
|
@@ -4,23 +4,25 @@
|
|
|
4
4
|
*
|
|
5
5
|
* This is the filesystem-writing orchestrator behind the public `init` operation and the
|
|
6
6
|
* `aipm init [dir]` CLI surface. The generated file *contents* live in `init-template.ts`; this
|
|
7
|
-
* module is the I/O boundary: it resolves the
|
|
8
|
-
*
|
|
7
|
+
* module is the I/O boundary: it resolves the versions to pin, refuses to clobber a non-empty
|
|
8
|
+
* target, writes the seed tree, and seeds the `.aipm/scaffold.json` refresh sidecar.
|
|
9
9
|
*
|
|
10
|
-
* **Version pinning
|
|
11
|
-
*
|
|
12
|
-
* `
|
|
13
|
-
*
|
|
14
|
-
* the
|
|
10
|
+
* **Version pinning.** `cli` and `core` ship independently and may differ (e.g. `cli 0.1.1` ships
|
|
11
|
+
* with `core 0.2.0`), so the generated `package.json` pins each to a caret of its *own* version.
|
|
12
|
+
* `core`'s version is read at runtime from this package's `package.json` (resolved relative to
|
|
13
|
+
* {@link import.meta.url}, exactly as `load-config.ts` resolves the package entrypoint); `cli`'s
|
|
14
|
+
* version is supplied by the cli entrypoint via {@link InitOptions.cliVersion} (it reads its own
|
|
15
|
+
* `package.json`). When `cliVersion` is omitted, it falls back to core's version.
|
|
15
16
|
*
|
|
16
17
|
* @see docs/specs/architecture.md §3.2 (template repo contents)
|
|
17
|
-
* @see docs/specs/architecture.md §9.1 (lockstep release lines)
|
|
18
18
|
* @see docs/specs/architecture.md §11 (template→toolkit dependency contract)
|
|
19
|
+
* @see docs/specs/scaffold-refresh-and-upgrade.md (`aipm init --refresh`)
|
|
19
20
|
*/
|
|
20
21
|
import * as fs from 'node:fs';
|
|
21
22
|
import * as path from 'node:path';
|
|
22
23
|
import { fileURLToPath } from 'node:url';
|
|
23
24
|
import { buildInitFiles } from './init-template.js';
|
|
25
|
+
import { writeScaffoldSidecar } from './scaffold-refresh.js';
|
|
24
26
|
/**
|
|
25
27
|
* Read this package's `package.json#version`, resolved relative to this module's location.
|
|
26
28
|
*
|
|
@@ -51,18 +53,20 @@ function isFreshTarget(dir) {
|
|
|
51
53
|
/**
|
|
52
54
|
* Scaffold a thin consumer repo at `targetDir` (§3.2).
|
|
53
55
|
*
|
|
54
|
-
* Writes `package.json` (with
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
* `aipm
|
|
58
|
-
* `
|
|
56
|
+
* Writes `package.json` (with `cli`/`core` dev dependencies pinned to carets of their respective
|
|
57
|
+
* versions), `.gitignore`, `README.md`, both repo-root marketplace registries (`{ "plugins": [] }`),
|
|
58
|
+
* an empty `plugins/` (tracked via `.gitkeep`), and a CI workflow that runs `aipm build` then
|
|
59
|
+
* `aipm validate` (§10.5 freshness). It also seeds `.aipm/scaffold.json` so a later
|
|
60
|
+
* `aipm init --refresh` can tell pristine toolkit-owned files from user edits. The repo name
|
|
61
|
+
* defaults to `basename(targetDir)`; override it with `opts.name`.
|
|
59
62
|
*
|
|
60
63
|
* **Refuses to clobber.** If `targetDir` exists and is a non-empty directory (or exists as a
|
|
61
64
|
* non-directory), the function throws and writes nothing. Creating into a fresh or empty directory
|
|
62
65
|
* is fine.
|
|
63
66
|
*
|
|
64
67
|
* @param targetDir - Absolute or relative path to the directory to scaffold into.
|
|
65
|
-
* @param opts - Init options; `name` overrides the derived repo name
|
|
68
|
+
* @param opts - Init options; `name` overrides the derived repo name, `cliVersion` the pinned cli
|
|
69
|
+
* dependency version (defaults to core's version).
|
|
66
70
|
* @throws {Error} When `targetDir` exists and is non-empty (or is not a directory).
|
|
67
71
|
*/
|
|
68
72
|
export async function runInit(targetDir, opts = {}) {
|
|
@@ -72,13 +76,17 @@ export async function runInit(targetDir, opts = {}) {
|
|
|
72
76
|
'Choose a new path or an empty directory.');
|
|
73
77
|
}
|
|
74
78
|
const name = opts.name ?? path.basename(resolved);
|
|
75
|
-
const
|
|
79
|
+
const core = coreVersion();
|
|
80
|
+
const cli = opts.cliVersion ?? core;
|
|
81
|
+
const files = buildInitFiles(name, cli, core);
|
|
76
82
|
fs.mkdirSync(resolved, { recursive: true });
|
|
77
83
|
for (const file of files) {
|
|
78
84
|
const full = path.join(resolved, file.path);
|
|
79
85
|
fs.mkdirSync(path.dirname(full), { recursive: true });
|
|
80
86
|
fs.writeFileSync(full, file.content, 'utf-8');
|
|
81
87
|
}
|
|
88
|
+
// Seed the refresh sidecar so `aipm init --refresh` has a baseline of toolkit-owned content.
|
|
89
|
+
writeScaffoldSidecar(resolved);
|
|
82
90
|
return Promise.resolve();
|
|
83
91
|
}
|
|
84
92
|
//# sourceMappingURL=init.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/pipeline/init.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/pipeline/init.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAG7D;;;;;;;GAOG;AACH,SAAS,WAAW;IAClB,MAAM,IAAI,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC5C,sFAAsF;IACtF,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;IAC1E,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAwB,CAAC;IACjF,OAAO,GAAG,CAAC,OAAO,CAAC;AACrB,CAAC;AAED;;;GAGG;AACH,SAAS,aAAa,CAAC,GAAW;IAChC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACrC,MAAM,IAAI,GAAG,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IAC9B,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE;QAAE,OAAO,KAAK,CAAC;IACtC,OAAO,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC;AAC1C,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,SAAiB,EAAE,OAAoB,EAAE;IACrE,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEzC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CACb,8BAA8B,QAAQ,oDAAoD;YACxF,0CAA0C,CAC7C,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAClD,MAAM,IAAI,GAAG,WAAW,EAAE,CAAC;IAC3B,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC;IACpC,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;IAE9C,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5C,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACtD,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAChD,CAAC;IAED,6FAA6F;IAC7F,oBAAoB,CAAC,QAAQ,CAAC,CAAC;IAE/B,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;AAC3B,CAAC"}
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* @see docs/specs/architecture.md §6.1 (envelope declaration), P6 (TypeScript end-to-end)
|
|
19
19
|
* @see docs/specs/architecture.md §5.2, §5.3 (build/validate consume the loaded envelope)
|
|
20
20
|
*/
|
|
21
|
-
import type { AipmConfig } from '../config.js';
|
|
21
|
+
import type { AipmConfig, AipmWorkspace } from '../config.js';
|
|
22
22
|
/** The canonical config filename every plugin must provide (§6.1). */
|
|
23
23
|
export declare const AIPM_CONFIG_FILENAME = "aipm.config.ts";
|
|
24
24
|
/**
|
|
@@ -31,6 +31,21 @@ export declare class ConfigLoadError extends Error {
|
|
|
31
31
|
cause?: unknown;
|
|
32
32
|
});
|
|
33
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* A per-invocation memo of loaded plugin configs, keyed by absolute plugin directory. Created
|
|
36
|
+
* fresh by an orchestrator (`runBuild`/`runValidate`) and threaded through the helpers it calls,
|
|
37
|
+
* so a single invocation transpiles each `aipm.config.ts` **once** instead of repeatedly (the
|
|
38
|
+
* build loop, registry collection, and post-build validate would otherwise each reload every
|
|
39
|
+
* config — an expensive jiti transpile with module/fs caching disabled).
|
|
40
|
+
*
|
|
41
|
+
* Intentionally **per-invocation, not a module-level cache**: configs are static within one CLI
|
|
42
|
+
* run but may change between runs (and tests overwrite-and-reload across invocations), so a
|
|
43
|
+
* longer-lived cache would risk serving stale parses. Each `createConfigCache()` lives only for
|
|
44
|
+
* the orchestrator call that created it.
|
|
45
|
+
*/
|
|
46
|
+
export type ConfigCache = Map<string, AipmConfig>;
|
|
47
|
+
/** Create an empty {@link ConfigCache} for a single orchestrator invocation. */
|
|
48
|
+
export declare function createConfigCache(): ConfigCache;
|
|
34
49
|
/**
|
|
35
50
|
* Load and validate a plugin's `aipm.config.ts`, returning the branded {@link AipmConfig}.
|
|
36
51
|
*
|
|
@@ -39,9 +54,54 @@ export declare class ConfigLoadError extends Error {
|
|
|
39
54
|
* `defineConfig` in their source (e.g. exported a plain object literal).
|
|
40
55
|
*
|
|
41
56
|
* @param pluginDir - Absolute path to the `plugins/<name>/` directory.
|
|
57
|
+
* @param cache - Optional per-invocation memo (see {@link ConfigCache}). When supplied, a config
|
|
58
|
+
* already loaded in this invocation is returned without re-transpiling.
|
|
42
59
|
* @returns The validated, branded config.
|
|
43
60
|
* @throws {ConfigLoadError} If the file is absent, fails to import, has no default export, or
|
|
44
61
|
* the default export fails schema validation.
|
|
45
62
|
*/
|
|
46
|
-
export declare function loadPluginConfig(pluginDir: string): Promise<AipmConfig>;
|
|
63
|
+
export declare function loadPluginConfig(pluginDir: string, cache?: ConfigCache): Promise<AipmConfig>;
|
|
64
|
+
/**
|
|
65
|
+
* Resolved repo-level configuration: the plugins/dist roots after defaults are applied. These are
|
|
66
|
+
* repo-root-relative directory names that {@link discoverPlugins} joins onto the repo root.
|
|
67
|
+
*/
|
|
68
|
+
export interface ResolvedRepoConfig {
|
|
69
|
+
/** Directory (relative to the repo root) holding plugin folders. Default: `'plugins'`. */
|
|
70
|
+
pluginsRoot: string;
|
|
71
|
+
/** Directory (relative to the repo root) for generated dist bundles. Default: `'dist'`. */
|
|
72
|
+
distDir: string;
|
|
73
|
+
}
|
|
74
|
+
/** The resolved config used when no `aipm.repo.ts` is present — i.e. the historical topology. */
|
|
75
|
+
export declare const DEFAULT_REPO_CONFIG: ResolvedRepoConfig;
|
|
76
|
+
/** True iff `repoRoot` contains an `aipm.repo.ts`. */
|
|
77
|
+
export declare function hasRepoConfig(repoRoot: string): boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Load the optional `aipm.repo.ts` at `repoRoot`, returning the resolved plugins/dist roots.
|
|
80
|
+
*
|
|
81
|
+
* When the file is **absent**, returns {@link DEFAULT_REPO_CONFIG} — so a repo with no repo
|
|
82
|
+
* config is byte-identical to the historical behavior. When **present**, the module's `default`
|
|
83
|
+
* export is re-validated through `defineRepoConfig` (applying defaults, rejecting absolute/`..`
|
|
84
|
+
* paths and unknown keys).
|
|
85
|
+
*
|
|
86
|
+
* @param repoRoot - Absolute path to the repo root.
|
|
87
|
+
* @returns The resolved repo config.
|
|
88
|
+
* @throws {ConfigLoadError} If the file exists but cannot be imported or fails validation.
|
|
89
|
+
*/
|
|
90
|
+
export declare function loadRepoConfig(repoRoot: string): Promise<ResolvedRepoConfig>;
|
|
91
|
+
/** True iff `repoRoot` contains an `aipm.workspace.ts` (i.e. registry generation is opted in). */
|
|
92
|
+
export declare function hasWorkspaceConfig(repoRoot: string): boolean;
|
|
93
|
+
/**
|
|
94
|
+
* Load the optional `aipm.workspace.ts` at `repoRoot`, returning the validated, branded
|
|
95
|
+
* {@link AipmWorkspace}.
|
|
96
|
+
*
|
|
97
|
+
* When the file is **absent**, returns `undefined` — the signal that this repo has NOT opted into
|
|
98
|
+
* registry generation (the toolkit then leaves the hand-authored registries alone). When
|
|
99
|
+
* **present**, the module's `default` export is re-validated through `defineWorkspace` so the
|
|
100
|
+
* result provably passed the canonical schema.
|
|
101
|
+
*
|
|
102
|
+
* @param repoRoot - Absolute path to the repo root.
|
|
103
|
+
* @returns The validated workspace config, or `undefined` when no `aipm.workspace.ts` exists.
|
|
104
|
+
* @throws {ConfigLoadError} If the file exists but cannot be imported or fails validation.
|
|
105
|
+
*/
|
|
106
|
+
export declare function loadWorkspaceConfig(repoRoot: string): Promise<AipmWorkspace | undefined>;
|
|
47
107
|
//# sourceMappingURL=load-config.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"load-config.d.ts","sourceRoot":"","sources":["../../src/pipeline/load-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AASH,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"load-config.d.ts","sourceRoot":"","sources":["../../src/pipeline/load-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AASH,OAAO,KAAK,EACV,UAAU,EAGV,aAAa,EAEd,MAAM,cAAc,CAAC;AAEtB,sEAAsE;AACtE,eAAO,MAAM,oBAAoB,mBAAmB,CAAC;AAoBrD;;;;GAIG;AACH,qBAAa,eAAgB,SAAQ,KAAK;gBAC5B,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE;CAI3D;AAuED;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,WAAW,GAAG,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AAElD,gFAAgF;AAChF,wBAAgB,iBAAiB,IAAI,WAAW,CAE/C;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,MAAM,EACjB,KAAK,CAAC,EAAE,WAAW,GAClB,OAAO,CAAC,UAAU,CAAC,CAyBrB;AAED;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,0FAA0F;IAC1F,WAAW,EAAE,MAAM,CAAC;IACpB,2FAA2F;IAC3F,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,iGAAiG;AACjG,eAAO,MAAM,mBAAmB,EAAE,kBAAgE,CAAC;AAEnG,sDAAsD;AACtD,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAelF;AAED,kGAAkG;AAClG,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAE5D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC,CAgB9F"}
|