siteplane 0.1.42 → 0.1.43
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/README.md +20 -1
- package/dist/bin/siteplane.js +1925 -433
- package/dist/index.js +1198 -377
- package/dist/next.js +1382 -396
- package/package.json +4 -1
package/dist/next.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
// src/next.ts
|
|
2
|
-
import { execFile as
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
2
|
+
import { execFile as execFile4 } from "child_process";
|
|
3
|
+
import { createHash as createHash5 } from "crypto";
|
|
4
|
+
import { readFile as readFile13 } from "fs/promises";
|
|
5
|
+
import { dirname as dirname9, join as join12, resolve as resolve4 } from "path";
|
|
6
|
+
import { promisify as promisify4 } from "util";
|
|
6
7
|
|
|
7
8
|
// ../cli/dist/analytics/manifest.js
|
|
8
9
|
import { mkdir, readFile, writeFile } from "fs/promises";
|
|
@@ -822,7 +823,7 @@ var bookingManifestSchema = z8.object({
|
|
|
822
823
|
var BOOKING_CREATE_PAYLOAD_LIMIT_BYTES = 16 * 1024;
|
|
823
824
|
|
|
824
825
|
// ../shared/dist/bridge-protocol.js
|
|
825
|
-
import { z as
|
|
826
|
+
import { z as z16 } from "zod";
|
|
826
827
|
|
|
827
828
|
// ../shared/dist/field-id.js
|
|
828
829
|
import { z as z9 } from "zod";
|
|
@@ -869,21 +870,70 @@ var imageValueSchema = z11.object({
|
|
|
869
870
|
]).optional()
|
|
870
871
|
});
|
|
871
872
|
|
|
873
|
+
// ../shared/dist/setup-deployment.js
|
|
874
|
+
import { z as z12 } from "zod";
|
|
875
|
+
var version = z12.string().regex(/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/u);
|
|
876
|
+
var hash = z12.string().regex(/^sha256:[0-9a-f]{64}$/u);
|
|
877
|
+
var setupDeploymentRecordSchema = z12.object({
|
|
878
|
+
version: z12.literal(1),
|
|
879
|
+
operationId: z12.string().uuid(),
|
|
880
|
+
provider: z12.literal("vercel"),
|
|
881
|
+
projectId: z12.string().regex(/^prj_[A-Za-z0-9]+$/u),
|
|
882
|
+
teamId: z12.string().regex(/^(?:team|user)_[A-Za-z0-9]+$/u),
|
|
883
|
+
origin: z12.string().url().refine((value) => {
|
|
884
|
+
const url = new URL(value);
|
|
885
|
+
return url.protocol === "https:" && url.origin === value && !url.username && !url.password;
|
|
886
|
+
}),
|
|
887
|
+
deploymentId: z12.string().regex(/^dpl_[A-Za-z0-9]+$/u).nullable(),
|
|
888
|
+
revision: z12.string().regex(/^[0-9a-f]{40}$/u),
|
|
889
|
+
fieldContractHash: hash,
|
|
890
|
+
packages: z12.object({ siteplane: version, runtimeNext: version }).strict(),
|
|
891
|
+
configurationFingerprint: hash,
|
|
892
|
+
adminSecretGeneration: z12.string().uuid(),
|
|
893
|
+
revalidationGeneration: z12.number().int().positive(),
|
|
894
|
+
startedAt: z12.string().datetime(),
|
|
895
|
+
environmentWrittenAt: z12.string().datetime().nullable(),
|
|
896
|
+
deployRequestedAt: z12.string().datetime().nullable(),
|
|
897
|
+
deadline: z12.string().datetime(),
|
|
898
|
+
phase: z12.enum([
|
|
899
|
+
"planned",
|
|
900
|
+
"environment_written",
|
|
901
|
+
"deploy_requested",
|
|
902
|
+
"deployed",
|
|
903
|
+
"verified",
|
|
904
|
+
"failed"
|
|
905
|
+
]),
|
|
906
|
+
build: z12.object({
|
|
907
|
+
node: version,
|
|
908
|
+
packageManager: z12.enum(["npm", "pnpm"]),
|
|
909
|
+
packageManagerVersion: version,
|
|
910
|
+
lockfileHash: hash
|
|
911
|
+
}).strict().nullable()
|
|
912
|
+
}).strict();
|
|
913
|
+
var setupDeploymentInputSchema = z12.discriminatedUnion("action", [
|
|
914
|
+
z12.object({ action: z12.literal("read") }).strict(),
|
|
915
|
+
z12.object({
|
|
916
|
+
action: z12.literal("record"),
|
|
917
|
+
expectedOperationId: z12.string().uuid().nullable(),
|
|
918
|
+
record: setupDeploymentRecordSchema
|
|
919
|
+
}).strict()
|
|
920
|
+
]);
|
|
921
|
+
|
|
872
922
|
// ../shared/dist/site-setup.js
|
|
873
|
-
import { z as
|
|
923
|
+
import { z as z15 } from "zod";
|
|
874
924
|
|
|
875
925
|
// ../shared/dist/site-field-contract.js
|
|
876
|
-
import { z as
|
|
926
|
+
import { z as z14 } from "zod";
|
|
877
927
|
|
|
878
928
|
// ../shared/dist/fallback-hash.js
|
|
879
|
-
import { z as
|
|
929
|
+
import { z as z13 } from "zod";
|
|
880
930
|
var SAFE_REPRESENTATION_REASONS = [
|
|
881
931
|
"asset_import_rewritten",
|
|
882
932
|
"relative_url_normalized",
|
|
883
933
|
"line_endings_normalized",
|
|
884
934
|
"image_value_serialized"
|
|
885
935
|
];
|
|
886
|
-
var safeRepresentationReasonSchema =
|
|
936
|
+
var safeRepresentationReasonSchema = z13.enum(SAFE_REPRESENTATION_REASONS);
|
|
887
937
|
function canonicalizeFallbackValue(input) {
|
|
888
938
|
const fieldType = fieldTypeSchema.parse(input.fieldType);
|
|
889
939
|
if (input.safeRepresentationReason !== void 0) {
|
|
@@ -919,10 +969,10 @@ function createCanonicalFallbackHash(input) {
|
|
|
919
969
|
const payload = stableJsonStringify(canonical);
|
|
920
970
|
return `sha256:${sha256Hex(payload)}`;
|
|
921
971
|
}
|
|
922
|
-
var linkFallbackSchema =
|
|
923
|
-
href:
|
|
924
|
-
label:
|
|
925
|
-
target:
|
|
972
|
+
var linkFallbackSchema = z13.object({
|
|
973
|
+
href: z13.string().trim().min(1),
|
|
974
|
+
label: z13.string().trim().min(1).optional(),
|
|
975
|
+
target: z13.enum(["_self", "_blank"]).optional()
|
|
926
976
|
}).passthrough();
|
|
927
977
|
function normalizeLineEndings(value) {
|
|
928
978
|
return value.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
@@ -1100,67 +1150,67 @@ var SHA256_CONSTANTS = [
|
|
|
1100
1150
|
// ../shared/dist/site-field-contract.js
|
|
1101
1151
|
var fieldContractVersion = "1.0.0";
|
|
1102
1152
|
var scannerContractVersion = "1.0.0";
|
|
1103
|
-
var siteFieldStatusSchema =
|
|
1104
|
-
var semanticVersionSchema =
|
|
1105
|
-
var siteFieldRouteKeySchema =
|
|
1106
|
-
var repositoryRelativePosixPathSchema =
|
|
1107
|
-
var sourceMappingSchema =
|
|
1108
|
-
kind:
|
|
1153
|
+
var siteFieldStatusSchema = z14.enum(["hidden", "active"]);
|
|
1154
|
+
var semanticVersionSchema = z14.string().regex(/^\d+\.\d+\.\d+$/u);
|
|
1155
|
+
var siteFieldRouteKeySchema = z14.string().trim().refine((value) => value === "$global" || value.startsWith("/") && !value.includes("?") && !value.includes("#") && (value === "/" || !value.endsWith("/")), "Route keys must be canonical paths or $global.");
|
|
1156
|
+
var repositoryRelativePosixPathSchema = z14.string().trim().min(1).refine((value) => !value.startsWith("/") && !value.includes("\\") && !/^[a-z]:/iu.test(value) && !value.split("/").includes(".."), "Source paths must be repository-relative POSIX paths.");
|
|
1157
|
+
var sourceMappingSchema = z14.object({
|
|
1158
|
+
kind: z14.literal("function"),
|
|
1109
1159
|
filePath: repositoryRelativePosixPathSchema,
|
|
1110
|
-
exportName:
|
|
1111
|
-
sourcePath:
|
|
1160
|
+
exportName: z14.string().trim().min(1).optional(),
|
|
1161
|
+
sourcePath: z14.string().trim().min(1).optional(),
|
|
1112
1162
|
editTarget: fieldIdSchema.optional()
|
|
1113
1163
|
}).strict();
|
|
1114
|
-
var domMappingSchema =
|
|
1115
|
-
attribute:
|
|
1116
|
-
previewStrategy:
|
|
1164
|
+
var domMappingSchema = z14.object({
|
|
1165
|
+
attribute: z14.literal("data-siteplane-field-id"),
|
|
1166
|
+
previewStrategy: z14.enum(["dom", "event"])
|
|
1117
1167
|
}).strict();
|
|
1118
|
-
var fieldBaseSchema =
|
|
1168
|
+
var fieldBaseSchema = z14.object({
|
|
1119
1169
|
fieldId: fieldIdSchema,
|
|
1120
1170
|
routeKey: siteFieldRouteKeySchema,
|
|
1121
1171
|
source: sourceMappingSchema,
|
|
1122
1172
|
dom: domMappingSchema.optional()
|
|
1123
1173
|
}).strict();
|
|
1124
|
-
var linkFallbackSchema2 =
|
|
1125
|
-
href:
|
|
1126
|
-
label:
|
|
1127
|
-
target:
|
|
1174
|
+
var linkFallbackSchema2 = z14.object({
|
|
1175
|
+
href: z14.string().trim().min(1),
|
|
1176
|
+
label: z14.string().trim().min(1).optional(),
|
|
1177
|
+
target: z14.enum(["_self", "_blank"]).optional()
|
|
1128
1178
|
}).strict();
|
|
1129
|
-
var imageFallbackSchema =
|
|
1130
|
-
src:
|
|
1131
|
-
alt:
|
|
1132
|
-
width:
|
|
1133
|
-
height:
|
|
1134
|
-
crop:
|
|
1135
|
-
x:
|
|
1136
|
-
y:
|
|
1137
|
-
zoom:
|
|
1138
|
-
aspectRatio:
|
|
1179
|
+
var imageFallbackSchema = z14.object({
|
|
1180
|
+
src: z14.string().trim().min(1),
|
|
1181
|
+
alt: z14.string().trim().max(300),
|
|
1182
|
+
width: z14.number().int().positive().optional(),
|
|
1183
|
+
height: z14.number().int().positive().optional(),
|
|
1184
|
+
crop: z14.object({
|
|
1185
|
+
x: z14.number().min(0).max(100),
|
|
1186
|
+
y: z14.number().min(0).max(100),
|
|
1187
|
+
zoom: z14.number().min(1).max(4),
|
|
1188
|
+
aspectRatio: z14.number().positive().max(10)
|
|
1139
1189
|
}).strict().optional()
|
|
1140
1190
|
}).strict();
|
|
1141
|
-
var siteFieldContractFieldSchema =
|
|
1191
|
+
var siteFieldContractFieldSchema = z14.discriminatedUnion("fieldType", [
|
|
1142
1192
|
fieldBaseSchema.extend({
|
|
1143
|
-
fieldType:
|
|
1144
|
-
fallback:
|
|
1193
|
+
fieldType: z14.literal("text"),
|
|
1194
|
+
fallback: z14.string()
|
|
1145
1195
|
}),
|
|
1146
1196
|
fieldBaseSchema.extend({
|
|
1147
|
-
fieldType:
|
|
1148
|
-
fallback:
|
|
1197
|
+
fieldType: z14.literal("longText"),
|
|
1198
|
+
fallback: z14.string()
|
|
1149
1199
|
}),
|
|
1150
1200
|
fieldBaseSchema.extend({
|
|
1151
|
-
fieldType:
|
|
1201
|
+
fieldType: z14.literal("link"),
|
|
1152
1202
|
fallback: linkFallbackSchema2
|
|
1153
1203
|
}),
|
|
1154
1204
|
fieldBaseSchema.extend({
|
|
1155
|
-
fieldType:
|
|
1205
|
+
fieldType: z14.literal("image"),
|
|
1156
1206
|
fallback: imageFallbackSchema
|
|
1157
1207
|
})
|
|
1158
1208
|
]);
|
|
1159
|
-
var siteFieldContractV1Schema =
|
|
1160
|
-
version:
|
|
1209
|
+
var siteFieldContractV1Schema = z14.object({
|
|
1210
|
+
version: z14.literal(1),
|
|
1161
1211
|
fieldContractVersion: semanticVersionSchema,
|
|
1162
1212
|
scannerContractVersion: semanticVersionSchema,
|
|
1163
|
-
fields:
|
|
1213
|
+
fields: z14.array(siteFieldContractFieldSchema)
|
|
1164
1214
|
}).strict().superRefine((contract, context) => {
|
|
1165
1215
|
const seen = /* @__PURE__ */ new Set();
|
|
1166
1216
|
for (const [index, field] of contract.fields.entries()) {
|
|
@@ -1220,20 +1270,20 @@ var SITE_SETUP_OWNER_EDITABILITY_NOTE_MAX_LENGTH = 2e3;
|
|
|
1220
1270
|
var SITE_SETUP_OWNER_EDITABILITY_NOTE_MAX_BYTES = 8e3;
|
|
1221
1271
|
var CONTINUE_SITE_SETUP_ITEMS_MAX_BYTES = 32 * 1024;
|
|
1222
1272
|
var CONTINUE_SITE_SETUP_HTTP_BODY_MAX_BYTES = 64 * 1024;
|
|
1223
|
-
var siteSetupRunStatusSchema =
|
|
1224
|
-
var siteSetupRunModeSchema =
|
|
1225
|
-
var siteSetupErrorCodeSchema =
|
|
1226
|
-
var editorFieldSchema =
|
|
1273
|
+
var siteSetupRunStatusSchema = z15.enum(SITE_SETUP_RUN_STATUSES);
|
|
1274
|
+
var siteSetupRunModeSchema = z15.enum(SITE_SETUP_RUN_MODES);
|
|
1275
|
+
var siteSetupErrorCodeSchema = z15.enum(SITE_SETUP_ERROR_CODES);
|
|
1276
|
+
var editorFieldSchema = z15.object({
|
|
1227
1277
|
fieldId: fieldIdSchema,
|
|
1228
|
-
label:
|
|
1229
|
-
subsection:
|
|
1230
|
-
description:
|
|
1231
|
-
required:
|
|
1232
|
-
maxLength:
|
|
1278
|
+
label: z15.string().trim().min(1),
|
|
1279
|
+
subsection: z15.string().trim().min(1).optional(),
|
|
1280
|
+
description: z15.string().trim().min(1).optional(),
|
|
1281
|
+
required: z15.boolean().optional(),
|
|
1282
|
+
maxLength: z15.number().int().positive().optional()
|
|
1233
1283
|
}).strict();
|
|
1234
|
-
var editorSectionSchema =
|
|
1235
|
-
label:
|
|
1236
|
-
fields:
|
|
1284
|
+
var editorSectionSchema = z15.object({
|
|
1285
|
+
label: z15.string().trim().min(1),
|
|
1286
|
+
fields: z15.array(editorFieldSchema).min(1)
|
|
1237
1287
|
}).strict().superRefine((section, context) => {
|
|
1238
1288
|
const closedSubsections = /* @__PURE__ */ new Set();
|
|
1239
1289
|
let currentSubsection;
|
|
@@ -1252,10 +1302,10 @@ var editorSectionSchema = z14.object({
|
|
|
1252
1302
|
}
|
|
1253
1303
|
}
|
|
1254
1304
|
});
|
|
1255
|
-
var editorRouteSchema =
|
|
1305
|
+
var editorRouteSchema = z15.object({
|
|
1256
1306
|
routeKey: siteFieldRouteKeySchema,
|
|
1257
|
-
label:
|
|
1258
|
-
sections:
|
|
1307
|
+
label: z15.string().trim().min(1),
|
|
1308
|
+
sections: z15.array(editorSectionSchema).min(1)
|
|
1259
1309
|
}).strict().superRefine((route, context) => {
|
|
1260
1310
|
const sections = /* @__PURE__ */ new Set();
|
|
1261
1311
|
for (const [index, section] of route.sections.entries()) {
|
|
@@ -1269,9 +1319,9 @@ var editorRouteSchema = z14.object({
|
|
|
1269
1319
|
sections.add(section.label);
|
|
1270
1320
|
}
|
|
1271
1321
|
});
|
|
1272
|
-
var editorDefinitionV1Schema =
|
|
1273
|
-
version:
|
|
1274
|
-
routes:
|
|
1322
|
+
var editorDefinitionV1Schema = z15.object({
|
|
1323
|
+
version: z15.literal(1),
|
|
1324
|
+
routes: z15.array(editorRouteSchema).min(1)
|
|
1275
1325
|
}).strict().superRefine((definition, context) => {
|
|
1276
1326
|
const routes = /* @__PURE__ */ new Set();
|
|
1277
1327
|
const fields = /* @__PURE__ */ new Set();
|
|
@@ -1309,7 +1359,7 @@ var editorDefinitionV1Schema = z14.object({
|
|
|
1309
1359
|
var forbiddenControlOrBidi = /[\u0000-\u001f\u007f-\u009f\u202a-\u202e\u2066-\u2069]/u;
|
|
1310
1360
|
var forbiddenOwnerNoteControlOrBidi = /[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f-\u009f\u202a-\u202e\u2066-\u2069]/u;
|
|
1311
1361
|
var unsafeLocator = /<\/?[a-z][^>]*>|\b(?:javascript|data:text\/html)\s*:|\bon[a-z]+\s*=/iu;
|
|
1312
|
-
var renderedPathSchema =
|
|
1362
|
+
var renderedPathSchema = z15.string().trim().transform((value) => value !== "/" ? value.replace(/\/+$/u, "") : value).superRefine((value, context) => {
|
|
1313
1363
|
if (!value.startsWith("/") || value === "$global" || value.includes("?") || value.includes("#")) {
|
|
1314
1364
|
context.addIssue({
|
|
1315
1365
|
code: "custom",
|
|
@@ -1319,7 +1369,7 @@ var renderedPathSchema = z14.string().trim().transform((value) => value !== "/"
|
|
|
1319
1369
|
addSafeByteIssues(value, CONTINUE_SITE_SETUP_RENDERED_PATH_MAX_BYTES, "renderedPath", context);
|
|
1320
1370
|
});
|
|
1321
1371
|
function normalizedSafeTextSchema(maxBytes, label) {
|
|
1322
|
-
return
|
|
1372
|
+
return z15.string().transform((value) => value.trim().replace(new RegExp("\\p{White_Space}+", "gu"), " ")).pipe(z15.string().min(1)).superRefine((value, context) => {
|
|
1323
1373
|
addSafeByteIssues(value, maxBytes, label, context);
|
|
1324
1374
|
if (label === "locatorHint" && unsafeLocator.test(value)) {
|
|
1325
1375
|
context.addIssue({
|
|
@@ -1336,12 +1386,12 @@ var correctionItemBase = {
|
|
|
1336
1386
|
requestedLabel: normalizedSafeTextSchema(CONTINUE_SITE_SETUP_REQUESTED_LABEL_MAX_BYTES, "requestedLabel").optional(),
|
|
1337
1387
|
requestedSection: normalizedSafeTextSchema(CONTINUE_SITE_SETUP_REQUESTED_SECTION_MAX_BYTES, "requestedSection").optional(),
|
|
1338
1388
|
requestedSubsection: normalizedSafeTextSchema(CONTINUE_SITE_SETUP_REQUESTED_SUBSECTION_MAX_BYTES, "requestedSubsection").optional(),
|
|
1339
|
-
requestedSortOrder:
|
|
1389
|
+
requestedSortOrder: z15.number().int().nonnegative().optional()
|
|
1340
1390
|
};
|
|
1341
|
-
var setupCorrectionItemSchema =
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1391
|
+
var setupCorrectionItemSchema = z15.discriminatedUnion("kind", [
|
|
1392
|
+
z15.object({ kind: z15.literal("text"), ...correctionItemBase }).strict(),
|
|
1393
|
+
z15.object({ kind: z15.literal("link"), ...correctionItemBase }).strict(),
|
|
1394
|
+
z15.object({ kind: z15.literal("image"), ...correctionItemBase }).strict()
|
|
1345
1395
|
]).superRefine((item, context) => {
|
|
1346
1396
|
if (item.requestedSubsection && !item.requestedSection) {
|
|
1347
1397
|
context.addIssue({
|
|
@@ -1351,7 +1401,7 @@ var setupCorrectionItemSchema = z14.discriminatedUnion("kind", [
|
|
|
1351
1401
|
});
|
|
1352
1402
|
}
|
|
1353
1403
|
});
|
|
1354
|
-
var setupCorrectionItemsSchema =
|
|
1404
|
+
var setupCorrectionItemsSchema = z15.array(setupCorrectionItemSchema).max(CONTINUE_SITE_SETUP_MAX_ITEMS).superRefine((items, context) => {
|
|
1355
1405
|
const bytes = utf8Bytes(stableJsonStringify(items));
|
|
1356
1406
|
if (bytes > CONTINUE_SITE_SETUP_ITEMS_MAX_BYTES) {
|
|
1357
1407
|
context.addIssue({
|
|
@@ -1360,7 +1410,7 @@ var setupCorrectionItemsSchema = z14.array(setupCorrectionItemSchema).max(CONTIN
|
|
|
1360
1410
|
});
|
|
1361
1411
|
}
|
|
1362
1412
|
});
|
|
1363
|
-
var siteSetupOwnerEditabilityNoteSchema =
|
|
1413
|
+
var siteSetupOwnerEditabilityNoteSchema = z15.string().max(SITE_SETUP_OWNER_EDITABILITY_NOTE_MAX_LENGTH).superRefine((value, context) => {
|
|
1364
1414
|
if (utf8Bytes(value) > SITE_SETUP_OWNER_EDITABILITY_NOTE_MAX_BYTES) {
|
|
1365
1415
|
context.addIssue({
|
|
1366
1416
|
code: "custom",
|
|
@@ -1385,7 +1435,7 @@ var SITE_SETUP_MODULE_SCOPES = {
|
|
|
1385
1435
|
"analytics:public_key_read"
|
|
1386
1436
|
]
|
|
1387
1437
|
};
|
|
1388
|
-
var siteSetupModulesSchema =
|
|
1438
|
+
var siteSetupModulesSchema = z15.array(z15.enum(["editing", "analytics"])).min(1).max(2).refine((modules) => modules[0] === "editing" && (modules.length === 1 || modules[1] === "analytics"), "Choose Editing with optional Analytics.");
|
|
1389
1439
|
function siteSetupScopes(modules) {
|
|
1390
1440
|
return modules.flatMap((module) => [...SITE_SETUP_MODULE_SCOPES[module]]);
|
|
1391
1441
|
}
|
|
@@ -1393,15 +1443,15 @@ function hasExactSiteSetupScopes(scopes, modules) {
|
|
|
1393
1443
|
const matches = (expected) => scopes.length === expected.length && expected.every((scope) => scopes.includes(scope));
|
|
1394
1444
|
return modules ? matches(siteSetupScopes(modules)) : matches(siteSetupScopes(["editing"])) || matches(siteSetupScopes(["editing", "analytics"]));
|
|
1395
1445
|
}
|
|
1396
|
-
var siteSetupActivityInputSchema =
|
|
1397
|
-
phase:
|
|
1446
|
+
var siteSetupActivityInputSchema = z15.object({
|
|
1447
|
+
phase: z15.enum([
|
|
1398
1448
|
"inspecting",
|
|
1399
1449
|
"integrating",
|
|
1400
1450
|
"deploying",
|
|
1401
1451
|
"verifying",
|
|
1402
1452
|
"repairing"
|
|
1403
1453
|
]),
|
|
1404
|
-
textId:
|
|
1454
|
+
textId: z15.enum([
|
|
1405
1455
|
"inspecting",
|
|
1406
1456
|
"integrating",
|
|
1407
1457
|
"deploying",
|
|
@@ -1410,8 +1460,8 @@ var siteSetupActivityInputSchema = z14.object({
|
|
|
1410
1460
|
])
|
|
1411
1461
|
}).strict().refine((value) => value.phase === value.textId, "Activity text must describe its phase.");
|
|
1412
1462
|
var nextActionFields = {
|
|
1413
|
-
actor:
|
|
1414
|
-
boundary:
|
|
1463
|
+
actor: z15.enum(["agent", "user", "siteplane"]),
|
|
1464
|
+
boundary: z15.enum([
|
|
1415
1465
|
"source",
|
|
1416
1466
|
"environment",
|
|
1417
1467
|
"deployment",
|
|
@@ -1419,33 +1469,33 @@ var nextActionFields = {
|
|
|
1419
1469
|
"authorization",
|
|
1420
1470
|
"review"
|
|
1421
1471
|
]),
|
|
1422
|
-
precondition:
|
|
1423
|
-
instruction:
|
|
1424
|
-
expectedEvidence:
|
|
1472
|
+
precondition: z15.string().min(1).max(1e3),
|
|
1473
|
+
instruction: z15.string().min(1).max(2e3),
|
|
1474
|
+
expectedEvidence: z15.string().min(1).max(1e3)
|
|
1425
1475
|
};
|
|
1426
|
-
var siteSetupNextActionSchema =
|
|
1427
|
-
|
|
1476
|
+
var siteSetupNextActionSchema = z15.discriminatedUnion("kind", [
|
|
1477
|
+
z15.object({
|
|
1428
1478
|
...nextActionFields,
|
|
1429
|
-
kind:
|
|
1430
|
-
command:
|
|
1479
|
+
kind: z15.literal("run_command"),
|
|
1480
|
+
command: z15.string().min(1).max(500)
|
|
1431
1481
|
}).strict(),
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1482
|
+
z15.object({ ...nextActionFields, kind: z15.literal("agent_edit") }).strict(),
|
|
1483
|
+
z15.object({ ...nextActionFields, kind: z15.literal("needs_user_action") }).strict(),
|
|
1484
|
+
z15.object({ ...nextActionFields, kind: z15.literal("wait") }).strict(),
|
|
1485
|
+
z15.object({ ...nextActionFields, kind: z15.literal("done") }).strict()
|
|
1436
1486
|
]);
|
|
1437
|
-
var siteSetupTaskRunSchema =
|
|
1438
|
-
runId:
|
|
1487
|
+
var siteSetupTaskRunSchema = z15.object({
|
|
1488
|
+
runId: z15.string().uuid(),
|
|
1439
1489
|
mode: siteSetupRunModeSchema,
|
|
1440
1490
|
status: siteSetupRunStatusSchema,
|
|
1441
|
-
fieldContractHash:
|
|
1442
|
-
deploymentOrigin:
|
|
1443
|
-
deploymentRevision:
|
|
1444
|
-
publicRuntimeKeyId:
|
|
1445
|
-
reviewVersion:
|
|
1491
|
+
fieldContractHash: z15.string().nullable(),
|
|
1492
|
+
deploymentOrigin: z15.string().url().nullable(),
|
|
1493
|
+
deploymentRevision: z15.string().nullable(),
|
|
1494
|
+
publicRuntimeKeyId: z15.string().uuid().nullable(),
|
|
1495
|
+
reviewVersion: z15.string().nullable()
|
|
1446
1496
|
}).strict();
|
|
1447
|
-
var siteSetupTaskProgressSchema =
|
|
1448
|
-
progressStage:
|
|
1497
|
+
var siteSetupTaskProgressSchema = z15.object({
|
|
1498
|
+
progressStage: z15.enum([
|
|
1449
1499
|
"waiting_for_connection",
|
|
1450
1500
|
"agent_connected",
|
|
1451
1501
|
"project_context_loaded",
|
|
@@ -1455,66 +1505,73 @@ var siteSetupTaskProgressSchema = z14.object({
|
|
|
1455
1505
|
"action_required",
|
|
1456
1506
|
"completed"
|
|
1457
1507
|
]),
|
|
1458
|
-
lastVerifiedAt:
|
|
1459
|
-
lastActivityAt:
|
|
1460
|
-
activitySource:
|
|
1508
|
+
lastVerifiedAt: z15.string().datetime().nullable(),
|
|
1509
|
+
lastActivityAt: z15.string().datetime(),
|
|
1510
|
+
activitySource: z15.enum(["user", "server", "agent"]),
|
|
1461
1511
|
activityPhase: siteSetupActivityInputSchema.shape.phase.nullable(),
|
|
1462
1512
|
activityTextId: siteSetupActivityInputSchema.shape.textId.nullable()
|
|
1463
1513
|
}).strict();
|
|
1464
|
-
var siteSetupTaskSchema =
|
|
1465
|
-
contractVersion:
|
|
1466
|
-
workflow:
|
|
1467
|
-
goal:
|
|
1514
|
+
var siteSetupTaskSchema = z15.object({
|
|
1515
|
+
contractVersion: z15.literal("siteplane.setup-task.v2"),
|
|
1516
|
+
workflow: z15.enum(["initial_setup", "structure_update"]),
|
|
1517
|
+
goal: z15.string().min(1),
|
|
1468
1518
|
modules: siteSetupModulesSchema,
|
|
1469
|
-
authorizationVersion:
|
|
1470
|
-
authorizedScopes:
|
|
1471
|
-
site:
|
|
1472
|
-
siteId:
|
|
1473
|
-
portalPath:
|
|
1474
|
-
adminOrigin:
|
|
1519
|
+
authorizationVersion: z15.number().int().positive(),
|
|
1520
|
+
authorizedScopes: z15.array(z15.string()).min(2),
|
|
1521
|
+
site: z15.object({
|
|
1522
|
+
siteId: z15.string().uuid(),
|
|
1523
|
+
portalPath: z15.string(),
|
|
1524
|
+
adminOrigin: z15.string().url()
|
|
1475
1525
|
}).strict().nullable(),
|
|
1476
1526
|
run: siteSetupTaskRunSchema.nullable(),
|
|
1477
1527
|
progress: siteSetupTaskProgressSchema.nullable(),
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1528
|
+
deployment: setupDeploymentRecordSchema.nullable(),
|
|
1529
|
+
revalidationGeneration: z15.number().int().positive(),
|
|
1530
|
+
assignment: z15.literal("owned"),
|
|
1531
|
+
deadline: z15.string().datetime().nullable(),
|
|
1532
|
+
userInstructions: z15.object({
|
|
1481
1533
|
text: siteSetupOwnerEditabilityNoteSchema,
|
|
1482
|
-
source:
|
|
1483
|
-
trust:
|
|
1534
|
+
source: z15.literal("user"),
|
|
1535
|
+
trust: z15.literal("untrusted")
|
|
1484
1536
|
}).strict(),
|
|
1485
1537
|
corrections: setupCorrectionItemsSchema,
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
source:
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1538
|
+
contentSelectionSummary: z15.object({
|
|
1539
|
+
text: siteSetupOwnerEditabilityNoteSchema,
|
|
1540
|
+
source: z15.literal("agent"),
|
|
1541
|
+
trust: z15.literal("untrusted")
|
|
1542
|
+
}).strict().nullable(),
|
|
1543
|
+
environmentBindings: z15.array(z15.object({
|
|
1544
|
+
name: z15.string().regex(/^[A-Z][A-Z0-9_]+$/u),
|
|
1545
|
+
source: z15.string().min(1),
|
|
1546
|
+
sensitivity: z15.enum(["public", "secret"]),
|
|
1547
|
+
usage: z15.enum(["build", "server", "build_and_server"]),
|
|
1548
|
+
evidence: z15.string().min(1)
|
|
1492
1549
|
}).strict()),
|
|
1493
1550
|
nextAction: siteSetupNextActionSchema,
|
|
1494
|
-
error:
|
|
1495
|
-
code:
|
|
1551
|
+
error: z15.object({
|
|
1552
|
+
code: z15.string().regex(/^[a-z0-9_.]+$/u).max(160),
|
|
1496
1553
|
boundary: nextActionFields.boundary,
|
|
1497
1554
|
responsibleActor: nextActionFields.actor,
|
|
1498
|
-
retryable:
|
|
1499
|
-
retryAfter:
|
|
1500
|
-
requestId:
|
|
1555
|
+
retryable: z15.boolean(),
|
|
1556
|
+
retryAfter: z15.number().int().nonnegative().nullable(),
|
|
1557
|
+
requestId: z15.string().regex(/^[A-Za-z0-9_-]+$/u).max(128)
|
|
1501
1558
|
}).strict().nullable(),
|
|
1502
|
-
packages:
|
|
1503
|
-
siteplane:
|
|
1504
|
-
runtimeNext:
|
|
1559
|
+
packages: z15.object({
|
|
1560
|
+
siteplane: z15.string().regex(/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/u),
|
|
1561
|
+
runtimeNext: z15.string().regex(/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/u)
|
|
1505
1562
|
}).strict(),
|
|
1506
|
-
communication:
|
|
1507
|
-
beforeSourceChanges:
|
|
1508
|
-
updates:
|
|
1509
|
-
blocker:
|
|
1563
|
+
communication: z15.object({
|
|
1564
|
+
beforeSourceChanges: z15.string().min(1),
|
|
1565
|
+
updates: z15.array(z15.string().min(1)).min(1),
|
|
1566
|
+
blocker: z15.string().min(1)
|
|
1510
1567
|
}).strict(),
|
|
1511
|
-
discovery:
|
|
1512
|
-
inspectPublicRoutes:
|
|
1513
|
-
contentKinds:
|
|
1514
|
-
rules:
|
|
1568
|
+
discovery: z15.object({
|
|
1569
|
+
inspectPublicRoutes: z15.boolean(),
|
|
1570
|
+
contentKinds: z15.array(z15.enum(["text", "longText", "link", "image"])).min(1),
|
|
1571
|
+
rules: z15.array(z15.string().min(1)).min(1)
|
|
1515
1572
|
}).strict(),
|
|
1516
|
-
steps:
|
|
1517
|
-
id:
|
|
1573
|
+
steps: z15.array(z15.object({
|
|
1574
|
+
id: z15.enum([
|
|
1518
1575
|
"inspect_repository",
|
|
1519
1576
|
"install_packages",
|
|
1520
1577
|
"instrument_fields",
|
|
@@ -1522,34 +1579,35 @@ var siteSetupTaskSchema = z14.object({
|
|
|
1522
1579
|
"deploy_production",
|
|
1523
1580
|
"verify_deployment"
|
|
1524
1581
|
]),
|
|
1525
|
-
instruction:
|
|
1582
|
+
instruction: z15.string().min(1)
|
|
1526
1583
|
}).strict()).length(6),
|
|
1527
|
-
completion:
|
|
1528
|
-
verifiedStatus:
|
|
1529
|
-
instruction:
|
|
1584
|
+
completion: z15.object({
|
|
1585
|
+
verifiedStatus: z15.literal("ready_for_review"),
|
|
1586
|
+
instruction: z15.string().min(1)
|
|
1530
1587
|
}).strict()
|
|
1531
1588
|
}).strict().refine((task) => hasExactSiteSetupScopes(task.authorizedScopes, task.modules), "Task scopes must exactly match its modules.");
|
|
1532
|
-
var canonicalHashSchema =
|
|
1589
|
+
var canonicalHashSchema = z15.string().regex(/^sha256:[0-9a-f]{64}$/iu);
|
|
1533
1590
|
var deploymentRevisionSchema = normalizedSafeTextSchema(256, "deploymentRevision");
|
|
1534
|
-
var continueSiteSetupInputSchema =
|
|
1535
|
-
siteId:
|
|
1536
|
-
runId:
|
|
1591
|
+
var continueSiteSetupInputSchema = z15.object({
|
|
1592
|
+
siteId: z15.string().uuid(),
|
|
1593
|
+
runId: z15.string().uuid(),
|
|
1537
1594
|
expectedFieldContractHash: canonicalHashSchema,
|
|
1538
1595
|
expectedDeploymentRevision: deploymentRevisionSchema,
|
|
1539
1596
|
correctionItems: setupCorrectionItemsSchema,
|
|
1540
1597
|
ownerEditabilityNote: siteSetupOwnerEditabilityNoteSchema.optional()
|
|
1541
1598
|
}).strict();
|
|
1542
|
-
var saveSiteSetupOwnerNoteInputSchema =
|
|
1543
|
-
siteId:
|
|
1544
|
-
runId:
|
|
1599
|
+
var saveSiteSetupOwnerNoteInputSchema = z15.object({
|
|
1600
|
+
siteId: z15.string().uuid(),
|
|
1601
|
+
runId: z15.string().uuid(),
|
|
1545
1602
|
expectedFieldContractHash: canonicalHashSchema,
|
|
1546
1603
|
expectedDeploymentRevision: deploymentRevisionSchema,
|
|
1547
1604
|
ownerEditabilityNote: siteSetupOwnerEditabilityNoteSchema
|
|
1548
1605
|
}).strict();
|
|
1549
|
-
var siteSetupContextInputSchema =
|
|
1550
|
-
var siteSetupApplyInputSchema =
|
|
1606
|
+
var siteSetupContextInputSchema = z15.object({}).strict();
|
|
1607
|
+
var siteSetupApplyInputSchema = z15.object({
|
|
1551
1608
|
fieldContract: siteFieldContractV1Schema,
|
|
1552
|
-
editorDefinition: editorDefinitionV1Schema
|
|
1609
|
+
editorDefinition: editorDefinitionV1Schema,
|
|
1610
|
+
contentSelectionSummary: siteSetupOwnerEditabilityNoteSchema.refine((text) => text.trim().length > 0, "Describe the selected content, important exclusions and any open gaps.")
|
|
1553
1611
|
}).strict().superRefine((input, context) => {
|
|
1554
1612
|
const contractRoutesByFieldId = new Map(input.fieldContract.fields.map((field) => [
|
|
1555
1613
|
field.fieldId,
|
|
@@ -1613,37 +1671,37 @@ var siteSetupApplyInputSchema = z14.object({
|
|
|
1613
1671
|
}
|
|
1614
1672
|
}
|
|
1615
1673
|
});
|
|
1616
|
-
var siteSetupVerifyInputSchema =
|
|
1617
|
-
deploymentUrl:
|
|
1674
|
+
var siteSetupVerifyInputSchema = z15.object({
|
|
1675
|
+
deploymentUrl: z15.string().url().refine((value) => value.startsWith("https://")),
|
|
1618
1676
|
deploymentRevision: deploymentRevisionSchema,
|
|
1619
|
-
wait:
|
|
1677
|
+
wait: z15.boolean().optional()
|
|
1620
1678
|
}).strict();
|
|
1621
|
-
var siteSetupEvidenceInputSchema =
|
|
1622
|
-
siteId:
|
|
1623
|
-
runId:
|
|
1679
|
+
var siteSetupEvidenceInputSchema = z15.object({
|
|
1680
|
+
siteId: z15.string().uuid(),
|
|
1681
|
+
runId: z15.string().uuid(),
|
|
1624
1682
|
expectedFieldContractHash: canonicalHashSchema,
|
|
1625
|
-
expectedDeploymentOrigin:
|
|
1683
|
+
expectedDeploymentOrigin: z15.string().url().refine((value) => value.startsWith("https://")),
|
|
1626
1684
|
expectedDeploymentRevision: deploymentRevisionSchema,
|
|
1627
|
-
publicRuntimeKeyId:
|
|
1685
|
+
publicRuntimeKeyId: z15.string().uuid(),
|
|
1628
1686
|
bridgeSessionId: normalizedSafeTextSchema(256, "bridgeSessionId"),
|
|
1629
|
-
observations:
|
|
1687
|
+
observations: z15.array(z15.object({
|
|
1630
1688
|
fieldId: fieldIdSchema,
|
|
1631
1689
|
routeKey: siteFieldRouteKeySchema,
|
|
1632
1690
|
renderedPath: renderedPathSchema,
|
|
1633
|
-
targetResolved:
|
|
1634
|
-
previewAck:
|
|
1691
|
+
targetResolved: z15.boolean(),
|
|
1692
|
+
previewAck: z15.boolean()
|
|
1635
1693
|
}).strict().refine((value) => !value.previewAck || value.targetResolved, "Preview ACK requires a resolved target.")).min(1).max(200)
|
|
1636
1694
|
}).strict();
|
|
1637
|
-
var completeSiteSetupInputSchema =
|
|
1638
|
-
siteId:
|
|
1639
|
-
runId:
|
|
1695
|
+
var completeSiteSetupInputSchema = z15.object({
|
|
1696
|
+
siteId: z15.string().uuid(),
|
|
1697
|
+
runId: z15.string().uuid(),
|
|
1640
1698
|
expectedFieldContractHash: canonicalHashSchema,
|
|
1641
1699
|
expectedDeploymentRevision: deploymentRevisionSchema,
|
|
1642
1700
|
expectedReadyFingerprint: canonicalHashSchema
|
|
1643
1701
|
}).strict();
|
|
1644
|
-
var refreshSiteSetupDeploymentInputSchema =
|
|
1645
|
-
siteId:
|
|
1646
|
-
deploymentUrl:
|
|
1702
|
+
var refreshSiteSetupDeploymentInputSchema = z15.object({
|
|
1703
|
+
siteId: z15.string().uuid(),
|
|
1704
|
+
deploymentUrl: z15.string().url().refine((value) => value.startsWith("https://")),
|
|
1647
1705
|
deploymentRevision: deploymentRevisionSchema
|
|
1648
1706
|
}).strict();
|
|
1649
1707
|
function addSafeByteIssues(value, maxBytes, label, context) {
|
|
@@ -1666,34 +1724,34 @@ function utf8Bytes(value) {
|
|
|
1666
1724
|
|
|
1667
1725
|
// ../shared/dist/bridge-protocol.js
|
|
1668
1726
|
var BRIDGE_PROTOCOL_VERSION = 2;
|
|
1669
|
-
var bridgeRectSchema =
|
|
1670
|
-
x:
|
|
1671
|
-
y:
|
|
1672
|
-
width:
|
|
1673
|
-
height:
|
|
1727
|
+
var bridgeRectSchema = z16.object({
|
|
1728
|
+
x: z16.number(),
|
|
1729
|
+
y: z16.number(),
|
|
1730
|
+
width: z16.number().nonnegative(),
|
|
1731
|
+
height: z16.number().nonnegative()
|
|
1674
1732
|
});
|
|
1675
|
-
var previewTextValueSchema =
|
|
1676
|
-
fieldType:
|
|
1677
|
-
value:
|
|
1733
|
+
var previewTextValueSchema = z16.object({
|
|
1734
|
+
fieldType: z16.enum(["text", "longText"]),
|
|
1735
|
+
value: z16.string()
|
|
1678
1736
|
});
|
|
1679
|
-
var previewLinkValueSchema =
|
|
1680
|
-
fieldType:
|
|
1681
|
-
value:
|
|
1682
|
-
href:
|
|
1683
|
-
label:
|
|
1737
|
+
var previewLinkValueSchema = z16.object({
|
|
1738
|
+
fieldType: z16.literal("link"),
|
|
1739
|
+
value: z16.object({
|
|
1740
|
+
href: z16.string().trim().min(1),
|
|
1741
|
+
label: z16.string().trim().min(1).optional()
|
|
1684
1742
|
})
|
|
1685
1743
|
});
|
|
1686
|
-
var previewImageValueSchema =
|
|
1687
|
-
fieldType:
|
|
1744
|
+
var previewImageValueSchema = z16.object({
|
|
1745
|
+
fieldType: z16.literal("image"),
|
|
1688
1746
|
value: imageValueSchema
|
|
1689
1747
|
});
|
|
1690
|
-
var bridgePreviewValueSchema =
|
|
1748
|
+
var bridgePreviewValueSchema = z16.discriminatedUnion("fieldType", [
|
|
1691
1749
|
previewTextValueSchema,
|
|
1692
1750
|
previewLinkValueSchema,
|
|
1693
1751
|
previewImageValueSchema
|
|
1694
1752
|
]);
|
|
1695
|
-
var fieldSelectionModeSchema =
|
|
1696
|
-
var fieldBridgeMissingContentActionSchema =
|
|
1753
|
+
var fieldSelectionModeSchema = z16.enum(["replace", "range", "toggle"]);
|
|
1754
|
+
var fieldBridgeMissingContentActionSchema = z16.enum([
|
|
1697
1755
|
"add",
|
|
1698
1756
|
"select",
|
|
1699
1757
|
"remove"
|
|
@@ -1712,77 +1770,77 @@ var FIELD_BRIDGE_MESSAGE_TYPES = [
|
|
|
1712
1770
|
"siteplane:field-bridge:preview-scrolled",
|
|
1713
1771
|
"siteplane:field-bridge:error"
|
|
1714
1772
|
];
|
|
1715
|
-
var canonicalFieldContractHashSchema =
|
|
1716
|
-
var bridgeSectionSchema =
|
|
1717
|
-
var realRenderedPathSchema =
|
|
1718
|
-
var fieldBridgeIdentitySchema =
|
|
1719
|
-
publicRuntimeKeyId:
|
|
1773
|
+
var canonicalFieldContractHashSchema = z16.string().regex(/^sha256:[0-9a-f]{64}$/u);
|
|
1774
|
+
var bridgeSectionSchema = z16.string().trim().min(1).max(256);
|
|
1775
|
+
var realRenderedPathSchema = z16.string().trim().refine((value) => value.startsWith("/") && value !== "$global" && !value.includes("?") && !value.includes("#"), "A field bridge rendered path must be a real canonical path.");
|
|
1776
|
+
var fieldBridgeIdentitySchema = z16.object({
|
|
1777
|
+
publicRuntimeKeyId: z16.string().uuid(),
|
|
1720
1778
|
fieldContractHash: canonicalFieldContractHashSchema,
|
|
1721
|
-
deploymentRevision:
|
|
1779
|
+
deploymentRevision: z16.string().trim().min(1).max(256)
|
|
1722
1780
|
}).strict();
|
|
1723
|
-
var fieldBridgeBaseSchema =
|
|
1724
|
-
version:
|
|
1725
|
-
type:
|
|
1726
|
-
siteId:
|
|
1727
|
-
sessionId:
|
|
1728
|
-
publicRuntimeKeyId:
|
|
1781
|
+
var fieldBridgeBaseSchema = z16.object({
|
|
1782
|
+
version: z16.literal(BRIDGE_PROTOCOL_VERSION),
|
|
1783
|
+
type: z16.enum(FIELD_BRIDGE_MESSAGE_TYPES),
|
|
1784
|
+
siteId: z16.string().uuid(),
|
|
1785
|
+
sessionId: z16.string().trim().min(1),
|
|
1786
|
+
publicRuntimeKeyId: z16.string().uuid(),
|
|
1729
1787
|
fieldContractHash: canonicalFieldContractHashSchema,
|
|
1730
|
-
deploymentRevision:
|
|
1731
|
-
requestId:
|
|
1732
|
-
sentAt:
|
|
1788
|
+
deploymentRevision: z16.string().trim().min(1).max(256),
|
|
1789
|
+
requestId: z16.string().trim().min(1),
|
|
1790
|
+
sentAt: z16.string().datetime()
|
|
1733
1791
|
}).strict();
|
|
1734
|
-
var fieldBridgeFieldSchema =
|
|
1792
|
+
var fieldBridgeFieldSchema = z16.object({
|
|
1735
1793
|
fieldId: fieldIdSchema,
|
|
1736
1794
|
fieldType: fieldTypeSchema,
|
|
1737
1795
|
routeKey: siteFieldRouteKeySchema,
|
|
1738
1796
|
renderedPath: realRenderedPathSchema,
|
|
1739
|
-
sourcePath:
|
|
1797
|
+
sourcePath: z16.string().trim().min(1).optional(),
|
|
1740
1798
|
editTarget: fieldIdSchema,
|
|
1741
1799
|
rect: bridgeRectSchema,
|
|
1742
|
-
targetResolved:
|
|
1800
|
+
targetResolved: z16.literal(true),
|
|
1743
1801
|
currentValue: bridgePreviewValueSchema.optional()
|
|
1744
1802
|
}).strict();
|
|
1745
1803
|
var fieldBridgeInitMessageSchema = fieldBridgeBaseSchema.extend({
|
|
1746
|
-
type:
|
|
1747
|
-
payload:
|
|
1748
|
-
adminOrigin:
|
|
1749
|
-
customerOrigin:
|
|
1804
|
+
type: z16.literal("siteplane:field-bridge:init"),
|
|
1805
|
+
payload: z16.object({
|
|
1806
|
+
adminOrigin: z16.string().url(),
|
|
1807
|
+
customerOrigin: z16.string().url(),
|
|
1750
1808
|
renderedPath: realRenderedPathSchema
|
|
1751
1809
|
}).strict()
|
|
1752
1810
|
});
|
|
1753
1811
|
var fieldBridgeReadyMessageSchema = fieldBridgeBaseSchema.extend({
|
|
1754
|
-
type:
|
|
1755
|
-
payload:
|
|
1812
|
+
type: z16.literal("siteplane:field-bridge:ready"),
|
|
1813
|
+
payload: z16.object({
|
|
1756
1814
|
renderedPath: realRenderedPathSchema,
|
|
1757
|
-
fieldCount:
|
|
1758
|
-
capabilities:
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1815
|
+
fieldCount: z16.number().int().nonnegative(),
|
|
1816
|
+
capabilities: z16.tuple([
|
|
1817
|
+
z16.literal("field_selection"),
|
|
1818
|
+
z16.literal("preview_values"),
|
|
1819
|
+
z16.literal("field_evidence"),
|
|
1820
|
+
z16.literal("visual_field_control")
|
|
1763
1821
|
])
|
|
1764
1822
|
}).strict()
|
|
1765
1823
|
});
|
|
1766
1824
|
var fieldBridgeFieldsMessageSchema = fieldBridgeBaseSchema.extend({
|
|
1767
|
-
type:
|
|
1768
|
-
payload:
|
|
1825
|
+
type: z16.literal("siteplane:field-bridge:fields"),
|
|
1826
|
+
payload: z16.object({
|
|
1769
1827
|
renderedPath: realRenderedPathSchema,
|
|
1770
|
-
fields:
|
|
1828
|
+
fields: z16.array(fieldBridgeFieldSchema)
|
|
1771
1829
|
}).strict()
|
|
1772
1830
|
});
|
|
1773
1831
|
var fieldBridgeSelectFieldMessageSchema = fieldBridgeBaseSchema.extend({
|
|
1774
|
-
type:
|
|
1775
|
-
payload:
|
|
1832
|
+
type: z16.literal("siteplane:field-bridge:select-field"),
|
|
1833
|
+
payload: z16.object({
|
|
1776
1834
|
fieldId: fieldIdSchema,
|
|
1777
1835
|
selectionMode: fieldSelectionModeSchema
|
|
1778
1836
|
}).strict()
|
|
1779
1837
|
});
|
|
1780
1838
|
var fieldBridgeSetSelectedFieldMessageSchema = fieldBridgeBaseSchema.extend({
|
|
1781
|
-
type:
|
|
1782
|
-
payload:
|
|
1783
|
-
fieldIds:
|
|
1839
|
+
type: z16.literal("siteplane:field-bridge:set-selected-field"),
|
|
1840
|
+
payload: z16.object({
|
|
1841
|
+
fieldIds: z16.array(fieldIdSchema).max(200),
|
|
1784
1842
|
primaryFieldId: fieldIdSchema.nullable(),
|
|
1785
|
-
scrollIntoView:
|
|
1843
|
+
scrollIntoView: z16.boolean().optional()
|
|
1786
1844
|
}).strict().superRefine((value, context) => {
|
|
1787
1845
|
if (value.fieldIds.length > 0 && value.primaryFieldId === null) {
|
|
1788
1846
|
context.addIssue({
|
|
@@ -1801,58 +1859,58 @@ var fieldBridgeSetSelectedFieldMessageSchema = fieldBridgeBaseSchema.extend({
|
|
|
1801
1859
|
})
|
|
1802
1860
|
});
|
|
1803
1861
|
var fieldBridgeApplyPreviewValuesMessageSchema = fieldBridgeBaseSchema.extend({
|
|
1804
|
-
type:
|
|
1805
|
-
payload:
|
|
1862
|
+
type: z16.literal("siteplane:field-bridge:apply-preview-values"),
|
|
1863
|
+
payload: z16.object({ values: z16.record(fieldIdSchema, bridgePreviewValueSchema) }).strict()
|
|
1806
1864
|
});
|
|
1807
1865
|
var fieldBridgeTestPreviewValuesMessageSchema = fieldBridgeBaseSchema.extend({
|
|
1808
|
-
type:
|
|
1809
|
-
payload:
|
|
1866
|
+
type: z16.literal("siteplane:field-bridge:test-preview-values"),
|
|
1867
|
+
payload: z16.object({ fieldIds: z16.array(fieldIdSchema).min(1).max(200) }).strict()
|
|
1810
1868
|
});
|
|
1811
1869
|
var fieldBridgePreviewAckMessageSchema = fieldBridgeBaseSchema.extend({
|
|
1812
|
-
type:
|
|
1813
|
-
payload:
|
|
1814
|
-
ackRequestId:
|
|
1815
|
-
kind:
|
|
1870
|
+
type: z16.literal("siteplane:field-bridge:preview-ack"),
|
|
1871
|
+
payload: z16.object({
|
|
1872
|
+
ackRequestId: z16.string().trim().min(1),
|
|
1873
|
+
kind: z16.enum(["apply", "test"]),
|
|
1816
1874
|
renderedPath: realRenderedPathSchema,
|
|
1817
|
-
fieldIds:
|
|
1875
|
+
fieldIds: z16.array(fieldIdSchema).max(200)
|
|
1818
1876
|
}).strict()
|
|
1819
1877
|
});
|
|
1820
1878
|
var fieldBridgeSetVisualControlStateMessageSchema = fieldBridgeBaseSchema.extend({
|
|
1821
|
-
type:
|
|
1822
|
-
payload:
|
|
1823
|
-
enabled:
|
|
1824
|
-
fieldProximityEnabled:
|
|
1825
|
-
pendingKeys:
|
|
1826
|
-
activeFieldIds:
|
|
1827
|
-
fieldSections:
|
|
1828
|
-
selectedPending:
|
|
1829
|
-
key:
|
|
1830
|
-
locatorHint:
|
|
1879
|
+
type: z16.literal("siteplane:field-bridge:set-visual-control-state"),
|
|
1880
|
+
payload: z16.object({
|
|
1881
|
+
enabled: z16.boolean(),
|
|
1882
|
+
fieldProximityEnabled: z16.boolean(),
|
|
1883
|
+
pendingKeys: z16.array(z16.string().trim().min(1).max(2048)).max(50),
|
|
1884
|
+
activeFieldIds: z16.array(fieldIdSchema),
|
|
1885
|
+
fieldSections: z16.record(fieldIdSchema, bridgeSectionSchema),
|
|
1886
|
+
selectedPending: z16.array(z16.object({
|
|
1887
|
+
key: z16.string().trim().min(1).max(2048),
|
|
1888
|
+
locatorHint: z16.string().trim().min(1).max(2048)
|
|
1831
1889
|
}).strict()).max(50),
|
|
1832
|
-
scrollPendingIntoView:
|
|
1890
|
+
scrollPendingIntoView: z16.boolean().optional()
|
|
1833
1891
|
}).strict()
|
|
1834
1892
|
});
|
|
1835
1893
|
var fieldBridgeMissingContentMessageSchema = fieldBridgeBaseSchema.extend({
|
|
1836
|
-
type:
|
|
1837
|
-
payload:
|
|
1894
|
+
type: z16.literal("siteplane:field-bridge:missing-content"),
|
|
1895
|
+
payload: z16.object({
|
|
1838
1896
|
action: fieldBridgeMissingContentActionSchema,
|
|
1839
1897
|
item: setupCorrectionItemSchema,
|
|
1840
1898
|
suggestedSection: bridgeSectionSchema.optional()
|
|
1841
1899
|
}).strict()
|
|
1842
1900
|
});
|
|
1843
1901
|
var fieldBridgePreviewScrolledMessageSchema = fieldBridgeBaseSchema.extend({
|
|
1844
|
-
type:
|
|
1845
|
-
payload:
|
|
1902
|
+
type: z16.literal("siteplane:field-bridge:preview-scrolled"),
|
|
1903
|
+
payload: z16.object({ renderedPath: realRenderedPathSchema }).strict()
|
|
1846
1904
|
});
|
|
1847
1905
|
var fieldBridgeErrorMessageSchema = fieldBridgeBaseSchema.extend({
|
|
1848
|
-
type:
|
|
1849
|
-
payload:
|
|
1850
|
-
code:
|
|
1851
|
-
message:
|
|
1852
|
-
recoverable:
|
|
1906
|
+
type: z16.literal("siteplane:field-bridge:error"),
|
|
1907
|
+
payload: z16.object({
|
|
1908
|
+
code: z16.string().trim().min(1),
|
|
1909
|
+
message: z16.string().trim().min(1),
|
|
1910
|
+
recoverable: z16.boolean().default(false)
|
|
1853
1911
|
}).strict()
|
|
1854
1912
|
});
|
|
1855
|
-
var fieldBridgeMessageSchema =
|
|
1913
|
+
var fieldBridgeMessageSchema = z16.discriminatedUnion("type", [
|
|
1856
1914
|
fieldBridgeInitMessageSchema,
|
|
1857
1915
|
fieldBridgeReadyMessageSchema,
|
|
1858
1916
|
fieldBridgeFieldsMessageSchema,
|
|
@@ -1868,51 +1926,51 @@ var fieldBridgeMessageSchema = z15.discriminatedUnion("type", [
|
|
|
1868
1926
|
]);
|
|
1869
1927
|
|
|
1870
1928
|
// ../shared/dist/commands.js
|
|
1871
|
-
import { z as
|
|
1929
|
+
import { z as z18 } from "zod";
|
|
1872
1930
|
|
|
1873
1931
|
// ../shared/dist/errors.js
|
|
1874
|
-
import { z as
|
|
1932
|
+
import { z as z17 } from "zod";
|
|
1875
1933
|
var UI_ERROR_CATEGORIES = [
|
|
1876
1934
|
"site_member",
|
|
1877
1935
|
"workspace_member",
|
|
1878
1936
|
"internal"
|
|
1879
1937
|
];
|
|
1880
|
-
var uiErrorCategorySchema =
|
|
1881
|
-
var commandErrorPayloadSchema =
|
|
1882
|
-
code:
|
|
1883
|
-
message:
|
|
1938
|
+
var uiErrorCategorySchema = z17.enum(UI_ERROR_CATEGORIES);
|
|
1939
|
+
var commandErrorPayloadSchema = z17.object({
|
|
1940
|
+
code: z17.string().min(1),
|
|
1941
|
+
message: z17.string().min(1),
|
|
1884
1942
|
category: uiErrorCategorySchema,
|
|
1885
|
-
details:
|
|
1943
|
+
details: z17.record(z17.string(), z17.unknown()).optional()
|
|
1886
1944
|
});
|
|
1887
1945
|
|
|
1888
1946
|
// ../shared/dist/commands.js
|
|
1889
|
-
var commandSuccessSchema =
|
|
1890
|
-
ok:
|
|
1891
|
-
data:
|
|
1947
|
+
var commandSuccessSchema = z18.object({
|
|
1948
|
+
ok: z18.literal(true),
|
|
1949
|
+
data: z18.unknown()
|
|
1892
1950
|
});
|
|
1893
|
-
var commandErrorSchema =
|
|
1894
|
-
ok:
|
|
1951
|
+
var commandErrorSchema = z18.object({
|
|
1952
|
+
ok: z18.literal(false),
|
|
1895
1953
|
error: commandErrorPayloadSchema
|
|
1896
1954
|
});
|
|
1897
|
-
var commandResultSchema =
|
|
1955
|
+
var commandResultSchema = z18.discriminatedUnion("ok", [
|
|
1898
1956
|
commandSuccessSchema,
|
|
1899
1957
|
commandErrorSchema
|
|
1900
1958
|
]);
|
|
1901
1959
|
|
|
1902
1960
|
// ../shared/dist/editor-settings.js
|
|
1903
|
-
import { z as
|
|
1904
|
-
var editorColorSchemeSchema =
|
|
1961
|
+
import { z as z19 } from "zod";
|
|
1962
|
+
var editorColorSchemeSchema = z19.enum([
|
|
1905
1963
|
"paper",
|
|
1906
1964
|
"slate",
|
|
1907
1965
|
"siteplane",
|
|
1908
1966
|
"bloom"
|
|
1909
1967
|
]);
|
|
1910
1968
|
var editorColorSchemes = editorColorSchemeSchema.options;
|
|
1911
|
-
var editorColorModeSchema =
|
|
1969
|
+
var editorColorModeSchema = z19.enum(["light", "dark"]);
|
|
1912
1970
|
var editorColorModes = editorColorModeSchema.options;
|
|
1913
1971
|
|
|
1914
1972
|
// ../shared/dist/site-slug.js
|
|
1915
|
-
import { z as
|
|
1973
|
+
import { z as z20 } from "zod";
|
|
1916
1974
|
var SITE_SLUG_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
1917
1975
|
var RESERVED_SITE_SLUGS = /* @__PURE__ */ new Set([
|
|
1918
1976
|
"account",
|
|
@@ -1929,31 +1987,31 @@ var RESERVED_SITE_SLUGS = /* @__PURE__ */ new Set([
|
|
|
1929
1987
|
"support",
|
|
1930
1988
|
"workspace"
|
|
1931
1989
|
]);
|
|
1932
|
-
var siteSlugSchema =
|
|
1990
|
+
var siteSlugSchema = z20.string().regex(SITE_SLUG_PATTERN, "Invalid site slug").refine((value) => !RESERVED_SITE_SLUGS.has(value), "Reserved site slug");
|
|
1933
1991
|
|
|
1934
1992
|
// ../shared/dist/entitlements.js
|
|
1935
|
-
import { z as
|
|
1936
|
-
var entitlementSnapshotSchema =
|
|
1937
|
-
planKey:
|
|
1938
|
-
sitesLimit:
|
|
1939
|
-
siteMembersPerSiteLimit:
|
|
1940
|
-
customAdminDomainsEnabled:
|
|
1941
|
-
agentMcpEnabled:
|
|
1942
|
-
emailNotificationsEnabled:
|
|
1943
|
-
analyticsEnabled:
|
|
1944
|
-
analyticsSitesLimit:
|
|
1945
|
-
analyticsPortalPerformanceEnabled:
|
|
1946
|
-
analyticsMonthlyReportsEnabled:
|
|
1947
|
-
analyticsAiSummaryEnabled:
|
|
1948
|
-
analyticsRawEventRetentionDays:
|
|
1949
|
-
analyticsMonthlyEventLimit:
|
|
1950
|
-
bookingEnabled:
|
|
1951
|
-
bookingSitesLimit:
|
|
1952
|
-
bookingPortalManagementEnabled:
|
|
1953
|
-
bookingResourcesPerSiteLimit:
|
|
1954
|
-
bookingServicesPerSiteLimit:
|
|
1955
|
-
bookingMonthlyBookingsLimit:
|
|
1956
|
-
bookingRemindersEnabled:
|
|
1993
|
+
import { z as z21 } from "zod";
|
|
1994
|
+
var entitlementSnapshotSchema = z21.object({
|
|
1995
|
+
planKey: z21.string().trim().min(1),
|
|
1996
|
+
sitesLimit: z21.number().int().positive(),
|
|
1997
|
+
siteMembersPerSiteLimit: z21.number().int().positive(),
|
|
1998
|
+
customAdminDomainsEnabled: z21.boolean(),
|
|
1999
|
+
agentMcpEnabled: z21.boolean(),
|
|
2000
|
+
emailNotificationsEnabled: z21.boolean(),
|
|
2001
|
+
analyticsEnabled: z21.boolean(),
|
|
2002
|
+
analyticsSitesLimit: z21.number().int().min(0),
|
|
2003
|
+
analyticsPortalPerformanceEnabled: z21.boolean(),
|
|
2004
|
+
analyticsMonthlyReportsEnabled: z21.boolean(),
|
|
2005
|
+
analyticsAiSummaryEnabled: z21.boolean(),
|
|
2006
|
+
analyticsRawEventRetentionDays: z21.number().int().min(1).max(ANALYTICS_RETENTION_DEFAULTS.maxRawEventRetentionDaysWithoutAdr),
|
|
2007
|
+
analyticsMonthlyEventLimit: z21.number().int().min(0),
|
|
2008
|
+
bookingEnabled: z21.boolean().default(false),
|
|
2009
|
+
bookingSitesLimit: z21.number().int().min(0).default(0),
|
|
2010
|
+
bookingPortalManagementEnabled: z21.boolean().default(false),
|
|
2011
|
+
bookingResourcesPerSiteLimit: z21.number().int().min(0).default(0),
|
|
2012
|
+
bookingServicesPerSiteLimit: z21.number().int().min(0).default(0),
|
|
2013
|
+
bookingMonthlyBookingsLimit: z21.number().int().min(0).default(0),
|
|
2014
|
+
bookingRemindersEnabled: z21.boolean().default(false)
|
|
1957
2015
|
});
|
|
1958
2016
|
var EARLY_ACCESS_PLAN = {
|
|
1959
2017
|
planKey: "early_access_2026",
|
|
@@ -1979,7 +2037,7 @@ var EARLY_ACCESS_PLAN = {
|
|
|
1979
2037
|
};
|
|
1980
2038
|
|
|
1981
2039
|
// ../shared/dist/readiness.js
|
|
1982
|
-
import { z as
|
|
2040
|
+
import { z as z22 } from "zod";
|
|
1983
2041
|
var READINESS_CHECK_KEYS = [
|
|
1984
2042
|
"agent_instructions_installed",
|
|
1985
2043
|
"runtime_package_connected",
|
|
@@ -1994,19 +2052,19 @@ var READINESS_STATUSES = [
|
|
|
1994
2052
|
"failing",
|
|
1995
2053
|
"warning"
|
|
1996
2054
|
];
|
|
1997
|
-
var readinessCheckKeySchema =
|
|
1998
|
-
var readinessStatusSchema =
|
|
2055
|
+
var readinessCheckKeySchema = z22.enum(READINESS_CHECK_KEYS);
|
|
2056
|
+
var readinessStatusSchema = z22.enum(READINESS_STATUSES);
|
|
1999
2057
|
|
|
2000
2058
|
// ../shared/dist/site.js
|
|
2001
|
-
import { z as
|
|
2059
|
+
import { z as z23 } from "zod";
|
|
2002
2060
|
var SITE_STATUSES = [
|
|
2003
2061
|
"setup",
|
|
2004
2062
|
"active",
|
|
2005
2063
|
"disabled",
|
|
2006
2064
|
"archived"
|
|
2007
2065
|
];
|
|
2008
|
-
var siteStatusSchema =
|
|
2009
|
-
var websiteUrlSchema =
|
|
2066
|
+
var siteStatusSchema = z23.enum(SITE_STATUSES);
|
|
2067
|
+
var websiteUrlSchema = z23.string().trim().url().refine((value) => value.startsWith("https://") || value.startsWith("http://"), "Website URL must use http or https");
|
|
2010
2068
|
|
|
2011
2069
|
// ../cli/dist/analytics/static-scan.js
|
|
2012
2070
|
import ts from "typescript";
|
|
@@ -2044,16 +2102,16 @@ ${analyticsRulesTemplate}`;
|
|
|
2044
2102
|
import { createHash } from "crypto";
|
|
2045
2103
|
|
|
2046
2104
|
// ../cli/dist/commands/analytics/public-key.js
|
|
2047
|
-
import { z as
|
|
2048
|
-
var responseSchema =
|
|
2049
|
-
ok:
|
|
2050
|
-
data:
|
|
2051
|
-
rawPublicKey:
|
|
2105
|
+
import { z as z24 } from "zod";
|
|
2106
|
+
var responseSchema = z24.object({
|
|
2107
|
+
ok: z24.literal(true),
|
|
2108
|
+
data: z24.object({
|
|
2109
|
+
rawPublicKey: z24.string().regex(/^pk_siteplane_[A-Za-z0-9_-]{16}_[A-Za-z0-9_-]{43}$/)
|
|
2052
2110
|
})
|
|
2053
2111
|
});
|
|
2054
|
-
var errorResponseSchema =
|
|
2055
|
-
error:
|
|
2056
|
-
code:
|
|
2112
|
+
var errorResponseSchema = z24.object({
|
|
2113
|
+
error: z24.object({
|
|
2114
|
+
code: z24.string().regex(/^[a-z][a-z0-9_.-]+$/u)
|
|
2057
2115
|
})
|
|
2058
2116
|
});
|
|
2059
2117
|
|
|
@@ -2087,14 +2145,22 @@ ${bookingRulesTemplate}`;
|
|
|
2087
2145
|
import { access, chmod, open, readFile as readFile5, rename, rm } from "fs/promises";
|
|
2088
2146
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
2089
2147
|
import { join as join3 } from "path";
|
|
2090
|
-
import { z as
|
|
2091
|
-
var siteplaneProjectConfigSchema =
|
|
2092
|
-
version:
|
|
2093
|
-
apiBaseUrl:
|
|
2094
|
-
siteId:
|
|
2095
|
-
publicSiteKeyId:
|
|
2096
|
-
publicSiteKey:
|
|
2097
|
-
|
|
2148
|
+
import { z as z25 } from "zod";
|
|
2149
|
+
var siteplaneProjectConfigSchema = z25.object({
|
|
2150
|
+
version: z25.literal(2),
|
|
2151
|
+
apiBaseUrl: z25.string().url(),
|
|
2152
|
+
siteId: z25.string().uuid(),
|
|
2153
|
+
publicSiteKeyId: z25.string().uuid(),
|
|
2154
|
+
publicSiteKey: z25.string().trim().min(1),
|
|
2155
|
+
runId: z25.string().uuid(),
|
|
2156
|
+
appDirectory: z25.string().min(1),
|
|
2157
|
+
taskContractVersion: z25.literal("siteplane.setup-task.v2"),
|
|
2158
|
+
adminProtocolVersion: z25.literal(2),
|
|
2159
|
+
packages: z25.object({
|
|
2160
|
+
siteplane: z25.string().regex(/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/u),
|
|
2161
|
+
runtimeNext: z25.string().regex(/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/u)
|
|
2162
|
+
}).strict(),
|
|
2163
|
+
fieldContractHash: z25.string().regex(/^sha256:[0-9a-f]{64}$/iu).optional()
|
|
2098
2164
|
}).strict();
|
|
2099
2165
|
async function readProjectConfig(projectDir) {
|
|
2100
2166
|
return siteplaneProjectConfigSchema.parse(JSON.parse(await readFile5(join3(projectDir, "siteplane.config.json"), "utf8")));
|
|
@@ -2103,45 +2169,545 @@ async function readProjectConfig(projectDir) {
|
|
|
2103
2169
|
// ../cli/dist/config/credentials.js
|
|
2104
2170
|
import { execFile } from "child_process";
|
|
2105
2171
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
2106
|
-
import { chmod as chmod2, mkdir as mkdir5, open as open2, readFile as readFile6, rename as rename2, rm as rm2 } from "fs/promises";
|
|
2172
|
+
import { chmod as chmod2, lstat, mkdir as mkdir5, open as open2, readFile as readFile6, rename as rename2, rm as rm2 } from "fs/promises";
|
|
2107
2173
|
import { dirname as dirname5, join as join4, relative } from "path";
|
|
2108
2174
|
import { promisify } from "util";
|
|
2109
|
-
import { z as
|
|
2110
|
-
var siteplaneCredentialsSchema =
|
|
2111
|
-
accessToken:
|
|
2112
|
-
siteRevalidationSecret:
|
|
2175
|
+
import { z as z26 } from "zod";
|
|
2176
|
+
var siteplaneCredentialsSchema = z26.object({
|
|
2177
|
+
accessToken: z26.string().trim().min(1),
|
|
2178
|
+
siteRevalidationSecret: z26.string().trim().min(1),
|
|
2179
|
+
adminSession: z26.object({
|
|
2180
|
+
secret: z26.string().regex(/^[A-Za-z0-9_-]{43}$/u),
|
|
2181
|
+
generation: z26.string().uuid()
|
|
2182
|
+
}).strict().optional()
|
|
2113
2183
|
}).strict();
|
|
2184
|
+
async function assertLocalCredentialsPathSafe(projectDir, options = {}) {
|
|
2185
|
+
const path = join4(projectDir, ".siteplane/credentials.json");
|
|
2186
|
+
await assertCredentialFilesystemSafe(projectDir);
|
|
2187
|
+
const isTrackedFile = options.isTrackedFile ?? ((targetPath) => gitPathMatches(projectDir, targetPath, "ls-files"));
|
|
2188
|
+
const isIgnoredFile = options.isIgnoredFile ?? ((targetPath) => gitPathMatches(projectDir, targetPath, "check-ignore"));
|
|
2189
|
+
if (await isTrackedFile(path)) {
|
|
2190
|
+
throw new Error("Refusing to write Siteplane credentials into a tracked file.");
|
|
2191
|
+
}
|
|
2192
|
+
if (!await isIgnoredFile(path)) {
|
|
2193
|
+
throw new Error("Add .siteplane/credentials.json to .gitignore before running Siteplane init.");
|
|
2194
|
+
}
|
|
2195
|
+
return path;
|
|
2196
|
+
}
|
|
2197
|
+
async function assertCredentialFilesystemSafe(projectDir) {
|
|
2198
|
+
for (const [path, directory, mode] of [
|
|
2199
|
+
[projectDir, true, null],
|
|
2200
|
+
[join4(projectDir, ".siteplane"), true, 448],
|
|
2201
|
+
[join4(projectDir, ".siteplane/credentials.json"), false, 384]
|
|
2202
|
+
]) {
|
|
2203
|
+
const stat = await lstat(path).catch((error) => {
|
|
2204
|
+
if (error.code === "ENOENT")
|
|
2205
|
+
return null;
|
|
2206
|
+
throw error;
|
|
2207
|
+
});
|
|
2208
|
+
if (!stat)
|
|
2209
|
+
continue;
|
|
2210
|
+
if (stat.isSymbolicLink() || (directory ? !stat.isDirectory() : !stat.isFile())) {
|
|
2211
|
+
throw new Error("Siteplane credential paths must not contain symlinks or unexpected file types.");
|
|
2212
|
+
}
|
|
2213
|
+
if (mode !== null && (stat.mode & 511) !== mode) {
|
|
2214
|
+
throw new Error(`Siteplane credential ${directory ? "directory" : "file"} permissions must be ${mode.toString(8)} before setup.`);
|
|
2215
|
+
}
|
|
2216
|
+
}
|
|
2217
|
+
}
|
|
2218
|
+
async function readLocalCredentials(projectDir) {
|
|
2219
|
+
await assertCredentialFilesystemSafe(projectDir);
|
|
2220
|
+
return siteplaneCredentialsSchema.parse(JSON.parse(await readFile6(join4(projectDir, ".siteplane/credentials.json"), "utf8")));
|
|
2221
|
+
}
|
|
2114
2222
|
var execFileAsync = promisify(execFile);
|
|
2223
|
+
async function gitPathMatches(projectDir, path, command) {
|
|
2224
|
+
const args = command === "check-ignore" ? ["check-ignore", "--quiet", relative(projectDir, path)] : ["ls-files", "--error-unmatch", relative(projectDir, path)];
|
|
2225
|
+
try {
|
|
2226
|
+
await execFileAsync("git", args, { cwd: projectDir });
|
|
2227
|
+
return true;
|
|
2228
|
+
} catch {
|
|
2229
|
+
return false;
|
|
2230
|
+
}
|
|
2231
|
+
}
|
|
2115
2232
|
|
|
2116
2233
|
// ../cli/dist/commands/init.js
|
|
2234
|
+
import { access as access3 } from "fs/promises";
|
|
2235
|
+
import { join as join7, relative as relative3 } from "path";
|
|
2236
|
+
import { z as z29 } from "zod";
|
|
2237
|
+
|
|
2238
|
+
// ../cli/dist/commands/setup-preflight.js
|
|
2239
|
+
import { createHash as createHash2 } from "crypto";
|
|
2240
|
+
import semver from "semver";
|
|
2241
|
+
import { minimatch } from "minimatch";
|
|
2242
|
+
import { parse as parseYaml } from "yaml";
|
|
2243
|
+
|
|
2244
|
+
// ../cli/dist/config/installed-package.js
|
|
2245
|
+
import { createRequire } from "module";
|
|
2246
|
+
import { readFile as readFile7 } from "fs/promises";
|
|
2117
2247
|
import { join as join5 } from "path";
|
|
2118
|
-
import { z as
|
|
2119
|
-
var
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2248
|
+
import { z as z27 } from "zod";
|
|
2249
|
+
var packageSchema = z27.object({
|
|
2250
|
+
name: z27.string().optional(),
|
|
2251
|
+
version: z27.string(),
|
|
2252
|
+
peerDependencies: z27.record(z27.string(), z27.string()).optional()
|
|
2253
|
+
});
|
|
2254
|
+
async function readInstalledPackage(projectDir, name2) {
|
|
2255
|
+
const require2 = createRequire(join5(projectDir, "package.json"));
|
|
2256
|
+
for (const directory of require2.resolve.paths(name2) ?? []) {
|
|
2257
|
+
try {
|
|
2258
|
+
return packageSchema.parse(JSON.parse(await readFile7(join5(directory, name2, "package.json"), "utf8")));
|
|
2259
|
+
} catch (error) {
|
|
2260
|
+
if (error.code !== "ENOENT")
|
|
2261
|
+
throw error;
|
|
2262
|
+
}
|
|
2263
|
+
}
|
|
2264
|
+
throw new Error(`Install ${name2} with the canonical package manager before setup.`);
|
|
2265
|
+
}
|
|
2266
|
+
|
|
2267
|
+
// ../cli/dist/commands/setup-preflight.js
|
|
2268
|
+
import { access as access2, readFile as readFile8, realpath, readdir, readlink } from "fs/promises";
|
|
2269
|
+
import { dirname as dirname6, join as join6, relative as relative2, resolve, sep } from "path";
|
|
2270
|
+
import { z as z28 } from "zod";
|
|
2271
|
+
|
|
2272
|
+
// ../cli/dist/commands/setup-process.js
|
|
2273
|
+
import { spawn } from "child_process";
|
|
2274
|
+
var SetupFailure = class extends Error {
|
|
2275
|
+
code;
|
|
2276
|
+
constructor(code, message) {
|
|
2277
|
+
super(message);
|
|
2278
|
+
this.code = code;
|
|
2279
|
+
}
|
|
2280
|
+
};
|
|
2281
|
+
async function setupProcess(binary, args, options) {
|
|
2282
|
+
return new Promise((resolve5, reject) => {
|
|
2283
|
+
const child = spawn(binary, args, {
|
|
2284
|
+
cwd: options.cwd,
|
|
2285
|
+
env: process.env,
|
|
2286
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
2287
|
+
});
|
|
2288
|
+
const chunks = [];
|
|
2289
|
+
const errors = [];
|
|
2290
|
+
let errorBytes = 0;
|
|
2291
|
+
let bytes = 0;
|
|
2292
|
+
let exceeded = false;
|
|
2293
|
+
const timer = setTimeout(() => {
|
|
2294
|
+
exceeded = true;
|
|
2295
|
+
child.kill("SIGKILL");
|
|
2296
|
+
}, options.timeoutMs ?? 12e4);
|
|
2297
|
+
const capture = (chunk) => {
|
|
2298
|
+
bytes += chunk.length;
|
|
2299
|
+
if (bytes > 4 * 1024 * 1024) {
|
|
2300
|
+
exceeded = true;
|
|
2301
|
+
child.kill("SIGKILL");
|
|
2302
|
+
} else
|
|
2303
|
+
chunks.push(chunk);
|
|
2304
|
+
};
|
|
2305
|
+
child.stdout.on("data", capture);
|
|
2306
|
+
child.stderr.on("data", (chunk) => {
|
|
2307
|
+
errorBytes += chunk.length;
|
|
2308
|
+
if (errorBytes <= 4 * 1024 * 1024)
|
|
2309
|
+
errors.push(chunk);
|
|
2310
|
+
else {
|
|
2311
|
+
exceeded = true;
|
|
2312
|
+
child.kill("SIGKILL");
|
|
2313
|
+
}
|
|
2314
|
+
});
|
|
2315
|
+
child.on("error", () => {
|
|
2316
|
+
clearTimeout(timer);
|
|
2317
|
+
reject(new SetupFailure("local_tool_unavailable", `${binary} could not be started. Check the local installation and access.`));
|
|
2318
|
+
});
|
|
2319
|
+
child.on("close", (code) => {
|
|
2320
|
+
clearTimeout(timer);
|
|
2321
|
+
if (exceeded)
|
|
2322
|
+
reject(new SetupFailure("provider_timeout", "The operation exceeded its time or response limit; inspect the existing operation before retrying."));
|
|
2323
|
+
else if (code !== 0) {
|
|
2324
|
+
const diagnostic = Buffer.concat([...chunks, ...errors]).toString("utf8");
|
|
2325
|
+
if (/\b(?:401|403|unauthorized|forbidden|not authenticated|not authorized|login required|E401|E403)\b/iu.test(diagnostic))
|
|
2326
|
+
reject(new SetupFailure("provider_access_denied", `${binary} denied access. Restore the existing local login and project/package permissions before retrying.`));
|
|
2327
|
+
else if (/\b(?:ECONNRESET|ETIMEDOUT|ENOTFOUND|EAI_AGAIN|ECONNREFUSED|429|502|503|504)\b/iu.test(diagnostic))
|
|
2328
|
+
reject(new SetupFailure("provider_transport_failed", `${binary} could not reach its provider. Inspect the existing operation before retrying.`));
|
|
2329
|
+
else
|
|
2330
|
+
reject(new SetupFailure("local_command_failed", `${binary} failed. Check its local login, permissions and project configuration.`));
|
|
2331
|
+
} else
|
|
2332
|
+
resolve5(Buffer.concat(options.includeStderr ? [...chunks, ...errors] : chunks).toString("utf8"));
|
|
2333
|
+
});
|
|
2334
|
+
child.stdin.on("error", () => {
|
|
2335
|
+
});
|
|
2336
|
+
child.stdin.end(options.input);
|
|
2337
|
+
});
|
|
2338
|
+
}
|
|
2339
|
+
async function setupVercelApi(cwd, endpoint, body, method, options) {
|
|
2340
|
+
const args = ["api", endpoint, "--raw"];
|
|
2341
|
+
if (body !== void 0)
|
|
2342
|
+
args.push("--method", method ?? "POST", "--input", "-");
|
|
2343
|
+
else if (method)
|
|
2344
|
+
args.push("--method", method);
|
|
2345
|
+
let output = "";
|
|
2346
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
2347
|
+
const remaining = (options?.deadline ?? Date.now() + 3e4) - Date.now();
|
|
2348
|
+
if (remaining <= 0)
|
|
2349
|
+
throw new SetupFailure("provider_deadline_exceeded", "The provider deadline expired; inspect the recorded operation before continuing.");
|
|
2350
|
+
try {
|
|
2351
|
+
output = await setupProcess("vercel", args, {
|
|
2352
|
+
cwd,
|
|
2353
|
+
timeoutMs: Math.min(3e4, remaining),
|
|
2354
|
+
...body === void 0 ? {} : { input: JSON.stringify(body) }
|
|
2355
|
+
});
|
|
2356
|
+
break;
|
|
2357
|
+
} catch (error) {
|
|
2358
|
+
if (!(error instanceof SetupFailure) || error.code !== "provider_transport_failed" || attempt === 2)
|
|
2359
|
+
throw error;
|
|
2360
|
+
await new Promise((resolve5) => setTimeout(resolve5, Math.min(1e3 * 2 ** attempt, Math.max(0, (options?.deadline ?? Date.now() + 2e3) - Date.now()))));
|
|
2361
|
+
}
|
|
2362
|
+
}
|
|
2363
|
+
try {
|
|
2364
|
+
return JSON.parse(output);
|
|
2365
|
+
} catch {
|
|
2366
|
+
throw new SetupFailure("invalid_provider_response", "Vercel did not return valid JSON for the bound project.");
|
|
2367
|
+
}
|
|
2368
|
+
}
|
|
2369
|
+
|
|
2370
|
+
// ../cli/dist/commands/setup-preflight.js
|
|
2371
|
+
var manifestSchema = z28.object({
|
|
2372
|
+
packageManager: z28.string().optional(),
|
|
2373
|
+
engines: z28.object({ node: z28.string().optional() }).optional(),
|
|
2374
|
+
dependencies: z28.record(z28.string(), z28.string()).optional(),
|
|
2375
|
+
devDependencies: z28.record(z28.string(), z28.string()).optional(),
|
|
2376
|
+
scripts: z28.record(z28.string(), z28.string()).optional(),
|
|
2377
|
+
workspaces: z28.unknown().optional()
|
|
2378
|
+
});
|
|
2379
|
+
var vercelProjectSchema = z28.object({
|
|
2380
|
+
id: z28.string(),
|
|
2381
|
+
accountId: z28.string(),
|
|
2382
|
+
name: z28.string(),
|
|
2383
|
+
nodeVersion: z28.string().nullable().optional(),
|
|
2384
|
+
rootDirectory: z28.string().nullable().optional(),
|
|
2385
|
+
framework: z28.string().nullable().optional(),
|
|
2386
|
+
installCommand: z28.string().nullable().optional(),
|
|
2387
|
+
buildCommand: z28.string().nullable().optional(),
|
|
2388
|
+
link: z28.object({
|
|
2389
|
+
type: z28.string(),
|
|
2390
|
+
repo: z28.string().optional(),
|
|
2391
|
+
repoId: z28.union([z28.string(), z28.number()]).optional(),
|
|
2392
|
+
org: z28.string().optional(),
|
|
2393
|
+
productionBranch: z28.string().optional()
|
|
2394
|
+
}).nullable().optional()
|
|
2395
|
+
});
|
|
2396
|
+
var exists = async (path) => access2(path).then(() => true, () => false);
|
|
2397
|
+
var fail = (code, message) => {
|
|
2398
|
+
throw new SetupFailure(code, message);
|
|
2399
|
+
};
|
|
2400
|
+
var stable = (version2, major) => new RegExp(`^${major}\\.\\d+\\.\\d+$`, "u").test(version2);
|
|
2401
|
+
async function inspectSetupLocalProject(projectDir) {
|
|
2402
|
+
const projectDirectory = await realpath(resolve(projectDir));
|
|
2403
|
+
const manifest = manifestSchema.parse(JSON.parse(await readFile8(join6(projectDirectory, "package.json"), "utf8")));
|
|
2404
|
+
const apps = (await Promise.all(["app", "src/app"].map(async (path) => await exists(join6(projectDirectory, path)) ? path : null))).filter((path) => path !== null);
|
|
2405
|
+
if (apps.length !== 1)
|
|
2406
|
+
fail("ambiguous_app_directory", "Select one Next.js App Router application with exactly one app/ or src/app/ directory.");
|
|
2407
|
+
const repositoryRoot = (await setupProcess("git", ["rev-parse", "--show-toplevel"], {
|
|
2408
|
+
cwd: projectDirectory
|
|
2409
|
+
})).trim();
|
|
2410
|
+
const tracked = await setupProcess("git", ["ls-files", "--stage", "-z"], {
|
|
2411
|
+
cwd: repositoryRoot
|
|
2412
|
+
});
|
|
2413
|
+
for (const entry of tracked.split("\0").filter(Boolean)) {
|
|
2414
|
+
if (entry.startsWith("160000 "))
|
|
2415
|
+
fail("git_submodule_conflict", "The repository contains Git submodules. Resolve the explicit deployment source boundary before setup; the CLI will not copy external repositories.");
|
|
2416
|
+
if (!entry.startsWith("120000 "))
|
|
2417
|
+
continue;
|
|
2418
|
+
const path = join6(repositoryRoot, entry.slice(entry.indexOf(" ") + 1));
|
|
2419
|
+
const target = resolve(dirname6(path), await readlink(path));
|
|
2420
|
+
const bound = relative2(repositoryRoot, target);
|
|
2421
|
+
if (bound.startsWith("..") || bound.startsWith(sep))
|
|
2422
|
+
fail("external_symlink_conflict", "A tracked symbolic link points outside this repository. Resolve that source boundary before setup; local external files cannot enter a deployment.");
|
|
2423
|
+
}
|
|
2424
|
+
let lockfileRoot = projectDirectory;
|
|
2425
|
+
const lockNames = [
|
|
2426
|
+
"package-lock.json",
|
|
2427
|
+
"npm-shrinkwrap.json",
|
|
2428
|
+
"pnpm-lock.yaml",
|
|
2429
|
+
"yarn.lock",
|
|
2430
|
+
"bun.lock",
|
|
2431
|
+
"bun.lockb"
|
|
2432
|
+
];
|
|
2433
|
+
let locks = [];
|
|
2434
|
+
for (; ; ) {
|
|
2435
|
+
locks = (await Promise.all(lockNames.map(async (name3) => await exists(join6(lockfileRoot, name3)) ? name3 : null))).filter((name3) => name3 !== null);
|
|
2436
|
+
if (locks.length || lockfileRoot === repositoryRoot || dirname6(lockfileRoot) === lockfileRoot)
|
|
2437
|
+
break;
|
|
2438
|
+
lockfileRoot = dirname6(lockfileRoot);
|
|
2439
|
+
}
|
|
2440
|
+
if (locks.length > 1)
|
|
2441
|
+
fail("conflicting_lockfiles", "Resolve conflicting package-manager lockfiles before setup; Siteplane does not replace them.");
|
|
2442
|
+
if (!locks.length)
|
|
2443
|
+
fail("lockfile_missing", "Install the existing application with its chosen package manager to create one canonical lockfile.");
|
|
2444
|
+
const lockName = locks[0];
|
|
2445
|
+
if (!["package-lock.json", "pnpm-lock.yaml"].includes(lockName))
|
|
2446
|
+
fail("unsupported_package_manager", "This setup supports npm 10 or pnpm 9/10 with their canonical lockfile.");
|
|
2447
|
+
const rootManifest = manifestSchema.parse(JSON.parse(await readFile8(join6(lockfileRoot, "package.json"), "utf8")));
|
|
2448
|
+
if (lockfileRoot !== projectDirectory) {
|
|
2449
|
+
const workspaceFile = join6(lockfileRoot, "pnpm-workspace.yaml");
|
|
2450
|
+
const workspace = lockName === "pnpm-lock.yaml" && await exists(workspaceFile) ? z28.object({ packages: z28.array(z28.string()) }).parse(parseYaml(await readFile8(workspaceFile, "utf8"))).packages : z28.union([
|
|
2451
|
+
z28.array(z28.string()),
|
|
2452
|
+
z28.object({ packages: z28.array(z28.string()) }).transform((value) => value.packages)
|
|
2453
|
+
]).parse(rootManifest.workspaces);
|
|
2454
|
+
const selected = relative2(lockfileRoot, projectDirectory).split(sep).join("/");
|
|
2455
|
+
if (!workspace.some((pattern) => !pattern.startsWith("!") && minimatch(selected, pattern)) || workspace.some((pattern) => pattern.startsWith("!") && minimatch(selected, pattern.slice(1))))
|
|
2456
|
+
fail("unbound_workspace_app", "The selected application is excluded from the canonical lockfile's workspace packages. Select its actual application root.");
|
|
2457
|
+
}
|
|
2458
|
+
for (let ancestor = dirname6(lockfileRoot); ancestor.startsWith(repositoryRoot + sep) || ancestor === repositoryRoot; ancestor = dirname6(ancestor)) {
|
|
2459
|
+
const ancestorLocks = await Promise.all(lockNames.map((name3) => exists(join6(ancestor, name3))));
|
|
2460
|
+
if (ancestorLocks.some(Boolean))
|
|
2461
|
+
fail("ambiguous_lockfile_root", "Both the selected package and its repository ancestors contain lockfiles. Select one canonical workspace resolution before setup.");
|
|
2462
|
+
if (ancestor === repositoryRoot)
|
|
2463
|
+
break;
|
|
2464
|
+
}
|
|
2465
|
+
const lockText = await readFile8(join6(lockfileRoot, lockName), "utf8");
|
|
2466
|
+
const npmLock = lockName === "package-lock.json" ? z28.object({
|
|
2467
|
+
lockfileVersion: z28.number(),
|
|
2468
|
+
packages: z28.record(z28.string(), z28.object({
|
|
2469
|
+
version: z28.string().optional(),
|
|
2470
|
+
peerDependencies: z28.record(z28.string(), z28.string()).optional()
|
|
2471
|
+
})).optional()
|
|
2472
|
+
}).parse(JSON.parse(lockText)) : null;
|
|
2473
|
+
async function version2(name3) {
|
|
2474
|
+
try {
|
|
2475
|
+
return (await readInstalledPackage(projectDirectory, name3)).version;
|
|
2476
|
+
} catch {
|
|
2477
|
+
const resolved = npmLock?.packages?.[`node_modules/${name3}`]?.version;
|
|
2478
|
+
if (resolved)
|
|
2479
|
+
return resolved;
|
|
2480
|
+
return fail("dependencies_not_installed", `Install the existing ${name3} dependency using the canonical lockfile before setup.`);
|
|
2481
|
+
}
|
|
2482
|
+
}
|
|
2483
|
+
const [nextVersion, reactVersion, reactDomVersion] = await Promise.all([
|
|
2484
|
+
version2("next"),
|
|
2485
|
+
version2("react"),
|
|
2486
|
+
version2("react-dom")
|
|
2487
|
+
]);
|
|
2488
|
+
if (!stable(nextVersion, 16))
|
|
2489
|
+
fail("unsupported_next_version", "Setup supports stable Next.js 16 App Router projects. Framework migration requires a separate owner decision.");
|
|
2490
|
+
if (!stable(reactVersion, 19) || reactDomVersion !== reactVersion)
|
|
2491
|
+
fail("react_version_conflict", "Use the same stable React 19/react-dom version compatible with the installed Next.js peers.");
|
|
2492
|
+
if (!stable(process.versions.node, 22))
|
|
2493
|
+
fail("unsupported_node_version", "Run setup under Node.js 22; this does not change your framework or package-manager versions.");
|
|
2494
|
+
const nextMetadata = await readInstalledPackage(projectDirectory, "next").catch(() => npmLock?.packages?.["node_modules/next"] ?? null);
|
|
2495
|
+
const peers = nextMetadata?.peerDependencies;
|
|
2496
|
+
if (!peers?.react || !peers["react-dom"])
|
|
2497
|
+
fail("next_peer_metadata_missing", "Install the locked Next.js dependency before setup so its actual React peer requirements can be checked.");
|
|
2498
|
+
if (!semver.satisfies(reactVersion, peers.react) || !semver.satisfies(reactDomVersion, peers["react-dom"]))
|
|
2499
|
+
fail("react_peer_conflict", "The installed React pair does not satisfy the installed Next.js peer requirements. Choose a compatible pair explicitly.");
|
|
2500
|
+
if (manifest.engines?.node && !semver.satisfies(process.versions.node, manifest.engines.node))
|
|
2501
|
+
fail("node_engine_conflict", "The selected application's Node engine declaration excludes the active supported Node.js 22 runtime.");
|
|
2502
|
+
const name2 = lockName === "package-lock.json" ? "npm" : "pnpm";
|
|
2503
|
+
const declared = rootManifest.packageManager ?? manifest.packageManager ?? null;
|
|
2504
|
+
if (rootManifest.packageManager && manifest.packageManager && rootManifest.packageManager !== manifest.packageManager)
|
|
2505
|
+
fail("package_manager_conflict", "Application and workspace packageManager declarations disagree.");
|
|
2506
|
+
if (declared && !new RegExp(`^${name2}@\\d+\\.\\d+\\.\\d+$`, "u").test(declared))
|
|
2507
|
+
fail("package_manager_conflict", "Declare an exact supported npm/pnpm packageManager version matching the canonical lockfile.");
|
|
2508
|
+
const localVersion = (await setupProcess(declared ? "npx" : name2, declared ? ["--yes", declared, "--version"] : ["--version"], { cwd: lockfileRoot })).trim();
|
|
2509
|
+
if (!(name2 === "npm" ? stable(localVersion, 10) : stable(localVersion, 9) || stable(localVersion, 10)))
|
|
2510
|
+
fail("unsupported_package_manager_version", "Use npm 10 or pnpm 9/10; other versions are outside the initial setup support range.");
|
|
2511
|
+
if (declared && declared !== `${name2}@${localVersion}`)
|
|
2512
|
+
fail("package_manager_conflict", "The actual local package-manager version differs from the project's exact packageManager declaration. Select the declared tool without rewriting the lockfile.");
|
|
2513
|
+
const format = npmLock ? String(npmLock.lockfileVersion) : /^lockfileVersion:\s*['"]?([\d.]+)/mu.exec(lockText)?.[1];
|
|
2514
|
+
if (name2 === "npm" && format !== "3" || name2 === "pnpm" && format !== "9.0" && format !== "9")
|
|
2515
|
+
fail("lockfile_format_conflict", "The canonical lockfile format does not match npm 10 or pnpm 9/10.");
|
|
2516
|
+
const sourceConflicts = [];
|
|
2517
|
+
for (const file of ["next.config.js", "next.config.mjs", "next.config.ts"]) {
|
|
2518
|
+
if (!await exists(join6(projectDirectory, file)))
|
|
2519
|
+
continue;
|
|
2520
|
+
const source = await readFile8(join6(projectDirectory, file), "utf8");
|
|
2521
|
+
if (/output\s*:\s*['"]export['"]/u.test(source))
|
|
2522
|
+
sourceConflicts.push("static_export");
|
|
2523
|
+
if (/\bbasePath\s*:/u.test(source))
|
|
2524
|
+
sourceConflicts.push("base_path");
|
|
2525
|
+
}
|
|
2526
|
+
if (sourceConflicts.length)
|
|
2527
|
+
fail("unsupported_server_configuration", "Resolve static export/basePath configuration explicitly; Siteplane requires its server-side admin and revalidation handlers.");
|
|
2528
|
+
for (const name3 of [
|
|
2529
|
+
"middleware.ts",
|
|
2530
|
+
"middleware.js",
|
|
2531
|
+
"proxy.ts",
|
|
2532
|
+
"proxy.js",
|
|
2533
|
+
"src/middleware.ts",
|
|
2534
|
+
"src/middleware.js",
|
|
2535
|
+
"src/proxy.ts",
|
|
2536
|
+
"src/proxy.js"
|
|
2537
|
+
]) {
|
|
2538
|
+
if (await exists(join6(projectDirectory, name3)))
|
|
2539
|
+
sourceConflicts.push(`inspect_routing:${name3}`);
|
|
2540
|
+
}
|
|
2541
|
+
async function inspectSource(directory) {
|
|
2542
|
+
for (const entry of await readdir(directory, { withFileTypes: true })) {
|
|
2543
|
+
if (entry.isSymbolicLink() || ["node_modules", ".git", ".next", ".siteplane", ".vercel"].includes(entry.name))
|
|
2544
|
+
continue;
|
|
2545
|
+
const path = join6(directory, entry.name);
|
|
2546
|
+
if (entry.isDirectory()) {
|
|
2547
|
+
await inspectSource(path);
|
|
2548
|
+
continue;
|
|
2549
|
+
}
|
|
2550
|
+
if (!/\.[cm]?[jt]sx?$/u.test(entry.name))
|
|
2551
|
+
continue;
|
|
2552
|
+
const source = await readFile8(path, "utf8");
|
|
2553
|
+
if (/from\s*["']next\/image["']/u.test(source))
|
|
2554
|
+
sourceConflicts.push(`inspect_image_policy:${relative2(projectDirectory, path)}`);
|
|
2555
|
+
if (/\b(?:Cookiebot|OneTrust|cookieyes|consentManager|cookieConsent)\b/iu.test(source))
|
|
2556
|
+
sourceConflicts.push(`inspect_existing_consent:${relative2(projectDirectory, path)}`);
|
|
2557
|
+
if (/from\s*["']next\/image["']/u.test(source) && semver.lt(nextVersion, "16.3.3"))
|
|
2558
|
+
fail("next_security_advisory", `Next.js ${nextVersion} uses image optimization affected by the August 2026 AVIF advisory. Review https://nextjs.org/blog/august-2026-security-release and explicitly update the affected dependency before setup; no framework upgrade was performed.`);
|
|
2559
|
+
if (/["']use server["']/u.test(source) && semver.lt(nextVersion, "16.2.11"))
|
|
2560
|
+
fail("next_security_advisory", `Next.js ${nextVersion} contains Server Actions affected by the July 2026 advisory. Review https://nextjs.org/blog/july-2026-security-release and explicitly update the affected dependency before setup.`);
|
|
2561
|
+
}
|
|
2562
|
+
}
|
|
2563
|
+
await inspectSource(join6(projectDirectory, apps[0]));
|
|
2564
|
+
const gitRead = async (args) => setupProcess("git", args, { cwd: projectDirectory }).then((value) => value.trim(), () => null);
|
|
2565
|
+
return {
|
|
2566
|
+
projectDirectory,
|
|
2567
|
+
repositoryRoot,
|
|
2568
|
+
lockfileRoot,
|
|
2569
|
+
appDirectory: apps[0],
|
|
2570
|
+
nextVersion,
|
|
2571
|
+
reactVersion,
|
|
2572
|
+
nodeVersion: process.versions.node,
|
|
2573
|
+
packageManager: { name: name2, version: localVersion, declared },
|
|
2574
|
+
lockfile: {
|
|
2575
|
+
path: relative2(repositoryRoot, join6(lockfileRoot, lockName)),
|
|
2576
|
+
format,
|
|
2577
|
+
sha256: createHash2("sha256").update(lockText).digest("hex")
|
|
2578
|
+
},
|
|
2579
|
+
git: {
|
|
2580
|
+
branch: await gitRead(["branch", "--show-current"]),
|
|
2581
|
+
revision: await gitRead(["rev-parse", "HEAD"]),
|
|
2582
|
+
remote: safeGitRemote(await gitRead(["remote", "get-url", "origin"])),
|
|
2583
|
+
changes: (await gitRead(["status", "--porcelain=v1", "--untracked-files=all"]))?.split("\n").filter(Boolean) ?? []
|
|
2584
|
+
},
|
|
2585
|
+
sourceConflicts
|
|
2586
|
+
};
|
|
2587
|
+
}
|
|
2588
|
+
async function setupPreflightCommand(input) {
|
|
2589
|
+
let local;
|
|
2590
|
+
try {
|
|
2591
|
+
local = await inspectSetupLocalProject(input.projectDir);
|
|
2592
|
+
await assertLocalCredentialsPathSafe(input.projectDir);
|
|
2593
|
+
let linkDirectory = local.projectDirectory;
|
|
2594
|
+
while (!await exists(join6(linkDirectory, ".vercel/project.json")) && linkDirectory !== local.repositoryRoot && dirname6(linkDirectory) !== linkDirectory)
|
|
2595
|
+
linkDirectory = dirname6(linkDirectory);
|
|
2596
|
+
if (!await exists(join6(linkDirectory, ".vercel/project.json")))
|
|
2597
|
+
fail("vercel_project_not_linked", "Link this application to its intended Vercel project before setup; Siteplane will not guess a target.");
|
|
2598
|
+
const linked = z28.object({
|
|
2599
|
+
projectId: z28.string().regex(/^prj_[A-Za-z0-9]+$/u),
|
|
2600
|
+
orgId: z28.string().regex(/^(?:team|user)_[A-Za-z0-9]+$/u)
|
|
2601
|
+
}).parse(JSON.parse(await readFile8(join6(linkDirectory, ".vercel/project.json"), "utf8")));
|
|
2602
|
+
const project = vercelProjectSchema.parse(await setupVercelApi(linkDirectory, `/v9/projects/${linked.projectId}?teamId=${linked.orgId}`));
|
|
2603
|
+
if (project.id !== linked.projectId || project.accountId !== linked.orgId)
|
|
2604
|
+
fail("vercel_identity_conflict", "The provider project does not match the locally linked project and team.");
|
|
2605
|
+
const expectedRoot = relative2(local.repositoryRoot, local.projectDirectory).split(sep).join("/");
|
|
2606
|
+
if ((project.rootDirectory ?? "") !== expectedRoot)
|
|
2607
|
+
fail("vercel_root_conflict", "Vercel Root Directory and the selected local app must identify the same application.");
|
|
2608
|
+
if (project.nodeVersion !== "22.x" || project.framework !== "nextjs")
|
|
2609
|
+
fail("vercel_framework_conflict", "The bound Vercel project must use Next.js with Node.js 22 before setup.");
|
|
2610
|
+
if (project.link && project.link.productionBranch !== local.git.branch)
|
|
2611
|
+
fail("vercel_production_branch_conflict", "The local branch differs from the bound Vercel Production branch.");
|
|
2612
|
+
if (project.link?.repo && project.link.org && !local.git.remote?.replace(/\.git$/u, "").endsWith(`${project.link.org}/${project.link.repo}`))
|
|
2613
|
+
fail("vercel_git_conflict", "The local origin repository differs from the Vercel Git connection.");
|
|
2614
|
+
const env = z28.object({
|
|
2615
|
+
envs: z28.array(z28.object({
|
|
2616
|
+
key: z28.string(),
|
|
2617
|
+
value: z28.string().optional(),
|
|
2618
|
+
target: z28.array(z28.string()).optional()
|
|
2619
|
+
}))
|
|
2620
|
+
}).parse(await setupVercelApi(linkDirectory, `/v10/projects/${linked.projectId}/env?teamId=${linked.orgId}`));
|
|
2621
|
+
const corepack = env.envs.some((item) => item.key === "ENABLE_EXPERIMENTAL_COREPACK" && item.value === "1" && item.target?.includes("production"));
|
|
2622
|
+
const install = project.installCommand ?? null;
|
|
2623
|
+
const selected = corepack ? "corepack" : install ? "install_override" : "automatic";
|
|
2624
|
+
if (local.packageManager.declared && selected === "automatic")
|
|
2625
|
+
fail("vercel_package_manager_pin_unconfirmed", "This project declares an exact packageManager but Vercel automatic selection does not bind that version. Enable its supported Corepack selection or set an exact install AND build override in the existing project, then rerun preflight. No package, lockfile or provider setting was changed.");
|
|
2626
|
+
if (install && /\b(?:yarn|bun)\b/u.test(install))
|
|
2627
|
+
fail("vercel_package_manager_conflict", "The Vercel install override selects an unsupported package manager.");
|
|
2628
|
+
const overridePin = install ? /\b(npm|pnpm)@(\d+\.\d+\.\d+)\b/u.exec(install) : null;
|
|
2629
|
+
if (overridePin && overridePin[1] !== local.packageManager.name)
|
|
2630
|
+
fail("vercel_package_manager_conflict", "The provider override selects a different package manager than the canonical lockfile.");
|
|
2631
|
+
const overrideFamily = install ? /(?:^|[;&|]\s*)(npm|pnpm)\s+(?:ci|install)\b/u.exec(install)?.[1] : null;
|
|
2632
|
+
if (overrideFamily && overrideFamily !== local.packageManager.name)
|
|
2633
|
+
fail("vercel_package_manager_conflict", "The provider install command conflicts with the canonical lockfile.");
|
|
2634
|
+
if (overridePin && local.packageManager.declared && `${overridePin[1]}@${overridePin[2]}` !== local.packageManager.declared)
|
|
2635
|
+
fail("vercel_package_manager_conflict", "The Vercel install override conflicts with the exact packageManager declaration.");
|
|
2636
|
+
return {
|
|
2637
|
+
status: "ready",
|
|
2638
|
+
local,
|
|
2639
|
+
provider: {
|
|
2640
|
+
projectId: project.id,
|
|
2641
|
+
teamId: project.accountId,
|
|
2642
|
+
name: project.name,
|
|
2643
|
+
rootDirectory: expectedRoot,
|
|
2644
|
+
nodeVersion: project.nodeVersion,
|
|
2645
|
+
git: project.link,
|
|
2646
|
+
installCommand: install,
|
|
2647
|
+
buildCommand: project.buildCommand ?? null,
|
|
2648
|
+
packageManagerSelection: selected,
|
|
2649
|
+
declaredPackageManager: local.packageManager.declared,
|
|
2650
|
+
observedPackageManager: null
|
|
2651
|
+
}
|
|
2652
|
+
};
|
|
2653
|
+
} catch (error) {
|
|
2654
|
+
return {
|
|
2655
|
+
status: "action_required",
|
|
2656
|
+
code: error instanceof SetupFailure ? error.code : "invalid_local_project",
|
|
2657
|
+
message: error instanceof SetupFailure ? error.message : "The selected project or provider response could not be validated. Check the application manifest and local project access.",
|
|
2658
|
+
...local ? { local } : {}
|
|
2659
|
+
};
|
|
2660
|
+
}
|
|
2661
|
+
}
|
|
2662
|
+
function safeGitRemote(value) {
|
|
2663
|
+
if (!value)
|
|
2664
|
+
return null;
|
|
2665
|
+
if (!value.includes("://"))
|
|
2666
|
+
return value;
|
|
2667
|
+
try {
|
|
2668
|
+
const url = new URL(value);
|
|
2669
|
+
url.username = "";
|
|
2670
|
+
url.password = "";
|
|
2671
|
+
url.search = "";
|
|
2672
|
+
url.hash = "";
|
|
2673
|
+
return url.toString().replace(/\/$/u, "");
|
|
2674
|
+
} catch {
|
|
2675
|
+
return null;
|
|
2676
|
+
}
|
|
2677
|
+
}
|
|
2678
|
+
|
|
2679
|
+
// ../cli/dist/commands/init.js
|
|
2680
|
+
var siteSetupBootstrapDataSchema = z29.object({
|
|
2681
|
+
credentialPurpose: z29.literal("site_setup"),
|
|
2682
|
+
apiBaseUrl: z29.string().url(),
|
|
2683
|
+
siteId: z29.string().uuid(),
|
|
2684
|
+
publicSiteKeyId: z29.string().uuid(),
|
|
2685
|
+
publicSiteKey: z29.string().trim().min(1),
|
|
2686
|
+
accessToken: z29.string().trim().min(1),
|
|
2687
|
+
siteRevalidationSecret: z29.string().regex(/^[A-Za-z0-9_-]{43}$/u),
|
|
2688
|
+
runId: z29.string().uuid(),
|
|
2689
|
+
packages: z29.object({
|
|
2690
|
+
siteplane: z29.string().regex(/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/u),
|
|
2691
|
+
runtimeNext: z29.string().regex(/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/u)
|
|
2692
|
+
}).strict()
|
|
2127
2693
|
}).strict();
|
|
2128
|
-
var featureBootstrapDataSchema =
|
|
2129
|
-
credentialPurpose:
|
|
2130
|
-
apiBaseUrl:
|
|
2131
|
-
siteId:
|
|
2132
|
-
accessToken:
|
|
2694
|
+
var featureBootstrapDataSchema = z29.object({
|
|
2695
|
+
credentialPurpose: z29.enum(["analytics", "booking"]),
|
|
2696
|
+
apiBaseUrl: z29.string().url(),
|
|
2697
|
+
siteId: z29.string().uuid(),
|
|
2698
|
+
accessToken: z29.string().trim().min(1)
|
|
2133
2699
|
}).strict();
|
|
2134
|
-
var bootstrapResponseSchema =
|
|
2135
|
-
ok:
|
|
2136
|
-
data:
|
|
2700
|
+
var bootstrapResponseSchema = z29.object({
|
|
2701
|
+
ok: z29.literal(true),
|
|
2702
|
+
data: z29.discriminatedUnion("credentialPurpose", [
|
|
2137
2703
|
siteSetupBootstrapDataSchema,
|
|
2138
2704
|
featureBootstrapDataSchema
|
|
2139
2705
|
])
|
|
2140
2706
|
}).strict();
|
|
2141
2707
|
|
|
2142
2708
|
// ../cli/dist/commands/scan.js
|
|
2143
|
-
import { readdir } from "fs/promises";
|
|
2144
|
-
import { extname, join as
|
|
2709
|
+
import { readdir as readdir2 } from "fs/promises";
|
|
2710
|
+
import { extname, join as join8 } from "path";
|
|
2145
2711
|
var defaultScanRoots = ["app", "src", "pages", "components", "lib"];
|
|
2146
2712
|
var excludedDirectories = /* @__PURE__ */ new Set([
|
|
2147
2713
|
".git",
|
|
@@ -2159,14 +2725,14 @@ async function resolveScanFilePaths(filePaths, options = {}) {
|
|
|
2159
2725
|
return filePaths;
|
|
2160
2726
|
}
|
|
2161
2727
|
const projectDir = options.projectDir ?? process.cwd();
|
|
2162
|
-
const discovered = await Promise.all(defaultScanRoots.map((root) => collectSourceFiles(
|
|
2728
|
+
const discovered = await Promise.all(defaultScanRoots.map((root) => collectSourceFiles(join8(projectDir, root))));
|
|
2163
2729
|
return [...new Set(discovered.flat())].sort();
|
|
2164
2730
|
}
|
|
2165
2731
|
async function collectSourceFiles(directory) {
|
|
2166
|
-
const entries = await
|
|
2732
|
+
const entries = await readdir2(directory, { withFileTypes: true }).catch(() => []);
|
|
2167
2733
|
const files = [];
|
|
2168
2734
|
for (const entry of entries) {
|
|
2169
|
-
const entryPath =
|
|
2735
|
+
const entryPath = join8(directory, entry.name);
|
|
2170
2736
|
if (entry.isDirectory()) {
|
|
2171
2737
|
if (!excludedDirectories.has(entry.name)) {
|
|
2172
2738
|
files.push(...await collectSourceFiles(entryPath));
|
|
@@ -2182,17 +2748,17 @@ async function collectSourceFiles(directory) {
|
|
|
2182
2748
|
|
|
2183
2749
|
// ../cli/dist/commands/site-setup.js
|
|
2184
2750
|
import { execFile as execFile2 } from "child_process";
|
|
2185
|
-
import { readFile as
|
|
2751
|
+
import { readFile as readFile9 } from "fs/promises";
|
|
2186
2752
|
import { promisify as promisify2 } from "util";
|
|
2187
|
-
import { z as
|
|
2753
|
+
import { z as z30 } from "zod";
|
|
2188
2754
|
|
|
2189
2755
|
// ../cli/dist/scan/next-source-scan.js
|
|
2190
2756
|
import ts2 from "typescript";
|
|
2191
|
-
import { isAbsolute, relative as
|
|
2757
|
+
import { isAbsolute, relative as relative4 } from "path";
|
|
2192
2758
|
var eventPreviewHandlerMissingMessage = "Event preview fields must consume preview values with useSiteplanePreviewText from @siteplane/runtime-next/client or a siteplane:preview-value-applied listener.";
|
|
2193
2759
|
var valueCallUnusedMessage = "Siteplane value calls must feed rendered content. Assign or await the returned value and render that value instead of ignoring the call.";
|
|
2194
2760
|
var legacyEditableComponentPrefix = "Editable";
|
|
2195
|
-
var editableComponentNames = new Set(["Image", "Text", "LongText", "Link"].map((
|
|
2761
|
+
var editableComponentNames = new Set(["Image", "Text", "LongText", "Link"].map((name2) => `${legacyEditableComponentPrefix}${name2}`));
|
|
2196
2762
|
var functionTypeByName = {
|
|
2197
2763
|
text: "text",
|
|
2198
2764
|
longText: "longText",
|
|
@@ -2730,17 +3296,17 @@ function readObjectLiteral(expression) {
|
|
|
2730
3296
|
if (!ts2.isPropertyAssignment(property)) {
|
|
2731
3297
|
continue;
|
|
2732
3298
|
}
|
|
2733
|
-
const
|
|
2734
|
-
if (!
|
|
3299
|
+
const name2 = getPropertyName(property.name);
|
|
3300
|
+
if (!name2) {
|
|
2735
3301
|
continue;
|
|
2736
3302
|
}
|
|
2737
|
-
value[
|
|
3303
|
+
value[name2] = staticExpressionValue(property.initializer);
|
|
2738
3304
|
}
|
|
2739
3305
|
return value;
|
|
2740
3306
|
}
|
|
2741
|
-
function getPropertyName(
|
|
2742
|
-
if (ts2.isIdentifier(
|
|
2743
|
-
return
|
|
3307
|
+
function getPropertyName(name2) {
|
|
3308
|
+
if (ts2.isIdentifier(name2) || ts2.isStringLiteral(name2)) {
|
|
3309
|
+
return name2.text;
|
|
2744
3310
|
}
|
|
2745
3311
|
return null;
|
|
2746
3312
|
}
|
|
@@ -2766,9 +3332,9 @@ function collectEventPreviewComponentPropUsages(node, eventPreviewAttrVariables,
|
|
|
2766
3332
|
});
|
|
2767
3333
|
}
|
|
2768
3334
|
}
|
|
2769
|
-
function getJsxAttributeName(
|
|
2770
|
-
if (ts2.isIdentifier(
|
|
2771
|
-
return
|
|
3335
|
+
function getJsxAttributeName(name2) {
|
|
3336
|
+
if (ts2.isIdentifier(name2)) {
|
|
3337
|
+
return name2.text;
|
|
2772
3338
|
}
|
|
2773
3339
|
return void 0;
|
|
2774
3340
|
}
|
|
@@ -2793,8 +3359,8 @@ function getFunctionComponentName(node) {
|
|
|
2793
3359
|
}
|
|
2794
3360
|
return void 0;
|
|
2795
3361
|
}
|
|
2796
|
-
function isComponentName(
|
|
2797
|
-
return /^[A-Z]/.test(
|
|
3362
|
+
function isComponentName(name2) {
|
|
3363
|
+
return /^[A-Z]/.test(name2);
|
|
2798
3364
|
}
|
|
2799
3365
|
function getAssignedVariableName(node) {
|
|
2800
3366
|
let current = node;
|
|
@@ -2842,7 +3408,7 @@ function inferRouteHint(filePath) {
|
|
|
2842
3408
|
return route ? `/${route}` : "/";
|
|
2843
3409
|
}
|
|
2844
3410
|
function toRepositoryRelativePosixPath(filePath, projectRoot) {
|
|
2845
|
-
const path = isAbsolute(filePath) ?
|
|
3411
|
+
const path = isAbsolute(filePath) ? relative4(projectRoot, filePath) : filePath;
|
|
2846
3412
|
return path.replaceAll("\\", "/");
|
|
2847
3413
|
}
|
|
2848
3414
|
function isPositionalFieldReference(value) {
|
|
@@ -2851,30 +3417,354 @@ function isPositionalFieldReference(value) {
|
|
|
2851
3417
|
|
|
2852
3418
|
// ../cli/dist/commands/site-setup.js
|
|
2853
3419
|
var execFileAsync2 = promisify2(execFile2);
|
|
2854
|
-
var safeErrorSchema =
|
|
2855
|
-
code:
|
|
2856
|
-
message:
|
|
3420
|
+
var safeErrorSchema = z30.object({
|
|
3421
|
+
code: z30.string().trim().min(1),
|
|
3422
|
+
message: z30.string().trim().min(1)
|
|
2857
3423
|
}).passthrough();
|
|
2858
|
-
var errorResponseSchema2 =
|
|
2859
|
-
var contextDataSchema =
|
|
2860
|
-
var contextResponseSchema =
|
|
2861
|
-
var applyDataSchema =
|
|
2862
|
-
status:
|
|
2863
|
-
runId:
|
|
2864
|
-
contractVersionId:
|
|
2865
|
-
fieldContractHash:
|
|
2866
|
-
editorDefinitionHash:
|
|
2867
|
-
fieldCount:
|
|
2868
|
-
routeCount:
|
|
3424
|
+
var errorResponseSchema2 = z30.object({ ok: z30.literal(false), error: safeErrorSchema }).passthrough();
|
|
3425
|
+
var contextDataSchema = z30.object({ task: siteSetupTaskSchema }).strict();
|
|
3426
|
+
var contextResponseSchema = z30.object({ ok: z30.literal(true), data: contextDataSchema }).strict();
|
|
3427
|
+
var applyDataSchema = z30.object({
|
|
3428
|
+
status: z30.enum(["applied", "ready_for_review"]),
|
|
3429
|
+
runId: z30.string().uuid().optional(),
|
|
3430
|
+
contractVersionId: z30.string().uuid().optional(),
|
|
3431
|
+
fieldContractHash: z30.string().regex(/^sha256:[0-9a-f]{64}$/u),
|
|
3432
|
+
editorDefinitionHash: z30.string().regex(/^sha256:[0-9a-f]{64}$/u).optional(),
|
|
3433
|
+
fieldCount: z30.number().int().nonnegative().optional(),
|
|
3434
|
+
routeCount: z30.number().int().nonnegative().optional()
|
|
2869
3435
|
}).strict();
|
|
2870
|
-
var applyResponseSchema =
|
|
2871
|
-
var verifyDataSchema =
|
|
2872
|
-
status:
|
|
2873
|
-
runId:
|
|
2874
|
-
deploymentOrigin:
|
|
2875
|
-
deploymentRevision:
|
|
3436
|
+
var applyResponseSchema = z30.object({ ok: z30.literal(true), data: applyDataSchema }).strict();
|
|
3437
|
+
var verifyDataSchema = z30.object({
|
|
3438
|
+
status: z30.literal("ready_for_review"),
|
|
3439
|
+
runId: z30.string().uuid().optional(),
|
|
3440
|
+
deploymentOrigin: z30.string().url().optional(),
|
|
3441
|
+
deploymentRevision: z30.string().optional()
|
|
2876
3442
|
}).strict();
|
|
2877
|
-
var verifyResponseSchema =
|
|
3443
|
+
var verifyResponseSchema = z30.object({ ok: z30.literal(true), data: verifyDataSchema }).strict();
|
|
3444
|
+
async function siteSetupContextCommand(input) {
|
|
3445
|
+
const response = await postSiteSetup(input, "context", {});
|
|
3446
|
+
const parsed = contextResponseSchema.safeParse(response.payload);
|
|
3447
|
+
if (response.ok && parsed.success) {
|
|
3448
|
+
return { status: "ok", ...parsed.data.data };
|
|
3449
|
+
}
|
|
3450
|
+
return actionRequired(response.payload, "Siteplane setup context is unavailable.");
|
|
3451
|
+
}
|
|
3452
|
+
async function siteSetupVerifyCommand(input) {
|
|
3453
|
+
const resolveSourceFiles = input.resolveSourceFiles ?? resolveScanFilePaths;
|
|
3454
|
+
const readSourceFile = input.readSourceFile ?? ((path) => readFile9(path, "utf8"));
|
|
3455
|
+
const paths = await resolveSourceFiles([], { projectDir: input.projectDir });
|
|
3456
|
+
const sources = await Promise.all(paths.map(readSourceFile));
|
|
3457
|
+
if (!sources.some(hasMountedFieldRuntimeBridge)) {
|
|
3458
|
+
return {
|
|
3459
|
+
status: "action_required",
|
|
3460
|
+
code: "missing_field_runtime_bridge",
|
|
3461
|
+
message: "Mount FieldRuntimeBridge from @siteplane/runtime-next/client before deployment verification."
|
|
3462
|
+
};
|
|
3463
|
+
}
|
|
3464
|
+
const deploymentRevision = await (input.readRevision ?? readGitRevision)(input.projectDir);
|
|
3465
|
+
const response = await postSiteSetup(input, "verify", {
|
|
3466
|
+
deploymentUrl: input.deploymentUrl,
|
|
3467
|
+
deploymentRevision,
|
|
3468
|
+
...input.wait ? { wait: true } : {}
|
|
3469
|
+
});
|
|
3470
|
+
const parsed = verifyResponseSchema.safeParse(response.payload);
|
|
3471
|
+
if (response.ok && parsed.success) {
|
|
3472
|
+
return parsed.data.data;
|
|
3473
|
+
}
|
|
3474
|
+
return actionRequired(response.payload, "Siteplane deployment verification failed.");
|
|
3475
|
+
}
|
|
3476
|
+
function hasMountedFieldRuntimeBridge(source) {
|
|
3477
|
+
return /from\s+["']@siteplane\/runtime-next(?:\/client)?["']/u.test(source) && /<FieldRuntimeBridge(?:\s|\/|>)/u.test(source);
|
|
3478
|
+
}
|
|
3479
|
+
async function postSiteSetup(input, operation, body) {
|
|
3480
|
+
const [config, credentials] = await Promise.all([
|
|
3481
|
+
readProjectConfig(input.projectDir),
|
|
3482
|
+
readLocalCredentials(input.projectDir)
|
|
3483
|
+
]);
|
|
3484
|
+
try {
|
|
3485
|
+
const response = await (input.fetcher ?? fetch)(`${config.apiBaseUrl.replace(/\/$/u, "")}/api/cli/setup/${operation}`, {
|
|
3486
|
+
method: "POST",
|
|
3487
|
+
signal: AbortSignal.timeout(Math.max(1, Math.min(2e4, (input.deadline ?? Date.now() + 2e4) - Date.now()))),
|
|
3488
|
+
headers: {
|
|
3489
|
+
authorization: `Bearer ${credentials.accessToken}`,
|
|
3490
|
+
"content-type": "application/json",
|
|
3491
|
+
...input.vercelAutomationBypassSecret?.trim() ? {
|
|
3492
|
+
"x-vercel-protection-bypass": input.vercelAutomationBypassSecret.trim()
|
|
3493
|
+
} : {}
|
|
3494
|
+
},
|
|
3495
|
+
body: JSON.stringify(body)
|
|
3496
|
+
});
|
|
3497
|
+
const payload = await response.json().catch(() => null);
|
|
3498
|
+
return { ok: response.ok, payload };
|
|
3499
|
+
} catch {
|
|
3500
|
+
return {
|
|
3501
|
+
ok: false,
|
|
3502
|
+
payload: {
|
|
3503
|
+
ok: false,
|
|
3504
|
+
error: {
|
|
3505
|
+
code: "site_setup.transport_failed",
|
|
3506
|
+
message: "The setup request was not acknowledged. Reload the existing task before retrying; no credential values are included."
|
|
3507
|
+
}
|
|
3508
|
+
}
|
|
3509
|
+
};
|
|
3510
|
+
}
|
|
3511
|
+
}
|
|
3512
|
+
function actionRequired(payload, fallbackMessage) {
|
|
3513
|
+
const parsed = errorResponseSchema2.safeParse(payload);
|
|
3514
|
+
return parsed.success ? {
|
|
3515
|
+
status: "action_required",
|
|
3516
|
+
code: parsed.data.error.code,
|
|
3517
|
+
message: parsed.data.error.message
|
|
3518
|
+
} : {
|
|
3519
|
+
status: "action_required",
|
|
3520
|
+
code: "invalid_server_response",
|
|
3521
|
+
message: fallbackMessage
|
|
3522
|
+
};
|
|
3523
|
+
}
|
|
3524
|
+
async function readGitRevision(projectDir) {
|
|
3525
|
+
const { stdout } = await execFileAsync2("git", ["rev-parse", "HEAD"], {
|
|
3526
|
+
cwd: projectDir,
|
|
3527
|
+
encoding: "utf8"
|
|
3528
|
+
});
|
|
3529
|
+
const revision = stdout.trim();
|
|
3530
|
+
if (!revision) {
|
|
3531
|
+
throw new Error("A committed Git revision is required before setup verify.");
|
|
3532
|
+
}
|
|
3533
|
+
return revision;
|
|
3534
|
+
}
|
|
3535
|
+
|
|
3536
|
+
// ../cli/dist/commands/setup-prepare.js
|
|
3537
|
+
import { access as access4, lstat as lstat2, mkdir as mkdir6, open as open3, readFile as readFile10, rename as rename3, rm as rm3 } from "fs/promises";
|
|
3538
|
+
import { randomUUID as randomUUID4 } from "crypto";
|
|
3539
|
+
import { dirname as dirname7, join as join9, relative as relative5, sep as sep2 } from "path";
|
|
3540
|
+
import ts3 from "typescript";
|
|
3541
|
+
|
|
3542
|
+
// ../cli/dist/commands/setup-lock.js
|
|
3543
|
+
import { randomUUID as randomUUID5 } from "crypto";
|
|
3544
|
+
import { lstat as lstat3, mkdir as mkdir7, open as open4, readFile as readFile11, rm as rm4, rmdir } from "fs/promises";
|
|
3545
|
+
import { resolve as resolve2 } from "path";
|
|
3546
|
+
import { z as z31 } from "zod";
|
|
3547
|
+
var ownerSchema = z31.object({ pid: z31.number().int().positive(), nonce: z31.string().uuid() }).strict();
|
|
3548
|
+
|
|
3549
|
+
// ../cli/dist/config/build-provenance.js
|
|
3550
|
+
import { createHash as createHash3 } from "crypto";
|
|
3551
|
+
import { execFile as execFile3 } from "child_process";
|
|
3552
|
+
import { lstat as lstat4, readFile as readFile12, writeFile as writeFile5, mkdir as mkdir8 } from "fs/promises";
|
|
3553
|
+
import { dirname as dirname8, isAbsolute as isAbsolute2, join as join10, relative as relative6, resolve as resolve3, sep as sep3 } from "path";
|
|
3554
|
+
import { isDeepStrictEqual, promisify as promisify3 } from "util";
|
|
3555
|
+
import { z as z32 } from "zod";
|
|
3556
|
+
var execute = promisify3(execFile3);
|
|
3557
|
+
var name = ".siteplane/build-source.json";
|
|
3558
|
+
var oid = z32.string().regex(/^[0-9a-f]{40}$/u);
|
|
3559
|
+
var entrySchema = z32.object({
|
|
3560
|
+
path: z32.string().min(1).max(4096),
|
|
3561
|
+
mode: z32.enum(["100644", "100755", "120000"]),
|
|
3562
|
+
oid
|
|
3563
|
+
}).strict();
|
|
3564
|
+
var schema = z32.object({
|
|
3565
|
+
version: z32.literal(2),
|
|
3566
|
+
revision: oid,
|
|
3567
|
+
commit: z32.string().min(1).max(1048576),
|
|
3568
|
+
entries: z32.array(entrySchema).min(1).max(1e5),
|
|
3569
|
+
providerConfigurations: z32.array(z32.object({
|
|
3570
|
+
path: z32.string().max(4096).regex(/(?:^|\/)vercel\.json$/u),
|
|
3571
|
+
source: z32.string().max(1048576)
|
|
3572
|
+
}).strict()).max(1e3)
|
|
3573
|
+
}).strict();
|
|
3574
|
+
var gitHash = (type, content) => createHash3("sha1").update(`${type} ${content.length}\0`).update(content).digest("hex");
|
|
3575
|
+
async function writeBuildProvenance(checkout, revision) {
|
|
3576
|
+
const commit = (await execute("git", ["cat-file", "commit", revision], {
|
|
3577
|
+
cwd: checkout,
|
|
3578
|
+
maxBuffer: 1048576
|
|
3579
|
+
})).stdout;
|
|
3580
|
+
const tree = (await execute("git", ["ls-tree", "-rz", "--full-tree", revision], {
|
|
3581
|
+
cwd: checkout,
|
|
3582
|
+
maxBuffer: 16777216
|
|
3583
|
+
})).stdout;
|
|
3584
|
+
const entries = tree.split("\0").filter(Boolean).map((line) => {
|
|
3585
|
+
const match = /^(100644|100755|120000) blob ([0-9a-f]{40})\t([\s\S]+)$/u.exec(line);
|
|
3586
|
+
if (!match)
|
|
3587
|
+
throw new Error("Git submodules or unsupported tracked objects need an explicit deployment configuration.");
|
|
3588
|
+
return { path: match[3], mode: match[1], oid: match[2] };
|
|
3589
|
+
});
|
|
3590
|
+
for (const entry of entries) {
|
|
3591
|
+
if (entry.mode !== "120000")
|
|
3592
|
+
continue;
|
|
3593
|
+
const { readlink: readlink2 } = await import("fs/promises");
|
|
3594
|
+
const path = join10(checkout, entry.path);
|
|
3595
|
+
const target2 = resolve3(dirname8(path), await readlink2(path));
|
|
3596
|
+
const bound = relative6(checkout, target2);
|
|
3597
|
+
if (bound.startsWith("..") || isAbsolute2(bound))
|
|
3598
|
+
throw new Error("A tracked symbolic link escapes the committed upload; resolve that source boundary before deployment.");
|
|
3599
|
+
}
|
|
3600
|
+
const providerConfigurations = await Promise.all(entries.filter((entry) => /(?:^|\/)vercel\.json$/u.test(entry.path)).map(async (entry) => ({
|
|
3601
|
+
path: entry.path,
|
|
3602
|
+
source: await readFile12(join10(checkout, entry.path), "utf8")
|
|
3603
|
+
})));
|
|
3604
|
+
const record = schema.parse({
|
|
3605
|
+
version: 2,
|
|
3606
|
+
revision,
|
|
3607
|
+
commit,
|
|
3608
|
+
entries,
|
|
3609
|
+
providerConfigurations
|
|
3610
|
+
});
|
|
3611
|
+
const target = join10(checkout, name);
|
|
3612
|
+
await mkdir8(dirname8(target), { recursive: true, mode: 448 });
|
|
3613
|
+
await writeFile5(target, JSON.stringify(record), { flag: "wx", mode: 384 });
|
|
3614
|
+
}
|
|
3615
|
+
async function readBuildProvenance(projectDirectory) {
|
|
3616
|
+
let root = resolve3(projectDirectory);
|
|
3617
|
+
let raw = null;
|
|
3618
|
+
for (; ; ) {
|
|
3619
|
+
raw = await readFile12(join10(root, name), "utf8").catch((error) => {
|
|
3620
|
+
if (error.code === "ENOENT")
|
|
3621
|
+
return null;
|
|
3622
|
+
throw error;
|
|
3623
|
+
});
|
|
3624
|
+
if (raw !== null || dirname8(root) === root)
|
|
3625
|
+
break;
|
|
3626
|
+
root = dirname8(root);
|
|
3627
|
+
}
|
|
3628
|
+
if (raw === null)
|
|
3629
|
+
return null;
|
|
3630
|
+
if (Buffer.byteLength(raw) > 16777216)
|
|
3631
|
+
throw new Error("Build provenance is oversized.");
|
|
3632
|
+
const record = schema.parse(JSON.parse(raw));
|
|
3633
|
+
if (gitHash("commit", Buffer.from(record.commit)) !== record.revision)
|
|
3634
|
+
throw new Error("The build revision is not the supplied Git commit.");
|
|
3635
|
+
const expectedTree = /^tree ([0-9a-f]{40})\n/u.exec(record.commit)?.[1];
|
|
3636
|
+
if (treeHash(record.entries) !== expectedTree)
|
|
3637
|
+
throw new Error("The build file inventory does not belong to this Git commit.");
|
|
3638
|
+
const bound = new Map(record.entries.map((entry) => [entry.path, entry]));
|
|
3639
|
+
const configurations = /* @__PURE__ */ new Map();
|
|
3640
|
+
for (const config of record.providerConfigurations) {
|
|
3641
|
+
const entry = bound.get(config.path);
|
|
3642
|
+
if (!entry || entry.mode === "120000" || configurations.has(config.path) || gitHash("blob", Buffer.from(config.source)) !== entry.oid)
|
|
3643
|
+
throw new Error("The original provider configuration is not bound to the Git commit.");
|
|
3644
|
+
configurations.set(config.path, config.source);
|
|
3645
|
+
}
|
|
3646
|
+
if (record.entries.some((entry) => /(?:^|\/)vercel\.json$/u.test(entry.path) && !configurations.has(entry.path)))
|
|
3647
|
+
throw new Error("The committed provider configuration is missing from the build provenance.");
|
|
3648
|
+
const appRelative = relative6(root, projectDirectory).split(sep3).join("/");
|
|
3649
|
+
if (!bound.has(appRelative ? `${appRelative}/package.json` : "package.json"))
|
|
3650
|
+
throw new Error("The selected app is not part of the committed upload.");
|
|
3651
|
+
for (const entry of record.entries) {
|
|
3652
|
+
const path = join10(root, entry.path);
|
|
3653
|
+
const stat = await lstat4(path).catch((error) => {
|
|
3654
|
+
if (error.code === "ENOENT")
|
|
3655
|
+
return null;
|
|
3656
|
+
throw error;
|
|
3657
|
+
});
|
|
3658
|
+
if (!stat)
|
|
3659
|
+
continue;
|
|
3660
|
+
if (stat.isSymbolicLink()) {
|
|
3661
|
+
const { readlink: readlink2 } = await import("fs/promises");
|
|
3662
|
+
if (entry.mode !== "120000" || gitHash("blob", Buffer.from(await readlink2(path))) !== entry.oid)
|
|
3663
|
+
throw new Error("A deployed symbolic link differs from the commit.");
|
|
3664
|
+
} else {
|
|
3665
|
+
const contents = stat.isFile() ? await readFile12(path) : null;
|
|
3666
|
+
if (contents && entry.mode !== "120000" && gitHash("blob", contents) === entry.oid)
|
|
3667
|
+
continue;
|
|
3668
|
+
const original = configurations.get(entry.path);
|
|
3669
|
+
if (contents && original && entry.mode !== "120000") {
|
|
3670
|
+
try {
|
|
3671
|
+
const object = z32.record(z32.string(), z32.unknown());
|
|
3672
|
+
const actual = object.parse(JSON.parse(contents.toString("utf8")));
|
|
3673
|
+
const expected = object.parse(JSON.parse(original));
|
|
3674
|
+
if (!Object.hasOwn(expected, "version") && actual.version === 2)
|
|
3675
|
+
delete actual.version;
|
|
3676
|
+
if (!Object.hasOwn(expected, "name") && typeof actual.name === "string" && /^[a-z0-9][a-z0-9._-]{0,99}$/iu.test(actual.name))
|
|
3677
|
+
delete actual.name;
|
|
3678
|
+
if (isDeepStrictEqual(actual, expected))
|
|
3679
|
+
continue;
|
|
3680
|
+
} catch {
|
|
3681
|
+
}
|
|
3682
|
+
}
|
|
3683
|
+
throw new Error(`A deployed file ${JSON.stringify(entry.path).slice(0, 260)} differs from the committed upload.`);
|
|
3684
|
+
}
|
|
3685
|
+
}
|
|
3686
|
+
return record.revision;
|
|
3687
|
+
}
|
|
3688
|
+
function treeHash(entries) {
|
|
3689
|
+
const root = /* @__PURE__ */ new Map();
|
|
3690
|
+
for (const entry of entries) {
|
|
3691
|
+
const parts = entry.path.split("/");
|
|
3692
|
+
if (parts.some((part) => !part || part === "." || part === ".." || part.includes("\0") || part.includes("\\")))
|
|
3693
|
+
throw new Error("Unsafe Git inventory path.");
|
|
3694
|
+
let tree = root;
|
|
3695
|
+
for (const part of parts.slice(0, -1)) {
|
|
3696
|
+
let child = tree.get(part);
|
|
3697
|
+
if (!child) {
|
|
3698
|
+
child = /* @__PURE__ */ new Map();
|
|
3699
|
+
tree.set(part, child);
|
|
3700
|
+
}
|
|
3701
|
+
if (!(child instanceof Map))
|
|
3702
|
+
throw new Error("Conflicting Git inventory path.");
|
|
3703
|
+
tree = child;
|
|
3704
|
+
}
|
|
3705
|
+
const leaf = parts.at(-1);
|
|
3706
|
+
if (tree.has(leaf))
|
|
3707
|
+
throw new Error("Duplicate Git inventory path.");
|
|
3708
|
+
tree.set(leaf, { mode: entry.mode, oid: entry.oid });
|
|
3709
|
+
}
|
|
3710
|
+
const hash2 = (tree) => {
|
|
3711
|
+
const sorted = [...tree].sort(([a, av], [b, bv]) => Buffer.compare(Buffer.from(a + (av instanceof Map ? "/" : "")), Buffer.from(b + (bv instanceof Map ? "/" : ""))));
|
|
3712
|
+
return gitHash("tree", Buffer.concat(sorted.map(([path, value]) => Buffer.concat([
|
|
3713
|
+
Buffer.from(`${value instanceof Map ? "40000" : value.mode} ${path}\0`),
|
|
3714
|
+
Buffer.from(value instanceof Map ? hash2(value) : value.oid, "hex")
|
|
3715
|
+
]))));
|
|
3716
|
+
};
|
|
3717
|
+
return hash2(root);
|
|
3718
|
+
}
|
|
3719
|
+
|
|
3720
|
+
// ../cli/dist/commands/setup-deploy.js
|
|
3721
|
+
import { createHash as createHash4, randomBytes, randomUUID as randomUUID6 } from "crypto";
|
|
3722
|
+
import { access as access5, mkdir as mkdir9, mkdtemp, rm as rm5, writeFile as writeFile6 } from "fs/promises";
|
|
3723
|
+
import { tmpdir } from "os";
|
|
3724
|
+
import { join as join11 } from "path";
|
|
3725
|
+
import { z as z33 } from "zod";
|
|
3726
|
+
var envSchema = z33.object({
|
|
3727
|
+
id: z33.string(),
|
|
3728
|
+
key: z33.string(),
|
|
3729
|
+
target: z33.array(z33.string()),
|
|
3730
|
+
type: z33.string(),
|
|
3731
|
+
comment: z33.string().optional(),
|
|
3732
|
+
updatedAt: z33.number().optional()
|
|
3733
|
+
});
|
|
3734
|
+
var deploymentSchema = z33.object({
|
|
3735
|
+
id: z33.string(),
|
|
3736
|
+
projectId: z33.string(),
|
|
3737
|
+
ownerId: z33.string().optional(),
|
|
3738
|
+
target: z33.string().nullable(),
|
|
3739
|
+
readyState: z33.string(),
|
|
3740
|
+
createdAt: z33.number(),
|
|
3741
|
+
url: z33.string(),
|
|
3742
|
+
meta: z33.record(z33.string(), z33.unknown()).optional(),
|
|
3743
|
+
gitSource: z33.object({ sha: z33.string().optional() }).nullable().optional()
|
|
3744
|
+
});
|
|
3745
|
+
var buildProofSchema = z33.object({
|
|
3746
|
+
node: z33.string(),
|
|
3747
|
+
packageManager: z33.enum(["npm", "pnpm"]),
|
|
3748
|
+
packageManagerVersion: z33.string(),
|
|
3749
|
+
lockfileHash: z33.string(),
|
|
3750
|
+
revision: z33.string(),
|
|
3751
|
+
fieldContractHash: z33.string(),
|
|
3752
|
+
siteplane: z33.string(),
|
|
3753
|
+
runtimeNext: z33.string(),
|
|
3754
|
+
next: z33.string(),
|
|
3755
|
+
react: z33.string()
|
|
3756
|
+
}).strict();
|
|
3757
|
+
var defaults = {
|
|
3758
|
+
preflight: setupPreflightCommand,
|
|
3759
|
+
context: siteSetupContextCommand,
|
|
3760
|
+
api: setupVercelApi,
|
|
3761
|
+
process: setupProcess,
|
|
3762
|
+
verify: siteSetupVerifyCommand,
|
|
3763
|
+
post: postSiteSetup,
|
|
3764
|
+
writeBuildProvenance,
|
|
3765
|
+
now: Date.now,
|
|
3766
|
+
pause: (milliseconds) => new Promise((resolve5) => setTimeout(resolve5, milliseconds))
|
|
3767
|
+
};
|
|
2878
3768
|
|
|
2879
3769
|
// src/next.ts
|
|
2880
3770
|
var SiteplaneNextContractError = class extends Error {
|
|
@@ -2886,14 +3776,14 @@ var SiteplaneNextContractError = class extends Error {
|
|
|
2886
3776
|
code;
|
|
2887
3777
|
};
|
|
2888
3778
|
async function scanNextProjectFieldContract(projectDir) {
|
|
2889
|
-
const resolvedProjectDir =
|
|
3779
|
+
const resolvedProjectDir = resolve4(projectDir);
|
|
2890
3780
|
const filePaths = await resolveScanFilePaths([], {
|
|
2891
3781
|
projectDir: resolvedProjectDir
|
|
2892
3782
|
});
|
|
2893
3783
|
const files = await Promise.all(
|
|
2894
3784
|
filePaths.map(async (filePath) => ({
|
|
2895
3785
|
filePath,
|
|
2896
|
-
sourceText: await
|
|
3786
|
+
sourceText: await readFile13(filePath, "utf8")
|
|
2897
3787
|
}))
|
|
2898
3788
|
);
|
|
2899
3789
|
const result = scanNextSourceFilesToSiteFieldContract(files, {
|
|
@@ -2926,15 +3816,32 @@ async function withSiteplane(nextConfig, options = {}) {
|
|
|
2926
3816
|
"The instrumented source no longer matches siteplane.config.json. Run siteplane setup apply again."
|
|
2927
3817
|
);
|
|
2928
3818
|
}
|
|
2929
|
-
const
|
|
2930
|
-
|
|
3819
|
+
const checkoutRevision = await readGitRevision2(projectDir) || await readBuildProvenance(projectDir) || (process.env.VERCEL === "1" ? process.env.VERCEL_GIT_COMMIT_SHA?.trim() : "");
|
|
3820
|
+
const requestedRevision = options.buildRevision?.trim() || process.env.SITEPLANE_BUILD_REVISION?.trim();
|
|
3821
|
+
if (!checkoutRevision || !/^[0-9a-f]{40}$/u.test(checkoutRevision))
|
|
2931
3822
|
throw new SiteplaneNextContractError(
|
|
2932
3823
|
"missing_build_revision",
|
|
2933
|
-
"
|
|
3824
|
+
"Build from the committed Git checkout with provider Git metadata; an arbitrary revision override is insufficient."
|
|
3825
|
+
);
|
|
3826
|
+
if (requestedRevision && requestedRevision !== checkoutRevision)
|
|
3827
|
+
throw new SiteplaneNextContractError(
|
|
3828
|
+
"build_revision_conflict",
|
|
3829
|
+
"SITEPLANE_BUILD_REVISION does not match the actual build checkout. Deploy the applied commit with its current configuration."
|
|
3830
|
+
);
|
|
3831
|
+
const buildRevision = checkoutRevision;
|
|
3832
|
+
if (process.env.VERCEL === "1")
|
|
3833
|
+
await emitBuildProof(
|
|
3834
|
+
projectDir,
|
|
3835
|
+
config.packages,
|
|
3836
|
+
buildRevision,
|
|
3837
|
+
scan.fieldContractHash
|
|
2934
3838
|
);
|
|
2935
|
-
}
|
|
2936
3839
|
return {
|
|
2937
3840
|
...nextConfig,
|
|
3841
|
+
headers: async () => frameHeaders(
|
|
3842
|
+
await nextConfig.headers?.() ?? [],
|
|
3843
|
+
new URL(config.apiBaseUrl).origin
|
|
3844
|
+
),
|
|
2938
3845
|
env: {
|
|
2939
3846
|
...nextConfig.env ?? {},
|
|
2940
3847
|
SITEPLANE_BUILD_FIELD_CONTRACT_HASH: scan.fieldContractHash,
|
|
@@ -2943,8 +3850,8 @@ async function withSiteplane(nextConfig, options = {}) {
|
|
|
2943
3850
|
}
|
|
2944
3851
|
};
|
|
2945
3852
|
}
|
|
2946
|
-
var execFileAsync3 =
|
|
2947
|
-
async function
|
|
3853
|
+
var execFileAsync3 = promisify4(execFile4);
|
|
3854
|
+
async function readGitRevision2(projectDir) {
|
|
2948
3855
|
try {
|
|
2949
3856
|
const result = await execFileAsync3("git", ["rev-parse", "HEAD"], {
|
|
2950
3857
|
cwd: projectDir
|
|
@@ -2954,6 +3861,85 @@ async function readGitRevision(projectDir) {
|
|
|
2954
3861
|
return "";
|
|
2955
3862
|
}
|
|
2956
3863
|
}
|
|
3864
|
+
function frameHeaders(rules, adminOrigin) {
|
|
3865
|
+
const policy = `frame-ancestors 'self' ${adminOrigin}`;
|
|
3866
|
+
const prepared = rules.map((rule) => ({
|
|
3867
|
+
...rule,
|
|
3868
|
+
headers: rule.headers.map((header) => {
|
|
3869
|
+
if (header.key.toLowerCase() === "x-frame-options" && /^(DENY|SAMEORIGIN)$/iu.test(header.value.trim()))
|
|
3870
|
+
throw new SiteplaneNextContractError(
|
|
3871
|
+
"frame_policy_conflict",
|
|
3872
|
+
"The existing X-Frame-Options blocks the Siteplane preview. Reconcile that explicit website policy with the canonical admin origin."
|
|
3873
|
+
);
|
|
3874
|
+
if (header.key.toLowerCase() !== "content-security-policy") return header;
|
|
3875
|
+
const ancestors = /(?:^|;)\s*frame-ancestors\s+([^;]+)/iu.exec(
|
|
3876
|
+
header.value
|
|
3877
|
+
)?.[1];
|
|
3878
|
+
if (ancestors && (!ancestors.split(/\s+/u).includes(adminOrigin) || ancestors.includes("*")))
|
|
3879
|
+
throw new SiteplaneNextContractError(
|
|
3880
|
+
"frame_policy_conflict",
|
|
3881
|
+
"Keep the existing CSP directives and explicitly allow only the canonical Siteplane admin origin in frame-ancestors."
|
|
3882
|
+
);
|
|
3883
|
+
return {
|
|
3884
|
+
...header,
|
|
3885
|
+
value: ancestors ? header.value : `${header.value.replace(/;\s*$/u, "")}; ${policy}`
|
|
3886
|
+
};
|
|
3887
|
+
})
|
|
3888
|
+
}));
|
|
3889
|
+
return [
|
|
3890
|
+
{
|
|
3891
|
+
source: "/:path*",
|
|
3892
|
+
headers: [{ key: "Content-Security-Policy", value: policy }]
|
|
3893
|
+
},
|
|
3894
|
+
...prepared
|
|
3895
|
+
];
|
|
3896
|
+
}
|
|
3897
|
+
async function emitBuildProof(projectDir, packages, revision, fieldContractHash) {
|
|
3898
|
+
const [cli, runtime, next, react] = await Promise.all(
|
|
3899
|
+
["siteplane", "@siteplane/runtime-next", "next", "react"].map(
|
|
3900
|
+
(name2) => readInstalledPackage(projectDir, name2)
|
|
3901
|
+
)
|
|
3902
|
+
);
|
|
3903
|
+
if (cli.version !== packages.siteplane || runtime.version !== packages.runtimeNext)
|
|
3904
|
+
throw new SiteplaneNextContractError(
|
|
3905
|
+
"build_identity_missing",
|
|
3906
|
+
"The provider installed different Siteplane package versions than the task requires."
|
|
3907
|
+
);
|
|
3908
|
+
const executable = process.env.npm_execpath;
|
|
3909
|
+
if (!executable)
|
|
3910
|
+
throw new SiteplaneNextContractError(
|
|
3911
|
+
"build_identity_missing",
|
|
3912
|
+
"Run the provider build through the selected npm/pnpm executable so its actual version can be verified."
|
|
3913
|
+
);
|
|
3914
|
+
const packageManager = /pnpm/iu.test(executable) ? "pnpm" : "npm";
|
|
3915
|
+
const packageManagerVersion = (await execFileAsync3(process.execPath, [executable, "--version"], {
|
|
3916
|
+
cwd: projectDir
|
|
3917
|
+
})).stdout.trim();
|
|
3918
|
+
let directory = resolve4(projectDir);
|
|
3919
|
+
let lock = null;
|
|
3920
|
+
while (true) {
|
|
3921
|
+
lock = await readFile13(
|
|
3922
|
+
join12(
|
|
3923
|
+
directory,
|
|
3924
|
+
packageManager === "npm" ? "package-lock.json" : "pnpm-lock.yaml"
|
|
3925
|
+
),
|
|
3926
|
+
"utf8"
|
|
3927
|
+
).catch((error) => {
|
|
3928
|
+
if (error.code === "ENOENT") return null;
|
|
3929
|
+
throw error;
|
|
3930
|
+
});
|
|
3931
|
+
if (lock !== null || dirname9(directory) === directory) break;
|
|
3932
|
+
directory = dirname9(directory);
|
|
3933
|
+
}
|
|
3934
|
+
if (!lock)
|
|
3935
|
+
throw new SiteplaneNextContractError(
|
|
3936
|
+
"build_identity_missing",
|
|
3937
|
+
"The provider build is missing the selected canonical lockfile."
|
|
3938
|
+
);
|
|
3939
|
+
console.info(
|
|
3940
|
+
`SITEPLANE_BUILD_PROOF=${JSON.stringify({ node: process.versions.node, packageManager, packageManagerVersion, lockfileHash: `sha256:${createHash5("sha256").update(lock).digest("hex")}`, revision, fieldContractHash, siteplane: cli.version, runtimeNext: runtime.version, next: next.version, react: react.version })}`
|
|
3941
|
+
);
|
|
3942
|
+
}
|
|
2957
3943
|
export {
|
|
2958
3944
|
SiteplaneNextContractError,
|
|
2959
3945
|
scanNextProjectFieldContract,
|