@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
|
@@ -22,9 +22,22 @@ import * as fs from 'node:fs';
|
|
|
22
22
|
import * as path from 'node:path';
|
|
23
23
|
import { fileURLToPath } from 'node:url';
|
|
24
24
|
import { createJiti } from 'jiti';
|
|
25
|
-
import { defineConfig } from '../config.js';
|
|
25
|
+
import { defineConfig, defineRepoConfig, defineWorkspace } from '../config.js';
|
|
26
26
|
/** The canonical config filename every plugin must provide (§6.1). */
|
|
27
27
|
export const AIPM_CONFIG_FILENAME = 'aipm.config.ts';
|
|
28
|
+
/**
|
|
29
|
+
* Optional repo-level config filename. When present at a repo root it relocates the plugins/dist
|
|
30
|
+
* roots (embedded-marketplace support); when absent the toolkit uses the historical defaults.
|
|
31
|
+
* Module-private — callers use {@link hasRepoConfig}/{@link loadRepoConfig} rather than the name.
|
|
32
|
+
*/
|
|
33
|
+
const AIPM_REPO_CONFIG_FILENAME = 'aipm.repo.ts';
|
|
34
|
+
/**
|
|
35
|
+
* Optional workspace-level config filename. Its presence at a repo root opts the repo into
|
|
36
|
+
* marketplace-registry generation; absence preserves the historical hand-authored-registry
|
|
37
|
+
* behavior. Module-private — callers use {@link hasWorkspaceConfig}/{@link loadWorkspaceConfig}
|
|
38
|
+
* rather than the name (mirrors {@link AIPM_REPO_CONFIG_FILENAME}).
|
|
39
|
+
*/
|
|
40
|
+
const AIPM_WORKSPACE_CONFIG_FILENAME = 'aipm.workspace.ts';
|
|
28
41
|
/** The npm specifier a plugin's `aipm.config.ts` imports `defineConfig` from. */
|
|
29
42
|
const CORE_PACKAGE_SPECIFIER = '@ai-plugin-marketplace/core';
|
|
30
43
|
/**
|
|
@@ -39,45 +52,53 @@ export class ConfigLoadError extends Error {
|
|
|
39
52
|
}
|
|
40
53
|
}
|
|
41
54
|
/**
|
|
42
|
-
* Absolute path
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
55
|
+
* Absolute path (extension-less) that the config-file `import '@ai-plugin-marketplace/core'`
|
|
56
|
+
* specifier is aliased to when jiti loads a config. Resolves to `<src|dist>/config`, derived from
|
|
57
|
+
* this module's location; jiti's resolver appends `.ts` from source (vitest) or `.js` from the
|
|
58
|
+
* compiled `dist/` (production).
|
|
59
|
+
*
|
|
60
|
+
* **Why `config`, not `index`.** Config files only import the `define*` functions, which all live
|
|
61
|
+
* in `config.ts` (whose only deps are `zod` + the tiny `types.ts`). Aliasing to the package
|
|
62
|
+
* `index` would instead drag the *entire* source graph — `operations` → `build`/`validate` →
|
|
63
|
+
* all six target modules + `yaml` — through jiti's on-the-fly transpiler on **every** config load.
|
|
64
|
+
* With one fresh jiti instance per load, that meant re-transpiling the whole package hundreds of
|
|
65
|
+
* times across the test suite, blocking the vitest worker long enough to trip its `onTaskUpdate`
|
|
66
|
+
* RPC timeout intermittently on slow CI. Pointing the alias at the minimal `config` module keeps
|
|
67
|
+
* each load's transpile graph tiny. (Production is unaffected either way — `dist/*.js` is already
|
|
68
|
+
* compiled, so jiti loads it without transpiling.)
|
|
46
69
|
*/
|
|
47
|
-
function
|
|
70
|
+
function coreConfigEntrypoint() {
|
|
48
71
|
const here = fileURLToPath(import.meta.url);
|
|
49
|
-
// here = <pkgRoot>/<src|dist>/pipeline/load-config.<ts|js>;
|
|
50
|
-
return path.join(path.dirname(here), '..', '
|
|
72
|
+
// here = <pkgRoot>/<src|dist>/pipeline/load-config.<ts|js>; config.ts sits two levels up.
|
|
73
|
+
return path.join(path.dirname(here), '..', 'config');
|
|
51
74
|
}
|
|
52
75
|
/** Absolute path to a plugin's `aipm.config.ts`, given the plugin directory. */
|
|
53
76
|
function configPathFor(pluginDir) {
|
|
54
77
|
return path.join(pluginDir, AIPM_CONFIG_FILENAME);
|
|
55
78
|
}
|
|
56
79
|
/**
|
|
57
|
-
*
|
|
80
|
+
* Transpile-import a config module's `default` export via jiti, with the core package specifier
|
|
81
|
+
* aliased to this package's entrypoint (so a bare `import '@ai-plugin-marketplace/core'` resolves
|
|
82
|
+
* regardless of where the config file lives). Shared by {@link loadPluginConfig} and
|
|
83
|
+
* {@link loadRepoConfig}.
|
|
58
84
|
*
|
|
59
|
-
*
|
|
60
|
-
* receive a value that provably passed the canonical Zod schema — even if the author bypassed
|
|
61
|
-
* `defineConfig` in their source (e.g. exported a plain object literal).
|
|
62
|
-
*
|
|
63
|
-
* @param pluginDir - Absolute path to the `plugins/<name>/` directory.
|
|
64
|
-
* @returns The validated, branded config.
|
|
65
|
-
* @throws {ConfigLoadError} If the file is absent, fails to import, has no default export, or
|
|
66
|
-
* the default export fails schema validation.
|
|
85
|
+
* @throws {ConfigLoadError} If the module fails to import or has no usable default export.
|
|
67
86
|
*/
|
|
68
|
-
|
|
69
|
-
const configPath = configPathFor(pluginDir);
|
|
70
|
-
if (!fs.existsSync(configPath)) {
|
|
71
|
-
throw new ConfigLoadError(`No ${AIPM_CONFIG_FILENAME} found in ${pluginDir}. Every plugin must declare a support envelope (spec §6.1).`);
|
|
72
|
-
}
|
|
87
|
+
async function importDefaultExport(configPath, filename) {
|
|
73
88
|
const jiti = createJiti(import.meta.url, {
|
|
74
|
-
alias: { [CORE_PACKAGE_SPECIFIER]:
|
|
89
|
+
alias: { [CORE_PACKAGE_SPECIFIER]: coreConfigEntrypoint() },
|
|
75
90
|
// Disable the default↔namespace interop so a config with no `default` export reads as a
|
|
76
91
|
// genuinely-absent default rather than jiti synthesizing one from the namespace.
|
|
77
92
|
interopDefault: false,
|
|
78
|
-
//
|
|
93
|
+
// `moduleCache: false` so a config rewritten in-process (tests, freshness re-reads) is
|
|
94
|
+
// re-evaluated rather than served stale from jiti's in-memory, path-keyed module cache.
|
|
79
95
|
moduleCache: false,
|
|
80
|
-
fsCache:
|
|
96
|
+
// `fsCache: true` (jiti's default) caches the expensive *transpile* on disk, keyed by a hash
|
|
97
|
+
// of the source — so it is correctness-safe across rewrites (changed content → new key →
|
|
98
|
+
// recompile) while letting the many identical config loads in one run skip re-transpiling.
|
|
99
|
+
// This is the dominant per-load cost; caching it keeps the (jiti-heavy) test suite from
|
|
100
|
+
// pegging a worker long enough to trip vitest's birpc heartbeat ("Timeout calling onTaskUpdate").
|
|
101
|
+
fsCache: true,
|
|
81
102
|
});
|
|
82
103
|
let mod;
|
|
83
104
|
try {
|
|
@@ -85,22 +106,118 @@ export async function loadPluginConfig(pluginDir) {
|
|
|
85
106
|
}
|
|
86
107
|
catch (err) {
|
|
87
108
|
const message = err instanceof Error ? err.message : String(err);
|
|
88
|
-
throw new ConfigLoadError(`Failed to import ${
|
|
89
|
-
cause: err,
|
|
90
|
-
});
|
|
109
|
+
throw new ConfigLoadError(`Failed to import ${filename}: ${message}`, { cause: err });
|
|
91
110
|
}
|
|
92
111
|
const defaultExport = mod['default'];
|
|
93
112
|
if (defaultExport === undefined || defaultExport === null) {
|
|
94
|
-
throw new ConfigLoadError(`${
|
|
113
|
+
throw new ConfigLoadError(`${filename} at ${configPath} has no default export. Export the result of the matching \`define*({...})\` call as default.`);
|
|
114
|
+
}
|
|
115
|
+
return defaultExport;
|
|
116
|
+
}
|
|
117
|
+
/** Create an empty {@link ConfigCache} for a single orchestrator invocation. */
|
|
118
|
+
export function createConfigCache() {
|
|
119
|
+
return new Map();
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Load and validate a plugin's `aipm.config.ts`, returning the branded {@link AipmConfig}.
|
|
123
|
+
*
|
|
124
|
+
* The on-disk module's `default` export is re-validated through {@link defineConfig} so callers
|
|
125
|
+
* receive a value that provably passed the canonical Zod schema — even if the author bypassed
|
|
126
|
+
* `defineConfig` in their source (e.g. exported a plain object literal).
|
|
127
|
+
*
|
|
128
|
+
* @param pluginDir - Absolute path to the `plugins/<name>/` directory.
|
|
129
|
+
* @param cache - Optional per-invocation memo (see {@link ConfigCache}). When supplied, a config
|
|
130
|
+
* already loaded in this invocation is returned without re-transpiling.
|
|
131
|
+
* @returns The validated, branded config.
|
|
132
|
+
* @throws {ConfigLoadError} If the file is absent, fails to import, has no default export, or
|
|
133
|
+
* the default export fails schema validation.
|
|
134
|
+
*/
|
|
135
|
+
export async function loadPluginConfig(pluginDir, cache) {
|
|
136
|
+
const cached = cache?.get(pluginDir);
|
|
137
|
+
if (cached !== undefined)
|
|
138
|
+
return cached;
|
|
139
|
+
const configPath = configPathFor(pluginDir);
|
|
140
|
+
if (!fs.existsSync(configPath)) {
|
|
141
|
+
throw new ConfigLoadError(`No ${AIPM_CONFIG_FILENAME} found in ${pluginDir}. Every plugin must declare a support envelope (spec §6.1).`);
|
|
95
142
|
}
|
|
143
|
+
const defaultExport = await importDefaultExport(configPath, AIPM_CONFIG_FILENAME);
|
|
96
144
|
// Re-validate through defineConfig so the result is a branded AipmConfig. defineConfig throws
|
|
97
145
|
// a ZodError on malformed input; wrap it so callers get a single ConfigLoadError type.
|
|
146
|
+
let config;
|
|
98
147
|
try {
|
|
99
|
-
|
|
148
|
+
config = defineConfig(defaultExport);
|
|
100
149
|
}
|
|
101
150
|
catch (err) {
|
|
102
151
|
const message = err instanceof Error ? err.message : String(err);
|
|
103
152
|
throw new ConfigLoadError(`Invalid ${AIPM_CONFIG_FILENAME}: ${message}`, { cause: err });
|
|
104
153
|
}
|
|
154
|
+
cache?.set(pluginDir, config);
|
|
155
|
+
return config;
|
|
156
|
+
}
|
|
157
|
+
/** The resolved config used when no `aipm.repo.ts` is present — i.e. the historical topology. */
|
|
158
|
+
export const DEFAULT_REPO_CONFIG = { pluginsRoot: 'plugins', distDir: 'dist' };
|
|
159
|
+
/** True iff `repoRoot` contains an `aipm.repo.ts`. */
|
|
160
|
+
export function hasRepoConfig(repoRoot) {
|
|
161
|
+
return fs.existsSync(path.join(repoRoot, AIPM_REPO_CONFIG_FILENAME));
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Load the optional `aipm.repo.ts` at `repoRoot`, returning the resolved plugins/dist roots.
|
|
165
|
+
*
|
|
166
|
+
* When the file is **absent**, returns {@link DEFAULT_REPO_CONFIG} — so a repo with no repo
|
|
167
|
+
* config is byte-identical to the historical behavior. When **present**, the module's `default`
|
|
168
|
+
* export is re-validated through `defineRepoConfig` (applying defaults, rejecting absolute/`..`
|
|
169
|
+
* paths and unknown keys).
|
|
170
|
+
*
|
|
171
|
+
* @param repoRoot - Absolute path to the repo root.
|
|
172
|
+
* @returns The resolved repo config.
|
|
173
|
+
* @throws {ConfigLoadError} If the file exists but cannot be imported or fails validation.
|
|
174
|
+
*/
|
|
175
|
+
export async function loadRepoConfig(repoRoot) {
|
|
176
|
+
const configPath = path.join(repoRoot, AIPM_REPO_CONFIG_FILENAME);
|
|
177
|
+
if (!fs.existsSync(configPath)) {
|
|
178
|
+
return { ...DEFAULT_REPO_CONFIG };
|
|
179
|
+
}
|
|
180
|
+
const defaultExport = await importDefaultExport(configPath, AIPM_REPO_CONFIG_FILENAME);
|
|
181
|
+
try {
|
|
182
|
+
const config = defineRepoConfig(defaultExport);
|
|
183
|
+
return { pluginsRoot: config.pluginsRoot, distDir: config.distDir };
|
|
184
|
+
}
|
|
185
|
+
catch (err) {
|
|
186
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
187
|
+
throw new ConfigLoadError(`Invalid ${AIPM_REPO_CONFIG_FILENAME}: ${message}`, { cause: err });
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
/** True iff `repoRoot` contains an `aipm.workspace.ts` (i.e. registry generation is opted in). */
|
|
191
|
+
export function hasWorkspaceConfig(repoRoot) {
|
|
192
|
+
return fs.existsSync(path.join(repoRoot, AIPM_WORKSPACE_CONFIG_FILENAME));
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Load the optional `aipm.workspace.ts` at `repoRoot`, returning the validated, branded
|
|
196
|
+
* {@link AipmWorkspace}.
|
|
197
|
+
*
|
|
198
|
+
* When the file is **absent**, returns `undefined` — the signal that this repo has NOT opted into
|
|
199
|
+
* registry generation (the toolkit then leaves the hand-authored registries alone). When
|
|
200
|
+
* **present**, the module's `default` export is re-validated through `defineWorkspace` so the
|
|
201
|
+
* result provably passed the canonical schema.
|
|
202
|
+
*
|
|
203
|
+
* @param repoRoot - Absolute path to the repo root.
|
|
204
|
+
* @returns The validated workspace config, or `undefined` when no `aipm.workspace.ts` exists.
|
|
205
|
+
* @throws {ConfigLoadError} If the file exists but cannot be imported or fails validation.
|
|
206
|
+
*/
|
|
207
|
+
export async function loadWorkspaceConfig(repoRoot) {
|
|
208
|
+
const configPath = path.join(repoRoot, AIPM_WORKSPACE_CONFIG_FILENAME);
|
|
209
|
+
if (!fs.existsSync(configPath)) {
|
|
210
|
+
return undefined;
|
|
211
|
+
}
|
|
212
|
+
const defaultExport = await importDefaultExport(configPath, AIPM_WORKSPACE_CONFIG_FILENAME);
|
|
213
|
+
try {
|
|
214
|
+
return defineWorkspace(defaultExport);
|
|
215
|
+
}
|
|
216
|
+
catch (err) {
|
|
217
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
218
|
+
throw new ConfigLoadError(`Invalid ${AIPM_WORKSPACE_CONFIG_FILENAME}: ${message}`, {
|
|
219
|
+
cause: err,
|
|
220
|
+
});
|
|
221
|
+
}
|
|
105
222
|
}
|
|
106
223
|
//# sourceMappingURL=load-config.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"load-config.js","sourceRoot":"","sources":["../../src/pipeline/load-config.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,UAAU,EAAE,MAAM,MAAM,CAAC;AAElC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"load-config.js","sourceRoot":"","sources":["../../src/pipeline/load-config.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
*
|
|
10
10
|
* @see docs/specs/architecture.md §8.1
|
|
11
11
|
*/
|
|
12
|
-
import type { BuildOptions, BuildResult, InitOptions, MigrateOptions, MigrateResult, ScaffoldOptions, SupportReport, TargetId, ValidateOptions, ValidationResult } from './types.js';
|
|
12
|
+
import type { BuildOptions, BuildResult, InitOptions, MigrateOptions, MigrateResult, RefreshOptions, RefreshOutcome, ScaffoldOptions, SupportReport, TargetId, ValidateOptions, ValidationResult } from './types.js';
|
|
13
13
|
/**
|
|
14
14
|
* Build a single plugin or every plugin under a repo root. `path` may be a plugin directory
|
|
15
15
|
* (contains `aipm.config.ts`) or a repo root (contains `plugins/`); the orchestrator detects
|
|
@@ -35,8 +35,20 @@ export declare function validate(targetPath: string, opts?: ValidateOptions): Pr
|
|
|
35
35
|
*/
|
|
36
36
|
export declare function init(targetDir: string, opts?: InitOptions): Promise<void>;
|
|
37
37
|
/**
|
|
38
|
-
*
|
|
39
|
-
*
|
|
38
|
+
* Refresh the toolkit-owned scaffold files (CI workflow, `.gitignore`) of an existing marketplace
|
|
39
|
+
* repo at `targetDir` to match the installed tooling — the upgrade path after
|
|
40
|
+
* `pnpm up @ai-plugin-marketplace/*`. Guarded by the `.aipm/scaffold.json` content-hash sidecar:
|
|
41
|
+
* user-modified files are reported as conflicts and left untouched unless `opts.force` is set.
|
|
42
|
+
* Returns one outcome per managed file; never rejects on conflict.
|
|
43
|
+
*
|
|
44
|
+
* @public
|
|
45
|
+
*/
|
|
46
|
+
export declare function refreshScaffold(targetDir: string, opts?: RefreshOptions): Promise<RefreshOutcome[]>;
|
|
47
|
+
/**
|
|
48
|
+
* Scaffold a new plugin under the cwd's configured plugins root (`<cwd>/plugins/<name>` by
|
|
49
|
+
* default, or the relocated `pluginsRoot` from an `aipm.repo.ts`). The plugins directory is
|
|
50
|
+
* derived from the current working directory, matching how `aipm scaffold` is invoked from a repo
|
|
51
|
+
* root.
|
|
40
52
|
*
|
|
41
53
|
* @public
|
|
42
54
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"operations.d.ts","sourceRoot":"","sources":["../../src/pipeline/operations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;
|
|
1
|
+
{"version":3,"file":"operations.d.ts","sourceRoot":"","sources":["../../src/pipeline/operations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAWH,OAAO,KAAK,EACV,YAAY,EACZ,WAAW,EACX,WAAW,EACX,cAAc,EACd,aAAa,EACb,cAAc,EACd,cAAc,EACd,eAAe,EACf,aAAa,EACb,QAAQ,EACR,eAAe,EACf,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAOpB;;;;;;GAMG;AACH,wBAAgB,KAAK,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAErF;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAE9F;AAED;;;;;;;GAOG;AACH,wBAAgB,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAEzE;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,cAAc,GACpB,OAAO,CAAC,cAAc,EAAE,CAAC,CAK3B;AAED;;;;;;;GAOG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,eAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAKtF;AAED;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CAMrF;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAEtE;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAE5E;AAED;;;;GAIG;AACH,wBAAgB,WAAW,IAAI,SAAS,QAAQ,EAAE,CAEjD"}
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
import * as path from 'node:path';
|
|
13
13
|
import { runBuild } from './build.js';
|
|
14
14
|
import { runInit } from './init.js';
|
|
15
|
+
import { loadRepoConfig } from './load-config.js';
|
|
16
|
+
import { runRefreshScaffold } from './scaffold-refresh.js';
|
|
15
17
|
import { runScaffold, runAddTarget, runCheckSupport } from './scaffold.js';
|
|
16
18
|
import { TARGET_IDS } from './types.js';
|
|
17
19
|
import { runValidate } from './validate.js';
|
|
@@ -50,13 +52,32 @@ export function init(targetDir, opts) {
|
|
|
50
52
|
return runInit(targetDir, opts);
|
|
51
53
|
}
|
|
52
54
|
/**
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
+
* Refresh the toolkit-owned scaffold files (CI workflow, `.gitignore`) of an existing marketplace
|
|
56
|
+
* repo at `targetDir` to match the installed tooling — the upgrade path after
|
|
57
|
+
* `pnpm up @ai-plugin-marketplace/*`. Guarded by the `.aipm/scaffold.json` content-hash sidecar:
|
|
58
|
+
* user-modified files are reported as conflicts and left untouched unless `opts.force` is set.
|
|
59
|
+
* Returns one outcome per managed file; never rejects on conflict.
|
|
55
60
|
*
|
|
56
61
|
* @public
|
|
57
62
|
*/
|
|
58
|
-
export function
|
|
59
|
-
|
|
63
|
+
export function refreshScaffold(targetDir, opts) {
|
|
64
|
+
// Defer into the microtask queue so a synchronous failure in the orchestrator (e.g. an I/O error)
|
|
65
|
+
// surfaces as a rejected promise — matching `refreshScaffold(...).catch(...)` expectations —
|
|
66
|
+
// rather than throwing from this call before the promise exists.
|
|
67
|
+
return Promise.resolve().then(() => runRefreshScaffold(targetDir, opts));
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Scaffold a new plugin under the cwd's configured plugins root (`<cwd>/plugins/<name>` by
|
|
71
|
+
* default, or the relocated `pluginsRoot` from an `aipm.repo.ts`). The plugins directory is
|
|
72
|
+
* derived from the current working directory, matching how `aipm scaffold` is invoked from a repo
|
|
73
|
+
* root.
|
|
74
|
+
*
|
|
75
|
+
* @public
|
|
76
|
+
*/
|
|
77
|
+
export async function scaffold(name, opts = {}) {
|
|
78
|
+
const cwd = process.cwd();
|
|
79
|
+
const repoConfig = await loadRepoConfig(cwd);
|
|
80
|
+
const pluginsDir = path.join(cwd, repoConfig.pluginsRoot);
|
|
60
81
|
return runScaffold(name, pluginsDir, opts);
|
|
61
82
|
}
|
|
62
83
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"operations.js","sourceRoot":"","sources":["../../src/pipeline/operations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAC3E,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"operations.js","sourceRoot":"","sources":["../../src/pipeline/operations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAC3E,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAgB5C,sGAAsG;AACtG,SAAS,IAAI;IACX,OAAO,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;AACpC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,KAAK,CAAC,UAAkB,EAAE,IAAmB;IAC3D,OAAO,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;AACpC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,QAAQ,CAAC,UAAkB,EAAE,IAAsB;IACjE,OAAO,WAAW,CAAC,UAAU,EAAE,EAAE,GAAG,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;AAC1D,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,IAAI,CAAC,SAAiB,EAAE,IAAkB;IACxD,OAAO,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAClC,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,eAAe,CAC7B,SAAiB,EACjB,IAAqB;IAErB,kGAAkG;IAClG,6FAA6F;IAC7F,iEAAiE;IACjE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,kBAAkB,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC;AAC3E,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,IAAY,EAAE,OAAwB,EAAE;IACrE,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1B,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,GAAG,CAAC,CAAC;IAC7C,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,WAAW,CAAC,CAAC;IAC1D,OAAO,WAAW,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC;AAC7C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,OAAO,CAAC,KAAa,EAAE,KAAsB;IAC3D,OAAO,OAAO,CAAC,OAAO,CAAC;QACrB,MAAM,EAAE,sBAAsB;QAC9B,iBAAiB,EAAE,CAAC;QACpB,YAAY,EAAE,EAAE;KACjB,CAAC,CAAC;AACL,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,SAAiB;IAC5C,OAAO,eAAe,CAAC,SAAS,CAAC,CAAC;AACpC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAAC,SAAiB,EAAE,MAAgB;IAC3D,OAAO,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;AACzC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,WAAW;IACzB,OAAO,UAAU,CAAC;AACpB,CAAC"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `aipm init --refresh` — keep a marketplace repo's **toolkit-owned scaffold files** (the CI
|
|
3
|
+
* workflow and `.gitignore`) in sync with the installed tooling, and serve as the upgrade path for
|
|
4
|
+
* any marketplace repo after `pnpm up @ai-plugin-marketplace/*`.
|
|
5
|
+
*
|
|
6
|
+
* Safety rests on a content-hash sidecar at `.aipm/scaffold.json` (mirroring the root-emission
|
|
7
|
+
* sidecar `.aipm/generated-root.json`): it records a hash of the exact content the toolkit last
|
|
8
|
+
* wrote each managed file. Refresh updates a file only when it is still pristine (matches the
|
|
9
|
+
* recorded hash) or missing; a file the user has edited surfaces as a reported conflict and is left
|
|
10
|
+
* untouched unless `--force` is given. A repo with no sidecar entry bootstraps: an already-in-sync
|
|
11
|
+
* file is adopted silently, a diverged one is a conflict to review.
|
|
12
|
+
*
|
|
13
|
+
* The managed set is deliberately narrow — only the pure tooling-recipe files (see
|
|
14
|
+
* {@link buildManagedScaffoldFiles}). `package.json` (deps are `pnpm up`'s job), `aipm.workspace.ts`
|
|
15
|
+
* (repo identity), `README.md` (authored), plugins, and `aipm build` output are never touched.
|
|
16
|
+
*
|
|
17
|
+
* @see docs/specs/scaffold-refresh-and-upgrade.md
|
|
18
|
+
*/
|
|
19
|
+
import type { RefreshOptions, RefreshOutcome } from './types.js';
|
|
20
|
+
/** A recorded `{ path, hash }` pair: the hash of the content the toolkit last wrote at `path`. */
|
|
21
|
+
interface SidecarEntry {
|
|
22
|
+
path: string;
|
|
23
|
+
hash: string;
|
|
24
|
+
}
|
|
25
|
+
/** Content hash recorded in the sidecar. `sha256-`-prefixed hex over the UTF-8 bytes. */
|
|
26
|
+
export declare function hashScaffoldContent(content: string): string;
|
|
27
|
+
/**
|
|
28
|
+
* Serialize a sidecar payload: `{ version, files }` with `files` sorted by path for determinism,
|
|
29
|
+
* 2-space JSON + trailing newline (matching the repo's other generated JSON).
|
|
30
|
+
*/
|
|
31
|
+
export declare function serializeScaffoldSidecar(entries: readonly SidecarEntry[]): string;
|
|
32
|
+
/** Inputs to the pure per-file refresh decision. */
|
|
33
|
+
export interface ManagedFileDecisionInput {
|
|
34
|
+
/** Canonical content the toolkit would render for this file. */
|
|
35
|
+
render: string;
|
|
36
|
+
/** Current on-disk content, or `null` when the file is missing. */
|
|
37
|
+
current: string | null;
|
|
38
|
+
/** Hash recorded in the sidecar for this file, or `null` when untracked. */
|
|
39
|
+
recordedHash: string | null;
|
|
40
|
+
/** Whether `--force` was given. */
|
|
41
|
+
force: boolean;
|
|
42
|
+
}
|
|
43
|
+
/** Result of the pure per-file refresh decision. */
|
|
44
|
+
export interface ManagedFileDecision {
|
|
45
|
+
status: RefreshOutcome['status'];
|
|
46
|
+
/** Whether to write `render` to disk. */
|
|
47
|
+
write: boolean;
|
|
48
|
+
/** Hash to record in the new sidecar, or `null` to preserve the prior entry (or stay untracked). */
|
|
49
|
+
recordHash: string | null;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Decide what to do with one managed scaffold file. Pure — all filesystem state is passed in — so
|
|
53
|
+
* the decision table is unit-testable in isolation.
|
|
54
|
+
*
|
|
55
|
+
* | On-disk state | Result |
|
|
56
|
+
* |-------------------------------------------------|---------------|
|
|
57
|
+
* | missing | `recreated` |
|
|
58
|
+
* | matches the current render | `unchanged` |
|
|
59
|
+
* | differs from render, matches recorded hash | `updated` |
|
|
60
|
+
* | differs from render & recorded (or untracked) | `conflict` * |
|
|
61
|
+
* | …same, with `force` | `overwritten` |
|
|
62
|
+
*
|
|
63
|
+
* \* `unchanged` also adopts an untracked-but-in-sync file by recording its hash.
|
|
64
|
+
*/
|
|
65
|
+
export declare function decideManagedFile(input: ManagedFileDecisionInput): ManagedFileDecision;
|
|
66
|
+
/**
|
|
67
|
+
* Seed `.aipm/scaffold.json` for a freshly scaffolded repo, recording the hash of every managed
|
|
68
|
+
* scaffold file as just written by `aipm init`. Called by {@link runInit} after the seed tree is
|
|
69
|
+
* written so the first `--refresh` has a baseline.
|
|
70
|
+
*/
|
|
71
|
+
export declare function writeScaffoldSidecar(repoRoot: string): void;
|
|
72
|
+
/**
|
|
73
|
+
* Refresh the toolkit-owned scaffold files of an existing repo at `repoRoot`, re-rendering each
|
|
74
|
+
* from the installed tooling and updating it in place when safe (see {@link decideManagedFile}).
|
|
75
|
+
* Writes the updated `.aipm/scaffold.json` sidecar and returns one {@link RefreshOutcome} per
|
|
76
|
+
* managed file. Never throws on conflict — conflicts are reported, not failures.
|
|
77
|
+
*/
|
|
78
|
+
export declare function runRefreshScaffold(repoRoot: string, opts?: RefreshOptions): RefreshOutcome[];
|
|
79
|
+
export {};
|
|
80
|
+
//# sourceMappingURL=scaffold-refresh.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scaffold-refresh.d.ts","sourceRoot":"","sources":["../../src/pipeline/scaffold-refresh.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAOH,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAOjE,kGAAkG;AAClG,UAAU,YAAY;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAOD,yFAAyF;AACzF,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,GAAG,MAAM,CAGjF;AA+BD,oDAAoD;AACpD,MAAM,WAAW,wBAAwB;IACvC,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAC;IACf,mEAAmE;IACnE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,4EAA4E;IAC5E,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,mCAAmC;IACnC,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,oDAAoD;AACpD,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAC;IACjC,yCAAyC;IACzC,KAAK,EAAE,OAAO,CAAC;IACf,oGAAoG;IACpG,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,wBAAwB,GAAG,mBAAmB,CAmBtF;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAQ3D;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,GAAE,cAAmB,GAAG,cAAc,EAAE,CAmChG"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `aipm init --refresh` — keep a marketplace repo's **toolkit-owned scaffold files** (the CI
|
|
3
|
+
* workflow and `.gitignore`) in sync with the installed tooling, and serve as the upgrade path for
|
|
4
|
+
* any marketplace repo after `pnpm up @ai-plugin-marketplace/*`.
|
|
5
|
+
*
|
|
6
|
+
* Safety rests on a content-hash sidecar at `.aipm/scaffold.json` (mirroring the root-emission
|
|
7
|
+
* sidecar `.aipm/generated-root.json`): it records a hash of the exact content the toolkit last
|
|
8
|
+
* wrote each managed file. Refresh updates a file only when it is still pristine (matches the
|
|
9
|
+
* recorded hash) or missing; a file the user has edited surfaces as a reported conflict and is left
|
|
10
|
+
* untouched unless `--force` is given. A repo with no sidecar entry bootstraps: an already-in-sync
|
|
11
|
+
* file is adopted silently, a diverged one is a conflict to review.
|
|
12
|
+
*
|
|
13
|
+
* The managed set is deliberately narrow — only the pure tooling-recipe files (see
|
|
14
|
+
* {@link buildManagedScaffoldFiles}). `package.json` (deps are `pnpm up`'s job), `aipm.workspace.ts`
|
|
15
|
+
* (repo identity), `README.md` (authored), plugins, and `aipm build` output are never touched.
|
|
16
|
+
*
|
|
17
|
+
* @see docs/specs/scaffold-refresh-and-upgrade.md
|
|
18
|
+
*/
|
|
19
|
+
import { createHash } from 'node:crypto';
|
|
20
|
+
import * as fs from 'node:fs';
|
|
21
|
+
import * as path from 'node:path';
|
|
22
|
+
import { buildManagedScaffoldFiles } from './init-template.js';
|
|
23
|
+
/** Sidecar location relative to the repo root. */
|
|
24
|
+
const SIDECAR_REL = ['.aipm', 'scaffold.json'];
|
|
25
|
+
/** Schema version of the sidecar payload. */
|
|
26
|
+
const SIDECAR_VERSION = 1;
|
|
27
|
+
/** Absolute path of the scaffold sidecar under `repoRoot`. */
|
|
28
|
+
function sidecarPath(repoRoot) {
|
|
29
|
+
return path.join(repoRoot, ...SIDECAR_REL);
|
|
30
|
+
}
|
|
31
|
+
/** Content hash recorded in the sidecar. `sha256-`-prefixed hex over the UTF-8 bytes. */
|
|
32
|
+
export function hashScaffoldContent(content) {
|
|
33
|
+
return `sha256-${createHash('sha256').update(content, 'utf-8').digest('hex')}`;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Serialize a sidecar payload: `{ version, files }` with `files` sorted by path for determinism,
|
|
37
|
+
* 2-space JSON + trailing newline (matching the repo's other generated JSON).
|
|
38
|
+
*/
|
|
39
|
+
export function serializeScaffoldSidecar(entries) {
|
|
40
|
+
const files = [...entries].sort((a, b) => a.path.localeCompare(b.path));
|
|
41
|
+
return `${JSON.stringify({ version: SIDECAR_VERSION, files }, null, 2)}\n`;
|
|
42
|
+
}
|
|
43
|
+
/** Read the prior sidecar into a `path → hash` map. Missing or malformed sidecar → empty map. */
|
|
44
|
+
function readSidecar(repoRoot) {
|
|
45
|
+
const map = new Map();
|
|
46
|
+
const abs = sidecarPath(repoRoot);
|
|
47
|
+
if (!fs.existsSync(abs))
|
|
48
|
+
return map;
|
|
49
|
+
// Read errors (permissions, transient I/O) propagate — they are real operational problems, not a
|
|
50
|
+
// "malformed sidecar" we should silently swallow. Only a JSON parse failure is tolerated.
|
|
51
|
+
const raw = fs.readFileSync(abs, 'utf-8');
|
|
52
|
+
let parsed;
|
|
53
|
+
try {
|
|
54
|
+
parsed = JSON.parse(raw);
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
// A malformed sidecar is treated as absent: every managed file becomes "untracked" and must
|
|
58
|
+
// either already match the current render (adopted) or be resolved via --force.
|
|
59
|
+
return map;
|
|
60
|
+
}
|
|
61
|
+
if (Array.isArray(parsed.files)) {
|
|
62
|
+
for (const rawEntry of parsed.files) {
|
|
63
|
+
const entry = rawEntry;
|
|
64
|
+
if (typeof entry.path === 'string' && typeof entry.hash === 'string') {
|
|
65
|
+
map.set(entry.path, entry.hash);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return map;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Decide what to do with one managed scaffold file. Pure — all filesystem state is passed in — so
|
|
73
|
+
* the decision table is unit-testable in isolation.
|
|
74
|
+
*
|
|
75
|
+
* | On-disk state | Result |
|
|
76
|
+
* |-------------------------------------------------|---------------|
|
|
77
|
+
* | missing | `recreated` |
|
|
78
|
+
* | matches the current render | `unchanged` |
|
|
79
|
+
* | differs from render, matches recorded hash | `updated` |
|
|
80
|
+
* | differs from render & recorded (or untracked) | `conflict` * |
|
|
81
|
+
* | …same, with `force` | `overwritten` |
|
|
82
|
+
*
|
|
83
|
+
* \* `unchanged` also adopts an untracked-but-in-sync file by recording its hash.
|
|
84
|
+
*/
|
|
85
|
+
export function decideManagedFile(input) {
|
|
86
|
+
const { render, current, recordedHash, force } = input;
|
|
87
|
+
const renderHash = hashScaffoldContent(render);
|
|
88
|
+
if (current === null)
|
|
89
|
+
return { status: 'recreated', write: true, recordHash: renderHash };
|
|
90
|
+
const currentHash = hashScaffoldContent(current);
|
|
91
|
+
if (currentHash === renderHash)
|
|
92
|
+
return { status: 'unchanged', write: false, recordHash: renderHash };
|
|
93
|
+
// Content differs from the current render.
|
|
94
|
+
if (recordedHash !== null && currentHash === recordedHash) {
|
|
95
|
+
// Pristine: the file is exactly what the toolkit last wrote, so it is safe to upgrade.
|
|
96
|
+
return { status: 'updated', write: true, recordHash: renderHash };
|
|
97
|
+
}
|
|
98
|
+
// Diverged from the recorded hash (user-edited) or untracked and not in sync.
|
|
99
|
+
if (force)
|
|
100
|
+
return { status: 'overwritten', write: true, recordHash: renderHash };
|
|
101
|
+
return { status: 'conflict', write: false, recordHash: null };
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Seed `.aipm/scaffold.json` for a freshly scaffolded repo, recording the hash of every managed
|
|
105
|
+
* scaffold file as just written by `aipm init`. Called by {@link runInit} after the seed tree is
|
|
106
|
+
* written so the first `--refresh` has a baseline.
|
|
107
|
+
*/
|
|
108
|
+
export function writeScaffoldSidecar(repoRoot) {
|
|
109
|
+
const entries = buildManagedScaffoldFiles().map((file) => ({
|
|
110
|
+
path: file.path,
|
|
111
|
+
hash: hashScaffoldContent(file.content),
|
|
112
|
+
}));
|
|
113
|
+
const abs = sidecarPath(repoRoot);
|
|
114
|
+
fs.mkdirSync(path.dirname(abs), { recursive: true });
|
|
115
|
+
fs.writeFileSync(abs, serializeScaffoldSidecar(entries), 'utf-8');
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Refresh the toolkit-owned scaffold files of an existing repo at `repoRoot`, re-rendering each
|
|
119
|
+
* from the installed tooling and updating it in place when safe (see {@link decideManagedFile}).
|
|
120
|
+
* Writes the updated `.aipm/scaffold.json` sidecar and returns one {@link RefreshOutcome} per
|
|
121
|
+
* managed file. Never throws on conflict — conflicts are reported, not failures.
|
|
122
|
+
*/
|
|
123
|
+
export function runRefreshScaffold(repoRoot, opts = {}) {
|
|
124
|
+
const force = opts.force ?? false;
|
|
125
|
+
const resolved = path.resolve(repoRoot);
|
|
126
|
+
const recorded = readSidecar(resolved);
|
|
127
|
+
const outcomes = [];
|
|
128
|
+
const newEntries = [];
|
|
129
|
+
for (const file of buildManagedScaffoldFiles()) {
|
|
130
|
+
const abs = path.join(resolved, file.path);
|
|
131
|
+
const current = fs.existsSync(abs) ? fs.readFileSync(abs, 'utf-8') : null;
|
|
132
|
+
const recordedHash = recorded.get(file.path) ?? null;
|
|
133
|
+
const decision = decideManagedFile({ render: file.content, current, recordedHash, force });
|
|
134
|
+
if (decision.write) {
|
|
135
|
+
fs.mkdirSync(path.dirname(abs), { recursive: true });
|
|
136
|
+
fs.writeFileSync(abs, file.content, 'utf-8');
|
|
137
|
+
}
|
|
138
|
+
if (decision.recordHash !== null) {
|
|
139
|
+
newEntries.push({ path: file.path, hash: decision.recordHash });
|
|
140
|
+
}
|
|
141
|
+
else if (recordedHash !== null) {
|
|
142
|
+
// Conflict left untouched: preserve the prior recorded hash so it stays tracked.
|
|
143
|
+
newEntries.push({ path: file.path, hash: recordedHash });
|
|
144
|
+
}
|
|
145
|
+
outcomes.push({ path: file.path, status: decision.status });
|
|
146
|
+
}
|
|
147
|
+
const sidecarAbs = sidecarPath(resolved);
|
|
148
|
+
fs.mkdirSync(path.dirname(sidecarAbs), { recursive: true });
|
|
149
|
+
fs.writeFileSync(sidecarAbs, serializeScaffoldSidecar(newEntries), 'utf-8');
|
|
150
|
+
return outcomes;
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=scaffold-refresh.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scaffold-refresh.js","sourceRoot":"","sources":["../../src/pipeline/scaffold-refresh.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../src/pipeline/scaffold.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;
|
|
1
|
+
{"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../src/pipeline/scaffold.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAcH,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AA2B3E;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAerD;AAMD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,SAAS,QAAQ,EAAE,GAAG,MAAM,CAUrE;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,YAAY,EAAE,MAAM,GAAG,QAAQ,EAAE,CAcrE;AA4MD;;;;;;;;;;;;GAYG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAClB,IAAI,GAAE,eAAoB,GACzB,OAAO,CAAC,IAAI,CAAC,CA+Bf;AAMD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAgCrF;AAmCD;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CA+B/E"}
|