@wairon/cli 5.1.1-dev.87 → 5.1.1-dev.88
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/cli/index.js +3757 -2421
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +329 -109
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3060,7 +3060,7 @@ var require_dist = __commonJS({
|
|
|
3060
3060
|
function slug(name) {
|
|
3061
3061
|
return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
3062
3062
|
}
|
|
3063
|
-
var
|
|
3063
|
+
var fs25 = __toESM2(require("fs"));
|
|
3064
3064
|
var path46 = __toESM2(require("path"));
|
|
3065
3065
|
var import_fflate = require_node();
|
|
3066
3066
|
var SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", ".git", ".hg", ".svn"]);
|
|
@@ -3100,8 +3100,8 @@ var require_dist = __commonJS({
|
|
|
3100
3100
|
function writeTree(destDir, files) {
|
|
3101
3101
|
for (const file of files) {
|
|
3102
3102
|
const absolute = path46.join(destDir, file.path);
|
|
3103
|
-
|
|
3104
|
-
|
|
3103
|
+
fs25.mkdirSync(path46.dirname(absolute), { recursive: true });
|
|
3104
|
+
fs25.writeFileSync(absolute, file.contents);
|
|
3105
3105
|
}
|
|
3106
3106
|
}
|
|
3107
3107
|
function classifyKind(name, symlinks) {
|
|
@@ -3110,14 +3110,14 @@ var require_dist = __commonJS({
|
|
|
3110
3110
|
return "file";
|
|
3111
3111
|
}
|
|
3112
3112
|
function walkPackDir(root, current2, out) {
|
|
3113
|
-
for (const entry of
|
|
3113
|
+
for (const entry of fs25.readdirSync(current2, { withFileTypes: true })) {
|
|
3114
3114
|
if (entry.isDirectory()) {
|
|
3115
3115
|
if (SKIP_DIRS.has(entry.name)) continue;
|
|
3116
3116
|
walkPackDir(root, path46.join(current2, entry.name), out);
|
|
3117
3117
|
} else if (entry.isFile()) {
|
|
3118
3118
|
const absolute = path46.join(current2, entry.name);
|
|
3119
3119
|
const relative22 = path46.relative(root, absolute).split(path46.sep).join("/");
|
|
3120
|
-
out.push({ path: relative22, contents:
|
|
3120
|
+
out.push({ path: relative22, contents: fs25.readFileSync(absolute) });
|
|
3121
3121
|
}
|
|
3122
3122
|
}
|
|
3123
3123
|
}
|
|
@@ -3604,6 +3604,7 @@ __export(src_exports, {
|
|
|
3604
3604
|
generateDiagramSet: () => generateDiagramSet,
|
|
3605
3605
|
generateSequenceDiagram: () => generateSequenceDiagram,
|
|
3606
3606
|
getExporter: () => getExporter,
|
|
3607
|
+
getHostedLookup: () => getHostedLookup,
|
|
3607
3608
|
getLoaderIssues: () => getLoaderIssues,
|
|
3608
3609
|
getProjectRoot: () => getProjectRoot,
|
|
3609
3610
|
getProjectRootOverride: () => getProjectRootOverride,
|
|
@@ -3735,6 +3736,7 @@ __export(src_exports, {
|
|
|
3735
3736
|
resolveVariantGuidance: () => resolveVariantGuidance,
|
|
3736
3737
|
retireSpecialists: () => retireSpecialists,
|
|
3737
3738
|
rewriteReferences: () => rewriteReferences2,
|
|
3739
|
+
runWithHostedLookup: () => runWithHostedLookup,
|
|
3738
3740
|
runWithProjectBinding: () => runWithProjectBinding,
|
|
3739
3741
|
runWithProjectRoot: () => runWithProjectRoot,
|
|
3740
3742
|
sameContract: () => sameContract,
|
|
@@ -3844,18 +3846,33 @@ function runWithProjectBinding(dir, reach2, fn) {
|
|
|
3844
3846
|
root: path.resolve(dir),
|
|
3845
3847
|
topRoot: path.resolve(reach2.topRoot),
|
|
3846
3848
|
parentReach: reach2.parentReach,
|
|
3847
|
-
...reach2.narrowed ? { narrowed: true } : {}
|
|
3849
|
+
...reach2.narrowed ? { narrowed: true } : {},
|
|
3850
|
+
...reach2.unwritableRoots ? { unwritableRoots: reach2.unwritableRoots.map((r) => path.resolve(r)) } : {},
|
|
3851
|
+
...reach2.hostedLookup ? { hostedLookup: reach2.hostedLookup } : {}
|
|
3848
3852
|
},
|
|
3849
3853
|
fn
|
|
3850
3854
|
);
|
|
3851
3855
|
}
|
|
3856
|
+
function getHostedLookup() {
|
|
3857
|
+
return requestRootStore.getStore()?.hostedLookup ?? null;
|
|
3858
|
+
}
|
|
3859
|
+
function runWithHostedLookup(lookup2, fn) {
|
|
3860
|
+
const scope = requestRootStore.getStore();
|
|
3861
|
+
if (!scope?.hostedLookup) return fn();
|
|
3862
|
+
return requestRootStore.run({ ...scope, hostedLookup: lookup2 }, fn);
|
|
3863
|
+
}
|
|
3852
3864
|
function getRequestProjectRoot() {
|
|
3853
3865
|
return requestRootStore.getStore()?.root ?? null;
|
|
3854
3866
|
}
|
|
3855
3867
|
function getRequestParentReach() {
|
|
3856
3868
|
const scope = requestRootStore.getStore();
|
|
3857
3869
|
if (!scope || scope.parentReach === void 0) return null;
|
|
3858
|
-
return {
|
|
3870
|
+
return {
|
|
3871
|
+
topRoot: scope.topRoot,
|
|
3872
|
+
parentReach: scope.parentReach,
|
|
3873
|
+
...scope.narrowed ? { narrowed: true } : {},
|
|
3874
|
+
...scope.unwritableRoots ? { unwritableRoots: scope.unwritableRoots } : {}
|
|
3875
|
+
};
|
|
3859
3876
|
}
|
|
3860
3877
|
function setProjectRoot(dir) {
|
|
3861
3878
|
projectRootOverride = dir === null ? null : path.resolve(dir);
|
|
@@ -4571,7 +4588,8 @@ var ProjectProfileSelectionSchema = import_zod3.z.object({
|
|
|
4571
4588
|
selectedAt: import_zod3.z.string()
|
|
4572
4589
|
});
|
|
4573
4590
|
var ExternalSourceSchema = import_zod3.z.object({
|
|
4574
|
-
path: import_zod3.z.string()
|
|
4591
|
+
path: import_zod3.z.string().optional(),
|
|
4592
|
+
hosted: import_zod3.z.string().optional()
|
|
4575
4593
|
});
|
|
4576
4594
|
var ExternalDeclarationSchema = import_zod3.z.object({
|
|
4577
4595
|
/** The producer's project id; defaults to the alias. Plain string: a malformed id is REPORTED, never unreadable. */
|
|
@@ -4942,6 +4960,12 @@ function projectIdentity(config, lockedProjectId) {
|
|
|
4942
4960
|
};
|
|
4943
4961
|
}
|
|
4944
4962
|
var EXTERNAL_ALIAS_RE = /^[a-z0-9_-]+$/;
|
|
4963
|
+
function sourceProblem(source) {
|
|
4964
|
+
if (source === void 0) return void 0;
|
|
4965
|
+
const named2 = (source.path !== void 0 ? 1 : 0) + (source.hosted !== void 0 ? 1 : 0);
|
|
4966
|
+
if (named2 === 1) return void 0;
|
|
4967
|
+
return named2 === 0 ? "its `source` names neither `path` nor `hosted` \u2014 give exactly one" : "its `source` names both `path` and `hosted` \u2014 give exactly one";
|
|
4968
|
+
}
|
|
4945
4969
|
var USE_ENTRY_RE = /^(\*|[a-z0-9_-]+)$/;
|
|
4946
4970
|
function readUse(alias, use) {
|
|
4947
4971
|
const list = Array.isArray(use) ? use.map((u) => String(u)) : [];
|
|
@@ -4956,11 +4980,12 @@ function declaredExternals(config) {
|
|
|
4956
4980
|
return Object.entries(config.externals ?? {}).map(([alias, declaration2]) => {
|
|
4957
4981
|
const project = declaration2?.project ?? alias;
|
|
4958
4982
|
const imports = readUse(alias, declaration2?.use);
|
|
4959
|
-
const problem = !EXTERNAL_ALIAS_RE.test(alias) ? PROJECT_ID_RE.test(alias) ? `the alias "${alias}" is not a reference name ([a-z0-9-_]+) \u2014 a dotted producer id needs an explicit alias, e.g. \`${alias.replace(/\./g, "-")}: { project: ${alias} }\`` : `the alias "${alias}" breaks [a-z0-9-_]+` : config.members?.[alias] !== void 0 ? `the alias "${alias}" is also declared under \`members\` \u2014 one alias names one project` : !PROJECT_ID_RE.test(project) ? `the producer id "${project}" breaks the project-id grammar` : imports.problem;
|
|
4983
|
+
const problem = !EXTERNAL_ALIAS_RE.test(alias) ? PROJECT_ID_RE.test(alias) ? `the alias "${alias}" is not a reference name ([a-z0-9-_]+) \u2014 a dotted producer id needs an explicit alias, e.g. \`${alias.replace(/\./g, "-")}: { project: ${alias} }\`` : `the alias "${alias}" breaks [a-z0-9-_]+` : config.members?.[alias] !== void 0 ? `the alias "${alias}" is also declared under \`members\` \u2014 one alias names one project` : !PROJECT_ID_RE.test(project) ? `the producer id "${project}" breaks the project-id grammar` : sourceProblem(declaration2?.source) ?? imports.problem;
|
|
4960
4984
|
return {
|
|
4961
4985
|
alias,
|
|
4962
4986
|
project,
|
|
4963
4987
|
...declaration2?.source?.path !== void 0 ? { sourcePath: declaration2.source.path } : {},
|
|
4988
|
+
...declaration2?.source?.hosted !== void 0 ? { sourceHosted: declaration2.source.hosted } : {},
|
|
4964
4989
|
...problem ? { problem } : {},
|
|
4965
4990
|
use: imports.use
|
|
4966
4991
|
};
|
|
@@ -7556,10 +7581,10 @@ function stepGraph(method) {
|
|
|
7556
7581
|
const s = byNum.get(n);
|
|
7557
7582
|
if (s.type !== "parallel" || s.endStep === void 0 || !s.branches?.length) continue;
|
|
7558
7583
|
const entries = s.branches.map((b) => b.step).sort((a, b) => a - b);
|
|
7559
|
-
const
|
|
7584
|
+
const join28 = fallNext(s.endStep);
|
|
7560
7585
|
for (let i = 0; i < entries.length; i++) {
|
|
7561
7586
|
const armEnd = i + 1 < entries.length ? prevOf(entries[i + 1]) : s.endStep;
|
|
7562
|
-
if (armEnd !== void 0 && armEnd >= entries[i]) armEndJoin.set(armEnd,
|
|
7587
|
+
if (armEnd !== void 0 && armEnd >= entries[i]) armEndJoin.set(armEnd, join28);
|
|
7563
7588
|
}
|
|
7564
7589
|
}
|
|
7565
7590
|
const successorsOf = (n) => {
|
|
@@ -13418,10 +13443,11 @@ function isWithinDir(dir, target) {
|
|
|
13418
13443
|
const rel2 = path10.relative(path10.resolve(dir), path10.resolve(target));
|
|
13419
13444
|
return rel2 === "" || !rel2.startsWith("..") && !path10.isAbsolute(rel2);
|
|
13420
13445
|
}
|
|
13421
|
-
function producerUnreadable(
|
|
13446
|
+
function producerUnreadable(external) {
|
|
13447
|
+
const directory = external.directory;
|
|
13422
13448
|
if (!directory) return "the producer has no root directory";
|
|
13423
13449
|
const reach2 = getRequestParentReach();
|
|
13424
|
-
if (reach2) {
|
|
13450
|
+
if (reach2 && external.sourceKind !== "hosted") {
|
|
13425
13451
|
const bound2 = getProjectRoot();
|
|
13426
13452
|
const ceiling = reach2.parentReach ? reach2.topRoot ?? bound2 : bound2;
|
|
13427
13453
|
if (!isWithinDir(ceiling, directory)) return OUT_OF_REACH;
|
|
@@ -13450,7 +13476,7 @@ function usedDigests(usage, snapshot) {
|
|
|
13450
13476
|
function pinBinding(binding, lock) {
|
|
13451
13477
|
const { external } = binding;
|
|
13452
13478
|
const unexported = binding.usage?.unexported ?? [];
|
|
13453
|
-
const unreadable = producerUnreadable(external
|
|
13479
|
+
const unreadable = producerUnreadable(external);
|
|
13454
13480
|
let snapshot;
|
|
13455
13481
|
try {
|
|
13456
13482
|
if (unreadable) throw new Error(unreadable);
|
|
@@ -13553,7 +13579,7 @@ function externalStatus(binding, lock) {
|
|
|
13553
13579
|
const entry = lock?.externals[external.alias];
|
|
13554
13580
|
const pinned = entry !== void 0 && externalsRepository.readSnapshot(external.alias) !== null;
|
|
13555
13581
|
const base = { alias: external.alias, project: external.project, sourceKind: external.sourceKind, pinned };
|
|
13556
|
-
const unreadable = external.sourceKind === "unresolved" ? `the external does not resolve: ${external.problem}` : producerUnreadable(external
|
|
13582
|
+
const unreadable = external.sourceKind === "unresolved" ? hostedOnly(external) ? external.problem : `the external does not resolve: ${external.problem}` : producerUnreadable(external);
|
|
13557
13583
|
let live = null;
|
|
13558
13584
|
let reason = unreadable;
|
|
13559
13585
|
if (!reason) {
|
|
@@ -13564,7 +13590,7 @@ function externalStatus(binding, lock) {
|
|
|
13564
13590
|
}
|
|
13565
13591
|
}
|
|
13566
13592
|
if (!live) {
|
|
13567
|
-
const outOfReach = reason === OUT_OF_REACH || !binding.reachable && external.sourceKind !== "family";
|
|
13593
|
+
const outOfReach = reason === OUT_OF_REACH || hostedOutOfReach(external) || !binding.reachable && external.sourceKind !== "family";
|
|
13568
13594
|
return {
|
|
13569
13595
|
...base,
|
|
13570
13596
|
reachable: false,
|
|
@@ -13575,7 +13601,7 @@ function externalStatus(binding, lock) {
|
|
|
13575
13601
|
};
|
|
13576
13602
|
}
|
|
13577
13603
|
const drifted = entry !== void 0 ? contentDigest(live) !== entry.digest : void 0;
|
|
13578
|
-
if (external.sourceKind === "path") {
|
|
13604
|
+
if (external.sourceKind === "path" || external.sourceKind === "hosted") {
|
|
13579
13605
|
return { ...base, reachable: true, stale: false, ...drifted !== void 0 ? { drifted } : {}, uses: [{ state: "unavailable", code: CHECK_UNAVAILABLE, detail: OUTSIDE_FAMILY }], detail: OUTSIDE_FAMILY };
|
|
13580
13606
|
}
|
|
13581
13607
|
const uses = compareUses(entry, binding.usage, live);
|
|
@@ -13587,6 +13613,12 @@ function externalStatus(binding, lock) {
|
|
|
13587
13613
|
uses
|
|
13588
13614
|
};
|
|
13589
13615
|
}
|
|
13616
|
+
function hostedOnly(external) {
|
|
13617
|
+
return external.hosted !== void 0 && external.sourceKind === "unresolved" && getHostedLookup() === null;
|
|
13618
|
+
}
|
|
13619
|
+
function hostedOutOfReach(external) {
|
|
13620
|
+
return external.hosted !== void 0 && external.sourceKind === "unresolved" && getHostedLookup() !== null;
|
|
13621
|
+
}
|
|
13590
13622
|
function getExternalsStatus() {
|
|
13591
13623
|
const bindings = resolveDeclared();
|
|
13592
13624
|
const lock = externalsRepository.readLock();
|
|
@@ -14250,7 +14282,7 @@ function defaultTargetConfig(type) {
|
|
|
14250
14282
|
enabled: true
|
|
14251
14283
|
};
|
|
14252
14284
|
}
|
|
14253
|
-
var WAIRON_VERSION = "5.1.1-dev.
|
|
14285
|
+
var WAIRON_VERSION = "5.1.1-dev.88";
|
|
14254
14286
|
var GITHUB_REPO = "SYW-Apps/Waffle-AIron";
|
|
14255
14287
|
var ARCHITECT_AGENT_ID = "agent-architect";
|
|
14256
14288
|
var ARCHITECT_TEMPLATE_ID = "architect";
|
|
@@ -15047,13 +15079,13 @@ function buildCodeIndex(model) {
|
|
|
15047
15079
|
const to = resolveImport(scope, specifier, paths);
|
|
15048
15080
|
return to ? republishedFrom(to) : NO_ORIGIN;
|
|
15049
15081
|
};
|
|
15050
|
-
const
|
|
15082
|
+
const scopeOf2 = (site, from) => {
|
|
15051
15083
|
const path46 = pathKey(site.from ?? from);
|
|
15052
15084
|
const f = facts.get(path46);
|
|
15053
15085
|
return f?.status === "analyzed" && f.analysisGrade === "exact" ? { path: path46, facts: f } : void 0;
|
|
15054
15086
|
};
|
|
15055
15087
|
const originOf2 = (site, from) => {
|
|
15056
|
-
const resolved =
|
|
15088
|
+
const resolved = scopeOf2(site, from);
|
|
15057
15089
|
if (!resolved) return NO_ORIGIN;
|
|
15058
15090
|
const { path: scope, facts: f } = resolved;
|
|
15059
15091
|
const landing = (specifier) => landingFrom(scope, specifier);
|
|
@@ -15075,7 +15107,7 @@ function buildCodeIndex(model) {
|
|
|
15075
15107
|
const possibleOriginsOf = (site, from) => {
|
|
15076
15108
|
const proven = originOf2(site, from);
|
|
15077
15109
|
if (!site.field && !site.constructed && !site.via) return proven;
|
|
15078
|
-
const resolved =
|
|
15110
|
+
const resolved = scopeOf2(site, from);
|
|
15079
15111
|
if (!resolved) return proven;
|
|
15080
15112
|
const { path: scope, facts: f } = resolved;
|
|
15081
15113
|
const out = new Set(proven);
|
|
@@ -21455,7 +21487,7 @@ var technologyRule = {
|
|
|
21455
21487
|
for (const tech of impl.technologies) declarations.push({ comp, tech });
|
|
21456
21488
|
}
|
|
21457
21489
|
const scopes = /* @__PURE__ */ new Map();
|
|
21458
|
-
const
|
|
21490
|
+
const scopeOf2 = (comp) => {
|
|
21459
21491
|
const cached = scopes.get(comp.id);
|
|
21460
21492
|
if (cached) return cached;
|
|
21461
21493
|
const compSet = ownsClosure(ownershipRoot(comp.id));
|
|
@@ -21482,7 +21514,7 @@ var technologyRule = {
|
|
|
21482
21514
|
const key = tech.toLowerCase().split(/[^a-z0-9]+/).filter(Boolean).join("");
|
|
21483
21515
|
const home = homes.get(key) ?? { label: tech, match: match2, ownerComponents: /* @__PURE__ */ new Set(), scope: /* @__PURE__ */ new Set() };
|
|
21484
21516
|
home.ownerComponents.add(comp.id);
|
|
21485
|
-
for (const id of
|
|
21517
|
+
for (const id of scopeOf2(comp)) home.scope.add(id);
|
|
21486
21518
|
homes.set(key, home);
|
|
21487
21519
|
}
|
|
21488
21520
|
if (homes.size === 0) return;
|
|
@@ -25167,6 +25199,7 @@ function bindExternals(node, root, nodes) {
|
|
|
25167
25199
|
return declaredExternals(root.config).map((decl) => {
|
|
25168
25200
|
const unresolved = (problem) => ({ alias: decl.alias, project: decl.project, sourceKind: "unresolved", audience: "instance", problem });
|
|
25169
25201
|
if (decl.problem) return unresolved(decl.problem);
|
|
25202
|
+
if (decl.sourceHosted !== void 0) return { alias: decl.alias, project: decl.project, sourceKind: "hosted", hosted: decl.sourceHosted, audience: "instance" };
|
|
25170
25203
|
if (decl.sourcePath !== void 0) {
|
|
25171
25204
|
const directory = path18.resolve(node.directory, decl.sourcePath);
|
|
25172
25205
|
const found = nodes.find((n) => dirKey(n.directory) === dirKey(directory));
|
|
@@ -30169,6 +30202,17 @@ function unregisterDomain(id) {
|
|
|
30169
30202
|
|
|
30170
30203
|
// src/core/external-producers.ts
|
|
30171
30204
|
var path21 = __toESM(require("path"));
|
|
30205
|
+
function hostedOnlyProducer(id) {
|
|
30206
|
+
return `hosted-only producer \`${id}\`: available only through the hosted server`;
|
|
30207
|
+
}
|
|
30208
|
+
function resolveHosted(external) {
|
|
30209
|
+
if (external.sourceKind !== "hosted" || external.hosted === void 0) return external;
|
|
30210
|
+
const lookup2 = getHostedLookup();
|
|
30211
|
+
const unresolved = (problem) => ({ ...external, sourceKind: "unresolved", problem });
|
|
30212
|
+
if (!lookup2) return unresolved(hostedOnlyProducer(external.hosted));
|
|
30213
|
+
const root = lookup2(external.hosted);
|
|
30214
|
+
return root === null ? unresolved(`the hosted producer \`${external.hosted}\` is unknown or outside this request's reach`) : { ...external, directory: path21.resolve(root) };
|
|
30215
|
+
}
|
|
30172
30216
|
function dirKey2(dir) {
|
|
30173
30217
|
const resolved = path21.resolve(dir);
|
|
30174
30218
|
return process.platform === "win32" ? resolved.toLowerCase() : resolved;
|
|
@@ -30194,11 +30238,14 @@ function resolveDeclared() {
|
|
|
30194
30238
|
const family = graph();
|
|
30195
30239
|
const node = consumerNode(family, bound2);
|
|
30196
30240
|
if (!node) return null;
|
|
30197
|
-
return node.externals.map((
|
|
30198
|
-
external
|
|
30199
|
-
|
|
30200
|
-
|
|
30201
|
-
|
|
30241
|
+
return node.externals.map((declared) => {
|
|
30242
|
+
const external = resolveHosted(declared);
|
|
30243
|
+
return {
|
|
30244
|
+
external,
|
|
30245
|
+
...external.sourceKind === "family" && external.producer !== void 0 ? { usage: exportUsage(node.namespace, external.producer) } : {},
|
|
30246
|
+
reachable: whole
|
|
30247
|
+
};
|
|
30248
|
+
});
|
|
30202
30249
|
});
|
|
30203
30250
|
return answer(top) ?? answer(bound2) ?? [];
|
|
30204
30251
|
}
|
|
@@ -30881,7 +30928,7 @@ function carryDeclarations(scan, result) {
|
|
|
30881
30928
|
const bound2 = projectConfigRepository.load() ?? {};
|
|
30882
30929
|
for (const [alias, decl] of Object.entries(scan.config?.externals ?? {})) {
|
|
30883
30930
|
if (carriedExternal(scan, alias, decl) === "parent") continue;
|
|
30884
|
-
const source = decl.source && !path22.isAbsolute(decl.source.path) ? { path: toPosixPath(path22.relative(root, path22.resolve(scan.memberDir, decl.source.path))) } : decl.source;
|
|
30931
|
+
const source = decl.source?.path !== void 0 && !path22.isAbsolute(decl.source.path) ? { path: toPosixPath(path22.relative(root, path22.resolve(scan.memberDir, decl.source.path))) } : decl.source;
|
|
30885
30932
|
if (bound2.members?.[alias] === void 0) {
|
|
30886
30933
|
projectConfigRepository.declareExternal(alias, {
|
|
30887
30934
|
...decl.project !== void 0 ? { project: decl.project } : {},
|
|
@@ -32583,7 +32630,7 @@ function importSpecTree(archive, options) {
|
|
|
32583
32630
|
throw new Error("incompatible .waitree archive (format or minimum wairon version)");
|
|
32584
32631
|
}
|
|
32585
32632
|
const destDir = path31.resolve(options.destDir ?? getProjectRoot());
|
|
32586
|
-
const
|
|
32633
|
+
const occupied2 = hasSpecTree(destDir);
|
|
32587
32634
|
const authored = hasAuthoredSpecs(destDir);
|
|
32588
32635
|
if (authored && options.replaceExisting !== true) {
|
|
32589
32636
|
throw new Error(
|
|
@@ -32598,7 +32645,7 @@ function importSpecTree(archive, options) {
|
|
|
32598
32645
|
discardStagingDir(stagingDir);
|
|
32599
32646
|
throw err;
|
|
32600
32647
|
}
|
|
32601
|
-
const backupPath = commitStagedTree(stagingDir, destDir, extraction.roots,
|
|
32648
|
+
const backupPath = commitStagedTree(stagingDir, destDir, extraction.roots, occupied2);
|
|
32602
32649
|
discardStagingDir(stagingDir);
|
|
32603
32650
|
invalidateSpecCache();
|
|
32604
32651
|
const result = {
|
|
@@ -32606,7 +32653,7 @@ function importSpecTree(archive, options) {
|
|
|
32606
32653
|
projectName: extraction.manifest.projectName,
|
|
32607
32654
|
roots: extraction.roots,
|
|
32608
32655
|
fileCount: extraction.writtenPaths.length,
|
|
32609
|
-
replaced:
|
|
32656
|
+
replaced: occupied2
|
|
32610
32657
|
};
|
|
32611
32658
|
if (backupPath) result.backupPath = backupPath;
|
|
32612
32659
|
if (extraction.manifest.stateId) result.stateId = extraction.manifest.stateId;
|
|
@@ -35205,6 +35252,7 @@ function pin(p, log) {
|
|
|
35205
35252
|
}
|
|
35206
35253
|
|
|
35207
35254
|
// src/migrations/membership.ts
|
|
35255
|
+
var fs22 = __toESM(require("fs"));
|
|
35208
35256
|
var path40 = __toESM(require("path"));
|
|
35209
35257
|
|
|
35210
35258
|
// src/migrations/family-files.ts
|
|
@@ -35285,39 +35333,93 @@ function within2(root, candidate) {
|
|
|
35285
35333
|
const rel2 = nodePath.relative(root, candidate);
|
|
35286
35334
|
return rel2 === "" || !rel2.startsWith("..") && !nodePath.isAbsolute(rel2);
|
|
35287
35335
|
}
|
|
35336
|
+
function areaFiles(owner, area) {
|
|
35337
|
+
const out = [];
|
|
35338
|
+
const walk2 = (rel2) => {
|
|
35339
|
+
if (rel2 === `${WAI}/${TRANSACTIONS}`) return;
|
|
35340
|
+
const abs = nodePath.join(owner, ...rel2.split("/"));
|
|
35341
|
+
let stat;
|
|
35342
|
+
try {
|
|
35343
|
+
stat = fs21.lstatSync(abs);
|
|
35344
|
+
} catch {
|
|
35345
|
+
return;
|
|
35346
|
+
}
|
|
35347
|
+
if (stat.isSymbolicLink()) return;
|
|
35348
|
+
if (stat.isFile()) {
|
|
35349
|
+
out.push(rel2);
|
|
35350
|
+
return;
|
|
35351
|
+
}
|
|
35352
|
+
if (!stat.isDirectory()) return;
|
|
35353
|
+
for (const name of fs21.readdirSync(abs)) walk2(`${rel2}/${name}`);
|
|
35354
|
+
};
|
|
35355
|
+
walk2(area.split(nodePath.sep).join("/").replace(/\/+$/, ""));
|
|
35356
|
+
return out.sort();
|
|
35357
|
+
}
|
|
35358
|
+
function everyFile(owner) {
|
|
35359
|
+
const out = [];
|
|
35360
|
+
const walk2 = (dir, rel2) => {
|
|
35361
|
+
let entries;
|
|
35362
|
+
try {
|
|
35363
|
+
entries = fs21.readdirSync(dir, { withFileTypes: true });
|
|
35364
|
+
} catch {
|
|
35365
|
+
return;
|
|
35366
|
+
}
|
|
35367
|
+
for (const entry of entries) {
|
|
35368
|
+
const relPath = rel2 ? `${rel2}/${entry.name}` : entry.name;
|
|
35369
|
+
if (relPath === `${WAI}/${TRANSACTIONS}`) continue;
|
|
35370
|
+
if (entry.isSymbolicLink()) continue;
|
|
35371
|
+
if (entry.isDirectory()) walk2(nodePath.join(dir, entry.name), relPath);
|
|
35372
|
+
else if (entry.isFile()) out.push(relPath);
|
|
35373
|
+
}
|
|
35374
|
+
};
|
|
35375
|
+
walk2(owner, "");
|
|
35376
|
+
return out.sort();
|
|
35377
|
+
}
|
|
35378
|
+
function insideWhole(whole, dir) {
|
|
35379
|
+
return whole.some((w) => within2(w, dir));
|
|
35380
|
+
}
|
|
35381
|
+
function scopedFiles(owner, areas) {
|
|
35382
|
+
return areas ? [...new Set(areas.flatMap((a) => areaFiles(owner, a)))].sort() : waiFiles(owner);
|
|
35383
|
+
}
|
|
35288
35384
|
function mirror(scope, target) {
|
|
35289
35385
|
const digests = /* @__PURE__ */ new Map();
|
|
35290
|
-
|
|
35291
|
-
|
|
35292
|
-
|
|
35293
|
-
|
|
35294
|
-
const at = nodePath.join(target, nodePath.relative(scope.familyRoot, project));
|
|
35295
|
-
for (const rel2 of waiFiles(project)) {
|
|
35296
|
-
const live = nodePath.join(project, ...rel2.split("/"));
|
|
35297
|
-
let bytes;
|
|
35298
|
-
try {
|
|
35299
|
-
bytes = fs21.readFileSync(live);
|
|
35300
|
-
} catch (e) {
|
|
35301
|
-
throw new Error(`could not copy ${live} into the rehearsal: ${e instanceof Error ? e.message : String(e)}`);
|
|
35302
|
-
}
|
|
35303
|
-
const copy = nodePath.join(at, ...rel2.split("/"));
|
|
35304
|
-
fs21.mkdirSync(nodePath.dirname(copy), { recursive: true });
|
|
35305
|
-
fs21.writeFileSync(copy, bytes);
|
|
35306
|
-
digests.set(live, sha2562(bytes));
|
|
35386
|
+
const whole = scope.whole ?? [];
|
|
35387
|
+
for (const owner of [...scope.projects, ...whole]) {
|
|
35388
|
+
if (!within2(scope.familyRoot, owner)) {
|
|
35389
|
+
throw new Error(`${owner} does not lie within the family root ${scope.familyRoot}; a rehearsal copies only the family's own trees`);
|
|
35307
35390
|
}
|
|
35308
35391
|
}
|
|
35392
|
+
for (const project of scope.projects.filter((p) => !insideWhole(whole, p))) {
|
|
35393
|
+
copyFiles(project, scopedFiles(project, scope.areas), nodePath.join(target, nodePath.relative(scope.familyRoot, project)), digests);
|
|
35394
|
+
}
|
|
35395
|
+
for (const owner of whole) {
|
|
35396
|
+
copyFiles(owner, everyFile(owner), nodePath.join(target, nodePath.relative(scope.familyRoot, owner)), digests);
|
|
35397
|
+
}
|
|
35309
35398
|
return digests;
|
|
35310
35399
|
}
|
|
35400
|
+
function copyFiles(owner, rels, at, digests) {
|
|
35401
|
+
fs21.mkdirSync(at, { recursive: true });
|
|
35402
|
+
for (const rel2 of rels) {
|
|
35403
|
+
const live = nodePath.join(owner, ...rel2.split("/"));
|
|
35404
|
+
let bytes;
|
|
35405
|
+
try {
|
|
35406
|
+
bytes = fs21.readFileSync(live);
|
|
35407
|
+
} catch (e) {
|
|
35408
|
+
throw new Error(`could not copy ${live} into the rehearsal: ${e instanceof Error ? e.message : String(e)}`);
|
|
35409
|
+
}
|
|
35410
|
+
const copy = nodePath.join(at, ...rel2.split("/"));
|
|
35411
|
+
fs21.mkdirSync(nodePath.dirname(copy), { recursive: true });
|
|
35412
|
+
fs21.writeFileSync(copy, bytes);
|
|
35413
|
+
digests.set(live, sha2562(bytes));
|
|
35414
|
+
}
|
|
35415
|
+
}
|
|
35311
35416
|
function compare4(rehearsal) {
|
|
35312
35417
|
const changes = [];
|
|
35313
35418
|
const seen = /* @__PURE__ */ new Set();
|
|
35314
|
-
for (const
|
|
35315
|
-
|
|
35316
|
-
|
|
35317
|
-
|
|
35318
|
-
const change = changeOf(rehearsal, live, rel2, sha2562(fs21.readFileSync(nodePath.join(owner, ...rel2.split("/")))));
|
|
35319
|
-
if (change) changes.push(change);
|
|
35320
|
-
}
|
|
35419
|
+
for (const [live, copyRoot, rel2] of comparedFiles(rehearsal)) {
|
|
35420
|
+
seen.add(nodePath.join(live, ...rel2.split("/")));
|
|
35421
|
+
const change = changeOf(rehearsal, live, rel2, sha2562(fs21.readFileSync(nodePath.join(copyRoot, ...rel2.split("/")))));
|
|
35422
|
+
if (change) changes.push(change);
|
|
35321
35423
|
}
|
|
35322
35424
|
for (const [liveFile, base] of rehearsal.baseDigests) {
|
|
35323
35425
|
if (seen.has(liveFile)) continue;
|
|
@@ -35326,6 +35428,16 @@ function compare4(rehearsal) {
|
|
|
35326
35428
|
}
|
|
35327
35429
|
return changes.sort(byOwnerThenPath);
|
|
35328
35430
|
}
|
|
35431
|
+
function comparedFiles(rehearsal) {
|
|
35432
|
+
const whole = rehearsal.whole ?? [];
|
|
35433
|
+
const owners = rehearsal.areas ? [...rehearsal.roots].map(([live, copy]) => [live, copy, scopedFiles(copy, rehearsal.areas)]) : waiOwners(rehearsal.directory).map((copy) => [nodePath.join(rehearsal.familyRoot, nodePath.relative(rehearsal.directory, copy)), copy, waiFiles(copy)]);
|
|
35434
|
+
const imageOf = (live) => nodePath.join(rehearsal.directory, nodePath.relative(rehearsal.familyRoot, live));
|
|
35435
|
+
const all = [
|
|
35436
|
+
...owners.filter(([live]) => !insideWhole(whole, live)),
|
|
35437
|
+
...whole.map((live) => [live, imageOf(live), everyFile(imageOf(live))])
|
|
35438
|
+
];
|
|
35439
|
+
return all.flatMap(([live, copy, rels]) => rels.map((rel2) => [live, copy, rel2]));
|
|
35440
|
+
}
|
|
35329
35441
|
function changeOf(rehearsal, live, rel2, staged) {
|
|
35330
35442
|
const base = rehearsal.baseDigests.get(nodePath.join(live, ...rel2.split("/")));
|
|
35331
35443
|
if (base === staged) return null;
|
|
@@ -35334,9 +35446,23 @@ function changeOf(rehearsal, live, rel2, staged) {
|
|
|
35334
35446
|
var order = (a, b) => a < b ? -1 : a > b ? 1 : 0;
|
|
35335
35447
|
var byOwnerThenPath = (a, b) => order(a.project, b.project) || order(a.path, b.path);
|
|
35336
35448
|
function ownerOf3(rehearsal, liveFile) {
|
|
35337
|
-
const
|
|
35449
|
+
const whole = (rehearsal.whole ?? []).find((w) => within2(w, liveFile));
|
|
35450
|
+
if (whole !== void 0) return whole;
|
|
35451
|
+
const roots = [...rehearsal.roots.keys()].filter((r) => within2(rehearsal.areas ? r : nodePath.join(r, WAI), liveFile));
|
|
35338
35452
|
return roots.sort((a, b) => b.length - a.length)[0] ?? nodePath.dirname(nodePath.dirname(liveFile));
|
|
35339
35453
|
}
|
|
35454
|
+
function move(from, to) {
|
|
35455
|
+
const rels = everyFile(from);
|
|
35456
|
+
const taken = rels.find((rel2) => fs21.existsSync(nodePath.join(to, ...rel2.split("/"))));
|
|
35457
|
+
if (taken !== void 0) throw new Error(`cannot move ${from} to ${to}: ${nodePath.join(to, ...taken.split("/"))} already exists`);
|
|
35458
|
+
for (const rel2 of rels) {
|
|
35459
|
+
const target = nodePath.join(to, ...rel2.split("/"));
|
|
35460
|
+
makeDirs(nodePath.dirname(target));
|
|
35461
|
+
replace(nodePath.join(from, ...rel2.split("/")), target);
|
|
35462
|
+
}
|
|
35463
|
+
for (const rel2 of rels) prune(nodePath.dirname(nodePath.join(from, ...rel2.split("/"))), nodePath.dirname(from));
|
|
35464
|
+
prune(from, nodePath.dirname(from));
|
|
35465
|
+
}
|
|
35340
35466
|
function read(path46) {
|
|
35341
35467
|
try {
|
|
35342
35468
|
return fs21.readFileSync(path46);
|
|
@@ -35478,6 +35604,13 @@ function hasSystemAt(dir) {
|
|
|
35478
35604
|
}
|
|
35479
35605
|
});
|
|
35480
35606
|
}
|
|
35607
|
+
function occupied(dir) {
|
|
35608
|
+
try {
|
|
35609
|
+
return !fs22.statSync(dir).isDirectory() || fs22.readdirSync(dir).length > 0;
|
|
35610
|
+
} catch {
|
|
35611
|
+
return false;
|
|
35612
|
+
}
|
|
35613
|
+
}
|
|
35481
35614
|
function boundNode(family, bound2) {
|
|
35482
35615
|
return familyNode(family, bound2);
|
|
35483
35616
|
}
|
|
@@ -35551,8 +35684,11 @@ function planDetach(family, bound2, request) {
|
|
|
35551
35684
|
const plan5 = emptyPlan(family, request);
|
|
35552
35685
|
const alias = request.alias ?? "";
|
|
35553
35686
|
const done = configAt3(familyNode(family, bound2).directory)?.externals?.[alias];
|
|
35554
|
-
if (done?.source?.path && !family.nodes.some((n) => n.parent === bound2 && n.mountAlias === alias)) return plan5;
|
|
35687
|
+
if ((done?.source?.path || done?.source?.hosted) && !family.nodes.some((n) => n.parent === bound2 && n.mountAlias === alias)) return plan5;
|
|
35555
35688
|
const member = memberUnder(family, bound2, alias, plan5);
|
|
35689
|
+
if (member && request.relocation && occupied(request.relocation.to)) {
|
|
35690
|
+
refuse(plan5, "relocation-target-exists", bound2, `the member "${alias}" cannot move to ${request.relocation.to}: it already exists`);
|
|
35691
|
+
}
|
|
35556
35692
|
if (!member) return plan5;
|
|
35557
35693
|
const table = resolveProjectExports(member.namespace || void 0);
|
|
35558
35694
|
const leaving = (key) => key !== void 0 && withinMember(family, member, key);
|
|
@@ -35605,27 +35741,34 @@ function planWidening(plan5, member, narrow) {
|
|
|
35605
35741
|
}
|
|
35606
35742
|
function detachEdits(plan5, family, bound2, member, alias, declared, consumers, outward) {
|
|
35607
35743
|
const boundDir = familyNode(family, bound2).directory;
|
|
35608
|
-
|
|
35744
|
+
const relocation = plan5.request.relocation;
|
|
35745
|
+
const sourceTo = (from, producer) => relocation ? { hosted: producer.id ?? producer.mountAlias ?? producer.namespace } : { path: posix3(path40.relative(from, producer.directory)) };
|
|
35746
|
+
const where = (source) => source.hosted !== void 0 ? `hosted record ${source.hosted}` : source.path;
|
|
35747
|
+
edit(plan5, bound2, "member", `members: ${alias} removed (${declared.path} ${relocation ? `moves to ${relocation.to}` : "stays as it is"})`, { root: boundDir, call: "removeMember", args: [alias] });
|
|
35748
|
+
const boundSource = relocation ? sourceTo(boundDir, member) : { path: declared.path };
|
|
35609
35749
|
const external = {
|
|
35610
35750
|
...member.id !== void 0 && member.id !== alias ? { project: member.id } : {},
|
|
35611
|
-
source:
|
|
35751
|
+
source: boundSource,
|
|
35612
35752
|
...declared.use && declared.use.length > 0 ? { use: declared.use } : {},
|
|
35613
35753
|
...declared.description !== void 0 ? { description: declared.description } : {}
|
|
35614
35754
|
};
|
|
35615
|
-
edit(plan5, bound2, "external", `externals: ${alias} \u2192 ${member.id ?? alias} at ${
|
|
35755
|
+
edit(plan5, bound2, "external", `externals: ${alias} \u2192 ${member.id ?? alias} at ${where(boundSource)}`, { root: boundDir, call: "declareExternal", args: [alias, external] });
|
|
35616
35756
|
for (const c of consumers) {
|
|
35617
35757
|
const held = configAt3(c.node.directory)?.externals?.[c.alias];
|
|
35618
|
-
const source =
|
|
35619
|
-
edit(plan5, c.node.namespace, "external", `externals: ${c.alias} found at ${source
|
|
35758
|
+
const source = sourceTo(c.node.directory, member);
|
|
35759
|
+
edit(plan5, c.node.namespace, "external", `externals: ${c.alias} found at ${where(source)} (it leaves the family)`, { root: c.node.directory, call: "repointExternal", args: [c.alias, held?.project ?? null, source] });
|
|
35620
35760
|
}
|
|
35621
35761
|
const own = configAt3(member.directory)?.externals ?? {};
|
|
35622
35762
|
for (const e of outward) {
|
|
35623
35763
|
const producer = familyNode(family, e.producer);
|
|
35624
|
-
const source =
|
|
35625
|
-
edit(plan5, member.namespace, "external", `externals: ${e.alias} found at ${source
|
|
35764
|
+
const source = sourceTo(member.directory, producer);
|
|
35765
|
+
edit(plan5, member.namespace, "external", `externals: ${e.alias} found at ${where(source)} (the member leaves the family)`, { root: member.directory, call: "repointExternal", args: [e.alias, own[e.alias]?.project ?? null, source] });
|
|
35766
|
+
}
|
|
35767
|
+
if (relocation) {
|
|
35768
|
+
edit(plan5, member.namespace, "move", `${member.directory} moved to ${relocation.to} (its own isolated root), its own members with it`, { root: member.directory, call: "move", args: [relocation.to] });
|
|
35626
35769
|
}
|
|
35627
35770
|
edit(plan5, bound2, "pin", `pin ${alias} (the detached project's surface, read last)`, { root: boundDir, call: "pinExternals", args: [[alias]] });
|
|
35628
|
-
plan5.notes.push(`Consumers outside the family are not affected: they already name ${member.id ?? alias} by path, or not at all.`);
|
|
35771
|
+
plan5.notes.push(`Consumers outside the family are not affected: they already name ${member.id ?? alias} by ${relocation ? "hosted record id" : "path"}, or not at all.`);
|
|
35629
35772
|
}
|
|
35630
35773
|
function planAdopt(family, bound2, request) {
|
|
35631
35774
|
const plan5 = emptyPlan(family, request);
|
|
@@ -35636,6 +35779,7 @@ function planAdopt(family, bound2, request) {
|
|
|
35636
35779
|
if (!external && boundConfig?.members?.[alias] !== void 0) return plan5;
|
|
35637
35780
|
let dir = null;
|
|
35638
35781
|
if (!external) refuse(plan5, "not-an-external", bound2, `${label4(bound2)} declares no external "${alias}"`);
|
|
35782
|
+
else if (request.relocation) return planRelocatedAdopt(plan5, family, bound2, alias, external, request.relocation);
|
|
35639
35783
|
else {
|
|
35640
35784
|
dir = resolve30(boundDir, external.source?.path ?? "");
|
|
35641
35785
|
if (dir === null) refuse(plan5, "not-contained", bound2, `the external "${alias}" ${external.source?.path ? `is found at "${external.source.path}", which is not strictly within ${label4(bound2)}` : "names no source.path"}`);
|
|
@@ -35644,7 +35788,18 @@ function planAdopt(family, bound2, request) {
|
|
|
35644
35788
|
if (plan5.refusals.length > 0) return plan5;
|
|
35645
35789
|
return adoptEdits(plan5, family, bound2, alias, external, dir);
|
|
35646
35790
|
}
|
|
35647
|
-
function
|
|
35791
|
+
function planRelocatedAdopt(plan5, family, bound2, alias, external, relocation) {
|
|
35792
|
+
const boundDir = familyNode(family, bound2).directory;
|
|
35793
|
+
const target = resolve30(boundDir, plan5.request.path ?? "");
|
|
35794
|
+
if (!external.source?.hosted) refuse(plan5, "not-contained", bound2, `the external "${alias}" names no source.hosted \u2014 a hosted adopt moves a project named by its hosted record id`);
|
|
35795
|
+
else if (target === null || path40.resolve(target) !== path40.resolve(relocation.to)) refuse(plan5, "not-contained", bound2, `the member path "${plan5.request.path ?? ""}" does not resolve strictly within ${label4(bound2)} to ${relocation.to}`);
|
|
35796
|
+
else if (occupied(relocation.to)) refuse(plan5, "relocation-target-exists", bound2, `the external "${alias}" cannot be adopted at ${relocation.to}: it already exists and is not an empty directory`);
|
|
35797
|
+
const from = relocation.from ?? (external.source?.hosted !== void 0 ? getHostedLookup()?.(external.source.hosted) ?? void 0 : void 0);
|
|
35798
|
+
if (plan5.refusals.length === 0 && !from) refuse(plan5, "not-a-project", bound2, `the hosted record "${external.source?.hosted}" is unknown or outside this request's reach \u2014 there is no root to adopt from`);
|
|
35799
|
+
if (plan5.refusals.length > 0) return plan5;
|
|
35800
|
+
return adoptEdits(plan5, family, bound2, alias, external, from, relocation.to);
|
|
35801
|
+
}
|
|
35802
|
+
function adoptEdits(plan5, family, bound2, alias, external, dir, at = dir) {
|
|
35648
35803
|
const boundDir = familyNode(family, bound2).directory;
|
|
35649
35804
|
const adoptee = configAt3(dir);
|
|
35650
35805
|
if (!adoptee && !hasSystemAt(dir)) {
|
|
@@ -35661,22 +35816,28 @@ function adoptEdits(plan5, family, bound2, alias, external, dir) {
|
|
|
35661
35816
|
edit(plan5, bound2, "pin", `pin ${alias} removed (the family supplies it now)`, { root: boundDir, call: "unpin", args: [alias] });
|
|
35662
35817
|
edit(plan5, bound2, "external", `externals: ${alias} removed`, { root: boundDir, call: "removeExternal", args: [alias] });
|
|
35663
35818
|
const declaration2 = {
|
|
35664
|
-
path: posix3(path40.relative(boundDir,
|
|
35819
|
+
path: posix3(path40.relative(boundDir, at)),
|
|
35665
35820
|
...external.description !== void 0 ? { description: external.description } : {},
|
|
35666
35821
|
...external.use && external.use.length > 0 ? { use: external.use } : {}
|
|
35667
35822
|
};
|
|
35668
35823
|
edit(plan5, bound2, "member", `members: ${alias} \u2192 ${declaration2.path}`, { root: boundDir, call: "declareMember", args: [alias, declaration2] });
|
|
35824
|
+
const namesAdoptee = (from, e) => e.source?.path !== void 0 && path40.resolve(from, e.source.path) === path40.resolve(dir) || plan5.request.relocation !== void 0 && id !== void 0 && e.source?.hosted === id;
|
|
35825
|
+
const sourceText = (e) => e.source?.hosted !== void 0 ? `source.hosted ${e.source.hosted}` : `source.path ${e.source?.path}`;
|
|
35669
35826
|
for (const n of family.nodes) {
|
|
35670
35827
|
for (const [a, e] of Object.entries(configAt3(n.directory)?.externals ?? {})) {
|
|
35671
35828
|
if (n.namespace === bound2 && a === alias) continue;
|
|
35672
|
-
if (!
|
|
35673
|
-
edit(plan5, n.namespace, "external", `externals: ${a} found through the family (its
|
|
35674
|
-
plan5.notes.push(`${label4(n.namespace)}'s external "${a}" named the adoptee by path; adopt removes it \u2014 detach-then-adopt is exact only when detach wrote that
|
|
35829
|
+
if (!namesAdoptee(n.directory, e)) continue;
|
|
35830
|
+
edit(plan5, n.namespace, "external", `externals: ${a} found through the family (its ${sourceText(e)} removed)`, { root: n.directory, call: "repointExternal", args: [a, e.project ?? null, null] });
|
|
35831
|
+
plan5.notes.push(`${label4(n.namespace)}'s external "${a}" named the adoptee by ${e.source?.hosted !== void 0 ? "hosted record id" : "path"}; adopt removes it \u2014 detach-then-adopt is exact only when detach wrote that source`);
|
|
35675
35832
|
}
|
|
35676
35833
|
}
|
|
35834
|
+
const namesFamily = (e) => e.source?.path !== void 0 && nodeAt(family, path40.resolve(dir, e.source.path)) !== void 0 || plan5.request.relocation !== void 0 && e.source?.hosted !== void 0 && family.nodes.some((n) => n.id === e.source.hosted);
|
|
35677
35835
|
for (const [a, e] of Object.entries(adoptee?.externals ?? {})) {
|
|
35678
|
-
if (!
|
|
35679
|
-
edit(plan5, key, "external", `externals: ${a} found through the family (its
|
|
35836
|
+
if (!namesFamily(e)) continue;
|
|
35837
|
+
edit(plan5, key, "external", `externals: ${a} found through the family (its ${sourceText(e)} removed)`, { root: dir, call: "repointExternal", args: [a, e.project ?? null, null] });
|
|
35838
|
+
}
|
|
35839
|
+
if (plan5.request.relocation) {
|
|
35840
|
+
edit(plan5, key, "move", `${dir} moved to ${at} (it joins the family's tree), its own members with it`, { root: dir, call: "move", args: [at] });
|
|
35680
35841
|
}
|
|
35681
35842
|
return plan5;
|
|
35682
35843
|
}
|
|
@@ -35688,11 +35849,13 @@ function write3(plan5, rehearsal) {
|
|
|
35688
35849
|
break;
|
|
35689
35850
|
case "detach":
|
|
35690
35851
|
for (const e of planned.filter((x) => x.write.call === "updateSpecGated")) writeOne(rehearsal, e.write);
|
|
35691
|
-
for (const e of planned.filter((x) =>
|
|
35852
|
+
for (const e of planned.filter((x) => !["pinExternals", "updateSpecGated", "move"].includes(x.write.call))) writeOne(rehearsal, e.write);
|
|
35853
|
+
for (const e of planned.filter((x) => x.write.call === "move")) writeOne(rehearsal, e.write);
|
|
35692
35854
|
for (const e of planned.filter((x) => x.write.call === "pinExternals")) writeOne(rehearsal, e.write);
|
|
35693
35855
|
break;
|
|
35694
35856
|
case "adopt":
|
|
35695
|
-
for (const e of planned) writeOne(rehearsal, e.write);
|
|
35857
|
+
for (const e of planned.filter((x) => x.write.call !== "move")) writeOne(rehearsal, e.write);
|
|
35858
|
+
for (const e of planned.filter((x) => x.write.call === "move")) writeOne(rehearsal, e.write);
|
|
35696
35859
|
break;
|
|
35697
35860
|
default:
|
|
35698
35861
|
throw new Error(`membership_migration writes attach, detach and adopt, not "${plan5.request.verb}"`);
|
|
@@ -35700,6 +35863,7 @@ function write3(plan5, rehearsal) {
|
|
|
35700
35863
|
}
|
|
35701
35864
|
function writeOne(rehearsal, w) {
|
|
35702
35865
|
const args = w.args;
|
|
35866
|
+
if (w.call === "move") return move(rehearsalRoot(rehearsal, w.root), rehearsalRoot(rehearsal, String(args[0])));
|
|
35703
35867
|
runWithProjectRoot(rehearsalRoot(rehearsal, w.root), () => {
|
|
35704
35868
|
switch (w.call) {
|
|
35705
35869
|
case "setId":
|
|
@@ -36124,11 +36288,11 @@ function planExternalize(family, bound2, request) {
|
|
|
36124
36288
|
const donePath = typeof done === "string" ? done : done?.path;
|
|
36125
36289
|
if (donePath !== void 0 && request.path !== void 0 && path42.resolve(node.directory, donePath) === path42.resolve(node.directory, request.path)) return plan5;
|
|
36126
36290
|
const dir = resolve30(node.directory, request.path ?? "");
|
|
36127
|
-
const
|
|
36291
|
+
const occupied2 = dir !== null && holdsProject(dir);
|
|
36128
36292
|
const sub = id.includes("::") ? null : loadSpec("subsystem", subKey);
|
|
36129
36293
|
if (!sub || sub.projectPath || (family.owners.get(subKey) ?? "") !== bound2) refuse3(plan5, "externalize-refused", bound2, `${label6(bound2)} has no subsystem "${id}" to externalize (it is missing, or already a member)`);
|
|
36130
36294
|
if (dir === null) refuse3(plan5, "not-contained", bound2, `the path "${request.path ?? ""}" does not resolve strictly within ${label6(bound2)}`);
|
|
36131
|
-
else if (family.nodes.some((n) => path42.resolve(n.directory) === dir) ||
|
|
36295
|
+
else if (family.nodes.some((n) => path42.resolve(n.directory) === dir) || occupied2) {
|
|
36132
36296
|
refuse3(plan5, "not-contained", bound2, `${dir} already holds a project`);
|
|
36133
36297
|
}
|
|
36134
36298
|
const config = configAt5(node.directory);
|
|
@@ -36243,11 +36407,11 @@ function writeOne3(rehearsal, w) {
|
|
|
36243
36407
|
|
|
36244
36408
|
// src/migrations/transaction.ts
|
|
36245
36409
|
var crypto6 = __toESM(require("crypto"));
|
|
36246
|
-
var
|
|
36410
|
+
var fs24 = __toESM(require("fs"));
|
|
36247
36411
|
var path43 = __toESM(require("path"));
|
|
36248
36412
|
|
|
36249
36413
|
// src/migrations/transaction-files.ts
|
|
36250
|
-
var
|
|
36414
|
+
var fs23 = __toESM(require("fs"));
|
|
36251
36415
|
var os6 = __toESM(require("os"));
|
|
36252
36416
|
var nodePath2 = __toESM(require("path"));
|
|
36253
36417
|
var yaml3 = __toESM(require("js-yaml"));
|
|
@@ -36261,7 +36425,7 @@ function pause2(ms) {
|
|
|
36261
36425
|
function removeTree(dir) {
|
|
36262
36426
|
for (let attempt = 1; ; attempt++) {
|
|
36263
36427
|
try {
|
|
36264
|
-
|
|
36428
|
+
fs23.rmSync(dir, { recursive: true, force: true });
|
|
36265
36429
|
return;
|
|
36266
36430
|
} catch (e) {
|
|
36267
36431
|
const code = e.code;
|
|
@@ -36271,20 +36435,20 @@ function removeTree(dir) {
|
|
|
36271
36435
|
}
|
|
36272
36436
|
}
|
|
36273
36437
|
function writeDurably(file, bytes) {
|
|
36274
|
-
|
|
36438
|
+
fs23.mkdirSync(nodePath2.dirname(file), { recursive: true });
|
|
36275
36439
|
const tmp = `${file}.tmp`;
|
|
36276
36440
|
try {
|
|
36277
|
-
const fd =
|
|
36441
|
+
const fd = fs23.openSync(tmp, "w");
|
|
36278
36442
|
try {
|
|
36279
|
-
|
|
36280
|
-
|
|
36443
|
+
fs23.writeSync(fd, typeof bytes === "string" ? Buffer.from(bytes, "utf8") : bytes);
|
|
36444
|
+
fs23.fsyncSync(fd);
|
|
36281
36445
|
} finally {
|
|
36282
|
-
|
|
36446
|
+
fs23.closeSync(fd);
|
|
36283
36447
|
}
|
|
36284
|
-
|
|
36448
|
+
fs23.renameSync(tmp, file);
|
|
36285
36449
|
} catch (e) {
|
|
36286
36450
|
try {
|
|
36287
|
-
|
|
36451
|
+
fs23.unlinkSync(tmp);
|
|
36288
36452
|
} catch {
|
|
36289
36453
|
}
|
|
36290
36454
|
throw e;
|
|
@@ -36294,18 +36458,18 @@ function writeDurably(file, bytes) {
|
|
|
36294
36458
|
function syncDirectory(dir) {
|
|
36295
36459
|
if (process.platform === "win32") return;
|
|
36296
36460
|
try {
|
|
36297
|
-
const fd =
|
|
36461
|
+
const fd = fs23.openSync(dir, "r");
|
|
36298
36462
|
try {
|
|
36299
|
-
|
|
36463
|
+
fs23.fsyncSync(fd);
|
|
36300
36464
|
} finally {
|
|
36301
|
-
|
|
36465
|
+
fs23.closeSync(fd);
|
|
36302
36466
|
}
|
|
36303
36467
|
} catch {
|
|
36304
36468
|
}
|
|
36305
36469
|
}
|
|
36306
36470
|
function openRehearsal(id) {
|
|
36307
36471
|
const dir = rehearsalDir(id);
|
|
36308
|
-
|
|
36472
|
+
fs23.mkdirSync(dir);
|
|
36309
36473
|
return dir;
|
|
36310
36474
|
}
|
|
36311
36475
|
function dropRehearsal(id) {
|
|
@@ -36316,14 +36480,14 @@ function dropRehearsal(id) {
|
|
|
36316
36480
|
}
|
|
36317
36481
|
function saveJournal(journal) {
|
|
36318
36482
|
const ignore = nodePath2.join(transactionsDir(journal.owner), ".gitignore");
|
|
36319
|
-
if (!
|
|
36483
|
+
if (!fs23.existsSync(ignore)) writeDurably(ignore, "*\n");
|
|
36320
36484
|
writeDurably(nodePath2.join(transactionDir(journal.owner, journal.id), "journal.yaml"), yaml3.dump(journal, { noRefs: true, lineWidth: 200 }));
|
|
36321
36485
|
}
|
|
36322
36486
|
function readJournal(owner, id) {
|
|
36323
36487
|
const file = nodePath2.join(transactionDir(owner, id), "journal.yaml");
|
|
36324
36488
|
let text3;
|
|
36325
36489
|
try {
|
|
36326
|
-
text3 =
|
|
36490
|
+
text3 = fs23.readFileSync(file, "utf8");
|
|
36327
36491
|
} catch (e) {
|
|
36328
36492
|
if (e.code === "ENOENT") return null;
|
|
36329
36493
|
throw e;
|
|
@@ -36338,7 +36502,7 @@ function listJournals(owner) {
|
|
|
36338
36502
|
const dir = transactionsDir(owner);
|
|
36339
36503
|
let names;
|
|
36340
36504
|
try {
|
|
36341
|
-
names =
|
|
36505
|
+
names = fs23.readdirSync(dir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name).sort();
|
|
36342
36506
|
} catch {
|
|
36343
36507
|
return [];
|
|
36344
36508
|
}
|
|
@@ -36360,7 +36524,7 @@ function putFile(owner, id, area, path46, bytes) {
|
|
|
36360
36524
|
}
|
|
36361
36525
|
function readFile(owner, id, area, path46) {
|
|
36362
36526
|
try {
|
|
36363
|
-
return
|
|
36527
|
+
return fs23.readFileSync(locate(owner, id, area, path46));
|
|
36364
36528
|
} catch (e) {
|
|
36365
36529
|
if (e.code === "ENOENT") return null;
|
|
36366
36530
|
throw e;
|
|
@@ -36374,7 +36538,7 @@ function close(owner, id) {
|
|
|
36374
36538
|
const dir = transactionsDir(owner);
|
|
36375
36539
|
let left;
|
|
36376
36540
|
try {
|
|
36377
|
-
left =
|
|
36541
|
+
left = fs23.readdirSync(dir);
|
|
36378
36542
|
} catch {
|
|
36379
36543
|
return;
|
|
36380
36544
|
}
|
|
@@ -36382,7 +36546,11 @@ function close(owner, id) {
|
|
|
36382
36546
|
removeTree(dir);
|
|
36383
36547
|
const wai = nodePath2.dirname(dir);
|
|
36384
36548
|
try {
|
|
36385
|
-
if (
|
|
36549
|
+
if (fs23.readdirSync(wai).length === 0) fs23.rmdirSync(wai);
|
|
36550
|
+
} catch {
|
|
36551
|
+
}
|
|
36552
|
+
try {
|
|
36553
|
+
if (fs23.readdirSync(owner).length === 0) fs23.rmdirSync(owner);
|
|
36386
36554
|
} catch {
|
|
36387
36555
|
}
|
|
36388
36556
|
}
|
|
@@ -36469,15 +36637,16 @@ function rehearse(scope) {
|
|
|
36469
36637
|
const directory = transactionRepository.openRehearsal(id);
|
|
36470
36638
|
const familyRoot = path43.resolve(scope.familyRoot);
|
|
36471
36639
|
const projects = [...new Set(scope.projects.map((p) => path43.resolve(p)))];
|
|
36640
|
+
const whole = scope.whole ? [...new Set(scope.whole.map((p) => path43.resolve(p)))] : void 0;
|
|
36472
36641
|
let baseDigests;
|
|
36473
36642
|
try {
|
|
36474
|
-
baseDigests = mirror({ familyRoot, projects }, directory);
|
|
36643
|
+
baseDigests = mirror({ familyRoot, projects, ...scope.areas ? { areas: scope.areas } : {}, ...whole ? { whole } : {} }, directory);
|
|
36475
36644
|
} catch (e) {
|
|
36476
36645
|
transactionRepository.dropRehearsal(id);
|
|
36477
36646
|
throw e;
|
|
36478
36647
|
}
|
|
36479
36648
|
const roots = new Map(projects.map((p) => [p, path43.join(directory, path43.relative(familyRoot, p))]));
|
|
36480
|
-
return { id, directory, familyRoot, roots, baseDigests };
|
|
36649
|
+
return { id, directory, familyRoot, roots, baseDigests, ...scope.areas ? { areas: [...scope.areas] } : {}, ...whole ? { whole } : {} };
|
|
36481
36650
|
}
|
|
36482
36651
|
function diff(rehearsal) {
|
|
36483
36652
|
return compare4(rehearsal);
|
|
@@ -36564,7 +36733,7 @@ function missingDirs(owner, entries) {
|
|
|
36564
36733
|
for (const entry of entries.filter((e) => e.action === "create")) {
|
|
36565
36734
|
const missing = [];
|
|
36566
36735
|
let at = path43.dirname(liveOf(owner, entry.path));
|
|
36567
|
-
while (!
|
|
36736
|
+
while (!fs24.existsSync(at) && at !== path43.dirname(at)) {
|
|
36568
36737
|
missing.unshift(at);
|
|
36569
36738
|
at = path43.dirname(at);
|
|
36570
36739
|
}
|
|
@@ -36598,7 +36767,7 @@ function stageBytes(rehearsal, journal, entry) {
|
|
|
36598
36767
|
function checkVolume(journal, entry, target) {
|
|
36599
36768
|
const staged = transactionRepository.locate(journal.owner, journal.id, "staged", entry.path);
|
|
36600
36769
|
let nearest = path43.dirname(target);
|
|
36601
|
-
while (!
|
|
36770
|
+
while (!fs24.existsSync(nearest) && nearest !== path43.dirname(nearest)) nearest = path43.dirname(nearest);
|
|
36602
36771
|
if (!sameVolume(staged, nearest)) {
|
|
36603
36772
|
throw new StagingError(`cross-volume: ${target} lies on another volume than its staged copy; a rename across volumes is not atomic`);
|
|
36604
36773
|
}
|
|
@@ -36682,7 +36851,7 @@ function recover(root, fix) {
|
|
|
36682
36851
|
var coordinatorRoot = (journal) => path43.resolve(journal.owner, journal.coordinator);
|
|
36683
36852
|
function journalAt(owner, id) {
|
|
36684
36853
|
try {
|
|
36685
|
-
const journal =
|
|
36854
|
+
const journal = fs24.existsSync(owner) ? transactionRepository.readJournal(owner, id) : null;
|
|
36686
36855
|
return journal ? { ...journal, owner } : null;
|
|
36687
36856
|
} catch {
|
|
36688
36857
|
return null;
|
|
@@ -36714,7 +36883,7 @@ function resolveOne(journal) {
|
|
|
36714
36883
|
for (const owner of [...owners.filter((o) => o !== coordinator.owner), coordinator.owner]) transactionRepository.close(owner, journal.id);
|
|
36715
36884
|
return { ...base, owners, phase, action: "cleaned", detail: "it had committed; its transaction directories were removed" };
|
|
36716
36885
|
}
|
|
36717
|
-
const absent = owners.filter((o) => !
|
|
36886
|
+
const absent = phase === "staging" ? [] : owners.filter((o) => !fs24.existsSync(o));
|
|
36718
36887
|
if (absent.length > 0) {
|
|
36719
36888
|
return { ...base, owners, phase, action: "refused", detail: `owner(s) out of reach: ${absent.join(", ")}` };
|
|
36720
36889
|
}
|
|
@@ -36745,14 +36914,15 @@ function plan3(request) {
|
|
|
36745
36914
|
const { top, whole } = climb3(bound2);
|
|
36746
36915
|
const family = runWithProjectRoot(top, () => graph());
|
|
36747
36916
|
const boundKey = family.nodes.find((n) => path44.resolve(n.directory) === path44.resolve(bound2))?.namespace ?? "";
|
|
36748
|
-
const pending3 = unfinished(top, bound2);
|
|
36917
|
+
const pending3 = unfinished(top, bound2, request.relocation?.coordinator);
|
|
36749
36918
|
if (pending3.length > 0) return refusedForPending(request, top, whole, pending3);
|
|
36750
36919
|
const planned = request.verb === "chaining" ? route(request, family, boundKey) : runWithProjectRoot(top, () => route(request, family, boundKey));
|
|
36751
36920
|
return rehearse2(request.verb === "chaining" ? planned : { ...planned, familyRoot: top, whole });
|
|
36752
36921
|
}
|
|
36753
|
-
function unfinished(top, bound2) {
|
|
36922
|
+
function unfinished(top, bound2, coordinator) {
|
|
36754
36923
|
const found = recover(top, false);
|
|
36755
36924
|
if (path44.resolve(bound2) !== path44.resolve(top)) found.push(...recover(bound2, false));
|
|
36925
|
+
if (coordinator !== void 0) found.push(...recover(coordinator, false));
|
|
36756
36926
|
return found.filter((t, i) => found.findIndex((u) => u.id === t.id) === i);
|
|
36757
36927
|
}
|
|
36758
36928
|
function refusedForPending(request, top, whole, pending3) {
|
|
@@ -36830,17 +37000,62 @@ function rehearse2(plan5) {
|
|
|
36830
37000
|
if (blocked(plan5) || plan5.request.rehearse === false) return plan5;
|
|
36831
37001
|
const family = runWithProjectRoot(plan5.familyRoot, () => graph());
|
|
36832
37002
|
const projects = [...family.nodes.map((n) => n.directory), ...broughtIn(plan5, family), ...pathProducers(plan5, family)];
|
|
36833
|
-
const rehearsal = rehearse(
|
|
37003
|
+
const rehearsal = rehearse(scopeOf(plan5, projects));
|
|
36834
37004
|
try {
|
|
36835
|
-
onCopy(rehearsal, () => writeVerb(plan5, rehearsal));
|
|
37005
|
+
onCopy(rehearsal, () => relocatedLookup(plan5, rehearsal, () => writeVerb(plan5, rehearsal)));
|
|
36836
37006
|
} catch (e) {
|
|
36837
37007
|
discard(rehearsal);
|
|
36838
37008
|
const detail = e instanceof Error ? e.message : String(e);
|
|
36839
37009
|
return { ...plan5, refusals: [...plan5.refusals, { code: `${plan5.request.verb}-refused`, project: "", detail }] };
|
|
36840
37010
|
}
|
|
36841
37011
|
const changes = diff(rehearsal);
|
|
37012
|
+
const outside = unwritableOwners(changes);
|
|
37013
|
+
if (outside.length > 0) {
|
|
37014
|
+
discard(rehearsal);
|
|
37015
|
+
return { ...plan5, refusals: [...plan5.refusals, ...outside.map((o) => ({ code: "family-partial", project: o, detail: `the plan must write ${o}, which this request may not write` }))] };
|
|
37016
|
+
}
|
|
36842
37017
|
return { ...plan5, rehearsal, changes, relock: relockOf(plan5, changes) };
|
|
36843
37018
|
}
|
|
37019
|
+
function movedOf(plan5) {
|
|
37020
|
+
const relocation = plan5.request.relocation;
|
|
37021
|
+
const move2 = plan5.edits.find((e) => e.write?.call === "move");
|
|
37022
|
+
if (!relocation || !move2?.write) return null;
|
|
37023
|
+
return { from: path44.resolve(move2.write.root), to: path44.resolve(relocation.to) };
|
|
37024
|
+
}
|
|
37025
|
+
function scopeOf(plan5, projects) {
|
|
37026
|
+
const relocation = plan5.request.relocation;
|
|
37027
|
+
const moved = movedOf(plan5);
|
|
37028
|
+
if (!relocation || !moved) return { familyRoot: plan5.familyRoot, projects };
|
|
37029
|
+
return {
|
|
37030
|
+
familyRoot: relocation.coordinator,
|
|
37031
|
+
projects: [relocation.coordinator, ...projects],
|
|
37032
|
+
areas: [".wai", ...relocation.areas],
|
|
37033
|
+
whole: [moved.from, moved.to]
|
|
37034
|
+
};
|
|
37035
|
+
}
|
|
37036
|
+
function relocatedLookup(plan5, rehearsal, run3) {
|
|
37037
|
+
const moved = movedOf(plan5);
|
|
37038
|
+
const live = getHostedLookup();
|
|
37039
|
+
if (!moved || !live) return run3();
|
|
37040
|
+
const copied = [...rehearsal.roots.keys(), ...rehearsal.whole ?? []].filter((r) => r !== path44.resolve(rehearsal.familyRoot));
|
|
37041
|
+
const inside = (root, dir) => {
|
|
37042
|
+
const rel2 = path44.relative(root, dir);
|
|
37043
|
+
return rel2 === "" || !rel2.startsWith("..") && !path44.isAbsolute(rel2);
|
|
37044
|
+
};
|
|
37045
|
+
return runWithHostedLookup((id) => {
|
|
37046
|
+
const root = live(id);
|
|
37047
|
+
if (root === null) return null;
|
|
37048
|
+
const at = path44.resolve(root);
|
|
37049
|
+
if (inside(moved.from, at)) return path44.join(rehearsalRoot(rehearsal, moved.to), path44.relative(moved.from, at));
|
|
37050
|
+
return copied.some((r) => inside(r, at)) ? rehearsalRoot(rehearsal, at) : at;
|
|
37051
|
+
}, run3);
|
|
37052
|
+
}
|
|
37053
|
+
function unwritableOwners(changes) {
|
|
37054
|
+
const denied = getRequestParentReach()?.unwritableRoots ?? [];
|
|
37055
|
+
if (denied.length === 0) return [];
|
|
37056
|
+
const owners = [...new Set(changes.map((c) => path44.resolve(c.project)))];
|
|
37057
|
+
return owners.filter((o) => denied.includes(o));
|
|
37058
|
+
}
|
|
36844
37059
|
function pathProducers(plan5, family) {
|
|
36845
37060
|
const inside = (dir) => {
|
|
36846
37061
|
const rel2 = path44.relative(plan5.familyRoot, dir);
|
|
@@ -36883,7 +37098,9 @@ function onCopy(rehearsal, run3) {
|
|
|
36883
37098
|
function relockOf(plan5, changes) {
|
|
36884
37099
|
const ended = new Set(changes.filter((c) => c.action === "delete" && c.path === ".wai/project.yaml").map((c) => path44.resolve(c.project)));
|
|
36885
37100
|
const owners = [...new Set(changes.map((c) => path44.resolve(c.project)))].filter((o) => !ended.has(o));
|
|
36886
|
-
|
|
37101
|
+
const moved = movedOf(plan5);
|
|
37102
|
+
const relocated = moved !== null && approvalRecord(moved.from) !== null ? [moved.to] : [];
|
|
37103
|
+
if (plan5.request.verb !== "rename") return [...owners.filter((owner) => approvalRecord(owner) !== null), ...relocated];
|
|
36887
37104
|
const renamed = plan5.edits.find((e) => e.write?.call === "renameId")?.write?.root;
|
|
36888
37105
|
const first = renamed !== void 0 ? path44.resolve(renamed) : void 0;
|
|
36889
37106
|
return [...owners.filter((o) => o === first), ...owners.filter((o) => o !== first)];
|
|
@@ -38060,9 +38277,10 @@ ${renderChangeReport(report2)}`,
|
|
|
38060
38277
|
server,
|
|
38061
38278
|
"sdd_adopt_member",
|
|
38062
38279
|
{
|
|
38063
|
-
description: "Make the bound project's external found by a path inside it a
|
|
38280
|
+
description: "Make the bound project's external a member \u2014 sdd_detach_member's inverse. Locally the external is found by a path inside the bound project and adopted where it is; on a hosted instance it names a project by source.hosted and `path` says where to adopt it (the hosting server relocates it there). All-or-nothing; dryRun answers the plan and writes nothing. Never locks.",
|
|
38064
38281
|
inputSchema: {
|
|
38065
38282
|
alias: import_zod11.z.string().describe("The external's alias"),
|
|
38283
|
+
path: import_zod11.z.string().optional().describe("Hosted: the member path to adopt a source.hosted external at, relative to the bound project; a source.path external is adopted where it is"),
|
|
38066
38284
|
dryRun: dryRunArg
|
|
38067
38285
|
}
|
|
38068
38286
|
},
|
|
@@ -39127,6 +39345,7 @@ function loadProjectConfig3() {
|
|
|
39127
39345
|
generateDiagramSet,
|
|
39128
39346
|
generateSequenceDiagram,
|
|
39129
39347
|
getExporter,
|
|
39348
|
+
getHostedLookup,
|
|
39130
39349
|
getLoaderIssues,
|
|
39131
39350
|
getProjectRoot,
|
|
39132
39351
|
getProjectRootOverride,
|
|
@@ -39258,6 +39477,7 @@ function loadProjectConfig3() {
|
|
|
39258
39477
|
resolveVariantGuidance,
|
|
39259
39478
|
retireSpecialists,
|
|
39260
39479
|
rewriteReferences,
|
|
39480
|
+
runWithHostedLookup,
|
|
39261
39481
|
runWithProjectBinding,
|
|
39262
39482
|
runWithProjectRoot,
|
|
39263
39483
|
sameContract,
|