@neocompose/cli 0.26.5 → 0.27.1
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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,43 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.27.1] - 2026-08-12
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- Treat member-level `required` as non-semantic for Function and NSFunction
|
|
8
|
+
records during CLI reads and comparisons. Historical records stored with
|
|
9
|
+
`required: true` no longer produce permanent phantom changes in `neo pull`,
|
|
10
|
+
`neo status`, or `neo push --dry-run`; return nullability remains represented
|
|
11
|
+
by `returnTypeInfo.required`.
|
|
12
|
+
- Preserve independently mergeable edits on both sides of a `neo pull`
|
|
13
|
+
conflict marker, including nested fields and stable-ID collection entries.
|
|
14
|
+
Resolving with `neo resolve --mine` or `--theirs` now discards only genuinely
|
|
15
|
+
contested values instead of clean changes made on the other side.
|
|
16
|
+
|
|
17
|
+
## [0.27.0] - 2026-08-10
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
|
|
21
|
+
- `neo logout [--api <url>]`: targeted local credential deletion for exactly
|
|
22
|
+
one API origin — the namespaced OS-keychain entry and the credentials-file
|
|
23
|
+
row — plus best-effort server session revocation. Other origins, other
|
|
24
|
+
namespaces, and the rest of the config home are never touched.
|
|
25
|
+
- `NEO_COMPOSE_CONFIG_HOME`: an absolute directory that replaces
|
|
26
|
+
`$XDG_CONFIG_HOME/neo-compose` for Neo credential state only, so isolated
|
|
27
|
+
environments (P53 agent rigs) keep their own credential store without
|
|
28
|
+
changing the ambient XDG configuration of unrelated tools.
|
|
29
|
+
- `NEO_COMPOSE_CREDENTIAL_NAMESPACE`: scopes the OS-keychain account
|
|
30
|
+
(`<namespace>::<api origin>`) so isolated environments sharing one OS user
|
|
31
|
+
cannot read or delete each other's tokens.
|
|
32
|
+
|
|
33
|
+
### Fixed
|
|
34
|
+
|
|
35
|
+
- The credential-store docstring described a two-level precedence with the
|
|
36
|
+
OS keychain "layering in later"; the keychain layer has existed for some
|
|
37
|
+
time. The docstring now matches the real precedence (env var, then
|
|
38
|
+
keychain, then credentials file) and documents that the metadata row is
|
|
39
|
+
written even when the keychain holds the token.
|
|
40
|
+
|
|
3
41
|
## [0.26.5] - 2026-08-10
|
|
4
42
|
|
|
5
43
|
### Changed
|
package/README.md
CHANGED
|
@@ -419,6 +419,7 @@ authorization boundary.
|
|
|
419
419
|
| `--version` | Print the installed CLI package version. |
|
|
420
420
|
| `login` | Authenticate the selected profile. |
|
|
421
421
|
| `whoami` | Inspect the selected profile. |
|
|
422
|
+
| `logout [--api <url>]` | Delete the stored credential for one API origin and revoke its session. |
|
|
422
423
|
| `init --project <id> [--version <id>]` | Create a format-4 working copy and perform its first reset pull. |
|
|
423
424
|
| `doctor` | Validate format/compiler/editor/source/file contracts; no .NET discovery. |
|
|
424
425
|
| `pull [--force\|--reset] [--regenerate-source-names]` | Merge remote changes or regenerate canonical source, names, and binaries. |
|
package/dist/neo.mjs
CHANGED
|
@@ -44,7 +44,12 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
44
44
|
// src/token-store.ts
|
|
45
45
|
var token_store_exports = {};
|
|
46
46
|
__export(token_store_exports, {
|
|
47
|
+
NEO_CONFIG_HOME_ENV_VAR: () => NEO_CONFIG_HOME_ENV_VAR,
|
|
48
|
+
NEO_CREDENTIAL_NAMESPACE_ENV_VAR: () => NEO_CREDENTIAL_NAMESPACE_ENV_VAR,
|
|
47
49
|
NEO_TOKEN_ENV_VAR: () => NEO_TOKEN_ENV_VAR,
|
|
50
|
+
credentialsDir: () => credentialsDir,
|
|
51
|
+
deleteCredential: () => deleteCredential,
|
|
52
|
+
keychainAccount: () => keychainAccount,
|
|
48
53
|
loadCredential: () => loadCredential,
|
|
49
54
|
loadToken: () => loadToken,
|
|
50
55
|
saveCredential: () => saveCredential
|
|
@@ -54,12 +59,22 @@ import {
|
|
|
54
59
|
existsSync,
|
|
55
60
|
mkdirSync,
|
|
56
61
|
readFileSync,
|
|
62
|
+
rmSync,
|
|
57
63
|
writeFileSync
|
|
58
64
|
} from "node:fs";
|
|
59
65
|
import { execFileSync } from "node:child_process";
|
|
60
66
|
import { homedir } from "node:os";
|
|
61
|
-
import { join } from "node:path";
|
|
67
|
+
import { isAbsolute, join } from "node:path";
|
|
62
68
|
function credentialsDir() {
|
|
69
|
+
const configHome = process.env[NEO_CONFIG_HOME_ENV_VAR];
|
|
70
|
+
if (configHome !== void 0 && configHome !== "") {
|
|
71
|
+
if (!isAbsolute(configHome)) {
|
|
72
|
+
throw new Error(
|
|
73
|
+
`${NEO_CONFIG_HOME_ENV_VAR} must be an absolute directory path, got "${configHome}".`
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
return configHome;
|
|
77
|
+
}
|
|
63
78
|
const xdg = process.env.XDG_CONFIG_HOME;
|
|
64
79
|
const base = xdg !== void 0 && xdg !== "" ? xdg : join(homedir(), ".config");
|
|
65
80
|
return join(base, "neo-compose");
|
|
@@ -80,6 +95,11 @@ function readCredentialsFile() {
|
|
|
80
95
|
}
|
|
81
96
|
return file;
|
|
82
97
|
}
|
|
98
|
+
function keychainAccount(apiBaseUrl) {
|
|
99
|
+
const namespace = process.env[NEO_CREDENTIAL_NAMESPACE_ENV_VAR];
|
|
100
|
+
if (namespace === void 0 || namespace === "") return apiBaseUrl;
|
|
101
|
+
return `${namespace}::${apiBaseUrl}`;
|
|
102
|
+
}
|
|
83
103
|
function keychainSet(account, secret) {
|
|
84
104
|
if (process.platform !== "darwin") return false;
|
|
85
105
|
try {
|
|
@@ -116,8 +136,24 @@ function keychainGet(account) {
|
|
|
116
136
|
return null;
|
|
117
137
|
}
|
|
118
138
|
}
|
|
139
|
+
function keychainDelete(account) {
|
|
140
|
+
if (process.platform !== "darwin") return false;
|
|
141
|
+
try {
|
|
142
|
+
execFileSync(
|
|
143
|
+
"security",
|
|
144
|
+
["delete-generic-password", "-s", KEYCHAIN_SERVICE, "-a", account],
|
|
145
|
+
{ stdio: "ignore" }
|
|
146
|
+
);
|
|
147
|
+
return true;
|
|
148
|
+
} catch {
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
119
152
|
function saveCredential(credential) {
|
|
120
|
-
const inKeychain = keychainSet(
|
|
153
|
+
const inKeychain = keychainSet(
|
|
154
|
+
keychainAccount(credential.apiBaseUrl),
|
|
155
|
+
credential.token
|
|
156
|
+
);
|
|
121
157
|
mkdirSync(credentialsDir(), { recursive: true, mode: 448 });
|
|
122
158
|
const file = readCredentialsFile();
|
|
123
159
|
file.credentials[credential.apiBaseUrl] = inKeychain ? { ...credential, token: "" } : credential;
|
|
@@ -132,7 +168,7 @@ function saveCredential(credential) {
|
|
|
132
168
|
function loadToken(apiBaseUrl) {
|
|
133
169
|
const envToken = process.env[NEO_TOKEN_ENV_VAR];
|
|
134
170
|
if (envToken !== void 0 && envToken !== "") return envToken;
|
|
135
|
-
const fromKeychain = keychainGet(apiBaseUrl);
|
|
171
|
+
const fromKeychain = keychainGet(keychainAccount(apiBaseUrl));
|
|
136
172
|
if (fromKeychain !== null) return fromKeychain;
|
|
137
173
|
const file = readCredentialsFile();
|
|
138
174
|
const credential = file.credentials[apiBaseUrl];
|
|
@@ -143,11 +179,38 @@ function loadCredential(apiBaseUrl) {
|
|
|
143
179
|
const file = readCredentialsFile();
|
|
144
180
|
return file.credentials[apiBaseUrl] ?? null;
|
|
145
181
|
}
|
|
146
|
-
|
|
182
|
+
function deleteCredential(apiBaseUrl) {
|
|
183
|
+
const account = keychainAccount(apiBaseUrl);
|
|
184
|
+
const fromKeychain = keychainGet(account);
|
|
185
|
+
const file = readCredentialsFile();
|
|
186
|
+
const fileEntry = file.credentials[apiBaseUrl];
|
|
187
|
+
const token = fromKeychain ?? (fileEntry !== void 0 && fileEntry.token !== "" ? fileEntry.token : null);
|
|
188
|
+
const deletedKeychainEntry = keychainDelete(account);
|
|
189
|
+
let deletedFileEntry = false;
|
|
190
|
+
if (fileEntry !== void 0) {
|
|
191
|
+
delete file.credentials[apiBaseUrl];
|
|
192
|
+
deletedFileEntry = true;
|
|
193
|
+
const path = credentialsPath();
|
|
194
|
+
if (Object.keys(file.credentials).length === 0) {
|
|
195
|
+
rmSync(path, { force: true });
|
|
196
|
+
} else {
|
|
197
|
+
writeFileSync(path, `${JSON.stringify(file, null, 2)}
|
|
198
|
+
`, {
|
|
199
|
+
encoding: "utf8",
|
|
200
|
+
mode: 384
|
|
201
|
+
});
|
|
202
|
+
chmodSync(path, 384);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return { token, deletedKeychainEntry, deletedFileEntry };
|
|
206
|
+
}
|
|
207
|
+
var NEO_TOKEN_ENV_VAR, NEO_CONFIG_HOME_ENV_VAR, NEO_CREDENTIAL_NAMESPACE_ENV_VAR, KEYCHAIN_SERVICE;
|
|
147
208
|
var init_token_store = __esm({
|
|
148
209
|
"src/token-store.ts"() {
|
|
149
210
|
"use strict";
|
|
150
211
|
NEO_TOKEN_ENV_VAR = "NEO_COMPOSE_TOKEN";
|
|
212
|
+
NEO_CONFIG_HOME_ENV_VAR = "NEO_COMPOSE_CONFIG_HOME";
|
|
213
|
+
NEO_CREDENTIAL_NAMESPACE_ENV_VAR = "NEO_COMPOSE_CREDENTIAL_NAMESPACE";
|
|
151
214
|
KEYCHAIN_SERVICE = "neo-compose-cli";
|
|
152
215
|
}
|
|
153
216
|
});
|
|
@@ -427,6 +490,44 @@ async function runLogin(options) {
|
|
|
427
490
|
return;
|
|
428
491
|
}
|
|
429
492
|
}
|
|
493
|
+
async function runLogout(apiBaseUrl) {
|
|
494
|
+
const { deleteCredential: deleteCredential2 } = await Promise.resolve().then(() => (init_token_store(), token_store_exports));
|
|
495
|
+
const deleted = deleteCredential2(apiBaseUrl);
|
|
496
|
+
if (deleted.token === null && !deleted.deletedKeychainEntry && !deleted.deletedFileEntry) {
|
|
497
|
+
console.log(`No credentials stored for "${apiBaseUrl}".`);
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
500
|
+
if (deleted.token !== null) {
|
|
501
|
+
try {
|
|
502
|
+
const response = await fetch(new URL("/api/auth/sign-out", apiBaseUrl), {
|
|
503
|
+
body: "{}",
|
|
504
|
+
headers: {
|
|
505
|
+
Authorization: `Bearer ${deleted.token}`,
|
|
506
|
+
"Content-Type": "application/json"
|
|
507
|
+
},
|
|
508
|
+
method: "POST"
|
|
509
|
+
});
|
|
510
|
+
if (response.ok) {
|
|
511
|
+
console.log(`Revoked the server session at ${apiBaseUrl}.`);
|
|
512
|
+
} else {
|
|
513
|
+
console.log(
|
|
514
|
+
`Server session revocation returned ${response.status}; the local credential was still deleted.`
|
|
515
|
+
);
|
|
516
|
+
}
|
|
517
|
+
} catch {
|
|
518
|
+
console.log(
|
|
519
|
+
"Server session revocation was unreachable; the local credential was still deleted."
|
|
520
|
+
);
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
const surfaces = [
|
|
524
|
+
deleted.deletedKeychainEntry ? "Keychain entry" : null,
|
|
525
|
+
deleted.deletedFileEntry ? "credentials file entry" : null
|
|
526
|
+
].filter((surface) => surface !== null);
|
|
527
|
+
console.log(
|
|
528
|
+
`Logged out of ${apiBaseUrl}${surfaces.length > 0 ? ` (removed ${surfaces.join(" and ")})` : ""}.`
|
|
529
|
+
);
|
|
530
|
+
}
|
|
430
531
|
async function runWhoami(apiBaseUrl) {
|
|
431
532
|
const { loadToken: loadToken2 } = await Promise.resolve().then(() => (init_token_store(), token_store_exports));
|
|
432
533
|
const token = loadToken2(apiBaseUrl);
|
|
@@ -12789,13 +12890,13 @@ var init_strict_resolver = __esm({
|
|
|
12789
12890
|
scope,
|
|
12790
12891
|
pos
|
|
12791
12892
|
);
|
|
12792
|
-
const
|
|
12893
|
+
const selected = intrinsic(
|
|
12793
12894
|
"select" /* Select */,
|
|
12794
12895
|
{ collectionPointer: receiver.pointer, function: fn },
|
|
12795
12896
|
{ kind: "list", elementType: resultType, readOnly: true }
|
|
12796
12897
|
);
|
|
12797
12898
|
return {
|
|
12798
|
-
...
|
|
12899
|
+
...selected,
|
|
12799
12900
|
entryWritability: inferredReturn.writability,
|
|
12800
12901
|
writeRoot: inferredReturn.writeRoot
|
|
12801
12902
|
};
|
|
@@ -25750,9 +25851,9 @@ function declaredConstructorNamedArguments(analysis, typeName, used) {
|
|
|
25750
25851
|
)
|
|
25751
25852
|
)
|
|
25752
25853
|
);
|
|
25753
|
-
const
|
|
25854
|
+
const selected = reachable.length > 0 ? reachable : contract.constructors;
|
|
25754
25855
|
const fields = /* @__PURE__ */ new Map();
|
|
25755
|
-
for (const constructor2 of
|
|
25856
|
+
for (const constructor2 of selected) {
|
|
25756
25857
|
for (const parameter4 of constructor2.parameters) {
|
|
25757
25858
|
if (fields.has(parameter4.name)) continue;
|
|
25758
25859
|
fields.set(parameter4.name, parameterArgumentField(parameter4));
|
|
@@ -29398,14 +29499,14 @@ function sourceLocation(value, environment, field) {
|
|
|
29398
29499
|
}
|
|
29399
29500
|
function spanAndSelectionLocations(spanValue, selectionValue, environment, field) {
|
|
29400
29501
|
const navigation = spanLocation(spanValue, environment, field);
|
|
29401
|
-
const
|
|
29502
|
+
const selection2 = spanLocation(
|
|
29402
29503
|
selectionValue,
|
|
29403
29504
|
environment,
|
|
29404
29505
|
`${field}.selection`
|
|
29405
29506
|
);
|
|
29406
29507
|
return {
|
|
29407
29508
|
...navigation,
|
|
29408
|
-
...
|
|
29509
|
+
...selection2.location ? { selectionLocation: selection2.location } : {}
|
|
29409
29510
|
};
|
|
29410
29511
|
}
|
|
29411
29512
|
function scriptDefinitionLocations(member, environment, field) {
|
|
@@ -31121,6 +31222,9 @@ function normalizeDocumentFields(recordKind, value) {
|
|
|
31121
31222
|
if (current === void 0) normalized[field] = null;
|
|
31122
31223
|
}
|
|
31123
31224
|
if (recordKind === "member") {
|
|
31225
|
+
if (CALLABLE_MEMBER_KINDS.has(normalized.kind)) {
|
|
31226
|
+
normalized.required = false;
|
|
31227
|
+
}
|
|
31124
31228
|
normalizeTypeInfoBindings(normalized.returnTypeInfo);
|
|
31125
31229
|
if (Array.isArray(normalized.argumentTypes)) {
|
|
31126
31230
|
for (const argument2 of normalized.argumentTypes) {
|
|
@@ -31232,13 +31336,14 @@ function deepNormalizeValue(value) {
|
|
|
31232
31336
|
function isRecord(value) {
|
|
31233
31337
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
31234
31338
|
}
|
|
31235
|
-
var SchemaDocumentContractError;
|
|
31339
|
+
var CALLABLE_MEMBER_KINDS, SchemaDocumentContractError;
|
|
31236
31340
|
var init_contracts = __esm({
|
|
31237
31341
|
"src/project-manifest/contracts.ts"() {
|
|
31238
31342
|
"use strict";
|
|
31239
31343
|
init_document_contracts();
|
|
31240
31344
|
init_machine_strings();
|
|
31241
31345
|
init_document_contracts();
|
|
31346
|
+
CALLABLE_MEMBER_KINDS = /* @__PURE__ */ new Set([13, 23]);
|
|
31242
31347
|
SchemaDocumentContractError = class extends Error {
|
|
31243
31348
|
constructor(recordKind, field) {
|
|
31244
31349
|
super(
|
|
@@ -31264,6 +31369,8 @@ function threeWayMergeRecord(base, server, local, policy = {}) {
|
|
|
31264
31369
|
const comparisonServer = policy.comparison?.server ?? serverRecord;
|
|
31265
31370
|
const comparisonLocal = policy.comparison?.local ?? localRecord;
|
|
31266
31371
|
const merged = {};
|
|
31372
|
+
const localVariant = {};
|
|
31373
|
+
const serverVariant = {};
|
|
31267
31374
|
const conflictFields = [];
|
|
31268
31375
|
const keys = /* @__PURE__ */ new Set([
|
|
31269
31376
|
...Object.keys(serverRecord),
|
|
@@ -31274,7 +31381,11 @@ function threeWayMergeRecord(base, server, local, policy = {}) {
|
|
|
31274
31381
|
const rawServerValue = serverRecord[key];
|
|
31275
31382
|
const rawLocalValue = localRecord[key];
|
|
31276
31383
|
if (policy.serverWinsFields?.has(key) === true) {
|
|
31277
|
-
if (rawServerValue !== void 0)
|
|
31384
|
+
if (rawServerValue !== void 0) {
|
|
31385
|
+
merged[key] = rawServerValue;
|
|
31386
|
+
localVariant[key] = rawServerValue;
|
|
31387
|
+
serverVariant[key] = rawServerValue;
|
|
31388
|
+
}
|
|
31278
31389
|
continue;
|
|
31279
31390
|
}
|
|
31280
31391
|
const baseValue = comparisonBase[key];
|
|
@@ -31295,25 +31406,31 @@ function threeWayMergeRecord(base, server, local, policy = {}) {
|
|
|
31295
31406
|
} else if (result.present) {
|
|
31296
31407
|
merged[key] = result.value;
|
|
31297
31408
|
}
|
|
31409
|
+
if (result.local.present) localVariant[key] = result.local.value;
|
|
31410
|
+
if (result.server.present) serverVariant[key] = result.server.value;
|
|
31298
31411
|
}
|
|
31299
|
-
return { merged, conflictFields };
|
|
31412
|
+
return { merged, localVariant, serverVariant, conflictFields };
|
|
31300
31413
|
}
|
|
31301
31414
|
function mergeValue(args) {
|
|
31302
31415
|
if (canonicallyEqual(args.server, args.base)) {
|
|
31303
|
-
return
|
|
31416
|
+
return sharedSelection(args.rawLocal);
|
|
31304
31417
|
}
|
|
31305
31418
|
if (canonicallyEqual(args.local, args.base)) {
|
|
31306
|
-
return
|
|
31419
|
+
return sharedSelection(args.rawServer);
|
|
31307
31420
|
}
|
|
31308
31421
|
if (canonicallyEqual(args.local, args.server)) {
|
|
31309
|
-
return
|
|
31422
|
+
return sharedSelection(args.rawLocal);
|
|
31423
|
+
}
|
|
31424
|
+
if (!args.recursive) {
|
|
31425
|
+
return conflict(args.path, args.rawLocal, args.rawServer);
|
|
31310
31426
|
}
|
|
31311
|
-
if (!args.recursive) return conflict(args.path);
|
|
31312
31427
|
if (isObjectRecord2(args.rawBase) && isObjectRecord2(args.rawServer) && isObjectRecord2(args.rawLocal)) {
|
|
31313
31428
|
const comparisonBase = isObjectRecord2(args.base) ? args.base : args.rawBase;
|
|
31314
31429
|
const comparisonServer = isObjectRecord2(args.server) ? args.server : args.rawServer;
|
|
31315
31430
|
const comparisonLocal = isObjectRecord2(args.local) ? args.local : args.rawLocal;
|
|
31316
31431
|
const value = {};
|
|
31432
|
+
const localVariant = {};
|
|
31433
|
+
const serverVariant = {};
|
|
31317
31434
|
const conflicts = [];
|
|
31318
31435
|
const keys = /* @__PURE__ */ new Set([
|
|
31319
31436
|
...Object.keys(args.rawBase),
|
|
@@ -31333,8 +31450,16 @@ function mergeValue(args) {
|
|
|
31333
31450
|
});
|
|
31334
31451
|
conflicts.push(...nested.conflicts);
|
|
31335
31452
|
if (nested.present) value[key] = nested.value;
|
|
31453
|
+
if (nested.local.present) localVariant[key] = nested.local.value;
|
|
31454
|
+
if (nested.server.present) serverVariant[key] = nested.server.value;
|
|
31336
31455
|
}
|
|
31337
|
-
return {
|
|
31456
|
+
return {
|
|
31457
|
+
present: true,
|
|
31458
|
+
value,
|
|
31459
|
+
local: { present: true, value: localVariant },
|
|
31460
|
+
server: { present: true, value: serverVariant },
|
|
31461
|
+
conflicts
|
|
31462
|
+
};
|
|
31338
31463
|
}
|
|
31339
31464
|
if (Array.isArray(args.rawBase) && Array.isArray(args.rawServer) && Array.isArray(args.rawLocal)) {
|
|
31340
31465
|
return mergeIdentityArray(
|
|
@@ -31344,17 +31469,24 @@ function mergeValue(args) {
|
|
|
31344
31469
|
args.path
|
|
31345
31470
|
);
|
|
31346
31471
|
}
|
|
31347
|
-
return conflict(args.path);
|
|
31472
|
+
return conflict(args.path, args.rawLocal, args.rawServer);
|
|
31348
31473
|
}
|
|
31349
31474
|
function mergeIdentityArray(base, server, local, path) {
|
|
31350
31475
|
const baseItems = indexIdentityArray(base);
|
|
31351
31476
|
const serverItems = indexIdentityArray(server);
|
|
31352
31477
|
const localItems = indexIdentityArray(local);
|
|
31353
31478
|
if (baseItems === null || serverItems === null || localItems === null) {
|
|
31354
|
-
return conflict(path);
|
|
31479
|
+
return conflict(path, local, server);
|
|
31355
31480
|
}
|
|
31356
|
-
const
|
|
31481
|
+
const mergedValues = /* @__PURE__ */ new Map();
|
|
31482
|
+
const localValues = /* @__PURE__ */ new Map();
|
|
31483
|
+
const serverValues = /* @__PURE__ */ new Map();
|
|
31357
31484
|
const conflicts = [];
|
|
31485
|
+
const retainShared = (id2, value2) => {
|
|
31486
|
+
mergedValues.set(id2, value2);
|
|
31487
|
+
localValues.set(id2, value2);
|
|
31488
|
+
serverValues.set(id2, value2);
|
|
31489
|
+
};
|
|
31358
31490
|
const ids = /* @__PURE__ */ new Set([
|
|
31359
31491
|
...baseItems.order,
|
|
31360
31492
|
...serverItems.order,
|
|
@@ -31370,46 +31502,79 @@ function mergeIdentityArray(base, server, local, path) {
|
|
|
31370
31502
|
if (baseHas && !serverHas && !localHas) continue;
|
|
31371
31503
|
if (baseHas && !serverHas) {
|
|
31372
31504
|
if (canonicallyEqual(localValue, baseValue)) continue;
|
|
31373
|
-
conflicts.push(
|
|
31505
|
+
conflicts.push(path + "[" + JSON.stringify(id2) + "]");
|
|
31506
|
+
localValues.set(id2, localValue);
|
|
31374
31507
|
continue;
|
|
31375
31508
|
}
|
|
31376
31509
|
if (baseHas && !localHas) {
|
|
31377
31510
|
if (canonicallyEqual(serverValue, baseValue)) continue;
|
|
31378
|
-
conflicts.push(
|
|
31511
|
+
conflicts.push(path + "[" + JSON.stringify(id2) + "]");
|
|
31512
|
+
serverValues.set(id2, serverValue);
|
|
31379
31513
|
continue;
|
|
31380
31514
|
}
|
|
31381
31515
|
if (!serverHas && localHas) {
|
|
31382
|
-
|
|
31516
|
+
retainShared(id2, localValue);
|
|
31383
31517
|
continue;
|
|
31384
31518
|
}
|
|
31385
31519
|
if (!localHas && serverHas) {
|
|
31386
|
-
|
|
31520
|
+
retainShared(id2, serverValue);
|
|
31387
31521
|
continue;
|
|
31388
31522
|
}
|
|
31389
|
-
const
|
|
31523
|
+
const item = mergeValue({
|
|
31390
31524
|
rawBase: baseValue,
|
|
31391
31525
|
rawServer: serverValue,
|
|
31392
31526
|
rawLocal: localValue,
|
|
31393
31527
|
base: baseValue,
|
|
31394
31528
|
server: serverValue,
|
|
31395
31529
|
local: localValue,
|
|
31396
|
-
path:
|
|
31530
|
+
path: path + "[" + JSON.stringify(id2) + "]",
|
|
31397
31531
|
recursive: true
|
|
31398
31532
|
});
|
|
31399
|
-
conflicts.push(...
|
|
31400
|
-
if (
|
|
31533
|
+
conflicts.push(...item.conflicts);
|
|
31534
|
+
if (item.present) mergedValues.set(id2, item.value);
|
|
31535
|
+
if (item.local.present) localValues.set(id2, item.local.value);
|
|
31536
|
+
if (item.server.present) serverValues.set(id2, item.server.value);
|
|
31401
31537
|
}
|
|
31402
|
-
|
|
31403
|
-
const
|
|
31538
|
+
const retainedIds = /* @__PURE__ */ new Set([...localValues.keys(), ...serverValues.keys()]);
|
|
31539
|
+
const sharedOrder = mergeIdentityOrder(
|
|
31540
|
+
baseItems.order,
|
|
31541
|
+
serverItems.order,
|
|
31542
|
+
localItems.order,
|
|
31543
|
+
retainedIds
|
|
31544
|
+
);
|
|
31545
|
+
if (sharedOrder === null) conflicts.push(path + ".$order");
|
|
31546
|
+
const localOrder = sharedOrder?.filter((id2) => localValues.has(id2)) ?? completeVariantOrder(
|
|
31547
|
+
localItems.order,
|
|
31548
|
+
serverItems.order,
|
|
31404
31549
|
baseItems.order,
|
|
31550
|
+
new Set(localValues.keys())
|
|
31551
|
+
);
|
|
31552
|
+
const serverOrder = sharedOrder?.filter((id2) => serverValues.has(id2)) ?? completeVariantOrder(
|
|
31405
31553
|
serverItems.order,
|
|
31406
31554
|
localItems.order,
|
|
31407
|
-
|
|
31555
|
+
baseItems.order,
|
|
31556
|
+
new Set(serverValues.keys())
|
|
31408
31557
|
);
|
|
31409
|
-
|
|
31558
|
+
const localVariant = localOrder.map((id2) => localValues.get(id2));
|
|
31559
|
+
const serverVariant = serverOrder.map((id2) => serverValues.get(id2));
|
|
31560
|
+
if (conflicts.length > 0) {
|
|
31561
|
+
return {
|
|
31562
|
+
present: true,
|
|
31563
|
+
value: [],
|
|
31564
|
+
local: { present: true, value: localVariant },
|
|
31565
|
+
server: { present: true, value: serverVariant },
|
|
31566
|
+
conflicts
|
|
31567
|
+
};
|
|
31568
|
+
}
|
|
31569
|
+
if (sharedOrder === null) {
|
|
31570
|
+
throw new Error("A conflict-free identity merge must have a shared order.");
|
|
31571
|
+
}
|
|
31572
|
+
const value = sharedOrder.map((id2) => mergedValues.get(id2));
|
|
31410
31573
|
return {
|
|
31411
31574
|
present: true,
|
|
31412
|
-
value
|
|
31575
|
+
value,
|
|
31576
|
+
local: { present: true, value },
|
|
31577
|
+
server: { present: true, value },
|
|
31413
31578
|
conflicts: []
|
|
31414
31579
|
};
|
|
31415
31580
|
}
|
|
@@ -31466,11 +31631,51 @@ function mergeIdentityOrder(base, server, local, retained) {
|
|
|
31466
31631
|
}
|
|
31467
31632
|
return result.length === nodes.length ? result : null;
|
|
31468
31633
|
}
|
|
31469
|
-
function
|
|
31470
|
-
|
|
31634
|
+
function completeVariantOrder(preferred, fallback, base, retained) {
|
|
31635
|
+
const result = preferred.filter((id2) => retained.has(id2));
|
|
31636
|
+
const included = new Set(result);
|
|
31637
|
+
for (const source of [fallback, base]) {
|
|
31638
|
+
for (let index = 0; index < source.length; index += 1) {
|
|
31639
|
+
const id2 = source[index];
|
|
31640
|
+
if (!retained.has(id2) || included.has(id2)) continue;
|
|
31641
|
+
let insertionIndex = -1;
|
|
31642
|
+
for (let next = index + 1; next < source.length; next += 1) {
|
|
31643
|
+
const nextIndex = result.indexOf(source[next]);
|
|
31644
|
+
if (nextIndex !== -1) {
|
|
31645
|
+
insertionIndex = nextIndex;
|
|
31646
|
+
break;
|
|
31647
|
+
}
|
|
31648
|
+
}
|
|
31649
|
+
if (insertionIndex === -1) {
|
|
31650
|
+
for (let previous = index - 1; previous >= 0; previous -= 1) {
|
|
31651
|
+
const previousIndex = result.indexOf(source[previous]);
|
|
31652
|
+
if (previousIndex !== -1) {
|
|
31653
|
+
insertionIndex = previousIndex + 1;
|
|
31654
|
+
break;
|
|
31655
|
+
}
|
|
31656
|
+
}
|
|
31657
|
+
}
|
|
31658
|
+
if (insertionIndex === -1) insertionIndex = result.length;
|
|
31659
|
+
result.splice(insertionIndex, 0, id2);
|
|
31660
|
+
included.add(id2);
|
|
31661
|
+
}
|
|
31662
|
+
}
|
|
31663
|
+
return result;
|
|
31471
31664
|
}
|
|
31472
|
-
function
|
|
31473
|
-
return { present: false
|
|
31665
|
+
function selection(value) {
|
|
31666
|
+
return value === void 0 ? { present: false } : { present: true, value };
|
|
31667
|
+
}
|
|
31668
|
+
function sharedSelection(value) {
|
|
31669
|
+
const selected = selection(value);
|
|
31670
|
+
return { ...selected, local: selected, server: selected, conflicts: [] };
|
|
31671
|
+
}
|
|
31672
|
+
function conflict(path, localValue, serverValue) {
|
|
31673
|
+
return {
|
|
31674
|
+
present: false,
|
|
31675
|
+
local: selection(localValue),
|
|
31676
|
+
server: selection(serverValue),
|
|
31677
|
+
conflicts: [path]
|
|
31678
|
+
};
|
|
31474
31679
|
}
|
|
31475
31680
|
var init_merge = __esm({
|
|
31476
31681
|
"src/project-sync/merge.ts"() {
|
|
@@ -51601,13 +51806,13 @@ function sourceBaseParameterNames(context, baseName, suppliedNames) {
|
|
|
51601
51806
|
return required2.parameters.map((parameter4) => parameter4.name);
|
|
51602
51807
|
}
|
|
51603
51808
|
const declared = context.declaredConstructors.byClassName.get(baseName) ?? [];
|
|
51604
|
-
const
|
|
51809
|
+
const selected = selectOverload(
|
|
51605
51810
|
declared.map(
|
|
51606
51811
|
(constructor2) => constructor2.parameters.map((parameter4) => parameter4.name)
|
|
51607
51812
|
),
|
|
51608
51813
|
suppliedNames
|
|
51609
51814
|
);
|
|
51610
|
-
return
|
|
51815
|
+
return selected;
|
|
51611
51816
|
}
|
|
51612
51817
|
function recordBaseParameterNames(context, baseName, suppliedNames) {
|
|
51613
51818
|
const baseClassId = context.classIdsByName.get(baseName);
|
|
@@ -64538,7 +64743,7 @@ function evaluateInitializerInContext(init, member, ctx, createdValues, argument
|
|
|
64538
64743
|
};
|
|
64539
64744
|
}
|
|
64540
64745
|
function encodeLookupInitializerResult(member, value, created, ctx) {
|
|
64541
|
-
const
|
|
64746
|
+
const selection2 = encodeLookupInitializerSelection(
|
|
64542
64747
|
member,
|
|
64543
64748
|
value,
|
|
64544
64749
|
created,
|
|
@@ -64550,7 +64755,7 @@ function encodeLookupInitializerResult(member, value, created, ctx) {
|
|
|
64550
64755
|
ctx.__executionState?.constructorGroups.delete(row.id);
|
|
64551
64756
|
}
|
|
64552
64757
|
}
|
|
64553
|
-
return { value:
|
|
64758
|
+
return { value: selection2, classId: null };
|
|
64554
64759
|
}
|
|
64555
64760
|
function encodeLookupInitializerSelection(member, value, created, ctx) {
|
|
64556
64761
|
if (value === null) return null;
|
|
@@ -72482,7 +72687,7 @@ var init_animation_clips = __esm({
|
|
|
72482
72687
|
const seenChildren = /* @__PURE__ */ new Set();
|
|
72483
72688
|
for (const row of rows) {
|
|
72484
72689
|
const rowClassId = this.requireNodeClassId(row, "animationChildOverride");
|
|
72485
|
-
const
|
|
72690
|
+
const selected = this.resolveSelector(
|
|
72486
72691
|
row,
|
|
72487
72692
|
rowClassId,
|
|
72488
72693
|
WORLD_ANIMATION_CHILD_OVERRIDE_SELECTOR_MEMBER_ID,
|
|
@@ -72490,8 +72695,8 @@ var init_animation_clips = __esm({
|
|
|
72490
72695
|
args.selectorOwnerNode,
|
|
72491
72696
|
`Animation clip "${args.clipName}" frame ${args.frameIndex} child override`
|
|
72492
72697
|
);
|
|
72493
|
-
if (
|
|
72494
|
-
const { childId, childClassId, childNode: child } =
|
|
72698
|
+
if (selected === null) continue;
|
|
72699
|
+
const { childId, childClassId, childNode: child } = selected;
|
|
72495
72700
|
if (!args.childIds.has(childId)) {
|
|
72496
72701
|
throw new Error(
|
|
72497
72702
|
`Animation clip "${args.clipName}" frame ${args.frameIndex} references child "${childId}" outside the owner's authored Children graph.`
|
|
@@ -72657,7 +72862,7 @@ var init_animation_clips = __esm({
|
|
|
72657
72862
|
* segment's length is instance data this document does not have.
|
|
72658
72863
|
*/
|
|
72659
72864
|
validateTrackBase(args) {
|
|
72660
|
-
const
|
|
72865
|
+
const selected = this.resolveSelector(
|
|
72661
72866
|
args.track,
|
|
72662
72867
|
args.trackClassId,
|
|
72663
72868
|
WORLD_ANIMATION_TRACK_SELECTOR_MEMBER_ID,
|
|
@@ -72665,9 +72870,9 @@ var init_animation_clips = __esm({
|
|
|
72665
72870
|
args.selectorOwnerNode,
|
|
72666
72871
|
args.label
|
|
72667
72872
|
);
|
|
72668
|
-
if (
|
|
72873
|
+
if (selected !== null && !args.childIds.has(selected.childId)) {
|
|
72669
72874
|
throw new Error(
|
|
72670
|
-
`${args.label} references child "${
|
|
72875
|
+
`${args.label} references child "${selected.childId}" outside the owner's authored Children graph.`
|
|
72671
72876
|
);
|
|
72672
72877
|
}
|
|
72673
72878
|
const startFrame = this.requireIntegerField(
|
|
@@ -72686,7 +72891,7 @@ var init_animation_clips = __esm({
|
|
|
72686
72891
|
}
|
|
72687
72892
|
this.validateTrackDirection(args.track, args.trackClassId, args.label);
|
|
72688
72893
|
this.validateTrackCropWindow(args.track, args.trackClassId, args.label);
|
|
72689
|
-
return
|
|
72894
|
+
return selected;
|
|
72690
72895
|
}
|
|
72691
72896
|
resolveSelector(parent, classId, selectorMemberId, refreshMemberId, _selectorOwnerNode, label) {
|
|
72692
72897
|
this.validateSelectorRefresh(parent, classId, refreshMemberId, label);
|
|
@@ -74157,7 +74362,7 @@ function explicitTargetIds(changes) {
|
|
|
74157
74362
|
return result;
|
|
74158
74363
|
}
|
|
74159
74364
|
function selectedRecordIds(records2, explicitIds, impactedIds, impactedTypeNames, constructedClassIds, impactedSourceNames, ownerId = () => null) {
|
|
74160
|
-
const
|
|
74365
|
+
const selected = new Set(explicitIds);
|
|
74161
74366
|
for (const record3 of records2) {
|
|
74162
74367
|
const owner = ownerId(record3);
|
|
74163
74368
|
if (owner !== null && impactedIds.has(owner) || recordDependsOnChangedContract(
|
|
@@ -74167,10 +74372,10 @@ function selectedRecordIds(records2, explicitIds, impactedIds, impactedTypeNames
|
|
|
74167
74372
|
constructedClassIds,
|
|
74168
74373
|
impactedSourceNames
|
|
74169
74374
|
)) {
|
|
74170
|
-
|
|
74375
|
+
selected.add(record3.id);
|
|
74171
74376
|
}
|
|
74172
74377
|
}
|
|
74173
|
-
return
|
|
74378
|
+
return selected;
|
|
74174
74379
|
}
|
|
74175
74380
|
function recordDependsOnChangedContract(record3, impactedIds, impactedTypeNames, constructedClassIds, impactedSourceNames) {
|
|
74176
74381
|
const recordId = isObjectRecord3(record3) ? record3.id : void 0;
|
|
@@ -85224,11 +85429,11 @@ var init_project_version_whole_graph_validation = __esm({
|
|
|
85224
85429
|
|
|
85225
85430
|
// src/project-source/workspace-status-core.ts
|
|
85226
85431
|
function listVirtualProjectSourceFilesV4(files) {
|
|
85227
|
-
const
|
|
85432
|
+
const selected = files.filter((file) => {
|
|
85228
85433
|
const kind = neoProjectSourceKind(file.path);
|
|
85229
85434
|
return kind !== null && isNeoProjectProductionSourceKind(kind) && !neoProjectPathHasIgnoredDirectory(file.path);
|
|
85230
85435
|
});
|
|
85231
|
-
const sorted = [...
|
|
85436
|
+
const sorted = [...selected].sort(
|
|
85232
85437
|
(left, right) => compareWorkspacePaths(left.path, right.path)
|
|
85233
85438
|
);
|
|
85234
85439
|
for (let index = 1; index < sorted.length; index += 1) {
|
|
@@ -91292,9 +91497,6 @@ function resolveLookupCollectionValueIds(context, member, collection, ownerValue
|
|
|
91292
91497
|
member.collectionMemberId,
|
|
91293
91498
|
collection.name
|
|
91294
91499
|
);
|
|
91295
|
-
if (declaredRows.size > 0) {
|
|
91296
|
-
return { valueIds: [...declaredRows], origin: "collectionMember" };
|
|
91297
|
-
}
|
|
91298
91500
|
const candidates = /* @__PURE__ */ new Set();
|
|
91299
91501
|
const collectionState = context.state[`member:${member.collectionMemberId}`];
|
|
91300
91502
|
const collectionMemberData = isObjectRecord2(collectionState?.data) ? collectionState.data : {};
|
|
@@ -91306,6 +91508,12 @@ function resolveLookupCollectionValueIds(context, member, collection, ownerValue
|
|
|
91306
91508
|
) ?? []) {
|
|
91307
91509
|
candidates.add(placedValueId);
|
|
91308
91510
|
}
|
|
91511
|
+
if (declaredRows.size > 0) {
|
|
91512
|
+
return {
|
|
91513
|
+
valueIds: [.../* @__PURE__ */ new Set([...declaredRows, ...candidates])],
|
|
91514
|
+
origin: "collectionMember"
|
|
91515
|
+
};
|
|
91516
|
+
}
|
|
91309
91517
|
return { valueIds: [...candidates], origin: "nameScan" };
|
|
91310
91518
|
}
|
|
91311
91519
|
function collectionRowsOfDeclaredMember(context, collectionMemberId, schemaKey) {
|
|
@@ -92268,13 +92476,13 @@ function storedValueConstructor(context, schemaClass2, constructorArgs) {
|
|
|
92268
92476
|
`Stored construction for ${schemaClass2.name} cannot select one constructor from ${candidates.length} ${count}-argument candidates.`
|
|
92269
92477
|
);
|
|
92270
92478
|
}
|
|
92271
|
-
const
|
|
92272
|
-
if (
|
|
92479
|
+
const selected = candidates[0];
|
|
92480
|
+
if (selected === void 0) {
|
|
92273
92481
|
throw new Error(
|
|
92274
92482
|
`Stored construction for ${schemaClass2.name} resolved no constructor.`
|
|
92275
92483
|
);
|
|
92276
92484
|
}
|
|
92277
|
-
return
|
|
92485
|
+
return selected;
|
|
92278
92486
|
}
|
|
92279
92487
|
function storedConstructorArgumentSource(context, type, value, environment, visited, cloneAggregateArguments = false) {
|
|
92280
92488
|
if (value === null) {
|
|
@@ -93879,7 +94087,7 @@ import {
|
|
|
93879
94087
|
readFileSync as readFileSync6,
|
|
93880
94088
|
readdirSync,
|
|
93881
94089
|
renameSync as renameSync4,
|
|
93882
|
-
rmSync,
|
|
94090
|
+
rmSync as rmSync2,
|
|
93883
94091
|
writeFileSync as writeFileSync6
|
|
93884
94092
|
} from "node:fs";
|
|
93885
94093
|
import { basename, dirname as dirname5, extname, join as join6, relative, sep } from "node:path";
|
|
@@ -94159,7 +94367,7 @@ function writeVerifiedBinaryDownloadV4(destination, bytes, expectedSha256) {
|
|
|
94159
94367
|
writeFileSync6(temporary, bytes);
|
|
94160
94368
|
renameSync4(temporary, destination);
|
|
94161
94369
|
} finally {
|
|
94162
|
-
|
|
94370
|
+
rmSync2(temporary, { force: true });
|
|
94163
94371
|
}
|
|
94164
94372
|
}
|
|
94165
94373
|
function writeBinaryConflictArtifactV4(root, fileId, fileName2, bytes, expectedSha256) {
|
|
@@ -95284,7 +95492,7 @@ import {
|
|
|
95284
95492
|
mkdirSync as mkdirSync7,
|
|
95285
95493
|
readFileSync as readFileSync8,
|
|
95286
95494
|
readdirSync as readdirSync3,
|
|
95287
|
-
rmSync as
|
|
95495
|
+
rmSync as rmSync3,
|
|
95288
95496
|
writeFileSync as writeFileSync7,
|
|
95289
95497
|
statSync
|
|
95290
95498
|
} from "node:fs";
|
|
@@ -95296,14 +95504,14 @@ function resetWorkspaceToProjectSourcesV4(workspace, document, options = {}) {
|
|
|
95296
95504
|
const previous = managedFilesBeforeReset(workspace.root);
|
|
95297
95505
|
const preservedSpecs = preserveManagedSpecs(workspace.root);
|
|
95298
95506
|
for (const directory of FORMAT_4_MANAGED_DIRECTORIES) {
|
|
95299
|
-
|
|
95507
|
+
rmSync3(join8(workspace.root, directory), { recursive: true, force: true });
|
|
95300
95508
|
}
|
|
95301
|
-
|
|
95509
|
+
rmSync3(join8(workspace.root, "Scripts"), { recursive: true, force: true });
|
|
95302
95510
|
for (const file of LEGACY_ROOT_FILES) {
|
|
95303
|
-
|
|
95511
|
+
rmSync3(join8(workspace.root, file), { force: true });
|
|
95304
95512
|
}
|
|
95305
95513
|
for (const privatePath of LEGACY_PRIVATE_PATHS) {
|
|
95306
|
-
|
|
95514
|
+
rmSync3(join8(workspace.root, privatePath), { recursive: true, force: true });
|
|
95307
95515
|
}
|
|
95308
95516
|
for (const [path, bytes] of preservedSpecs) {
|
|
95309
95517
|
const absolute = join8(workspace.root, path);
|
|
@@ -95559,7 +95767,7 @@ var init_http = __esm({
|
|
|
95559
95767
|
});
|
|
95560
95768
|
|
|
95561
95769
|
// src/project-source/project-file-pull.ts
|
|
95562
|
-
import { existsSync as existsSync6, rmSync as
|
|
95770
|
+
import { existsSync as existsSync6, rmSync as rmSync4 } from "node:fs";
|
|
95563
95771
|
import { join as join9 } from "node:path";
|
|
95564
95772
|
async function pullProjectBinariesV4(args) {
|
|
95565
95773
|
let client = args.client ?? null;
|
|
@@ -95688,7 +95896,7 @@ async function pullProjectBinariesV4(args) {
|
|
|
95688
95896
|
conflicted += 1;
|
|
95689
95897
|
continue;
|
|
95690
95898
|
}
|
|
95691
|
-
|
|
95899
|
+
rmSync4(absolute, { force: true });
|
|
95692
95900
|
removePreviousConflict(args.workspace.root, previous.projectBinary);
|
|
95693
95901
|
}
|
|
95694
95902
|
return { states, downloaded, conflicted, conflicts };
|
|
@@ -95758,7 +95966,7 @@ function fileName(data) {
|
|
|
95758
95966
|
}
|
|
95759
95967
|
function removePreviousConflict(root, state) {
|
|
95760
95968
|
if (state?.conflict?.artifactPath === void 0) return;
|
|
95761
|
-
|
|
95969
|
+
rmSync4(join9(root, state.conflict.artifactPath), { force: true });
|
|
95762
95970
|
}
|
|
95763
95971
|
var init_project_file_pull = __esm({
|
|
95764
95972
|
"src/project-source/project-file-pull.ts"() {
|
|
@@ -95823,7 +96031,7 @@ __export(pull_exports, {
|
|
|
95823
96031
|
import {
|
|
95824
96032
|
mkdirSync as mkdirSync8,
|
|
95825
96033
|
writeFileSync as writeFileSync8,
|
|
95826
|
-
rmSync as
|
|
96034
|
+
rmSync as rmSync5,
|
|
95827
96035
|
existsSync as existsSync7,
|
|
95828
96036
|
readFileSync as readFileSync9
|
|
95829
96037
|
} from "node:fs";
|
|
@@ -95972,7 +96180,7 @@ ${blockingErrors.map((error) => ` ${error.message}`).join("\n")}`
|
|
|
95972
96180
|
continue;
|
|
95973
96181
|
}
|
|
95974
96182
|
const localSide = locallyDeleted ? {} : local;
|
|
95975
|
-
const { merged, conflictFields } = mergeProjectDocumentRecord(
|
|
96183
|
+
const { merged, localVariant, serverVariant, conflictFields } = mergeProjectDocumentRecord(
|
|
95976
96184
|
serverRecord.recordKind,
|
|
95977
96185
|
baseState.data,
|
|
95978
96186
|
serverRecord.data,
|
|
@@ -95985,11 +96193,11 @@ ${blockingErrors.map((error) => ` ${error.message}`).join("\n")}`
|
|
|
95985
96193
|
plans.set(key, {
|
|
95986
96194
|
// The working copy renders the LOCAL side; the marker's other half
|
|
95987
96195
|
// comes from the server-variant emission.
|
|
95988
|
-
emitData: locallyDeleted ? void 0 :
|
|
96196
|
+
emitData: locallyDeleted ? void 0 : localVariant,
|
|
95989
96197
|
serverHash: serverRecord.contentHash,
|
|
95990
96198
|
serverData: serverRecord.data,
|
|
95991
96199
|
conflicted: true,
|
|
95992
|
-
|
|
96200
|
+
serverEmitData: locallyDeleted ? serverRecord.data : serverVariant
|
|
95993
96201
|
});
|
|
95994
96202
|
} else {
|
|
95995
96203
|
mergedCount += 1;
|
|
@@ -96024,8 +96232,7 @@ ${blockingErrors.map((error) => ` ${error.message}`).join("\n")}`
|
|
|
96024
96232
|
emitData: local,
|
|
96025
96233
|
serverHash: baseState.contentHash,
|
|
96026
96234
|
serverData: void 0,
|
|
96027
|
-
conflicted: true
|
|
96028
|
-
localData: local
|
|
96235
|
+
conflicted: true
|
|
96029
96236
|
});
|
|
96030
96237
|
continue;
|
|
96031
96238
|
}
|
|
@@ -96212,7 +96419,7 @@ async function finishFormat4Pull(args) {
|
|
|
96212
96419
|
if (previousPath === void 0 || emittedPaths.has(previousPath)) continue;
|
|
96213
96420
|
const absolute = join10(workspace.root, previousPath);
|
|
96214
96421
|
if (existsSync7(absolute)) {
|
|
96215
|
-
|
|
96422
|
+
rmSync5(absolute);
|
|
96216
96423
|
removed += 1;
|
|
96217
96424
|
}
|
|
96218
96425
|
}
|
|
@@ -96520,7 +96727,7 @@ function sourceComparableObjectRecord(recordKind, value, mainLocale) {
|
|
|
96520
96727
|
function buildEmitRecordSet(document, plans, side) {
|
|
96521
96728
|
const records2 = /* @__PURE__ */ new Map();
|
|
96522
96729
|
for (const [key, plan] of plans) {
|
|
96523
|
-
const data = side === "emit" ? plan.emitData : plan.serverData;
|
|
96730
|
+
const data = side === "emit" ? plan.emitData : plan.serverEmitData ?? plan.serverData;
|
|
96524
96731
|
if (data === void 0) continue;
|
|
96525
96732
|
const serverRecord = document.records.get(key);
|
|
96526
96733
|
const [recordKind, recordId] = key.split(/:(.+)/, 2);
|
|
@@ -100378,7 +100585,7 @@ import { createHash as createHash10, randomUUID as randomUUID2 } from "node:cryp
|
|
|
100378
100585
|
import {
|
|
100379
100586
|
mkdirSync as mkdirSync10,
|
|
100380
100587
|
writeFileSync as writeFileSync10,
|
|
100381
|
-
rmSync as
|
|
100588
|
+
rmSync as rmSync6,
|
|
100382
100589
|
existsSync as existsSync11,
|
|
100383
100590
|
readFileSync as readFileSync15
|
|
100384
100591
|
} from "node:fs";
|
|
@@ -101174,7 +101381,7 @@ async function runPush(workspace, options, preparationOverride) {
|
|
|
101174
101381
|
});
|
|
101175
101382
|
} finally {
|
|
101176
101383
|
if (preparedBuildDir !== void 0) {
|
|
101177
|
-
|
|
101384
|
+
rmSync6(preparedBuildDir, { recursive: true, force: true });
|
|
101178
101385
|
}
|
|
101179
101386
|
}
|
|
101180
101387
|
} else {
|
|
@@ -102387,7 +102594,7 @@ ${finalErrors.map(
|
|
|
102387
102594
|
const previousPath = recordState.file;
|
|
102388
102595
|
if (previousPath === void 0 || emittedPaths.has(previousPath)) continue;
|
|
102389
102596
|
const absolute = join15(workspace.root, previousPath);
|
|
102390
|
-
if (existsSync11(absolute))
|
|
102597
|
+
if (existsSync11(absolute)) rmSync6(absolute);
|
|
102391
102598
|
}
|
|
102392
102599
|
for (const file of files) {
|
|
102393
102600
|
const absolute = join15(workspace.root, file.path);
|
|
@@ -103197,7 +103404,7 @@ var init_registry2 = __esm({
|
|
|
103197
103404
|
PROJECT_SCHEMA_CONTRACT = Object.freeze({
|
|
103198
103405
|
formatVersion: 3,
|
|
103199
103406
|
contractVersion: "3.9",
|
|
103200
|
-
cliVersion: "0.
|
|
103407
|
+
cliVersion: "0.27.1",
|
|
103201
103408
|
projectFileUploadBatchSize: 32,
|
|
103202
103409
|
documentRecords: {
|
|
103203
103410
|
member: {
|
|
@@ -104498,14 +104705,14 @@ import {
|
|
|
104498
104705
|
readFileSync as readFileSync16,
|
|
104499
104706
|
realpathSync,
|
|
104500
104707
|
renameSync as renameSync5,
|
|
104501
|
-
rmSync as
|
|
104708
|
+
rmSync as rmSync7,
|
|
104502
104709
|
statSync as statSync2,
|
|
104503
104710
|
writeFileSync as writeFileSync11
|
|
104504
104711
|
} from "node:fs";
|
|
104505
104712
|
import {
|
|
104506
104713
|
basename as basename3,
|
|
104507
104714
|
dirname as dirname9,
|
|
104508
|
-
isAbsolute,
|
|
104715
|
+
isAbsolute as isAbsolute2,
|
|
104509
104716
|
join as join16,
|
|
104510
104717
|
relative as relative5,
|
|
104511
104718
|
resolve as resolve3,
|
|
@@ -104706,7 +104913,7 @@ function preparedHookCandidate(workspace) {
|
|
|
104706
104913
|
"test-build"
|
|
104707
104914
|
);
|
|
104708
104915
|
const pathFromRoot = relative5(cacheRoot, directory);
|
|
104709
|
-
if (
|
|
104916
|
+
if (isAbsolute2(pathFromRoot)) {
|
|
104710
104917
|
throw new NeoTestPreparedCandidateError(
|
|
104711
104918
|
"NEO_PREPARED_BUILD_DIR must not resolve to an absolute path outside this workspace's .neo/test-build directory."
|
|
104712
104919
|
);
|
|
@@ -104906,7 +105113,7 @@ function selectedSpecPaths(workspace, selectors) {
|
|
|
104906
105113
|
);
|
|
104907
105114
|
for (const selector of normalizedSelectors) {
|
|
104908
105115
|
if (/[*?]/u.test(selector)) continue;
|
|
104909
|
-
if (
|
|
105116
|
+
if (isAbsolute2(selector)) {
|
|
104910
105117
|
throw new Error(
|
|
104911
105118
|
`Spec selector ${JSON.stringify(selector)} must be workspace-relative.`
|
|
104912
105119
|
);
|
|
@@ -104953,8 +105160,8 @@ function selectedSpecPaths(workspace, selectors) {
|
|
|
104953
105160
|
const selectedPaths = all.filter((absolutePath) => {
|
|
104954
105161
|
const path = relativePaths.get(absolutePath);
|
|
104955
105162
|
const configured = configuredIncludes.length === 0 || configuredIncludes.some((pattern) => globMatches(pattern, path));
|
|
104956
|
-
const
|
|
104957
|
-
return configured &&
|
|
105163
|
+
const selected = normalizedSelectors.length === 0 || normalizedSelectors.some((selector) => selectorMatches(selector, path));
|
|
105164
|
+
return configured && selected && !(workspace.config.test?.exclude ?? []).some(
|
|
104958
105165
|
(pattern) => globMatches(pattern.replaceAll("\\", "/"), path)
|
|
104959
105166
|
);
|
|
104960
105167
|
});
|
|
@@ -105155,22 +105362,22 @@ function registerSpec(spec, document) {
|
|
|
105155
105362
|
);
|
|
105156
105363
|
return { spec, root, tests };
|
|
105157
105364
|
}
|
|
105158
|
-
function mockResponse(environment, mock,
|
|
105159
|
-
if (
|
|
105365
|
+
function mockResponse(environment, mock, selected, call) {
|
|
105366
|
+
if (selected === null) {
|
|
105160
105367
|
if (mock.callThrough) return { handled: false };
|
|
105161
105368
|
throw new NeoTestAssertionError(
|
|
105162
105369
|
`Mock for Function '${mock.memberId}' has no configured behavior. Add returns, throws, doesNothing, or implementation.`
|
|
105163
105370
|
);
|
|
105164
105371
|
}
|
|
105165
|
-
if (
|
|
105166
|
-
throw new NSGetterRuntimeError(
|
|
105372
|
+
if (selected.kind === "throw") {
|
|
105373
|
+
throw new NSGetterRuntimeError(selected.message);
|
|
105167
105374
|
}
|
|
105168
|
-
if (
|
|
105375
|
+
if (selected.kind === "implementation") {
|
|
105169
105376
|
return {
|
|
105170
105377
|
handled: true,
|
|
105171
105378
|
value: call.invokeDelegate(
|
|
105172
105379
|
bindNeoScriptDelegateToContext(
|
|
105173
|
-
|
|
105380
|
+
selected.delegate,
|
|
105174
105381
|
environment.context
|
|
105175
105382
|
),
|
|
105176
105383
|
mock.isStatic ? call.args : [call.receiver, ...call.args]
|
|
@@ -105179,7 +105386,7 @@ function mockResponse(environment, mock, selected2, call) {
|
|
|
105179
105386
|
}
|
|
105180
105387
|
return {
|
|
105181
105388
|
handled: true,
|
|
105182
|
-
value:
|
|
105389
|
+
value: selected.kind === "return" ? selected.value : null
|
|
105183
105390
|
};
|
|
105184
105391
|
}
|
|
105185
105392
|
function partialObjectMatch(actual, expected) {
|
|
@@ -105196,16 +105403,16 @@ function matchingMock(environment, call) {
|
|
|
105196
105403
|
(candidate) => candidate.receiverValueId !== void 0
|
|
105197
105404
|
);
|
|
105198
105405
|
const receiverValueId = needsReceiverLookup ? mockReceiverValueId(environment, call.receiver) : null;
|
|
105199
|
-
let
|
|
105406
|
+
let selected;
|
|
105200
105407
|
for (const candidate of candidates) {
|
|
105201
105408
|
if (candidate.receiverValueId !== void 0 && candidate.receiverValueId !== receiverValueId) {
|
|
105202
105409
|
continue;
|
|
105203
105410
|
}
|
|
105204
|
-
if (
|
|
105205
|
-
|
|
105411
|
+
if (selected === void 0 || candidate.id > selected.id) {
|
|
105412
|
+
selected = candidate;
|
|
105206
105413
|
}
|
|
105207
105414
|
}
|
|
105208
|
-
return
|
|
105415
|
+
return selected;
|
|
105209
105416
|
}
|
|
105210
105417
|
function mockReceiverValueId(environment, receiver) {
|
|
105211
105418
|
if (typeof receiver !== "object" || receiver === null) return null;
|
|
@@ -105550,15 +105757,15 @@ function failureFor(error, file, position, member = null) {
|
|
|
105550
105757
|
]
|
|
105551
105758
|
};
|
|
105552
105759
|
}
|
|
105553
|
-
function suiteHasSelectedTests(suite,
|
|
105554
|
-
return suite.tests.some((test) =>
|
|
105760
|
+
function suiteHasSelectedTests(suite, selected) {
|
|
105761
|
+
return suite.tests.some((test) => selected.has(test.id)) || suite.suites.some((child) => suiteHasSelectedTests(child, selected));
|
|
105555
105762
|
}
|
|
105556
|
-
async function executeRegisteredSpec(registered, document,
|
|
105763
|
+
async function executeRegisteredSpec(registered, document, selected, timeoutMs, interrupted) {
|
|
105557
105764
|
const results = [];
|
|
105558
105765
|
const fileFailures = [];
|
|
105559
105766
|
let testDurationMs = 0;
|
|
105560
105767
|
const executeSuite = async (suite, parentEnvironment, inheritedFailures) => {
|
|
105561
|
-
if (!suiteHasSelectedTests(suite,
|
|
105768
|
+
if (!suiteHasSelectedTests(suite, selected)) return;
|
|
105562
105769
|
const fixture = cloneTestEnvironment(parentEnvironment);
|
|
105563
105770
|
const suiteFailures = [...inheritedFailures];
|
|
105564
105771
|
const suiteDeadline = Date.now() + timeoutMs;
|
|
@@ -105575,7 +105782,7 @@ async function executeRegisteredSpec(registered, document, selected2, timeoutMs,
|
|
|
105575
105782
|
}
|
|
105576
105783
|
}
|
|
105577
105784
|
for (const test of suite.tests) {
|
|
105578
|
-
if (!
|
|
105785
|
+
if (!selected.has(test.id)) continue;
|
|
105579
105786
|
const started = performance.now();
|
|
105580
105787
|
const deadline = Date.now() + timeoutMs;
|
|
105581
105788
|
const environment = cloneTestEnvironment(fixture);
|
|
@@ -105691,16 +105898,16 @@ function maintainNeoTestBuildCache(root, maxBytes = TEST_BUILD_CACHE_LIMIT_BYTES
|
|
|
105691
105898
|
const resolvedProtected = protectedDirectory === void 0 ? null : resolve3(protectedDirectory);
|
|
105692
105899
|
const protectedInsideRoot = resolvedProtected !== null && (() => {
|
|
105693
105900
|
const fromRoot = relative5(resolvedRoot, resolvedProtected);
|
|
105694
|
-
return fromRoot === "" || !fromRoot.startsWith(`..${sep5}`) && fromRoot !== ".." && !
|
|
105901
|
+
return fromRoot === "" || !fromRoot.startsWith(`..${sep5}`) && fromRoot !== ".." && !isAbsolute2(fromRoot);
|
|
105695
105902
|
})();
|
|
105696
105903
|
const isProtected = (path) => {
|
|
105697
105904
|
if (!protectedInsideRoot || resolvedProtected === null) return false;
|
|
105698
105905
|
const fromProtected = relative5(resolvedProtected, resolve3(path));
|
|
105699
|
-
return fromProtected === "" || !fromProtected.startsWith(`..${sep5}`) && fromProtected !== ".." && !
|
|
105906
|
+
return fromProtected === "" || !fromProtected.startsWith(`..${sep5}`) && fromProtected !== ".." && !isAbsolute2(fromProtected);
|
|
105700
105907
|
};
|
|
105701
105908
|
for (const file of testBuildFiles(root)) {
|
|
105702
105909
|
if (!isProtected(file.path) && basename3(file.path).includes(".tmp-") && now - file.modifiedMs >= ABANDONED_TEMP_MAX_AGE_MS) {
|
|
105703
|
-
|
|
105910
|
+
rmSync7(file.path, { force: true });
|
|
105704
105911
|
}
|
|
105705
105912
|
}
|
|
105706
105913
|
const files = testBuildFiles(root);
|
|
@@ -105710,7 +105917,7 @@ function maintainNeoTestBuildCache(root, maxBytes = TEST_BUILD_CACHE_LIMIT_BYTES
|
|
|
105710
105917
|
).sort((left, right) => left.modifiedMs - right.modifiedMs);
|
|
105711
105918
|
for (const file of removable) {
|
|
105712
105919
|
if (total <= maxBytes) break;
|
|
105713
|
-
|
|
105920
|
+
rmSync7(file.path, { force: true });
|
|
105714
105921
|
total -= file.size;
|
|
105715
105922
|
}
|
|
105716
105923
|
}
|
|
@@ -106004,7 +106211,7 @@ async function runTest(workspace, options, dependencies = {}) {
|
|
|
106004
106211
|
if (options.outputFile !== null) {
|
|
106005
106212
|
try {
|
|
106006
106213
|
atomicWrite(
|
|
106007
|
-
|
|
106214
|
+
isAbsolute2(options.outputFile) ? options.outputFile : join16(workspace.root, options.outputFile),
|
|
106008
106215
|
serialized
|
|
106009
106216
|
);
|
|
106010
106217
|
} catch (error) {
|
|
@@ -106217,7 +106424,7 @@ import {
|
|
|
106217
106424
|
existsSync as existsSync13,
|
|
106218
106425
|
readFileSync as readFileSync17
|
|
106219
106426
|
} from "node:fs";
|
|
106220
|
-
import { extname as extname2, isAbsolute as
|
|
106427
|
+
import { extname as extname2, isAbsolute as isAbsolute3, join as join17, relative as relative6, sep as sep6 } from "node:path";
|
|
106221
106428
|
function inspectNeoDoctor(workspace) {
|
|
106222
106429
|
const formatCompatible = workspace.config.formatVersion === CURRENT_FORMAT_VERSION;
|
|
106223
106430
|
const compiler = inspectCompilerContract();
|
|
@@ -106397,7 +106604,7 @@ function inspectTrackedBinary(root, record3, errors) {
|
|
|
106397
106604
|
const binary = record3.projectBinary;
|
|
106398
106605
|
if (!binary) return;
|
|
106399
106606
|
const path = binary.path.replaceAll("\\", "/");
|
|
106400
|
-
if (
|
|
106607
|
+
if (isAbsolute3(path) || path.split("/").includes("..")) {
|
|
106401
106608
|
errors.push(
|
|
106402
106609
|
`Project file ${record3.recordId} has unsafe tracked path ${JSON.stringify(binary.path)}.`
|
|
106403
106610
|
);
|
|
@@ -109474,7 +109681,7 @@ __export(resolve_exports, {
|
|
|
109474
109681
|
runResolve: () => runResolve,
|
|
109475
109682
|
workspaceFilePath: () => workspaceFilePath
|
|
109476
109683
|
});
|
|
109477
|
-
import { readFileSync as readFileSync19, rmSync as
|
|
109684
|
+
import { readFileSync as readFileSync19, rmSync as rmSync8, writeFileSync as writeFileSync14 } from "node:fs";
|
|
109478
109685
|
import { join as join21 } from "node:path";
|
|
109479
109686
|
function runResolve(workspace, side) {
|
|
109480
109687
|
let resolvedFiles = 0;
|
|
@@ -109500,12 +109707,12 @@ function runResolve(workspace, side) {
|
|
|
109500
109707
|
);
|
|
109501
109708
|
binary.sha256 = conflict2.remoteSha256;
|
|
109502
109709
|
} else {
|
|
109503
|
-
|
|
109710
|
+
rmSync8(destination, { force: true });
|
|
109504
109711
|
binary.sha256 = null;
|
|
109505
109712
|
}
|
|
109506
109713
|
}
|
|
109507
109714
|
if (conflict2.artifactPath !== void 0) {
|
|
109508
|
-
|
|
109715
|
+
rmSync8(join21(workspace.root, conflict2.artifactPath), { force: true });
|
|
109509
109716
|
}
|
|
109510
109717
|
delete binary.conflict;
|
|
109511
109718
|
resolvedBinaries += 1;
|
|
@@ -109604,6 +109811,7 @@ ${h("Start")}
|
|
|
109604
109811
|
login ${d("[--api <url>] [--profile editor|release] [--save-project <id>]")}
|
|
109605
109812
|
init ${d("[--project <id>] [--version <id>] [--dir <path>] (interactive pickers)")}
|
|
109606
109813
|
whoami ${d("[--api <url>]")}
|
|
109814
|
+
logout ${d("[--api <url>] delete the stored credential for one API origin")}
|
|
109607
109815
|
help ${d("show this command overview")}
|
|
109608
109816
|
--version ${d("print the installed CLI version")}
|
|
109609
109817
|
|
|
@@ -109762,7 +109970,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
|
|
|
109762
109970
|
async function main() {
|
|
109763
109971
|
const args = parseArgs(process.argv.slice(2));
|
|
109764
109972
|
if (args.command === "--version") {
|
|
109765
|
-
console.log("0.
|
|
109973
|
+
console.log("0.27.1");
|
|
109766
109974
|
return;
|
|
109767
109975
|
}
|
|
109768
109976
|
if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {
|
|
@@ -109787,6 +109995,9 @@ async function main() {
|
|
|
109787
109995
|
case "whoami":
|
|
109788
109996
|
await runWhoami(apiBaseUrl);
|
|
109789
109997
|
return;
|
|
109998
|
+
case "logout":
|
|
109999
|
+
await runLogout(apiBaseUrl);
|
|
110000
|
+
return;
|
|
109790
110001
|
case "init":
|
|
109791
110002
|
{
|
|
109792
110003
|
const { runInit: runInit2 } = await Promise.resolve().then(() => (init_init(), init_exports));
|
package/package.json
CHANGED
|
@@ -83,7 +83,7 @@ wrappers.
|
|
|
83
83
|
The marker near the top of `SKILL.md` must exactly match the package version:
|
|
84
84
|
|
|
85
85
|
```html
|
|
86
|
-
<!-- reviewed-through-cli: 0.
|
|
86
|
+
<!-- reviewed-through-cli: 0.27.1 -->
|
|
87
87
|
```
|
|
88
88
|
|
|
89
89
|
The quoted version above is checked too, so this instruction cannot go stale
|
|
@@ -145,5 +145,16 @@ and a protected file only as fallback. Use `NEO_COMPOSE_TOKEN` or
|
|
|
145
145
|
`--token-stdin` in CI. The editor profile cannot publish releases; server
|
|
146
146
|
scopes remain the security boundary.
|
|
147
147
|
|
|
148
|
+
`neo logout [--api <url>]` deletes the stored credential for exactly one API
|
|
149
|
+
origin (keychain entry and credentials-file row) and revokes the server
|
|
150
|
+
session best-effort. It never clears other origins or the whole store.
|
|
151
|
+
|
|
152
|
+
Isolated environments (P53 agent rigs) set `NEO_COMPOSE_CONFIG_HOME` (an
|
|
153
|
+
absolute directory replacing `$XDG_CONFIG_HOME/neo-compose` for Neo state
|
|
154
|
+
only) and `NEO_COMPOSE_CREDENTIAL_NAMESPACE` (scopes the OS-keychain account)
|
|
155
|
+
so concurrent environments sharing one OS user cannot read, overwrite, or
|
|
156
|
+
delete each other's tokens. Login, logout, and authenticated commands all
|
|
157
|
+
honor both variables.
|
|
158
|
+
|
|
148
159
|
Pass explicit project/version IDs and flags in automation. Prefer `--json` for
|
|
149
160
|
machine-readable output and do not depend on interactive pickers or confirms.
|