veryfront 0.1.976 → 0.1.978
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/esm/cli/commands/push/command.d.ts +15 -0
- package/esm/cli/commands/push/command.d.ts.map +1 -1
- package/esm/cli/commands/push/command.js +73 -26
- package/esm/deno.js +1 -1
- package/esm/src/agent/runtime/provider-tool-compat.d.ts.map +1 -1
- package/esm/src/agent/runtime/provider-tool-compat.js +40 -5
- package/esm/src/utils/version-constant.d.ts +1 -1
- package/esm/src/utils/version-constant.js +1 -1
- package/package.json +1 -1
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import type { InferSchema } from "../../../src/extensions/schema/index.js";
|
|
10
10
|
import { type ApiClient } from "../../shared/config.js";
|
|
11
|
+
import { type PullSource } from "../pull/index.js";
|
|
11
12
|
/**
|
|
12
13
|
* Schema factory for push command arguments
|
|
13
14
|
*/
|
|
@@ -72,8 +73,21 @@ export interface BranchResponse {
|
|
|
72
73
|
name: string;
|
|
73
74
|
projectId: string;
|
|
74
75
|
}
|
|
76
|
+
interface BranchListItem {
|
|
77
|
+
id: string;
|
|
78
|
+
name: string;
|
|
79
|
+
}
|
|
80
|
+
interface RemoteFile {
|
|
81
|
+
path: string;
|
|
82
|
+
}
|
|
75
83
|
export declare function generateBranchName(): string;
|
|
76
84
|
export declare function createBranch(client: ApiClient, projectSlug: string, branchName: string): Promise<BranchResponse>;
|
|
85
|
+
export declare function ensureBranch(client: ApiClient, projectSlug: string, branchName: string): Promise<BranchListItem>;
|
|
86
|
+
export declare function resolvePushRemoteFiles(client: ApiClient, projectSlug: string, branchName: string, mainFiles: RemoteFile[]): Promise<{
|
|
87
|
+
branchId: string | null;
|
|
88
|
+
remoteFiles: RemoteFile[];
|
|
89
|
+
source: PullSource;
|
|
90
|
+
}>;
|
|
77
91
|
export declare function uploadFiles(client: ApiClient, projectSlug: string, branchId: string | null, ops: UploadOp[], dryRun: boolean): Promise<{
|
|
78
92
|
uploaded: number;
|
|
79
93
|
failed: number;
|
|
@@ -83,4 +97,5 @@ export declare function deleteFiles(client: ApiClient, projectSlug: string, bran
|
|
|
83
97
|
failed: number;
|
|
84
98
|
}>;
|
|
85
99
|
export declare function pushCommand(options?: PushOptions): Promise<void>;
|
|
100
|
+
export {};
|
|
86
101
|
//# sourceMappingURL=command.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/push/command.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAC;AAK3E,OAAO,EACL,KAAK,SAAS,EAKf,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/push/command.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAC;AAK3E,OAAO,EACL,KAAK,SAAS,EAKf,MAAM,wBAAwB,CAAC;AAMhC,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAGjE;;GAEG;AACH,eAAO,MAAM,iBAAiB;;;;;;;GAS7B,CAAC;AAEF,eAAO,MAAM,cAAc;;;;;;;GAAgC,CAAC;AAE5D,MAAM,MAAM,QAAQ,GAAG,WAAW,CAAC,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC,CAAC;AAEzE;;GAEG;AACH,eAAO,MAAM,aAAa;;;;;;;GAOxB,CAAC;AAEH;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,iDAAiD;IACjD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sCAAsC;IACtC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,8DAA8D;IAC9D,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,oDAAoD;IACpD,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,cAAc;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd;AASD,UAAU,UAAU;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AAkCD,wBAAgB,kBAAkB,IAAI,MAAM,CAG3C;AAED,wBAAgB,YAAY,CAC1B,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,cAAc,CAAC,CAEzB;AAoCD,wBAAsB,YAAY,CAChC,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,cAAc,CAAC,CAWzB;AAED,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,UAAU,EAAE,GACtB,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,WAAW,EAAE,UAAU,EAAE,CAAC;IAAC,MAAM,EAAE,UAAU,CAAA;CAAE,CAAC,CAUrF;AAQD,wBAAsB,WAAW,CAC/B,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,GAAG,EAAE,QAAQ,EAAE,EACf,MAAM,EAAE,OAAO,GACd,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAqB/C;AAED,wBAAsB,WAAW,CAC/B,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,KAAK,EAAE,MAAM,EAAE,EACf,MAAM,EAAE,OAAO,GACd,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAqB9C;AA+BD,wBAAgB,WAAW,CAAC,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CA8KpE"}
|
|
@@ -13,7 +13,7 @@ import { cwd } from "../../../src/platform/index.js";
|
|
|
13
13
|
import { createFileSystem } from "../../../src/platform/index.js";
|
|
14
14
|
import { createApiClient, resolveConfigWithAuth, writeProjectSlug, } from "../../shared/config.js";
|
|
15
15
|
import { reserveProjectSlug } from "../../shared/reserve-slug.js";
|
|
16
|
-
import { confirmPrompt,
|
|
16
|
+
import { confirmPrompt, logInfo, logSuccess, logWarning } from "../../utils/index.js";
|
|
17
17
|
import { createNoopSpinner, createSpinner } from "../../ui/index.js";
|
|
18
18
|
import { withSpan } from "../../../src/observability/tracing/otlp-setup.js";
|
|
19
19
|
import { createIgnoreChecker, loadIgnorePatterns } from "../../sync/ignore.js";
|
|
@@ -72,6 +72,52 @@ export function generateBranchName() {
|
|
|
72
72
|
export function createBranch(client, projectSlug, branchName) {
|
|
73
73
|
return client.post(`/projects/${projectSlug}/branches`, { name: branchName });
|
|
74
74
|
}
|
|
75
|
+
function getErrorStatus(error) {
|
|
76
|
+
if (typeof error !== "object" || error === null)
|
|
77
|
+
return undefined;
|
|
78
|
+
const status = error.status;
|
|
79
|
+
return typeof status === "number" ? status : undefined;
|
|
80
|
+
}
|
|
81
|
+
async function getBranchByName(client, projectSlug, branchName) {
|
|
82
|
+
let cursor;
|
|
83
|
+
do {
|
|
84
|
+
const params = {
|
|
85
|
+
search: branchName,
|
|
86
|
+
limit: "100",
|
|
87
|
+
...(cursor ? { cursor } : {}),
|
|
88
|
+
};
|
|
89
|
+
const response = await client.get(`/projects/${projectSlug}/branches`, params);
|
|
90
|
+
const branch = response.data.find((candidate) => candidate.name === branchName);
|
|
91
|
+
if (branch)
|
|
92
|
+
return branch;
|
|
93
|
+
cursor = response.page_info?.next;
|
|
94
|
+
} while (cursor);
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
export async function ensureBranch(client, projectSlug, branchName) {
|
|
98
|
+
try {
|
|
99
|
+
return await createBranch(client, projectSlug, branchName);
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
if (getErrorStatus(error) !== 409)
|
|
103
|
+
throw error;
|
|
104
|
+
const existingBranch = await getBranchByName(client, projectSlug, branchName);
|
|
105
|
+
if (existingBranch)
|
|
106
|
+
return existingBranch;
|
|
107
|
+
throw error;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
export async function resolvePushRemoteFiles(client, projectSlug, branchName, mainFiles) {
|
|
111
|
+
const mainSource = { type: "main" };
|
|
112
|
+
if (branchName === "main")
|
|
113
|
+
return { branchId: null, remoteFiles: mainFiles, source: mainSource };
|
|
114
|
+
const existingBranch = await getBranchByName(client, projectSlug, branchName);
|
|
115
|
+
if (!existingBranch)
|
|
116
|
+
return { branchId: null, remoteFiles: mainFiles, source: mainSource };
|
|
117
|
+
const branchSource = { type: "branch", name: branchName };
|
|
118
|
+
const remoteFiles = await listAllFiles(client, projectSlug, branchSource);
|
|
119
|
+
return { branchId: existingBranch.id, remoteFiles, source: branchSource };
|
|
120
|
+
}
|
|
75
121
|
function buildFileUrl(projectSlug, path, branchId) {
|
|
76
122
|
const encodedPath = encodeURIComponent(path);
|
|
77
123
|
const base = `/projects/${projectSlug}/files/${encodedPath}`;
|
|
@@ -157,15 +203,16 @@ export function pushCommand(options = {}) {
|
|
|
157
203
|
const localPaths = new Set(ops.map((op) => op.path));
|
|
158
204
|
spinner.update("Fetching remote files...");
|
|
159
205
|
const client = createApiClient(config);
|
|
206
|
+
const branchName = branch || generateBranchName();
|
|
207
|
+
const isMainBranch = branchName === "main";
|
|
160
208
|
// First-push: If project doesn't exist on server yet, create it
|
|
161
|
-
let
|
|
209
|
+
let mainFiles = [];
|
|
162
210
|
try {
|
|
163
|
-
|
|
211
|
+
mainFiles = await listAllFiles(client, config.projectSlug, { type: "main" });
|
|
164
212
|
}
|
|
165
213
|
catch (error) {
|
|
166
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
167
214
|
// Project doesn't exist yet - create it on first push
|
|
168
|
-
if (
|
|
215
|
+
if (getErrorStatus(error) === 404) {
|
|
169
216
|
spinner.update("Creating project...");
|
|
170
217
|
const reserveResult = await reserveProjectSlug(config.projectSlug, config.apiToken);
|
|
171
218
|
if (reserveResult.slug !== config.projectSlug) {
|
|
@@ -175,18 +222,19 @@ export function pushCommand(options = {}) {
|
|
|
175
222
|
config = { ...config, projectSlug: reserveResult.slug };
|
|
176
223
|
// Now try to get files again (should be empty for new project)
|
|
177
224
|
try {
|
|
178
|
-
|
|
225
|
+
mainFiles = await listAllFiles(client, config.projectSlug, { type: "main" });
|
|
179
226
|
}
|
|
180
227
|
catch {
|
|
181
228
|
// Project just created, no files yet
|
|
182
|
-
|
|
229
|
+
mainFiles = [];
|
|
183
230
|
}
|
|
184
231
|
}
|
|
185
232
|
else {
|
|
186
233
|
throw error;
|
|
187
234
|
}
|
|
188
235
|
}
|
|
189
|
-
const
|
|
236
|
+
const target = await resolvePushRemoteFiles(client, config.projectSlug, branchName, mainFiles);
|
|
237
|
+
const toDelete = target.remoteFiles.map((f) => f.path).filter((p) => !localPaths.has(p));
|
|
190
238
|
if (ops.length === 0 && toDelete.length === 0) {
|
|
191
239
|
spinner.stop();
|
|
192
240
|
if (!quiet)
|
|
@@ -194,8 +242,6 @@ export function pushCommand(options = {}) {
|
|
|
194
242
|
return;
|
|
195
243
|
}
|
|
196
244
|
spinner.stop();
|
|
197
|
-
const branchName = branch || generateBranchName();
|
|
198
|
-
const isMainBranch = branchName === "main";
|
|
199
245
|
if (!quiet) {
|
|
200
246
|
const parts = buildSummaryParts(ops, toDelete);
|
|
201
247
|
cliLogger.info(`\nFound ${formatParts(parts)} for ${isMainBranch ? "main" : `branch "${branchName}"`}.`);
|
|
@@ -204,7 +250,9 @@ export function pushCommand(options = {}) {
|
|
|
204
250
|
const parts = buildConfirmParts(ops, toDelete);
|
|
205
251
|
const confirmMessage = isMainBranch
|
|
206
252
|
? `Push to main (${parts.join(", ")} files)?`
|
|
207
|
-
:
|
|
253
|
+
: target.branchId
|
|
254
|
+
? `Push to branch "${branchName}" and ${parts.join(", ")} files?`
|
|
255
|
+
: `Create branch "${branchName}" and ${parts.join(", ")} files?`;
|
|
208
256
|
const confirmed = await confirmPrompt(confirmMessage, true);
|
|
209
257
|
if (!confirmed) {
|
|
210
258
|
cliLogger.info("Push cancelled.");
|
|
@@ -212,10 +260,11 @@ export function pushCommand(options = {}) {
|
|
|
212
260
|
}
|
|
213
261
|
}
|
|
214
262
|
if (dryRun) {
|
|
215
|
-
if (ops.length > 0)
|
|
216
|
-
await uploadFiles(client, config.projectSlug,
|
|
263
|
+
if (ops.length > 0) {
|
|
264
|
+
await uploadFiles(client, config.projectSlug, target.branchId, ops, true);
|
|
265
|
+
}
|
|
217
266
|
if (toDelete.length > 0) {
|
|
218
|
-
await deleteFiles(client, config.projectSlug,
|
|
267
|
+
await deleteFiles(client, config.projectSlug, target.branchId, toDelete, true);
|
|
219
268
|
}
|
|
220
269
|
if (!quiet) {
|
|
221
270
|
const parts = buildConfirmParts(ops, toDelete);
|
|
@@ -223,24 +272,22 @@ export function pushCommand(options = {}) {
|
|
|
223
272
|
}
|
|
224
273
|
return;
|
|
225
274
|
}
|
|
226
|
-
let branchId =
|
|
227
|
-
const uploadMsg = isMainBranch
|
|
275
|
+
let branchId = target.branchId;
|
|
276
|
+
const uploadMsg = isMainBranch
|
|
277
|
+
? "Pushing to main..."
|
|
278
|
+
: branchId
|
|
279
|
+
? `Pushing to branch "${branchName}"...`
|
|
280
|
+
: `Creating branch "${branchName}"...`;
|
|
228
281
|
spinner = quiet ? createNoopSpinner() : createSpinner(uploadMsg);
|
|
229
|
-
if (!isMainBranch) {
|
|
282
|
+
if (!isMainBranch && !branchId) {
|
|
230
283
|
try {
|
|
231
|
-
const
|
|
232
|
-
branchId =
|
|
284
|
+
const preparedBranch = await ensureBranch(client, config.projectSlug, branchName);
|
|
285
|
+
branchId = preparedBranch.id;
|
|
233
286
|
}
|
|
234
287
|
catch (error) {
|
|
235
288
|
spinner.stop();
|
|
236
289
|
const message = error instanceof Error ? error.message : String(error);
|
|
237
|
-
|
|
238
|
-
logError(`Branch "${branchName}" already exists. Use --branch to specify a different name.`);
|
|
239
|
-
}
|
|
240
|
-
else {
|
|
241
|
-
logError(`Failed to create branch: ${message}`);
|
|
242
|
-
}
|
|
243
|
-
return;
|
|
290
|
+
throw new Error(`Failed to prepare branch "${branchName}": ${message}`);
|
|
244
291
|
}
|
|
245
292
|
}
|
|
246
293
|
let uploadResult = { uploaded: 0, failed: 0 };
|
package/esm/deno.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider-tool-compat.d.ts","sourceRoot":"","sources":["../../../../src/src/agent/runtime/provider-tool-compat.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAE7D,6DAA6D;AAC7D,MAAM,MAAM,0BAA0B,GAClC,WAAW,GACX,QAAQ,GACR,UAAU,GACV,QAAQ,GACR,SAAS,CAAC;AAEd,qDAAqD;AACrD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,0BAA0B,CAAC;IACrC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,OAAO,CAAC;CACzB;AAED,gDAAgD;AAChD,MAAM,WAAW,yBAAyB;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACvC;AA2BD,oCAAoC;AACpC,wBAAgB,sBAAsB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,mBAAmB,CAuB1E;AAeD,oDAAoD;AACpD,wBAAgB,iCAAiC,CAC/C,SAAS,EAAE,SAAS,MAAM,EAAE,EAC5B,OAAO,GAAE,yBAA8B,GACtC,MAAM,EAAE,CAsBV;AAED,+CAA+C;AAC/C,wBAAgB,6BAA6B,CAC3C,KAAK,EAAE,SAAS,cAAc,EAAE,EAChC,OAAO,GAAE,yBAA8B,GACtC,cAAc,EAAE,CAclB;
|
|
1
|
+
{"version":3,"file":"provider-tool-compat.d.ts","sourceRoot":"","sources":["../../../../src/src/agent/runtime/provider-tool-compat.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAE7D,6DAA6D;AAC7D,MAAM,MAAM,0BAA0B,GAClC,WAAW,GACX,QAAQ,GACR,UAAU,GACV,QAAQ,GACR,SAAS,CAAC;AAEd,qDAAqD;AACrD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,0BAA0B,CAAC;IACrC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,OAAO,CAAC;CACzB;AAED,gDAAgD;AAChD,MAAM,WAAW,yBAAyB;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACvC;AA2BD,oCAAoC;AACpC,wBAAgB,sBAAsB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,mBAAmB,CAuB1E;AAeD,oDAAoD;AACpD,wBAAgB,iCAAiC,CAC/C,SAAS,EAAE,SAAS,MAAM,EAAE,EAC5B,OAAO,GAAE,yBAA8B,GACtC,MAAM,EAAE,CAsBV;AAED,+CAA+C;AAC/C,wBAAgB,6BAA6B,CAC3C,KAAK,EAAE,SAAS,cAAc,EAAE,EAChC,OAAO,GAAE,yBAA8B,GACtC,cAAc,EAAE,CAclB;AA6PD;;;;GAIG;AACH,wBAAgB,gCAAgC,CAAC,MAAM,EAAE,UAAU,GAAG,UAAU,CAa/E;AAED,6CAA6C;AAC7C,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,UAAU,EAClB,OAAO,GAAE,IAAI,CAAC,yBAAyB,EAAE,OAAO,CAAM,GACrD,UAAU,CAeZ"}
|
|
@@ -228,13 +228,48 @@ function sanitizeGoogleSchemaValue(value) {
|
|
|
228
228
|
}
|
|
229
229
|
return sanitized;
|
|
230
230
|
}
|
|
231
|
-
function
|
|
231
|
+
function decodeJsonPointerSegment(segment) {
|
|
232
|
+
return segment.replaceAll("~1", "/").replaceAll("~0", "~");
|
|
233
|
+
}
|
|
234
|
+
function resolveLocalJsonPointer(root, ref) {
|
|
235
|
+
if (!ref.startsWith("#/")) {
|
|
236
|
+
return undefined;
|
|
237
|
+
}
|
|
238
|
+
let current = root;
|
|
239
|
+
for (const rawSegment of ref.slice(2).split("/")) {
|
|
240
|
+
if (!isPlainRecord(current) && !Array.isArray(current)) {
|
|
241
|
+
return undefined;
|
|
242
|
+
}
|
|
243
|
+
const segment = decodeJsonPointerSegment(rawSegment);
|
|
244
|
+
current = Reflect.get(current, segment);
|
|
245
|
+
}
|
|
246
|
+
return current;
|
|
247
|
+
}
|
|
248
|
+
function sanitizeMoonshotSchemaValue(value, root = value, seenRefs = new Set()) {
|
|
232
249
|
if (Array.isArray(value)) {
|
|
233
|
-
return value.map((item) => sanitizeMoonshotSchemaValue(item));
|
|
250
|
+
return value.map((item) => sanitizeMoonshotSchemaValue(item, root, seenRefs));
|
|
234
251
|
}
|
|
235
252
|
if (!isPlainRecord(value)) {
|
|
236
253
|
return value;
|
|
237
254
|
}
|
|
255
|
+
if (typeof value.$ref === "string" &&
|
|
256
|
+
!value.$ref.startsWith("#/$defs/") &&
|
|
257
|
+
!value.$ref.startsWith("#/definitions/") &&
|
|
258
|
+
!seenRefs.has(value.$ref)) {
|
|
259
|
+
const resolved = resolveLocalJsonPointer(root, value.$ref);
|
|
260
|
+
if (resolved !== undefined && resolved !== value) {
|
|
261
|
+
const nextSeenRefs = new Set(seenRefs);
|
|
262
|
+
nextSeenRefs.add(value.$ref);
|
|
263
|
+
const sanitizedResolved = sanitizeMoonshotSchemaValue(resolved, root, nextSeenRefs);
|
|
264
|
+
const { $ref: _ref, ...siblings } = value;
|
|
265
|
+
const sanitizedSiblings = Object.keys(siblings).length > 0
|
|
266
|
+
? sanitizeMoonshotSchemaValue(siblings, root, nextSeenRefs)
|
|
267
|
+
: undefined;
|
|
268
|
+
return isPlainRecord(sanitizedResolved) && isPlainRecord(sanitizedSiblings)
|
|
269
|
+
? { ...sanitizedResolved, ...sanitizedSiblings }
|
|
270
|
+
: sanitizedResolved;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
238
273
|
const sanitized = {};
|
|
239
274
|
for (const [key, child] of Object.entries(value)) {
|
|
240
275
|
if (key === "$ref" && typeof child === "string") {
|
|
@@ -242,17 +277,17 @@ function sanitizeMoonshotSchemaValue(value) {
|
|
|
242
277
|
continue;
|
|
243
278
|
}
|
|
244
279
|
if (key === "definitions") {
|
|
245
|
-
sanitized.$defs = sanitizeMoonshotSchemaValue(child);
|
|
280
|
+
sanitized.$defs = sanitizeMoonshotSchemaValue(child, root, seenRefs);
|
|
246
281
|
continue;
|
|
247
282
|
}
|
|
248
283
|
if (key === "properties" && isPlainRecord(child)) {
|
|
249
284
|
sanitized.properties = Object.fromEntries(Object.entries(child).map(([propertyName, propertySchema]) => [
|
|
250
285
|
propertyName,
|
|
251
|
-
sanitizeMoonshotSchemaValue(propertySchema),
|
|
286
|
+
sanitizeMoonshotSchemaValue(propertySchema, root, seenRefs),
|
|
252
287
|
]));
|
|
253
288
|
continue;
|
|
254
289
|
}
|
|
255
|
-
sanitized[key] = sanitizeMoonshotSchemaValue(child);
|
|
290
|
+
sanitized[key] = sanitizeMoonshotSchemaValue(child, root, seenRefs);
|
|
256
291
|
}
|
|
257
292
|
return sanitized;
|
|
258
293
|
}
|