acrylblends 1.2.0 → 1.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/index.d.ts +2 -1
- package/dist/index.js +39 -7
- package/dist/index.js.map +1 -1
- package/docs/framework/guides/create-acrylblends.md +4 -2
- package/docs/framework/workshop/README.md +2 -2
- package/docs/framework/workshop/facilitator.md +1 -1
- package/lib/cordis/door.d.ts +45 -2
- package/lib/cordis/door.js +120 -0
- package/package.json +1 -1
- package/plugins/acryl-door/plugin.json +3 -0
- package/plugins/acryl-door/src/cli/acryl.ts +63 -6
- package/plugins/acryl-door/src/host/door.ts +75 -1
- package/plugins/acryl-door/src/host/operator-routes.ts +21 -1
- package/plugins/acryl-door/src/host/verbs.ts +11 -1
- package/plugins/acryl-door/src/index.ts +2 -1
- package/plugins/builder/index.ts +13 -35
- package/plugins/builder/package.ts +186 -0
- package/plugins/builder/plugin.json +3 -1
- package/plugins/extensions/index.ts +21 -17
- package/plugins/extensions/plugin-store.ts +27 -0
- package/plugins/extensions/plugin.json +1 -1
- package/plugins/extensions/stage.ts +15 -5
- package/plugins/manifest/plugin.json +1 -1
- package/plugins/plugin-share/README.md +51 -0
- package/plugins/plugin-share/index.ts +467 -0
- package/plugins/plugin-share/plugin.json +15 -0
- package/plugins/plugin-share/publish.ts +65 -0
- package/plugins/plugin-share/pull-check.ts +129 -0
- package/plugins/plugin-share/pulled-records.ts +70 -0
- package/templates/agent/.gitattributes +2 -0
- package/templates/agent/blend.yaml +2 -0
- package/templates/agent/src/app.ts +4 -0
- package/templates/agent/template.json +1 -0
- package/templates/blank/.gitattributes +2 -0
- package/templates/chat/.gitattributes +2 -0
- package/templates/nodejs/.gitattributes +2 -0
- package/templates/notes/.gitattributes +2 -0
- package/templates/todo/.gitattributes +2 -0
package/dist/index.d.ts
CHANGED
|
@@ -187,7 +187,8 @@ export declare function assertTargetFree(target: string): void;
|
|
|
187
187
|
export declare function copyTemplate(source: string, target: string, name: string): string[];
|
|
188
188
|
export declare function readTemplatePlugins(templateDir: string): string[];
|
|
189
189
|
/**
|
|
190
|
-
* Add run-time dependencies to an app's package.json
|
|
190
|
+
* Add run-time dependencies to an app's package.json and sort the keys. Returns the names to install: those added, and those moved because a plugin asks for a newer
|
|
191
|
+
* version than the app lists (the plugin's new code needs it). A version the app lists that is the same or newer stays. A package the app lists as a development
|
|
191
192
|
* dependency too is taken out of that list: npm lets the development entry win, so `npm install --omit=dev` would leave a run-time dependency out.
|
|
192
193
|
*/
|
|
193
194
|
export declare function mergeDependencies(appDir: string, dependencies: Readonly<Record<string, string>>): string[];
|
package/dist/index.js
CHANGED
|
@@ -1002,6 +1002,18 @@ function applyIdeProfile(root, input) {
|
|
|
1002
1002
|
//#region src/version.ts
|
|
1003
1003
|
/** The version of this package. */
|
|
1004
1004
|
const VERSION = createRequire(import.meta.url)("../package.json").version;
|
|
1005
|
+
/** Semver order for the release versions (numeric segments; a pre-release sorts before its release). */
|
|
1006
|
+
function compareVersions(a, b) {
|
|
1007
|
+
const pa = a.split(/[.-]/u).map((part) => Number.isNaN(Number(part)) ? part : Number(part));
|
|
1008
|
+
const pb = b.split(/[.-]/u).map((part) => Number.isNaN(Number(part)) ? part : Number(part));
|
|
1009
|
+
for (let i = 0; i < Math.max(pa.length, pb.length); i += 1) {
|
|
1010
|
+
const x = pa[i] ?? 0;
|
|
1011
|
+
const y = pb[i] ?? 0;
|
|
1012
|
+
if (x < y) return -1;
|
|
1013
|
+
if (x > y) return 1;
|
|
1014
|
+
}
|
|
1015
|
+
return 0;
|
|
1016
|
+
}
|
|
1005
1017
|
/** The DSH release the frame's packages pin as peers, so an app's DSH pin is the same one. */
|
|
1006
1018
|
const FRAME_DSH_VERSION = dshVersion;
|
|
1007
1019
|
/** Every package the frame publishes, in the file's order. */
|
|
@@ -1151,6 +1163,11 @@ const HOST_PROVIDED_IDS = /* @__PURE__ */ new Set([
|
|
|
1151
1163
|
"save",
|
|
1152
1164
|
"acryl-door"
|
|
1153
1165
|
]);
|
|
1166
|
+
/**
|
|
1167
|
+
* Services the app's rows provide that the host's own rows call: the door and the frame reach `pluginShare`, and no host row provides that name. Left out of
|
|
1168
|
+
* the isolate list, so they find it; every other service stays in the app's realm.
|
|
1169
|
+
*/
|
|
1170
|
+
const REACHED_FROM_HOST = /* @__PURE__ */ new Set(["pluginShare"]);
|
|
1154
1171
|
/** The generated `frame/app-plugins.mjs`, by the row that mounts it. */
|
|
1155
1172
|
const APP_PLUGINS_FILE = "frame/app-plugins.mjs";
|
|
1156
1173
|
/**
|
|
@@ -1176,12 +1193,14 @@ function appPluginsRow(prefix) {
|
|
|
1176
1193
|
" return path === base || path.startsWith(base + '/') ? path : base + (path.startsWith('/') ? '' : '/') + path",
|
|
1177
1194
|
"}",
|
|
1178
1195
|
"",
|
|
1179
|
-
"/** The router as the app's rows see it: mounts land under the prefix, every other member is the host router's. */",
|
|
1196
|
+
"/** The router as the app's rows see it: mounts land under the prefix, and a plugin's own request (its install check) finds them there; every other member is the host router's. */",
|
|
1180
1197
|
"function appRouter(router, prefix) {",
|
|
1181
1198
|
" const route = (path, app) => router.route(prefixedAppRoute(prefix, path), app)",
|
|
1199
|
+
" const request = (input, ...rest) => router.request(typeof input === 'string' && input.startsWith('/') ? prefixedAppRoute(prefix, input) : input, ...rest)",
|
|
1182
1200
|
" return new Proxy(router, {",
|
|
1183
1201
|
" get(target, property) {",
|
|
1184
1202
|
" if (property === 'route') return route",
|
|
1203
|
+
" if (property === 'request') return request",
|
|
1185
1204
|
" const value = Reflect.get(target, property, target)",
|
|
1186
1205
|
" return typeof value === 'function' ? value.bind(target) : value",
|
|
1187
1206
|
" },",
|
|
@@ -1229,7 +1248,7 @@ function providedServices(appDir) {
|
|
|
1229
1248
|
}
|
|
1230
1249
|
};
|
|
1231
1250
|
for (const row of ownRowIds(appDir)) walk(join(appDir, "plugins", row));
|
|
1232
|
-
return Object.fromEntries([...provided].sort().map((name) => [name, true]));
|
|
1251
|
+
return Object.fromEntries([...provided].filter((name) => !REACHED_FROM_HOST.has(name)).sort().map((name) => [name, true]));
|
|
1233
1252
|
}
|
|
1234
1253
|
/**
|
|
1235
1254
|
* The frame rows for an app: its routes row when it carries `src/frame.ts`, and the composition row when its `src/app.ts` exports `composeInto`.
|
|
@@ -1662,8 +1681,19 @@ function readTemplatePlugins(templateDir) {
|
|
|
1662
1681
|
const { plugins } = JSON.parse(readFileSync(file, "utf8"));
|
|
1663
1682
|
return plugins ?? [];
|
|
1664
1683
|
}
|
|
1684
|
+
/** A version a plugin's pin can be compared with: an exact one or a caret or tilde range. A tag, a path or a URL is the app's own choice. */
|
|
1685
|
+
function comparableVersion(spec) {
|
|
1686
|
+
return /^[\^~]?\d+\.\d+\.\d+(?:-[\w.]+)?$/u.test(spec) ? spec.replace(/^[\^~]/u, "") : void 0;
|
|
1687
|
+
}
|
|
1688
|
+
/** Whether a plugin's pin asks for more than what the app has: the plugin's code was written against that version. */
|
|
1689
|
+
function asksForNewer(wanted, current) {
|
|
1690
|
+
const a = comparableVersion(wanted);
|
|
1691
|
+
const b = comparableVersion(current);
|
|
1692
|
+
return a !== void 0 && b !== void 0 && compareVersions(a, b) > 0;
|
|
1693
|
+
}
|
|
1665
1694
|
/**
|
|
1666
|
-
* Add run-time dependencies to an app's package.json
|
|
1695
|
+
* Add run-time dependencies to an app's package.json and sort the keys. Returns the names to install: those added, and those moved because a plugin asks for a newer
|
|
1696
|
+
* version than the app lists (the plugin's new code needs it). A version the app lists that is the same or newer stays. A package the app lists as a development
|
|
1667
1697
|
* dependency too is taken out of that list: npm lets the development entry win, so `npm install --omit=dev` would leave a run-time dependency out.
|
|
1668
1698
|
*/
|
|
1669
1699
|
function mergeDependencies(appDir, dependencies) {
|
|
@@ -1671,14 +1701,16 @@ function mergeDependencies(appDir, dependencies) {
|
|
|
1671
1701
|
const manifest = JSON.parse(readFileSync(file, "utf8"));
|
|
1672
1702
|
const current = manifest.dependencies ?? {};
|
|
1673
1703
|
const added = Object.keys(dependencies).filter((name) => !(name in current));
|
|
1704
|
+
const moved = Object.entries(dependencies).filter(([name, wanted]) => current[name] !== void 0 && asksForNewer(wanted, current[name]));
|
|
1674
1705
|
const merged = {
|
|
1675
1706
|
...dependencies,
|
|
1676
|
-
...current
|
|
1707
|
+
...current,
|
|
1708
|
+
...Object.fromEntries(moved)
|
|
1677
1709
|
};
|
|
1678
1710
|
manifest.dependencies = Object.fromEntries(Object.entries(merged).sort(([a], [b]) => a.localeCompare(b)));
|
|
1679
1711
|
if (manifest.devDependencies !== void 0) manifest.devDependencies = Object.fromEntries(Object.entries(manifest.devDependencies).filter(([name]) => !(name in merged)));
|
|
1680
1712
|
writeFileSync(file, `${JSON.stringify(manifest, null, 2)}\n`);
|
|
1681
|
-
return added;
|
|
1713
|
+
return [...added, ...moved.map(([name]) => name)];
|
|
1682
1714
|
}
|
|
1683
1715
|
/** Add `package.json` "imports" entries (`#acryl-kv`: `./plugins/acryl-kv/src/index.ts`); an entry the app already has is kept. Returns the names added. */
|
|
1684
1716
|
function mergeImports(appDir, imports, pluginsDir) {
|
|
@@ -2142,7 +2174,7 @@ async function add(options, io) {
|
|
|
2142
2174
|
if (refused !== 0) return refused;
|
|
2143
2175
|
}
|
|
2144
2176
|
io.stdout.write(`added ${toCopy.map((plugin) => plugin.name).join(", ")} to ${appDir}\n`);
|
|
2145
|
-
if (addedDependencies.length > 0) io.stdout.write(`
|
|
2177
|
+
if (addedDependencies.length > 0) io.stdout.write(`dependencies to install: ${addedDependencies.join(", ")} (run npm install)\n`);
|
|
2146
2178
|
for (const plugin of toCopy.filter((plugin) => names.includes(plugin.name))) {
|
|
2147
2179
|
const mounted = MOUNTED.find((candidate) => candidate.name === plugin.name);
|
|
2148
2180
|
const result = mounted ? mount(appDir, mounted) : void 0;
|
|
@@ -3765,7 +3797,7 @@ async function upgrade(options, io) {
|
|
|
3765
3797
|
const upgradedPlugins = plans.filter((p) => [...p.files.values()].some((s) => s !== "same" && s !== "extra") || p.isNew).map((p) => p.plugin.name);
|
|
3766
3798
|
io.stdout.write(`\nupgraded ${[...upgradedPlugins, ...frameChanged ? ["the frame"] : []].join(", ")}\n`);
|
|
3767
3799
|
if (conflicts + frameBackups > 0) io.stdout.write(`the ${conflicts + frameBackups} edited file(s) replaced by --force are saved in ${posix$1(relative(appDir, backup))}/\n`);
|
|
3768
|
-
io.stdout.write(`acrylblends is now ^${VERSION} in package.json${addedDependencies.length > 0 ? `;
|
|
3800
|
+
io.stdout.write(`acrylblends is now ^${VERSION} in package.json${addedDependencies.length > 0 ? `; dependencies to install: ${[...new Set(addedDependencies)].join(", ")}` : ""}: run npm install, then npm run check and npm test\n`);
|
|
3769
3801
|
return 0;
|
|
3770
3802
|
} finally {
|
|
3771
3803
|
rmSync(scratch, {
|