@ai-plugin-marketplace/core 0.1.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/LICENSE +21 -0
- package/README.md +67 -0
- package/dist/config.d.ts +47 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +38 -0
- package/dist/config.js.map +1 -0
- package/dist/core.d.ts +291 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/pipeline/build.d.ts +90 -0
- package/dist/pipeline/build.d.ts.map +1 -0
- package/dist/pipeline/build.js +224 -0
- package/dist/pipeline/build.js.map +1 -0
- package/dist/pipeline/discover.d.ts +37 -0
- package/dist/pipeline/discover.d.ts.map +1 -0
- package/dist/pipeline/discover.js +71 -0
- package/dist/pipeline/discover.js.map +1 -0
- package/dist/pipeline/init-template.d.ts +33 -0
- package/dist/pipeline/init-template.d.ts.map +1 -0
- package/dist/pipeline/init-template.js +142 -0
- package/dist/pipeline/init-template.js.map +1 -0
- package/dist/pipeline/init.d.ts +39 -0
- package/dist/pipeline/init.d.ts.map +1 -0
- package/dist/pipeline/init.js +84 -0
- package/dist/pipeline/init.js.map +1 -0
- package/dist/pipeline/load-config.d.ts +47 -0
- package/dist/pipeline/load-config.d.ts.map +1 -0
- package/dist/pipeline/load-config.js +106 -0
- package/dist/pipeline/load-config.js.map +1 -0
- package/dist/pipeline/operations.d.ts +70 -0
- package/dist/pipeline/operations.d.ts.map +1 -0
- package/dist/pipeline/operations.js +100 -0
- package/dist/pipeline/operations.js.map +1 -0
- package/dist/pipeline/scaffold.d.ts +105 -0
- package/dist/pipeline/scaffold.d.ts.map +1 -0
- package/dist/pipeline/scaffold.js +422 -0
- package/dist/pipeline/scaffold.js.map +1 -0
- package/dist/pipeline/sentinel.d.ts +127 -0
- package/dist/pipeline/sentinel.d.ts.map +1 -0
- package/dist/pipeline/sentinel.js +263 -0
- package/dist/pipeline/sentinel.js.map +1 -0
- package/dist/pipeline/types.d.ts +178 -0
- package/dist/pipeline/types.d.ts.map +1 -0
- package/dist/pipeline/types.js +26 -0
- package/dist/pipeline/types.js.map +1 -0
- package/dist/pipeline/validate.d.ts +90 -0
- package/dist/pipeline/validate.d.ts.map +1 -0
- package/dist/pipeline/validate.js +617 -0
- package/dist/pipeline/validate.js.map +1 -0
- package/dist/targets/claude/scaffold.d.ts +32 -0
- package/dist/targets/claude/scaffold.d.ts.map +1 -0
- package/dist/targets/claude/scaffold.js +48 -0
- package/dist/targets/claude/scaffold.js.map +1 -0
- package/dist/targets/claude/schemas.d.ts +119 -0
- package/dist/targets/claude/schemas.d.ts.map +1 -0
- package/dist/targets/claude/schemas.js +204 -0
- package/dist/targets/claude/schemas.js.map +1 -0
- package/dist/targets/claude/transform.d.ts +40 -0
- package/dist/targets/claude/transform.d.ts.map +1 -0
- package/dist/targets/claude/transform.js +48 -0
- package/dist/targets/claude/transform.js.map +1 -0
- package/dist/targets/claude/validate.d.ts +25 -0
- package/dist/targets/claude/validate.d.ts.map +1 -0
- package/dist/targets/claude/validate.js +263 -0
- package/dist/targets/claude/validate.js.map +1 -0
- package/dist/targets/cursor/scaffold.d.ts +29 -0
- package/dist/targets/cursor/scaffold.d.ts.map +1 -0
- package/dist/targets/cursor/scaffold.js +45 -0
- package/dist/targets/cursor/scaffold.js.map +1 -0
- package/dist/targets/cursor/schemas.d.ts +49 -0
- package/dist/targets/cursor/schemas.d.ts.map +1 -0
- package/dist/targets/cursor/schemas.js +125 -0
- package/dist/targets/cursor/schemas.js.map +1 -0
- package/dist/targets/cursor/validate.d.ts +28 -0
- package/dist/targets/cursor/validate.d.ts.map +1 -0
- package/dist/targets/cursor/validate.js +181 -0
- package/dist/targets/cursor/validate.js.map +1 -0
- package/dist/targets/gemini/bundle.d.ts +25 -0
- package/dist/targets/gemini/bundle.d.ts.map +1 -0
- package/dist/targets/gemini/bundle.js +149 -0
- package/dist/targets/gemini/bundle.js.map +1 -0
- package/dist/targets/gemini/scaffold.d.ts +28 -0
- package/dist/targets/gemini/scaffold.d.ts.map +1 -0
- package/dist/targets/gemini/scaffold.js +57 -0
- package/dist/targets/gemini/scaffold.js.map +1 -0
- package/dist/targets/gemini/schemas.d.ts +53 -0
- package/dist/targets/gemini/schemas.d.ts.map +1 -0
- package/dist/targets/gemini/schemas.js +72 -0
- package/dist/targets/gemini/schemas.js.map +1 -0
- package/dist/targets/gemini/transform.d.ts +106 -0
- package/dist/targets/gemini/transform.d.ts.map +1 -0
- package/dist/targets/gemini/transform.js +137 -0
- package/dist/targets/gemini/transform.js.map +1 -0
- package/dist/targets/gemini/validate.d.ts +26 -0
- package/dist/targets/gemini/validate.d.ts.map +1 -0
- package/dist/targets/gemini/validate.js +146 -0
- package/dist/targets/gemini/validate.js.map +1 -0
- package/dist/targets/kiro/bundle.d.ts +32 -0
- package/dist/targets/kiro/bundle.d.ts.map +1 -0
- package/dist/targets/kiro/bundle.js +106 -0
- package/dist/targets/kiro/bundle.js.map +1 -0
- package/dist/targets/kiro/scaffold.d.ts +28 -0
- package/dist/targets/kiro/scaffold.d.ts.map +1 -0
- package/dist/targets/kiro/scaffold.js +55 -0
- package/dist/targets/kiro/scaffold.js.map +1 -0
- package/dist/targets/kiro/schemas.d.ts +100 -0
- package/dist/targets/kiro/schemas.d.ts.map +1 -0
- package/dist/targets/kiro/schemas.js +147 -0
- package/dist/targets/kiro/schemas.js.map +1 -0
- package/dist/targets/kiro/transform.d.ts +53 -0
- package/dist/targets/kiro/transform.d.ts.map +1 -0
- package/dist/targets/kiro/transform.js +113 -0
- package/dist/targets/kiro/transform.js.map +1 -0
- package/dist/targets/kiro/validate.d.ts +36 -0
- package/dist/targets/kiro/validate.d.ts.map +1 -0
- package/dist/targets/kiro/validate.js +232 -0
- package/dist/targets/kiro/validate.js.map +1 -0
- package/dist/targets/scaffold-kit.d.ts +56 -0
- package/dist/targets/scaffold-kit.d.ts.map +1 -0
- package/dist/targets/scaffold-kit.js +33 -0
- package/dist/targets/scaffold-kit.js.map +1 -0
- package/dist/targets/vercel/scaffold.d.ts +34 -0
- package/dist/targets/vercel/scaffold.d.ts.map +1 -0
- package/dist/targets/vercel/scaffold.js +58 -0
- package/dist/targets/vercel/scaffold.js.map +1 -0
- package/dist/targets/vercel/schemas.d.ts +42 -0
- package/dist/targets/vercel/schemas.d.ts.map +1 -0
- package/dist/targets/vercel/schemas.js +69 -0
- package/dist/targets/vercel/schemas.js.map +1 -0
- package/dist/targets/vercel/validate.d.ts +28 -0
- package/dist/targets/vercel/validate.d.ts.map +1 -0
- package/dist/targets/vercel/validate.js +180 -0
- package/dist/targets/vercel/validate.js.map +1 -0
- package/package.json +50 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `runInit` — scaffold a thin consumer repo (the "template") that depends on
|
|
3
|
+
* `@ai-plugin-marketplace/cli` and holds plugin sources only (§3.2, §11).
|
|
4
|
+
*
|
|
5
|
+
* This is the filesystem-writing orchestrator behind the public `init` operation and the
|
|
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 toolkit version to pin, refuses to clobber a
|
|
8
|
+
* non-empty target, and writes the seed tree.
|
|
9
|
+
*
|
|
10
|
+
* **Version pinning (§9.1 lockstep release).** core and cli ship in lockstep, so the `cli` dev
|
|
11
|
+
* dependency is pinned to a caret of core's *own* version — read at runtime from this package's
|
|
12
|
+
* `package.json`, resolved relative to {@link import.meta.url} exactly as `load-config.ts` resolves
|
|
13
|
+
* the package entrypoint. Today that yields `^0.1.0-alpha.0`; once 0.1.0 ships, an `init` run from
|
|
14
|
+
* the published cli pins `^0.1.0`.
|
|
15
|
+
*
|
|
16
|
+
* @see docs/specs/architecture.md §3.2 (template repo contents)
|
|
17
|
+
* @see docs/specs/architecture.md §9.1 (lockstep release lines)
|
|
18
|
+
* @see docs/specs/architecture.md §11 (template→toolkit dependency contract)
|
|
19
|
+
*/
|
|
20
|
+
import * as fs from 'node:fs';
|
|
21
|
+
import * as path from 'node:path';
|
|
22
|
+
import { fileURLToPath } from 'node:url';
|
|
23
|
+
import { buildInitFiles } from './init-template.js';
|
|
24
|
+
/**
|
|
25
|
+
* Read this package's `package.json#version`, resolved relative to this module's location.
|
|
26
|
+
*
|
|
27
|
+
* When bundled to `dist/pipeline/init.js` this resolves `<pkgRoot>/package.json`; when run from
|
|
28
|
+
* source as `src/pipeline/init.ts` it resolves the same file (both sit two levels up). Mirrors the
|
|
29
|
+
* version-resolution approach in `cli/src/run.ts` and the entrypoint resolution in
|
|
30
|
+
* `load-config.ts`.
|
|
31
|
+
*/
|
|
32
|
+
function coreVersion() {
|
|
33
|
+
const here = fileURLToPath(import.meta.url);
|
|
34
|
+
// here = <pkgRoot>/<src|dist>/pipeline/init.<ts|js>; package.json sits two levels up.
|
|
35
|
+
const pkgPath = path.join(path.dirname(here), '..', '..', 'package.json');
|
|
36
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
37
|
+
return pkg.version;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* True iff `dir` does not exist, or exists as an empty directory. A non-empty directory (or a
|
|
41
|
+
* path that exists as a non-directory) is treated as "would clobber".
|
|
42
|
+
*/
|
|
43
|
+
function isFreshTarget(dir) {
|
|
44
|
+
if (!fs.existsSync(dir))
|
|
45
|
+
return true;
|
|
46
|
+
const stat = fs.statSync(dir);
|
|
47
|
+
if (!stat.isDirectory())
|
|
48
|
+
return false;
|
|
49
|
+
return fs.readdirSync(dir).length === 0;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Scaffold a thin consumer repo at `targetDir` (§3.2).
|
|
53
|
+
*
|
|
54
|
+
* Writes `package.json` (with the `@ai-plugin-marketplace/cli` dev dependency pinned to a caret of
|
|
55
|
+
* the current toolkit version), `.gitignore`, `README.md`, both repo-root marketplace registries
|
|
56
|
+
* (`{ "plugins": [] }`), an empty `plugins/` (tracked via `.gitkeep`), and a CI workflow that runs
|
|
57
|
+
* `aipm build` then `aipm validate` (§10.5 freshness). The repo name defaults to
|
|
58
|
+
* `basename(targetDir)`; override it with `opts.name`.
|
|
59
|
+
*
|
|
60
|
+
* **Refuses to clobber.** If `targetDir` exists and is a non-empty directory (or exists as a
|
|
61
|
+
* non-directory), the function throws and writes nothing. Creating into a fresh or empty directory
|
|
62
|
+
* is fine.
|
|
63
|
+
*
|
|
64
|
+
* @param targetDir - Absolute or relative path to the directory to scaffold into.
|
|
65
|
+
* @param opts - Init options; `name` overrides the derived repo name.
|
|
66
|
+
* @throws {Error} When `targetDir` exists and is non-empty (or is not a directory).
|
|
67
|
+
*/
|
|
68
|
+
export async function runInit(targetDir, opts = {}) {
|
|
69
|
+
const resolved = path.resolve(targetDir);
|
|
70
|
+
if (!isFreshTarget(resolved)) {
|
|
71
|
+
throw new Error(`Refusing to scaffold into '${resolved}': the directory already exists and is not empty. ` +
|
|
72
|
+
'Choose a new path or an empty directory.');
|
|
73
|
+
}
|
|
74
|
+
const name = opts.name ?? path.basename(resolved);
|
|
75
|
+
const files = buildInitFiles(name, coreVersion());
|
|
76
|
+
fs.mkdirSync(resolved, { recursive: true });
|
|
77
|
+
for (const file of files) {
|
|
78
|
+
const full = path.join(resolved, file.path);
|
|
79
|
+
fs.mkdirSync(path.dirname(full), { recursive: true });
|
|
80
|
+
fs.writeFileSync(full, file.content, 'utf-8');
|
|
81
|
+
}
|
|
82
|
+
return Promise.resolve();
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/pipeline/init.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;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;AAGpD;;;;;;;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;;;;;;;;;;;;;;;;GAgBG;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,KAAK,GAAG,cAAc,CAAC,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC;IAElD,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,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;AAC3B,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime loader for a plugin's `aipm.config.ts` envelope (§6.1, P6).
|
|
3
|
+
*
|
|
4
|
+
* `aipm.config.ts` is authored in TypeScript and imports `defineConfig` from
|
|
5
|
+
* `@ai-plugin-marketplace/core`. The build (§5.2) and validate (§5.3) orchestrators need to
|
|
6
|
+
* evaluate that module at runtime to read its `default` export. We use {@link https://github.com/unjs/jiti | jiti}
|
|
7
|
+
* to transpile-and-import the TS module on the fly, then re-run it through {@link defineConfig}
|
|
8
|
+
* so the result is a properly-branded {@link AipmConfig} regardless of what the on-disk module
|
|
9
|
+
* happened to call.
|
|
10
|
+
*
|
|
11
|
+
* **Module resolution.** A plugin's `aipm.config.ts` can live anywhere on disk (including a
|
|
12
|
+
* temp dir during tests), so a bare `import '@ai-plugin-marketplace/core'` would not resolve
|
|
13
|
+
* by walking up from the config file. We register a jiti `alias` mapping the package specifier
|
|
14
|
+
* to this package's own entrypoint, derived from {@link import.meta.url}. The alias is
|
|
15
|
+
* extension-less so jiti resolves `index.ts` when running from source (vitest) and `index.js`
|
|
16
|
+
* when running from the compiled `dist/` (production) — both verified working.
|
|
17
|
+
*
|
|
18
|
+
* @see docs/specs/architecture.md §6.1 (envelope declaration), P6 (TypeScript end-to-end)
|
|
19
|
+
* @see docs/specs/architecture.md §5.2, §5.3 (build/validate consume the loaded envelope)
|
|
20
|
+
*/
|
|
21
|
+
import type { AipmConfig } from '../config.js';
|
|
22
|
+
/** The canonical config filename every plugin must provide (§6.1). */
|
|
23
|
+
export declare const AIPM_CONFIG_FILENAME = "aipm.config.ts";
|
|
24
|
+
/**
|
|
25
|
+
* Error thrown when a plugin's `aipm.config.ts` cannot be located, imported, or validated.
|
|
26
|
+
* The build orchestrator surfaces this as a thrown error; the validate orchestrator catches it
|
|
27
|
+
* and converts it into an `envelope-invalid` finding (§10.1 step 1).
|
|
28
|
+
*/
|
|
29
|
+
export declare class ConfigLoadError extends Error {
|
|
30
|
+
constructor(message: string, options?: {
|
|
31
|
+
cause?: unknown;
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Load and validate a plugin's `aipm.config.ts`, returning the branded {@link AipmConfig}.
|
|
36
|
+
*
|
|
37
|
+
* The on-disk module's `default` export is re-validated through {@link defineConfig} so callers
|
|
38
|
+
* receive a value that provably passed the canonical Zod schema — even if the author bypassed
|
|
39
|
+
* `defineConfig` in their source (e.g. exported a plain object literal).
|
|
40
|
+
*
|
|
41
|
+
* @param pluginDir - Absolute path to the `plugins/<name>/` directory.
|
|
42
|
+
* @returns The validated, branded config.
|
|
43
|
+
* @throws {ConfigLoadError} If the file is absent, fails to import, has no default export, or
|
|
44
|
+
* the default export fails schema validation.
|
|
45
|
+
*/
|
|
46
|
+
export declare function loadPluginConfig(pluginDir: string): Promise<AipmConfig>;
|
|
47
|
+
//# sourceMappingURL=load-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load-config.d.ts","sourceRoot":"","sources":["../../src/pipeline/load-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AASH,OAAO,KAAK,EAAE,UAAU,EAAmB,MAAM,cAAc,CAAC;AAEhE,sEAAsE;AACtE,eAAO,MAAM,oBAAoB,mBAAmB,CAAC;AAKrD;;;;GAIG;AACH,qBAAa,eAAgB,SAAQ,KAAK;gBAC5B,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE;CAI3D;AAmBD;;;;;;;;;;;GAWG;AACH,wBAAsB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CA4C7E"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime loader for a plugin's `aipm.config.ts` envelope (§6.1, P6).
|
|
3
|
+
*
|
|
4
|
+
* `aipm.config.ts` is authored in TypeScript and imports `defineConfig` from
|
|
5
|
+
* `@ai-plugin-marketplace/core`. The build (§5.2) and validate (§5.3) orchestrators need to
|
|
6
|
+
* evaluate that module at runtime to read its `default` export. We use {@link https://github.com/unjs/jiti | jiti}
|
|
7
|
+
* to transpile-and-import the TS module on the fly, then re-run it through {@link defineConfig}
|
|
8
|
+
* so the result is a properly-branded {@link AipmConfig} regardless of what the on-disk module
|
|
9
|
+
* happened to call.
|
|
10
|
+
*
|
|
11
|
+
* **Module resolution.** A plugin's `aipm.config.ts` can live anywhere on disk (including a
|
|
12
|
+
* temp dir during tests), so a bare `import '@ai-plugin-marketplace/core'` would not resolve
|
|
13
|
+
* by walking up from the config file. We register a jiti `alias` mapping the package specifier
|
|
14
|
+
* to this package's own entrypoint, derived from {@link import.meta.url}. The alias is
|
|
15
|
+
* extension-less so jiti resolves `index.ts` when running from source (vitest) and `index.js`
|
|
16
|
+
* when running from the compiled `dist/` (production) — both verified working.
|
|
17
|
+
*
|
|
18
|
+
* @see docs/specs/architecture.md §6.1 (envelope declaration), P6 (TypeScript end-to-end)
|
|
19
|
+
* @see docs/specs/architecture.md §5.2, §5.3 (build/validate consume the loaded envelope)
|
|
20
|
+
*/
|
|
21
|
+
import * as fs from 'node:fs';
|
|
22
|
+
import * as path from 'node:path';
|
|
23
|
+
import { fileURLToPath } from 'node:url';
|
|
24
|
+
import { createJiti } from 'jiti';
|
|
25
|
+
import { defineConfig } from '../config.js';
|
|
26
|
+
/** The canonical config filename every plugin must provide (§6.1). */
|
|
27
|
+
export const AIPM_CONFIG_FILENAME = 'aipm.config.ts';
|
|
28
|
+
/** The npm specifier a plugin's `aipm.config.ts` imports `defineConfig` from. */
|
|
29
|
+
const CORE_PACKAGE_SPECIFIER = '@ai-plugin-marketplace/core';
|
|
30
|
+
/**
|
|
31
|
+
* Error thrown when a plugin's `aipm.config.ts` cannot be located, imported, or validated.
|
|
32
|
+
* The build orchestrator surfaces this as a thrown error; the validate orchestrator catches it
|
|
33
|
+
* and converts it into an `envelope-invalid` finding (§10.1 step 1).
|
|
34
|
+
*/
|
|
35
|
+
export class ConfigLoadError extends Error {
|
|
36
|
+
constructor(message, options) {
|
|
37
|
+
super(message, options);
|
|
38
|
+
this.name = 'ConfigLoadError';
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Absolute path to this package's public entrypoint, **without** a file extension, derived from
|
|
43
|
+
* the location of this module. When bundled to `dist/pipeline/load-config.js` this resolves to
|
|
44
|
+
* `dist/index`; when run from source as `src/pipeline/load-config.ts` it resolves to `src/index`.
|
|
45
|
+
* jiti's resolver appends the correct extension in each case.
|
|
46
|
+
*/
|
|
47
|
+
function corePackageEntrypoint() {
|
|
48
|
+
const here = fileURLToPath(import.meta.url);
|
|
49
|
+
// here = <pkgRoot>/<src|dist>/pipeline/load-config.<ts|js>; index sits two levels up.
|
|
50
|
+
return path.join(path.dirname(here), '..', 'index');
|
|
51
|
+
}
|
|
52
|
+
/** Absolute path to a plugin's `aipm.config.ts`, given the plugin directory. */
|
|
53
|
+
function configPathFor(pluginDir) {
|
|
54
|
+
return path.join(pluginDir, AIPM_CONFIG_FILENAME);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Load and validate a plugin's `aipm.config.ts`, returning the branded {@link AipmConfig}.
|
|
58
|
+
*
|
|
59
|
+
* The on-disk module's `default` export is re-validated through {@link defineConfig} so callers
|
|
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.
|
|
67
|
+
*/
|
|
68
|
+
export async function loadPluginConfig(pluginDir) {
|
|
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
|
+
}
|
|
73
|
+
const jiti = createJiti(import.meta.url, {
|
|
74
|
+
alias: { [CORE_PACKAGE_SPECIFIER]: corePackageEntrypoint() },
|
|
75
|
+
// Disable the default↔namespace interop so a config with no `default` export reads as a
|
|
76
|
+
// genuinely-absent default rather than jiti synthesizing one from the namespace.
|
|
77
|
+
interopDefault: false,
|
|
78
|
+
// Disable caches so repeated loads (e.g. freshness re-reads) see current disk state.
|
|
79
|
+
moduleCache: false,
|
|
80
|
+
fsCache: false,
|
|
81
|
+
});
|
|
82
|
+
let mod;
|
|
83
|
+
try {
|
|
84
|
+
mod = await jiti.import(configPath);
|
|
85
|
+
}
|
|
86
|
+
catch (err) {
|
|
87
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
88
|
+
throw new ConfigLoadError(`Failed to import ${AIPM_CONFIG_FILENAME}: ${message}`, {
|
|
89
|
+
cause: err,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
const defaultExport = mod['default'];
|
|
93
|
+
if (defaultExport === undefined || defaultExport === null) {
|
|
94
|
+
throw new ConfigLoadError(`${AIPM_CONFIG_FILENAME} in ${pluginDir} has no default export. Export the result of \`defineConfig({...})\` as default.`);
|
|
95
|
+
}
|
|
96
|
+
// Re-validate through defineConfig so the result is a branded AipmConfig. defineConfig throws
|
|
97
|
+
// a ZodError on malformed input; wrap it so callers get a single ConfigLoadError type.
|
|
98
|
+
try {
|
|
99
|
+
return defineConfig(defaultExport);
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
103
|
+
throw new ConfigLoadError(`Invalid ${AIPM_CONFIG_FILENAME}: ${message}`, { cause: err });
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=load-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load-config.js","sourceRoot":"","sources":["../../src/pipeline/load-config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public operation implementations.
|
|
3
|
+
*
|
|
4
|
+
* Each function here is a thin adapter over a pipeline orchestrator, with the pinned public
|
|
5
|
+
* signature from §8.1 of the spec. Business logic lives in the orchestrators
|
|
6
|
+
* (`build.ts`, `validate.ts`, `scaffold.ts`); this module only adapts arguments (e.g. deriving
|
|
7
|
+
* the plugins directory from the cwd for `scaffold`, and reading the CI environment for the
|
|
8
|
+
* freshness severity) so the public contract stays stable as implementations evolve.
|
|
9
|
+
*
|
|
10
|
+
* @see docs/specs/architecture.md §8.1
|
|
11
|
+
*/
|
|
12
|
+
import type { BuildOptions, BuildResult, InitOptions, MigrateOptions, MigrateResult, ScaffoldOptions, SupportReport, TargetId, ValidateOptions, ValidationResult } from './types.js';
|
|
13
|
+
/**
|
|
14
|
+
* Build a single plugin or every plugin under a repo root. `path` may be a plugin directory
|
|
15
|
+
* (contains `aipm.config.ts`) or a repo root (contains `plugins/`); the orchestrator detects
|
|
16
|
+
* which and returns a length-1 array for single-plugin input. See §5.2, §8.1.
|
|
17
|
+
*
|
|
18
|
+
* @public
|
|
19
|
+
*/
|
|
20
|
+
export declare function build(targetPath: string, opts?: BuildOptions): Promise<BuildResult[]>;
|
|
21
|
+
/**
|
|
22
|
+
* Validate a single plugin or every plugin under a repo root, in the order defined by §10.1.
|
|
23
|
+
* Freshness severity follows the CI environment (§10.2).
|
|
24
|
+
*
|
|
25
|
+
* @public
|
|
26
|
+
*/
|
|
27
|
+
export declare function validate(targetPath: string, opts?: ValidateOptions): Promise<ValidationResult>;
|
|
28
|
+
/**
|
|
29
|
+
* Scaffold a thin consumer repo (the "template") at `targetDir` that depends on
|
|
30
|
+
* `@ai-plugin-marketplace/cli` and holds plugin sources only (§3.2, §11). The generated
|
|
31
|
+
* `package.json` pins the cli dev dependency to a caret of the current toolkit version (§9.1
|
|
32
|
+
* lockstep). Refuses to write into a non-empty directory.
|
|
33
|
+
*
|
|
34
|
+
* @public
|
|
35
|
+
*/
|
|
36
|
+
export declare function init(targetDir: string, opts?: InitOptions): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* Scaffold a new plugin under `<cwd>/plugins/<name>`. The plugins directory is derived from the
|
|
39
|
+
* current working directory, matching how `aipm scaffold` is invoked from a template repo root.
|
|
40
|
+
*
|
|
41
|
+
* @public
|
|
42
|
+
*/
|
|
43
|
+
export declare function scaffold(name: string, opts?: ScaffoldOptions): Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
* No-op in v0.1.0 per §8.1 of the spec. Always returns `status: 'no-migrations-needed'` because
|
|
46
|
+
* §9.4 constrains every `schemaVersion` to a single value. When real migrations ship, this
|
|
47
|
+
* must distinguish up-to-date from unknown-future-version.
|
|
48
|
+
*
|
|
49
|
+
* @public
|
|
50
|
+
*/
|
|
51
|
+
export declare function migrate(_path: string, _opts?: MigrateOptions): Promise<MigrateResult>;
|
|
52
|
+
/**
|
|
53
|
+
* Diagnose a plugin's support envelope: declared targets, missing artifacts, addable targets (§6.4).
|
|
54
|
+
*
|
|
55
|
+
* @public
|
|
56
|
+
*/
|
|
57
|
+
export declare function checkSupport(pluginDir: string): Promise<SupportReport>;
|
|
58
|
+
/**
|
|
59
|
+
* Scaffold skeleton files for a new target in an existing plugin (§6.4).
|
|
60
|
+
*
|
|
61
|
+
* @public
|
|
62
|
+
*/
|
|
63
|
+
export declare function addTarget(pluginDir: string, target: TargetId): Promise<void>;
|
|
64
|
+
/**
|
|
65
|
+
* List the target IDs this toolkit version knows about (§6.4).
|
|
66
|
+
*
|
|
67
|
+
* @public
|
|
68
|
+
*/
|
|
69
|
+
export declare function listTargets(): readonly TargetId[];
|
|
70
|
+
//# sourceMappingURL=operations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operations.d.ts","sourceRoot":"","sources":["../../src/pipeline/operations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AASH,OAAO,KAAK,EACV,YAAY,EACZ,WAAW,EACX,WAAW,EACX,cAAc,EACd,aAAa,EACb,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;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,eAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAGhF;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"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public operation implementations.
|
|
3
|
+
*
|
|
4
|
+
* Each function here is a thin adapter over a pipeline orchestrator, with the pinned public
|
|
5
|
+
* signature from §8.1 of the spec. Business logic lives in the orchestrators
|
|
6
|
+
* (`build.ts`, `validate.ts`, `scaffold.ts`); this module only adapts arguments (e.g. deriving
|
|
7
|
+
* the plugins directory from the cwd for `scaffold`, and reading the CI environment for the
|
|
8
|
+
* freshness severity) so the public contract stays stable as implementations evolve.
|
|
9
|
+
*
|
|
10
|
+
* @see docs/specs/architecture.md §8.1
|
|
11
|
+
*/
|
|
12
|
+
import * as path from 'node:path';
|
|
13
|
+
import { runBuild } from './build.js';
|
|
14
|
+
import { runInit } from './init.js';
|
|
15
|
+
import { runScaffold, runAddTarget, runCheckSupport } from './scaffold.js';
|
|
16
|
+
import { TARGET_IDS } from './types.js';
|
|
17
|
+
import { runValidate } from './validate.js';
|
|
18
|
+
/** True when running in a CI environment. Freshness findings are hard in CI, soft locally (§10.2). */
|
|
19
|
+
function isCi() {
|
|
20
|
+
return Boolean(process.env['CI']);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Build a single plugin or every plugin under a repo root. `path` may be a plugin directory
|
|
24
|
+
* (contains `aipm.config.ts`) or a repo root (contains `plugins/`); the orchestrator detects
|
|
25
|
+
* which and returns a length-1 array for single-plugin input. See §5.2, §8.1.
|
|
26
|
+
*
|
|
27
|
+
* @public
|
|
28
|
+
*/
|
|
29
|
+
export function build(targetPath, opts) {
|
|
30
|
+
return runBuild(targetPath, opts);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Validate a single plugin or every plugin under a repo root, in the order defined by §10.1.
|
|
34
|
+
* Freshness severity follows the CI environment (§10.2).
|
|
35
|
+
*
|
|
36
|
+
* @public
|
|
37
|
+
*/
|
|
38
|
+
export function validate(targetPath, opts) {
|
|
39
|
+
return runValidate(targetPath, { ...opts, ci: isCi() });
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Scaffold a thin consumer repo (the "template") at `targetDir` that depends on
|
|
43
|
+
* `@ai-plugin-marketplace/cli` and holds plugin sources only (§3.2, §11). The generated
|
|
44
|
+
* `package.json` pins the cli dev dependency to a caret of the current toolkit version (§9.1
|
|
45
|
+
* lockstep). Refuses to write into a non-empty directory.
|
|
46
|
+
*
|
|
47
|
+
* @public
|
|
48
|
+
*/
|
|
49
|
+
export function init(targetDir, opts) {
|
|
50
|
+
return runInit(targetDir, opts);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Scaffold a new plugin under `<cwd>/plugins/<name>`. The plugins directory is derived from the
|
|
54
|
+
* current working directory, matching how `aipm scaffold` is invoked from a template repo root.
|
|
55
|
+
*
|
|
56
|
+
* @public
|
|
57
|
+
*/
|
|
58
|
+
export function scaffold(name, opts = {}) {
|
|
59
|
+
const pluginsDir = path.join(process.cwd(), 'plugins');
|
|
60
|
+
return runScaffold(name, pluginsDir, opts);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* No-op in v0.1.0 per §8.1 of the spec. Always returns `status: 'no-migrations-needed'` because
|
|
64
|
+
* §9.4 constrains every `schemaVersion` to a single value. When real migrations ship, this
|
|
65
|
+
* must distinguish up-to-date from unknown-future-version.
|
|
66
|
+
*
|
|
67
|
+
* @public
|
|
68
|
+
*/
|
|
69
|
+
export function migrate(_path, _opts) {
|
|
70
|
+
return Promise.resolve({
|
|
71
|
+
status: 'no-migrations-needed',
|
|
72
|
+
migrationsApplied: 0,
|
|
73
|
+
filesChanged: [],
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Diagnose a plugin's support envelope: declared targets, missing artifacts, addable targets (§6.4).
|
|
78
|
+
*
|
|
79
|
+
* @public
|
|
80
|
+
*/
|
|
81
|
+
export function checkSupport(pluginDir) {
|
|
82
|
+
return runCheckSupport(pluginDir);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Scaffold skeleton files for a new target in an existing plugin (§6.4).
|
|
86
|
+
*
|
|
87
|
+
* @public
|
|
88
|
+
*/
|
|
89
|
+
export function addTarget(pluginDir, target) {
|
|
90
|
+
return runAddTarget(pluginDir, target);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* List the target IDs this toolkit version knows about (§6.4).
|
|
94
|
+
*
|
|
95
|
+
* @public
|
|
96
|
+
*/
|
|
97
|
+
export function listTargets() {
|
|
98
|
+
return TARGET_IDS;
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=operations.js.map
|
|
@@ -0,0 +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;AAc5C,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;;;;;GAKG;AACH,MAAM,UAAU,QAAQ,CAAC,IAAY,EAAE,OAAwB,EAAE;IAC/D,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,CAAC,CAAC;IACvD,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,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pipeline orchestration for scaffolding and compatibility-assist (§6.4).
|
|
3
|
+
*
|
|
4
|
+
* Three orchestrators perform filesystem I/O around the per-target *pure* scaffold functions:
|
|
5
|
+
*
|
|
6
|
+
* - `runScaffold` — create a brand-new plugin (the `aipm scaffold` surface).
|
|
7
|
+
* - `runAddTarget` — add one target's skeleton to an existing plugin (`aipm add-target`).
|
|
8
|
+
* - `runCheckSupport` — report declared-but-incomplete and plausibly-addable targets
|
|
9
|
+
* (`aipm check-support`).
|
|
10
|
+
*
|
|
11
|
+
* Per §3.4/§12.4 the pipeline layer is the orchestration boundary and MAY import each target's
|
|
12
|
+
* `scaffold.ts`; the per-target scaffold modules themselves never import one another.
|
|
13
|
+
*
|
|
14
|
+
* Envelope reading (§6.1): loading and executing a TypeScript `aipm.config.ts` from disk is the
|
|
15
|
+
* build orchestrator's job and is not yet built. `runCheckSupport`/`runAddTarget` therefore read
|
|
16
|
+
* the declared targets *pragmatically* — by extracting the `targets: [...]` array literal out of
|
|
17
|
+
* the config source text (see `parseDeclaredTargets`). This tolerates the canonical
|
|
18
|
+
* `defineConfig({ ... })` form this module emits and common hand-authored variants, but it is a
|
|
19
|
+
* lexical heuristic, not a TS evaluation. Documented limitation: a config that computes `targets`
|
|
20
|
+
* dynamically (spread, variable reference, conditional) is not understood and yields an error.
|
|
21
|
+
*
|
|
22
|
+
* @see docs/specs/architecture.md §6 (support envelope)
|
|
23
|
+
* @see docs/specs/architecture.md §6.4 (compatibility-assist tooling)
|
|
24
|
+
* @see docs/specs/architecture.md §10.1 (validation contract — artifact tables reused here)
|
|
25
|
+
* @see docs/specs/architecture.md §12.5 (per-target scaffold.ts)
|
|
26
|
+
*/
|
|
27
|
+
import type { ScaffoldOptions, SupportReport, TargetId } from './types.js';
|
|
28
|
+
/**
|
|
29
|
+
* Validate a plugin name against the canonical slug rules shared by every manifest schema:
|
|
30
|
+
* lowercase, starts with a letter, `[a-z0-9-]` only, no consecutive hyphens, no trailing hyphen.
|
|
31
|
+
*
|
|
32
|
+
* @throws Error with a clear message when the name is invalid.
|
|
33
|
+
*/
|
|
34
|
+
export declare function validatePluginName(name: string): void;
|
|
35
|
+
/**
|
|
36
|
+
* Render the canonical `aipm.config.ts` source for a plugin with the given targets.
|
|
37
|
+
*
|
|
38
|
+
* Emits a `defineConfig({ version, targets })` literal importing from the public package root
|
|
39
|
+
* (§8.1 — the only public subpath). Deterministic: stable target ordering, no timestamps.
|
|
40
|
+
*/
|
|
41
|
+
export declare function renderAipmConfig(targets: readonly TargetId[]): string;
|
|
42
|
+
/**
|
|
43
|
+
* Extract the declared targets from `aipm.config.ts` source text.
|
|
44
|
+
*
|
|
45
|
+
* Lexical heuristic (see module doc): finds the first `targets:` key and parses the immediately
|
|
46
|
+
* following `[...]` array of single/double-quoted string literals. Only IDs in `TARGET_IDS` are
|
|
47
|
+
* returned; unknown IDs are ignored (the shape validator surfaces those separately).
|
|
48
|
+
*
|
|
49
|
+
* @returns Declared target IDs in canonical order, deduplicated.
|
|
50
|
+
* @throws Error when no `targets: [...]` array literal can be located.
|
|
51
|
+
*/
|
|
52
|
+
export declare function parseDeclaredTargets(configSource: string): TargetId[];
|
|
53
|
+
/**
|
|
54
|
+
* Create a brand-new plugin under `pluginsDir/<name>/`.
|
|
55
|
+
*
|
|
56
|
+
* Writes `aipm.config.ts` (via the `defineConfig` literal), each declared target's skeleton
|
|
57
|
+
* files, and the canonical `README.md` / `LICENSE`. Default targets are all known IDs when
|
|
58
|
+
* `opts.targets` is absent.
|
|
59
|
+
*
|
|
60
|
+
* Also registers the plugin in the template-level marketplace registries (§4.4) for each of
|
|
61
|
+
* Claude/Cursor in the envelope (`repoRoot = dirname(pluginsDir)`), so the scaffolded plugin
|
|
62
|
+
* passes `validate`'s `marketplace-registration` check (§10.1.4) out of the box.
|
|
63
|
+
*
|
|
64
|
+
* @throws Error when `name` is invalid or the plugin directory already exists.
|
|
65
|
+
*/
|
|
66
|
+
export declare function runScaffold(name: string, pluginsDir: string, opts?: ScaffoldOptions): Promise<void>;
|
|
67
|
+
/**
|
|
68
|
+
* Scaffold one target's skeleton files into an existing plugin (§6.4 `aipm add-target`).
|
|
69
|
+
*
|
|
70
|
+
* Manifest fields are emitted as placeholders for the author to complete. Existing files are
|
|
71
|
+
* NEVER clobbered: if any file this target would write already exists, the function refuses and
|
|
72
|
+
* throws — the author resolves the conflict deliberately.
|
|
73
|
+
*
|
|
74
|
+
* The plugin's `aipm.config.ts` is updated to include `target` in its `targets` array when the
|
|
75
|
+
* lexical reader can locate the array (see module doc). Limitation: if the array cannot be parsed
|
|
76
|
+
* (dynamic/computed targets), the config is left untouched and the error message instructs the
|
|
77
|
+
* author to add the target manually — the function never leaves the envelope silently
|
|
78
|
+
* inconsistent.
|
|
79
|
+
*
|
|
80
|
+
* When `target` is Claude or Cursor, the plugin is also registered in the corresponding
|
|
81
|
+
* repo-root marketplace registry (§4.4) so adding the target keeps `validate` green. repoRoot is
|
|
82
|
+
* the plugin's grandparent (`<repoRoot>/plugins/<name>`), matching `discoverPlugins`.
|
|
83
|
+
*
|
|
84
|
+
* @throws Error when `pluginDir` does not exist, a target file already exists, or the config's
|
|
85
|
+
* targets array cannot be located for the update.
|
|
86
|
+
*/
|
|
87
|
+
export declare function runAddTarget(pluginDir: string, target: TargetId): Promise<void>;
|
|
88
|
+
/**
|
|
89
|
+
* Report a plugin's support posture (§6.4 `aipm check-support`).
|
|
90
|
+
*
|
|
91
|
+
* Reads the declared envelope from `aipm.config.ts` (lexically — see module doc), then:
|
|
92
|
+
* - `missingArtifacts`: for each declared target, the `TARGET_MIN_REQUIRED` files absent on disk
|
|
93
|
+
* (Vercel's "at least one SKILL.md under a skills subdirectory" rule is applied specially,
|
|
94
|
+
* mirroring the
|
|
95
|
+
* validator). Only targets with at least one missing artifact appear.
|
|
96
|
+
* - `suggestions`: each undeclared known target, with `wouldNeed` = that target's min-required
|
|
97
|
+
* files (the concrete list of files the author would write to add it).
|
|
98
|
+
*
|
|
99
|
+
* Reuses the validator's `TARGET_MIN_REQUIRED` table so "missing" stays consistent with
|
|
100
|
+
* `aipm validate`.
|
|
101
|
+
*
|
|
102
|
+
* @throws Error when `pluginDir` or its `aipm.config.ts` is missing, or the envelope is unreadable.
|
|
103
|
+
*/
|
|
104
|
+
export declare function runCheckSupport(pluginDir: string): Promise<SupportReport>;
|
|
105
|
+
//# sourceMappingURL=scaffold.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../src/pipeline/scaffold.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAaH,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AA0B3E;;;;;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;AAmJD;;;;;;;;;;;;GAYG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAClB,IAAI,GAAE,eAAoB,GACzB,OAAO,CAAC,IAAI,CAAC,CA8Bf;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"}
|