riverbankcms 0.22.1 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/acceptance/matrix.mjs +3 -3
- package/dist/cli/index.mjs +2283 -1628
- package/dist/cli/init-docs/content/cli-reference.md +2 -2
- package/dist/cli/init-docs/content/content-management.md +1 -1
- package/dist/cli/init-docs/content/workflow-custom-block.md +4 -4
- package/dist/cli/init-docs/content/workflow-publish.md +11 -5
- package/dist/{entryCommands-Bu-z9kxb.mjs → entryCommands-BdN5YrqI.mjs} +253 -174
- package/dist/{eventUpsertInputSchema-xHmuEKwM.mjs → eventUpsertInputSchema-kp-U13TZ.mjs} +70 -32
- package/dist/load-config-C7Rd822n.mjs +4 -0
- package/dist/{load-config-pAPKpeE0.mjs → load-config-D5DDfmv1.mjs} +2 -2
- package/dist/{plan-DUdJbgTV.mjs → plan-6m8gsGI8.mjs} +1 -1
- package/dist/scaffold/index.mjs +2 -2
- package/dist/{sdk-event-upsert-B3gflo1K.mjs → sdk-event-upsert-BnBxyTR6.mjs} +493 -122
- package/dist/{src-RfhyMOpX.mjs → src-BPh_OivC.mjs} +477 -93
- package/dist/testing.mjs +4 -4
- package/package.json +1 -1
- package/dist/load-config-BRd0EUsF.mjs +0 -4
|
@@ -52,6 +52,7 @@ const unsafeAsPageId = (id) => id;
|
|
|
52
52
|
const unsafeAsPageSurfaceId = (id) => id;
|
|
53
53
|
const unsafeAsEditLeaseToken = (id) => id;
|
|
54
54
|
const unsafeAsEditorClientId = (id) => id;
|
|
55
|
+
const unsafeAsPageDocumentCheckpointId = (id) => id;
|
|
55
56
|
const unsafeAsOccurrenceId = (id) => id;
|
|
56
57
|
const unsafeAsEventOfferingId = (id) => id;
|
|
57
58
|
const unsafeAsEventSeriesId = (id) => id;
|
|
@@ -166,6 +167,7 @@ const parsePageId = (value) => parseUuidBrand(value, unsafeAsPageId);
|
|
|
166
167
|
const parsePageSurfaceId = (value) => parseUuidBrand(value, unsafeAsPageSurfaceId);
|
|
167
168
|
const parseEditLeaseToken = (value) => parseUuidBrand(value, unsafeAsEditLeaseToken);
|
|
168
169
|
const parseEditorClientId = (value) => parseUuidBrand(value, unsafeAsEditorClientId);
|
|
170
|
+
const parsePageDocumentCheckpointId = (value) => parseUuidBrand(value, unsafeAsPageDocumentCheckpointId);
|
|
169
171
|
const parseOccurrenceId = (value) => parseUuidBrand(value, unsafeAsOccurrenceId);
|
|
170
172
|
const parseEventOfferingId = (value) => parseUuidBrand(value, unsafeAsEventOfferingId);
|
|
171
173
|
const parseEventAttendeeTicketLineId = (value) => parseUuidBrand(value, unsafeAsEventAttendeeTicketLineId);
|
|
@@ -1385,15 +1387,15 @@ function parseEventPageSurfaceDestinationMode(value) {
|
|
|
1385
1387
|
return value === "cms-managed" || value === "system-managed" ? value : undefined;
|
|
1386
1388
|
}
|
|
1387
1389
|
function parseEventPageSurfaceSubject(value) {
|
|
1388
|
-
if (!isRecord$
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
}
|
|
1390
|
+
if (!isRecord$10(value)) return err({ kind: "notObject" });
|
|
1391
|
+
const parsed = value.kind === "eventSeries" ? parseEventSeriesPageSurfaceSubject(value) : value.kind === "eventOffering" ? parseEventOfferingPageSurfaceSubject(value) : err({
|
|
1392
|
+
kind: "unsupportedSubject",
|
|
1393
|
+
subjectKind: value.kind
|
|
1394
|
+
});
|
|
1395
|
+
return parsed.ok && value.noindex === true ? ok({
|
|
1396
|
+
...parsed.value,
|
|
1397
|
+
noindex: true
|
|
1398
|
+
}) : parsed;
|
|
1397
1399
|
}
|
|
1398
1400
|
function parseEventSeriesPageSurfaceSubject(value) {
|
|
1399
1401
|
const eventSeriesId = parseEventSeriesId(value.eventSeriesId);
|
|
@@ -1458,7 +1460,7 @@ function parseEventSeriesIdList(values) {
|
|
|
1458
1460
|
}
|
|
1459
1461
|
return ok(parsed);
|
|
1460
1462
|
}
|
|
1461
|
-
function isRecord$
|
|
1463
|
+
function isRecord$10(value) {
|
|
1462
1464
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1463
1465
|
}
|
|
1464
1466
|
|
|
@@ -2009,6 +2011,12 @@ function resolveBookingTimeZoneId(...candidates) {
|
|
|
2009
2011
|
}
|
|
2010
2012
|
/** Canonical business-zone admission, shared by server and public wire boundaries. */
|
|
2011
2013
|
const DEFAULT_BOOKING_BUSINESS_TIME_ZONE = "Europe/London";
|
|
2014
|
+
/** Stored site zones must be valid; a broken read must not silently choose another zone. */
|
|
2015
|
+
function requireBookingTimeZone(value) {
|
|
2016
|
+
const parsed = parseBookingTimeZone(value);
|
|
2017
|
+
if (!parsed.ok) throw new Error("Expected a valid canonical site time zone");
|
|
2018
|
+
return parsed.value;
|
|
2019
|
+
}
|
|
2012
2020
|
/** Effect boundary for browser-authored local inputs; formats no displayed date. */
|
|
2013
2021
|
function getRuntimeBookingTimeZone() {
|
|
2014
2022
|
return resolveBookingTimeZoneId(new Intl.DateTimeFormat("en-GB").resolvedOptions().timeZone);
|
|
@@ -3105,28 +3113,6 @@ const RECTIFICATION_HISTORY_PROPAGATION_PLANS = {
|
|
|
3105
3113
|
blocked_immutable_history: { kind: "blocked_immutable_history" }
|
|
3106
3114
|
};
|
|
3107
3115
|
|
|
3108
|
-
//#endregion
|
|
3109
|
-
//#region ../core/src/location.ts
|
|
3110
|
-
function normalizeLocationAddressText(value) {
|
|
3111
|
-
if (typeof value !== "string") {
|
|
3112
|
-
return null;
|
|
3113
|
-
}
|
|
3114
|
-
const trimmed = value.trim();
|
|
3115
|
-
return trimmed.length > 0 ? trimmed : null;
|
|
3116
|
-
}
|
|
3117
|
-
function hasLocationCoordinates(value) {
|
|
3118
|
-
return value != null && typeof value.lat === "number" && typeof value.lng === "number";
|
|
3119
|
-
}
|
|
3120
|
-
function toLocationCoordinates(value) {
|
|
3121
|
-
if (!hasLocationCoordinates(value)) {
|
|
3122
|
-
return null;
|
|
3123
|
-
}
|
|
3124
|
-
return {
|
|
3125
|
-
lat: value.lat,
|
|
3126
|
-
lng: value.lng
|
|
3127
|
-
};
|
|
3128
|
-
}
|
|
3129
|
-
|
|
3130
3116
|
//#endregion
|
|
3131
3117
|
//#region ../core/src/string.ts
|
|
3132
3118
|
/**
|
|
@@ -3176,6 +3162,363 @@ function capitalize(str) {
|
|
|
3176
3162
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
3177
3163
|
}
|
|
3178
3164
|
|
|
3165
|
+
//#endregion
|
|
3166
|
+
//#region ../core/src/location.ts
|
|
3167
|
+
/** One complete, finite, bounded arrival pin; zero is a valid coordinate. */
|
|
3168
|
+
const locationPinSchema = z.strictObject({
|
|
3169
|
+
lat: z.number().min(-90).max(90),
|
|
3170
|
+
lng: z.number().min(-180).max(180)
|
|
3171
|
+
}).readonly().brand();
|
|
3172
|
+
const addressPart = z.string().trim().max(200).nullish().transform((value) => trimmedStringOrNull(value));
|
|
3173
|
+
/** Building identifies the place; unit/floor refine it without moving it. */
|
|
3174
|
+
const locationAddressSchema = z.strictObject({
|
|
3175
|
+
building: addressPart,
|
|
3176
|
+
unit: addressPart,
|
|
3177
|
+
floor: addressPart,
|
|
3178
|
+
street: addressPart,
|
|
3179
|
+
locality: addressPart,
|
|
3180
|
+
region: addressPart,
|
|
3181
|
+
postalCode: addressPart,
|
|
3182
|
+
country: addressPart.transform((value) => value?.length === 2 ? value.toUpperCase() : value)
|
|
3183
|
+
}).readonly().transform((address) => Object.values(address).some((part) => part !== null) ? address : null);
|
|
3184
|
+
const locationAddressMatchSchema = z.strictObject({
|
|
3185
|
+
point: locationPinSchema,
|
|
3186
|
+
precision: z.enum([
|
|
3187
|
+
"building",
|
|
3188
|
+
"street",
|
|
3189
|
+
"area",
|
|
3190
|
+
"unknown"
|
|
3191
|
+
]),
|
|
3192
|
+
placeId: z.string().trim().max(1024).regex(/^[a-z][a-z0-9-]*:\S+$/),
|
|
3193
|
+
attribution: z.array(z.strictObject({
|
|
3194
|
+
text: z.string().trim().min(1).max(500),
|
|
3195
|
+
url: z.url().max(2048).refine((value) => /^https?:\/\//.test(value))
|
|
3196
|
+
}).readonly()).min(1).max(4).readonly()
|
|
3197
|
+
}).readonly();
|
|
3198
|
+
const locationValueSchema = z.strictObject({
|
|
3199
|
+
address: locationAddressSchema.nullable().default(null),
|
|
3200
|
+
pin: locationPinSchema.nullable().default(null),
|
|
3201
|
+
doorNote: z.string().trim().max(1e3).nullish().transform(trimmedStringOrNull),
|
|
3202
|
+
addressMatch: locationAddressMatchSchema.nullable().default(null),
|
|
3203
|
+
ownerConfirmedPinAndAddress: z.boolean().default(false)
|
|
3204
|
+
}).superRefine((value, context) => {
|
|
3205
|
+
if (value.address === null && value.pin === null) {
|
|
3206
|
+
context.addIssue({
|
|
3207
|
+
code: "custom",
|
|
3208
|
+
path: ["address"],
|
|
3209
|
+
message: "Use null to remove a location."
|
|
3210
|
+
});
|
|
3211
|
+
}
|
|
3212
|
+
if (value.address === null && value.addressMatch !== null) {
|
|
3213
|
+
context.addIssue({
|
|
3214
|
+
code: "custom",
|
|
3215
|
+
path: ["addressMatch"],
|
|
3216
|
+
message: "Address evidence requires an address."
|
|
3217
|
+
});
|
|
3218
|
+
}
|
|
3219
|
+
if (value.ownerConfirmedPinAndAddress && (value.address === null || value.pin === null)) {
|
|
3220
|
+
context.addIssue({
|
|
3221
|
+
code: "custom",
|
|
3222
|
+
path: ["ownerConfirmedPinAndAddress"],
|
|
3223
|
+
message: "Confirmation requires both address and pin."
|
|
3224
|
+
});
|
|
3225
|
+
}
|
|
3226
|
+
}).readonly();
|
|
3227
|
+
/** API/DB ingress parses once. Removed locations are represented by null. */
|
|
3228
|
+
function parseLocationValue(input) {
|
|
3229
|
+
const parsed = locationValueSchema.nullable().safeParse(input);
|
|
3230
|
+
return parsed.success ? ok(parsed.data) : err({
|
|
3231
|
+
kind: "invalid_location",
|
|
3232
|
+
issues: parsed.error.issues
|
|
3233
|
+
});
|
|
3234
|
+
}
|
|
3235
|
+
function formatLocationAddress(address) {
|
|
3236
|
+
if (address === null) return null;
|
|
3237
|
+
const parts = [
|
|
3238
|
+
address.building,
|
|
3239
|
+
address.street,
|
|
3240
|
+
address.unit,
|
|
3241
|
+
address.floor,
|
|
3242
|
+
address.locality,
|
|
3243
|
+
address.region,
|
|
3244
|
+
address.postalCode,
|
|
3245
|
+
address.country
|
|
3246
|
+
];
|
|
3247
|
+
return parts.filter((part) => part !== null).join(", ") || null;
|
|
3248
|
+
}
|
|
3249
|
+
/** Permission belongs to the resource/source owner before this projection. */
|
|
3250
|
+
function projectPublicLocation(location) {
|
|
3251
|
+
return {
|
|
3252
|
+
address: location.address,
|
|
3253
|
+
displayAddress: formatLocationAddress(location.address),
|
|
3254
|
+
pin: location.pin,
|
|
3255
|
+
doorNote: location.doorNote,
|
|
3256
|
+
attribution: location.addressMatch?.attribution ?? []
|
|
3257
|
+
};
|
|
3258
|
+
}
|
|
3259
|
+
function normalizeLocationAddressText(value) {
|
|
3260
|
+
if (typeof value !== "string") {
|
|
3261
|
+
return null;
|
|
3262
|
+
}
|
|
3263
|
+
return trimmedStringOrNull(value);
|
|
3264
|
+
}
|
|
3265
|
+
function hasLocationCoordinates(value) {
|
|
3266
|
+
return value != null && typeof value.lat === "number" && Number.isFinite(value.lat) && Math.abs(value.lat) <= 90 && typeof value.lng === "number" && Number.isFinite(value.lng) && Math.abs(value.lng) <= 180;
|
|
3267
|
+
}
|
|
3268
|
+
function toLocationCoordinates(value) {
|
|
3269
|
+
if (!hasLocationCoordinates(value)) {
|
|
3270
|
+
return null;
|
|
3271
|
+
}
|
|
3272
|
+
return {
|
|
3273
|
+
lat: value.lat,
|
|
3274
|
+
lng: value.lng
|
|
3275
|
+
};
|
|
3276
|
+
}
|
|
3277
|
+
|
|
3278
|
+
//#endregion
|
|
3279
|
+
//#region ../core/src/location-relationship.ts
|
|
3280
|
+
/** Initial bounded policy; Opus can tune these values without changing callers. */
|
|
3281
|
+
const LOCATION_MATCH_THRESHOLDS_METRES = {
|
|
3282
|
+
building: 100,
|
|
3283
|
+
street: 300,
|
|
3284
|
+
area: 1e3
|
|
3285
|
+
};
|
|
3286
|
+
function locationDistanceMetres(a, b) {
|
|
3287
|
+
const radians = Math.PI / 180;
|
|
3288
|
+
const haversine = Math.sin((b.lat - a.lat) * radians / 2) ** 2 + Math.cos(a.lat * radians) * Math.cos(b.lat * radians) * Math.sin((b.lng - a.lng) * radians / 2) ** 2;
|
|
3289
|
+
return 6371e3 * 2 * Math.asin(Math.sqrt(Math.min(1, Math.max(0, haversine))));
|
|
3290
|
+
}
|
|
3291
|
+
/** Arrival pins are never substituted for missing provider address points. */
|
|
3292
|
+
function decideLocationRelationship(location) {
|
|
3293
|
+
if (location === null) return { kind: "empty" };
|
|
3294
|
+
if (location.pin === null) return { kind: "address_only" };
|
|
3295
|
+
if (location.address === null) return { kind: "pin_only" };
|
|
3296
|
+
if (location.addressMatch === null || location.addressMatch.precision === "unknown") {
|
|
3297
|
+
return { kind: "unchecked" };
|
|
3298
|
+
}
|
|
3299
|
+
const { point, precision } = location.addressMatch;
|
|
3300
|
+
const distanceMetres = locationDistanceMetres(point, location.pin);
|
|
3301
|
+
const thresholdMetres = LOCATION_MATCH_THRESHOLDS_METRES[precision];
|
|
3302
|
+
const beyondThreshold = distanceMetres > thresholdMetres * (1 + 8 * Number.EPSILON);
|
|
3303
|
+
return {
|
|
3304
|
+
kind: beyondThreshold ? "far" : precision === "building" ? "near" : "approximate",
|
|
3305
|
+
distanceMetres,
|
|
3306
|
+
thresholdMetres,
|
|
3307
|
+
precision
|
|
3308
|
+
};
|
|
3309
|
+
}
|
|
3310
|
+
const spatialAddressParts = [
|
|
3311
|
+
"building",
|
|
3312
|
+
"street",
|
|
3313
|
+
"locality",
|
|
3314
|
+
"postalCode",
|
|
3315
|
+
"country"
|
|
3316
|
+
];
|
|
3317
|
+
const comparisonText = (text) => (text ?? "").trim().replace(/\s+/g, " ").toLowerCase();
|
|
3318
|
+
function sameMeaningfulAddress(a, b) {
|
|
3319
|
+
if (a === null || b === null) return a === b;
|
|
3320
|
+
return spatialAddressParts.every((part) => comparisonText(a[part]) === comparisonText(b[part]));
|
|
3321
|
+
}
|
|
3322
|
+
function samePin(a, b) {
|
|
3323
|
+
return a === null || b === null ? a === b : a.lat === b.lat && a.lng === b.lng;
|
|
3324
|
+
}
|
|
3325
|
+
/** Edits cannot carry forward old confirmation or address evidence by accident. */
|
|
3326
|
+
function editLocationValue(previous, details) {
|
|
3327
|
+
if (details.address === null && details.pin === null) return ok(null);
|
|
3328
|
+
if (previous === null) {
|
|
3329
|
+
return parseLocationValue({
|
|
3330
|
+
...details,
|
|
3331
|
+
addressMatch: null,
|
|
3332
|
+
ownerConfirmedPinAndAddress: false
|
|
3333
|
+
});
|
|
3334
|
+
}
|
|
3335
|
+
const sameAddress = sameMeaningfulAddress(previous.address, details.address);
|
|
3336
|
+
const samePair = sameAddress && samePin(previous.pin, details.pin);
|
|
3337
|
+
return parseLocationValue({
|
|
3338
|
+
...details,
|
|
3339
|
+
addressMatch: sameAddress ? previous.addressMatch : null,
|
|
3340
|
+
ownerConfirmedPinAndAddress: samePair && previous.ownerConfirmedPinAndAddress
|
|
3341
|
+
});
|
|
3342
|
+
}
|
|
3343
|
+
function confirmLocationPair(location) {
|
|
3344
|
+
return location.address !== null && location.pin !== null ? ok({
|
|
3345
|
+
...location,
|
|
3346
|
+
ownerConfirmedPinAndAddress: true
|
|
3347
|
+
}) : err({ kind: "missing_address_or_pin" });
|
|
3348
|
+
}
|
|
3349
|
+
/** Forms receive the decided save value, rather than a collection of flags. */
|
|
3350
|
+
function decideLocationSave(location, activity) {
|
|
3351
|
+
if (activity === "address-check") return {
|
|
3352
|
+
kind: "blocked",
|
|
3353
|
+
reason: "pending_address_check"
|
|
3354
|
+
};
|
|
3355
|
+
if (activity === "reverse") return {
|
|
3356
|
+
kind: "blocked",
|
|
3357
|
+
reason: "pending_reverse"
|
|
3358
|
+
};
|
|
3359
|
+
const relationship = decideLocationRelationship(location);
|
|
3360
|
+
return relationship.kind === "far" && location?.ownerConfirmedPinAndAddress !== true ? {
|
|
3361
|
+
kind: "blocked",
|
|
3362
|
+
reason: "unconfirmed_mismatch"
|
|
3363
|
+
} : {
|
|
3364
|
+
kind: "ready",
|
|
3365
|
+
location
|
|
3366
|
+
};
|
|
3367
|
+
}
|
|
3368
|
+
|
|
3369
|
+
//#endregion
|
|
3370
|
+
//#region ../core/src/location-migration.ts
|
|
3371
|
+
/** Offline expand/contract conversions, not runtime fallback readers. */
|
|
3372
|
+
const legacyText = z.string().nullable().optional();
|
|
3373
|
+
const legacyCoordinatesSchema = z.strictObject({
|
|
3374
|
+
lat: z.number().min(-90).max(90).nullable().optional(),
|
|
3375
|
+
lng: z.number().min(-180).max(180).nullable().optional()
|
|
3376
|
+
}).superRefine((value, context) => {
|
|
3377
|
+
if (value.lat == null !== (value.lng == null)) {
|
|
3378
|
+
context.addIssue({
|
|
3379
|
+
code: "custom",
|
|
3380
|
+
message: "Legacy pin is incomplete."
|
|
3381
|
+
});
|
|
3382
|
+
}
|
|
3383
|
+
});
|
|
3384
|
+
const venueAddressSchema = z.strictObject({
|
|
3385
|
+
street: legacyText,
|
|
3386
|
+
line1: legacyText,
|
|
3387
|
+
line2: legacyText,
|
|
3388
|
+
city: legacyText,
|
|
3389
|
+
state: legacyText,
|
|
3390
|
+
region: legacyText,
|
|
3391
|
+
postalCode: legacyText,
|
|
3392
|
+
postal_code: legacyText,
|
|
3393
|
+
postcode: legacyText,
|
|
3394
|
+
country: legacyText,
|
|
3395
|
+
formatted: legacyText,
|
|
3396
|
+
summary: legacyText
|
|
3397
|
+
}).superRefine((value, context) => {
|
|
3398
|
+
const aliases = [
|
|
3399
|
+
[value.street, value.line1],
|
|
3400
|
+
[value.state, value.region],
|
|
3401
|
+
[
|
|
3402
|
+
value.postalCode,
|
|
3403
|
+
value.postal_code,
|
|
3404
|
+
value.postcode
|
|
3405
|
+
],
|
|
3406
|
+
[value.formatted, value.summary]
|
|
3407
|
+
];
|
|
3408
|
+
aliases.forEach((parts) => {
|
|
3409
|
+
const meaningful = parts.filter((part) => displayComparison(part) !== "");
|
|
3410
|
+
if (meaningful.some((part) => displayComparison(part) !== displayComparison(meaningful[0]))) {
|
|
3411
|
+
context.addIssue({
|
|
3412
|
+
code: "custom",
|
|
3413
|
+
message: "Legacy address aliases disagree."
|
|
3414
|
+
});
|
|
3415
|
+
}
|
|
3416
|
+
});
|
|
3417
|
+
}).nullable();
|
|
3418
|
+
const businessAddressSchema = legacyCoordinatesSchema.safeExtend({
|
|
3419
|
+
addressLine1: legacyText,
|
|
3420
|
+
addressLine2: legacyText,
|
|
3421
|
+
locality: legacyText,
|
|
3422
|
+
region: legacyText,
|
|
3423
|
+
postalCode: legacyText,
|
|
3424
|
+
countryCode: legacyText,
|
|
3425
|
+
displayAddress: legacyText
|
|
3426
|
+
});
|
|
3427
|
+
const customLocationSchema = legacyCoordinatesSchema.safeExtend({ addressText: legacyText });
|
|
3428
|
+
function finishConversion(address, coordinates) {
|
|
3429
|
+
const parsedAddress = locationAddressSchema.nullable().safeParse(address);
|
|
3430
|
+
if (!parsedAddress.success) return err({
|
|
3431
|
+
kind: "invalid_legacy_location",
|
|
3432
|
+
issues: parsedAddress.error.issues
|
|
3433
|
+
});
|
|
3434
|
+
const pin = coordinates.lat == null || coordinates.lng == null ? null : {
|
|
3435
|
+
lat: coordinates.lat,
|
|
3436
|
+
lng: coordinates.lng
|
|
3437
|
+
};
|
|
3438
|
+
if (parsedAddress.data === null && pin === null) return ok(null);
|
|
3439
|
+
const result = parseLocationValue({
|
|
3440
|
+
address: parsedAddress.data,
|
|
3441
|
+
pin,
|
|
3442
|
+
addressMatch: null,
|
|
3443
|
+
ownerConfirmedPinAndAddress: false
|
|
3444
|
+
});
|
|
3445
|
+
return result.ok ? result : err({
|
|
3446
|
+
kind: "invalid_legacy_location",
|
|
3447
|
+
issues: result.error.issues
|
|
3448
|
+
});
|
|
3449
|
+
}
|
|
3450
|
+
function convertVenue(input) {
|
|
3451
|
+
const address = venueAddressSchema.safeParse(input.addressJson ?? null);
|
|
3452
|
+
const coordinates = legacyCoordinatesSchema.safeParse(input.locationJson ?? {});
|
|
3453
|
+
if (!address.success) return err({
|
|
3454
|
+
kind: "invalid_legacy_location",
|
|
3455
|
+
issues: address.error.issues
|
|
3456
|
+
});
|
|
3457
|
+
if (!coordinates.success) return err({
|
|
3458
|
+
kind: "invalid_legacy_location",
|
|
3459
|
+
issues: coordinates.error.issues
|
|
3460
|
+
});
|
|
3461
|
+
const result = finishConversion(mapVenueAddress(address.data), coordinates.data);
|
|
3462
|
+
return checkDisplayText(result, firstText(address.data?.formatted, address.data?.summary));
|
|
3463
|
+
}
|
|
3464
|
+
const displayComparison = (text) => (text ?? "").trim().replace(/\s+/g, " ").toLowerCase();
|
|
3465
|
+
const firstText = (...parts) => parts.find((part) => part != null && part.trim().length > 0)?.trim() ?? null;
|
|
3466
|
+
function mapVenueAddress(address) {
|
|
3467
|
+
if (address === null) return null;
|
|
3468
|
+
const structured = {
|
|
3469
|
+
street: firstText(address.street, address.line1),
|
|
3470
|
+
unit: address.line2,
|
|
3471
|
+
locality: address.city,
|
|
3472
|
+
region: firstText(address.state, address.region),
|
|
3473
|
+
postalCode: firstText(address.postalCode, address.postal_code, address.postcode),
|
|
3474
|
+
country: address.country
|
|
3475
|
+
};
|
|
3476
|
+
return Object.values(structured).some((part) => displayComparison(part) !== "") ? structured : { street: firstText(address.formatted, address.summary) };
|
|
3477
|
+
}
|
|
3478
|
+
function checkDisplayText(result, text) {
|
|
3479
|
+
if (!result.ok) return result;
|
|
3480
|
+
const original = text?.trim() ?? "";
|
|
3481
|
+
const derived = formatLocationAddress(result.value?.address ?? null);
|
|
3482
|
+
return original.length > 0 && displayComparison(original) !== displayComparison(derived) ? err({
|
|
3483
|
+
kind: "display_address_conflict",
|
|
3484
|
+
original,
|
|
3485
|
+
derived
|
|
3486
|
+
}) : result;
|
|
3487
|
+
}
|
|
3488
|
+
function convertBusiness(value) {
|
|
3489
|
+
if (value == null) return ok(null);
|
|
3490
|
+
const parsed = businessAddressSchema.safeParse(value);
|
|
3491
|
+
if (!parsed.success) return err({
|
|
3492
|
+
kind: "invalid_legacy_location",
|
|
3493
|
+
issues: parsed.error.issues
|
|
3494
|
+
});
|
|
3495
|
+
const result = finishConversion({
|
|
3496
|
+
street: parsed.data.addressLine1,
|
|
3497
|
+
unit: parsed.data.addressLine2,
|
|
3498
|
+
locality: parsed.data.locality,
|
|
3499
|
+
region: parsed.data.region,
|
|
3500
|
+
postalCode: parsed.data.postalCode,
|
|
3501
|
+
country: parsed.data.countryCode
|
|
3502
|
+
}, parsed.data);
|
|
3503
|
+
return checkDisplayText(result, parsed.data.displayAddress);
|
|
3504
|
+
}
|
|
3505
|
+
function convertCustom(value) {
|
|
3506
|
+
if (value == null) return ok(null);
|
|
3507
|
+
const parsed = customLocationSchema.safeParse(value);
|
|
3508
|
+
return parsed.success ? finishConversion({ street: parsed.data.addressText }, parsed.data) : err({
|
|
3509
|
+
kind: "invalid_legacy_location",
|
|
3510
|
+
issues: parsed.error.issues
|
|
3511
|
+
});
|
|
3512
|
+
}
|
|
3513
|
+
/** Preserve pins exactly; never split free text or fabricate match evidence. */
|
|
3514
|
+
function convertLegacyLocation(input) {
|
|
3515
|
+
switch (input.kind) {
|
|
3516
|
+
case "venue": return convertVenue(input);
|
|
3517
|
+
case "business": return convertBusiness(input.value);
|
|
3518
|
+
case "custom": return convertCustom(input.value);
|
|
3519
|
+
}
|
|
3520
|
+
}
|
|
3521
|
+
|
|
3179
3522
|
//#endregion
|
|
3180
3523
|
//#region ../core/src/business-address.ts
|
|
3181
3524
|
function normalizeCountryCode(value) {
|
|
@@ -3192,15 +3535,16 @@ function isLongitude(value) {
|
|
|
3192
3535
|
return value >= -180 && value <= 180;
|
|
3193
3536
|
}
|
|
3194
3537
|
function buildBusinessAddressDisplayText(input) {
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
trimmedStringOrNull(input.
|
|
3198
|
-
trimmedStringOrNull(input.
|
|
3199
|
-
|
|
3200
|
-
trimmedStringOrNull(input.
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3538
|
+
return formatLocationAddress({
|
|
3539
|
+
building: null,
|
|
3540
|
+
street: trimmedStringOrNull(input.addressLine1),
|
|
3541
|
+
unit: trimmedStringOrNull(input.addressLine2),
|
|
3542
|
+
floor: null,
|
|
3543
|
+
locality: trimmedStringOrNull(input.locality),
|
|
3544
|
+
region: trimmedStringOrNull(input.region),
|
|
3545
|
+
postalCode: trimmedStringOrNull(input.postalCode),
|
|
3546
|
+
country: normalizeCountryCode(input.countryCode)
|
|
3547
|
+
});
|
|
3204
3548
|
}
|
|
3205
3549
|
function validateBusinessAddressDraft(input) {
|
|
3206
3550
|
const addressLine1 = trimmedStringOrNull(input.addressLine1);
|
|
@@ -3372,6 +3716,18 @@ function syncStateOf(sync) {
|
|
|
3372
3716
|
* reload handover is only worth presenting within it (issue 1570).
|
|
3373
3717
|
*/
|
|
3374
3718
|
const EDIT_LEASE_TTL_SECONDS = 60;
|
|
3719
|
+
/** One-use navigation transport for the same previous-client acquire contract. */
|
|
3720
|
+
const EDIT_LEASE_HANDOVER_QUERY_PARAM = "edit_lease_handover";
|
|
3721
|
+
/** Frozen at editor mount; reacquiring a lease never advances this session's admission stamp. */
|
|
3722
|
+
const PAGE_DOCUMENT_SESSION_CHECKPOINT_HEADER = "X-Riverbank-Page-Checkpoint";
|
|
3723
|
+
function parsePageDocumentSessionCheckpoint(value) {
|
|
3724
|
+
if (value === "legacy") return { kind: "legacy" };
|
|
3725
|
+
const parsed = parsePageDocumentCheckpointId(value);
|
|
3726
|
+
return parsed.ok ? {
|
|
3727
|
+
kind: "document",
|
|
3728
|
+
checkpointId: parsed.value
|
|
3729
|
+
} : undefined;
|
|
3730
|
+
}
|
|
3375
3731
|
function parseEditLeaseScope(input) {
|
|
3376
3732
|
switch (input.nodeType) {
|
|
3377
3733
|
case "page": {
|
|
@@ -4050,7 +4406,7 @@ const knownSocialPlatformLabels = {
|
|
|
4050
4406
|
x: "X",
|
|
4051
4407
|
youtube: "YouTube"
|
|
4052
4408
|
};
|
|
4053
|
-
function isRecord$
|
|
4409
|
+
function isRecord$9(value) {
|
|
4054
4410
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4055
4411
|
}
|
|
4056
4412
|
function trimmedOptionalString(value) {
|
|
@@ -4060,7 +4416,7 @@ function trimmedOptionalString(value) {
|
|
|
4060
4416
|
return trimmed.length > 0 ? trimmed : null;
|
|
4061
4417
|
}
|
|
4062
4418
|
function parsePublicContactDetails(value) {
|
|
4063
|
-
if (!isRecord$
|
|
4419
|
+
if (!isRecord$9(value)) {
|
|
4064
4420
|
return err({
|
|
4065
4421
|
code: "invalid_shape",
|
|
4066
4422
|
path: "contact",
|
|
@@ -4156,7 +4512,7 @@ function minutesSinceMidnight(value) {
|
|
|
4156
4512
|
}
|
|
4157
4513
|
function parseOpeningHoursDay(value, expectedWeekday, index) {
|
|
4158
4514
|
const path = `openingHours.days.${index}`;
|
|
4159
|
-
if (!isRecord$
|
|
4515
|
+
if (!isRecord$9(value) || value.weekday !== expectedWeekday) {
|
|
4160
4516
|
return err({
|
|
4161
4517
|
code: "invalid_weekdays",
|
|
4162
4518
|
path,
|
|
@@ -4177,7 +4533,7 @@ function parseOpeningHoursDay(value, expectedWeekday, index) {
|
|
|
4177
4533
|
const intervals = [];
|
|
4178
4534
|
for (const [intervalIndex, rawInterval] of value.intervals.entries()) {
|
|
4179
4535
|
const intervalPath = `${path}.intervals.${intervalIndex}`;
|
|
4180
|
-
if (!isRecord$
|
|
4536
|
+
if (!isRecord$9(rawInterval)) {
|
|
4181
4537
|
return err({
|
|
4182
4538
|
code: "invalid_interval",
|
|
4183
4539
|
path: intervalPath,
|
|
@@ -4249,7 +4605,7 @@ function parseOpeningHoursWeek(rawDays) {
|
|
|
4249
4605
|
]);
|
|
4250
4606
|
}
|
|
4251
4607
|
function parseWeeklyOpeningHours(value) {
|
|
4252
|
-
if (!isRecord$
|
|
4608
|
+
if (!isRecord$9(value) || !Array.isArray(value.days) || value.days.length !== publicProfileWeekdays.length) {
|
|
4253
4609
|
return err({
|
|
4254
4610
|
code: "invalid_weekdays",
|
|
4255
4611
|
path: "openingHours.days",
|
|
@@ -4318,7 +4674,7 @@ function parsePublicSocialLinks(value) {
|
|
|
4318
4674
|
const ids = new Set();
|
|
4319
4675
|
for (const [index, rawLink] of value.entries()) {
|
|
4320
4676
|
const path = `socialLinks.${index}`;
|
|
4321
|
-
if (!isRecord$
|
|
4677
|
+
if (!isRecord$9(rawLink)) {
|
|
4322
4678
|
return err({
|
|
4323
4679
|
code: "invalid_social_link",
|
|
4324
4680
|
path,
|
|
@@ -4391,7 +4747,7 @@ function parsePublicProfilePresentation(value) {
|
|
|
4391
4747
|
});
|
|
4392
4748
|
}
|
|
4393
4749
|
function parsePublicProfile(value) {
|
|
4394
|
-
if (!isRecord$
|
|
4750
|
+
if (!isRecord$9(value)) {
|
|
4395
4751
|
return err({
|
|
4396
4752
|
code: "invalid_shape",
|
|
4397
4753
|
path: "",
|
|
@@ -4429,7 +4785,7 @@ function parseContactVisibility(value) {
|
|
|
4429
4785
|
email: "shown"
|
|
4430
4786
|
});
|
|
4431
4787
|
}
|
|
4432
|
-
if (!isRecord$
|
|
4788
|
+
if (!isRecord$9(value)) {
|
|
4433
4789
|
return err({
|
|
4434
4790
|
code: "invalid_contact_visibility",
|
|
4435
4791
|
path: "contactVisibility",
|
|
@@ -4573,7 +4929,7 @@ function parsePublicExperience(value) {
|
|
|
4573
4929
|
|
|
4574
4930
|
//#endregion
|
|
4575
4931
|
//#region ../core/src/rich-text.ts
|
|
4576
|
-
function isRecord$
|
|
4932
|
+
function isRecord$8(value) {
|
|
4577
4933
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4578
4934
|
}
|
|
4579
4935
|
function hasOnlyKeys(value, allowed) {
|
|
@@ -4595,10 +4951,10 @@ function isDenseArrayOf(value, predicate) {
|
|
|
4595
4951
|
return true;
|
|
4596
4952
|
}
|
|
4597
4953
|
function isTipTapMark(value) {
|
|
4598
|
-
return isRecord$
|
|
4954
|
+
return isRecord$8(value) && hasOnlyKeys(value, markKeys) && typeof value.type === "string" && value.type.length > 0 && (value.attrs === undefined || isRecord$8(value.attrs));
|
|
4599
4955
|
}
|
|
4600
4956
|
function isTipTapNode(value) {
|
|
4601
|
-
if (!isRecord$
|
|
4957
|
+
if (!isRecord$8(value) || !hasOnlyKeys(value, nodeKeys) || typeof value.type !== "string" || value.type.length === 0 || value.type === "doc" || value.attrs !== undefined && !isRecord$8(value.attrs) || value.marks !== undefined && (!Array.isArray(value.marks) || !isDenseArrayOf(value.marks, isTipTapMark)) || value.content !== undefined && (!Array.isArray(value.content) || !isDenseArrayOf(value.content, isTipTapNode))) {
|
|
4602
4958
|
return false;
|
|
4603
4959
|
}
|
|
4604
4960
|
if (value.type === "text") {
|
|
@@ -4607,7 +4963,7 @@ function isTipTapNode(value) {
|
|
|
4607
4963
|
return value.text === undefined;
|
|
4608
4964
|
}
|
|
4609
4965
|
function isCanonicalRichTextDoc(value) {
|
|
4610
|
-
return isRecord$
|
|
4966
|
+
return isRecord$8(value) && hasOnlyKeys(value, rootKeys) && value.type === "doc" && Array.isArray(value.content) && isDenseArrayOf(value.content, isTipTapNode);
|
|
4611
4967
|
}
|
|
4612
4968
|
|
|
4613
4969
|
//#endregion
|
|
@@ -4847,10 +5203,10 @@ function presentVisitorSelection(selection, optionCount) {
|
|
|
4847
5203
|
//#region ../core/src/mailing-list-targeting-parser.ts
|
|
4848
5204
|
function parseMailingListPlacementTargeting(value) {
|
|
4849
5205
|
if (value == null) return ok(DEFAULT_MAILING_LIST_TARGETING);
|
|
4850
|
-
if (!isRecord$
|
|
5206
|
+
if (!isRecord$7(value)) return targetingError("shape");
|
|
4851
5207
|
if (value.mode === "default") return ok({ mode: "default" });
|
|
4852
5208
|
if (value.mode !== "custom") return targetingError("mode");
|
|
4853
|
-
if (!isRecord$
|
|
5209
|
+
if (!isRecord$7(value.selection)) return targetingError("selection");
|
|
4854
5210
|
switch (value.provider) {
|
|
4855
5211
|
case "native": return parseNativeTargeting(value.selection);
|
|
4856
5212
|
case "brevo": return parseBrevoTargeting(value.selection);
|
|
@@ -4859,7 +5215,7 @@ function parseMailingListPlacementTargeting(value) {
|
|
|
4859
5215
|
}
|
|
4860
5216
|
}
|
|
4861
5217
|
function parseMailingListVisitorSelection(value) {
|
|
4862
|
-
if (!isRecord$
|
|
5218
|
+
if (!isRecord$7(value)) return visitorSelectionError("shape");
|
|
4863
5219
|
switch (value.provider) {
|
|
4864
5220
|
case "native": {
|
|
4865
5221
|
if (Object.keys(value).some((key) => key !== "provider" && key !== "topicIds")) return visitorSelectionError("shape");
|
|
@@ -4990,7 +5346,7 @@ function parseVisitorIds(value, parseId) {
|
|
|
4990
5346
|
const parsed = parseNonEmptyUniqueIds(value, parseId);
|
|
4991
5347
|
return parsed.ok ? parsed.value : null;
|
|
4992
5348
|
}
|
|
4993
|
-
function isRecord$
|
|
5349
|
+
function isRecord$7(value) {
|
|
4994
5350
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4995
5351
|
}
|
|
4996
5352
|
function targetingError(field) {
|
|
@@ -5008,7 +5364,7 @@ function visitorSelectionError(field) {
|
|
|
5008
5364
|
|
|
5009
5365
|
//#endregion
|
|
5010
5366
|
//#region ../core/src/footer-engagement.ts
|
|
5011
|
-
function isRecord$
|
|
5367
|
+
function isRecord$6(value) {
|
|
5012
5368
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5013
5369
|
}
|
|
5014
5370
|
function invalid(path, message) {
|
|
@@ -5042,7 +5398,7 @@ function parseEngagementBase(value, base, path) {
|
|
|
5042
5398
|
}
|
|
5043
5399
|
const treatment = parseTreatment(value.treatment, `${path}.treatment`);
|
|
5044
5400
|
if (!treatment.ok) return treatment;
|
|
5045
|
-
if (!isRecord$
|
|
5401
|
+
if (!isRecord$6(value.source)) {
|
|
5046
5402
|
return err(invalid(`${path}.source`, "Footer engagement source is invalid."));
|
|
5047
5403
|
}
|
|
5048
5404
|
const intro = parseBoundedText(value.source.intro, `${path}.source.intro`, {
|
|
@@ -5089,7 +5445,7 @@ function parseFooterEngagementSectionValue(value, sectionBase, path) {
|
|
|
5089
5445
|
const base = parseEngagementBase(value, sectionBase, path);
|
|
5090
5446
|
if (!base.ok) return base;
|
|
5091
5447
|
const source = value.source;
|
|
5092
|
-
if (!isRecord$
|
|
5448
|
+
if (!isRecord$6(source)) {
|
|
5093
5449
|
return err(invalid(`${path}.source`, "Footer engagement source is invalid."));
|
|
5094
5450
|
}
|
|
5095
5451
|
switch (source.kind) {
|
|
@@ -5250,7 +5606,7 @@ function unsafeAsFooterModuleId(value) {
|
|
|
5250
5606
|
function parseFooterModuleId(value) {
|
|
5251
5607
|
return parseSectionId(value, "sectionId");
|
|
5252
5608
|
}
|
|
5253
|
-
function isRecord$
|
|
5609
|
+
function isRecord$5(value) {
|
|
5254
5610
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5255
5611
|
}
|
|
5256
5612
|
function isRichText(value) {
|
|
@@ -5280,7 +5636,7 @@ function parseHeading(value, path) {
|
|
|
5280
5636
|
}
|
|
5281
5637
|
function parseFooterSection(value, index) {
|
|
5282
5638
|
const path = `sections.${index}`;
|
|
5283
|
-
if (!isRecord$
|
|
5639
|
+
if (!isRecord$5(value)) {
|
|
5284
5640
|
return err({
|
|
5285
5641
|
code: "invalid_section",
|
|
5286
5642
|
path,
|
|
@@ -5315,7 +5671,7 @@ function parseFooterSection(value, index) {
|
|
|
5315
5671
|
}
|
|
5316
5672
|
break;
|
|
5317
5673
|
case "navigation":
|
|
5318
|
-
if (isRecord$
|
|
5674
|
+
if (isRecord$5(value.source) && value.source.kind === "menu-role" && value.source.role === "main") {
|
|
5319
5675
|
return ok({
|
|
5320
5676
|
...base,
|
|
5321
5677
|
kind: "navigation",
|
|
@@ -5328,7 +5684,7 @@ function parseFooterSection(value, index) {
|
|
|
5328
5684
|
}
|
|
5329
5685
|
break;
|
|
5330
5686
|
case "legal-navigation":
|
|
5331
|
-
if (isRecord$
|
|
5687
|
+
if (isRecord$5(value.source) && value.source.kind === "menu-role" && value.source.role === "legal-policy") {
|
|
5332
5688
|
return ok({
|
|
5333
5689
|
...base,
|
|
5334
5690
|
kind: "legal-navigation",
|
|
@@ -5341,7 +5697,7 @@ function parseFooterSection(value, index) {
|
|
|
5341
5697
|
}
|
|
5342
5698
|
break;
|
|
5343
5699
|
case "business-address":
|
|
5344
|
-
if (isRecord$
|
|
5700
|
+
if (isRecord$5(value.source) && value.source.kind === "business-address") {
|
|
5345
5701
|
return ok({
|
|
5346
5702
|
...base,
|
|
5347
5703
|
kind: "business-address",
|
|
@@ -5353,7 +5709,7 @@ function parseFooterSection(value, index) {
|
|
|
5353
5709
|
case "contact":
|
|
5354
5710
|
case "opening-hours":
|
|
5355
5711
|
case "social-links":
|
|
5356
|
-
if (isRecord$
|
|
5712
|
+
if (isRecord$5(value.source) && value.source.kind === "public-profile") {
|
|
5357
5713
|
return ok({
|
|
5358
5714
|
...base,
|
|
5359
5715
|
kind: value.kind,
|
|
@@ -5405,7 +5761,7 @@ function validateFooterComposition(composition) {
|
|
|
5405
5761
|
return ok(composition);
|
|
5406
5762
|
}
|
|
5407
5763
|
function parseFooterCompositionV1(value) {
|
|
5408
|
-
if (!isRecord$
|
|
5764
|
+
if (!isRecord$5(value)) {
|
|
5409
5765
|
return err({
|
|
5410
5766
|
code: "invalid_shape",
|
|
5411
5767
|
path: "",
|
|
@@ -5438,7 +5794,7 @@ function parseFooterCompositionV1(value) {
|
|
|
5438
5794
|
});
|
|
5439
5795
|
}
|
|
5440
5796
|
function parseLegacyPlacementSection(value, index, selectedIds) {
|
|
5441
|
-
if (!isRecord$
|
|
5797
|
+
if (!isRecord$5(value)) {
|
|
5442
5798
|
return err({
|
|
5443
5799
|
code: "invalid_section",
|
|
5444
5800
|
path: `modules.${index}`,
|
|
@@ -5446,7 +5802,7 @@ function parseLegacyPlacementSection(value, index, selectedIds) {
|
|
|
5446
5802
|
});
|
|
5447
5803
|
}
|
|
5448
5804
|
const selected = typeof value.id === "string" && selectedIds.has(value.id);
|
|
5449
|
-
const source = isRecord$
|
|
5805
|
+
const source = isRecord$5(value.source) ? value.source : null;
|
|
5450
5806
|
const mapped = value.kind === "navigation" && source?.kind === "menu-role" && source.role === "footer" ? {
|
|
5451
5807
|
...value,
|
|
5452
5808
|
source: {
|
|
@@ -5465,7 +5821,7 @@ function parseLegacyPlacementSection(value, index, selectedIds) {
|
|
|
5465
5821
|
* It is intentionally not called by the runtime parser.
|
|
5466
5822
|
*/
|
|
5467
5823
|
function upgradePlacementFooterCompositionV1(value) {
|
|
5468
|
-
if (!isRecord$
|
|
5824
|
+
if (!isRecord$5(value) || value.schemaVersion !== 1 || !Array.isArray(value.modules) || !Array.isArray(value.placements)) {
|
|
5469
5825
|
return err({
|
|
5470
5826
|
code: "invalid_shape",
|
|
5471
5827
|
path: "",
|
|
@@ -5474,7 +5830,7 @@ function upgradePlacementFooterCompositionV1(value) {
|
|
|
5474
5830
|
}
|
|
5475
5831
|
const selectedIds = new Set();
|
|
5476
5832
|
for (const [index, placement] of value.placements.entries()) {
|
|
5477
|
-
if (!isRecord$
|
|
5833
|
+
if (!isRecord$5(placement) || typeof placement.moduleId !== "string") {
|
|
5478
5834
|
return err({
|
|
5479
5835
|
code: "invalid_shape",
|
|
5480
5836
|
path: `placements.${index}`,
|
|
@@ -5689,7 +6045,7 @@ const defaultSections = (legacy, options) => {
|
|
|
5689
6045
|
];
|
|
5690
6046
|
};
|
|
5691
6047
|
function normalizeLegacyFooterContentToV1(value, options = {}) {
|
|
5692
|
-
if (!isRecord$
|
|
6048
|
+
if (!isRecord$5(value)) {
|
|
5693
6049
|
return err({
|
|
5694
6050
|
code: "invalid_shape",
|
|
5695
6051
|
path: "",
|
|
@@ -5704,7 +6060,7 @@ function normalizeLegacyFooterContentToV1(value, options = {}) {
|
|
|
5704
6060
|
|
|
5705
6061
|
//#endregion
|
|
5706
6062
|
//#region ../core/src/mailing-list-setup.ts
|
|
5707
|
-
function isRecord$
|
|
6063
|
+
function isRecord$4(value) {
|
|
5708
6064
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5709
6065
|
}
|
|
5710
6066
|
/** The name shown to people for each provider; the native one is the product brand. */
|
|
@@ -5819,7 +6175,7 @@ function mailingListProviderScopeFromConfigured(provider) {
|
|
|
5819
6175
|
}
|
|
5820
6176
|
}
|
|
5821
6177
|
function parseMailingListProviderScope(value) {
|
|
5822
|
-
if (!isRecord$
|
|
6178
|
+
if (!isRecord$4(value)) return err("invalid_mailing_list_provider_scope");
|
|
5823
6179
|
if (value.provider === "native") return ok({ provider: "native" });
|
|
5824
6180
|
if (value.provider === "brevo") {
|
|
5825
6181
|
const accountId = parseBrevoAccountId(value.accountId);
|
|
@@ -5861,7 +6217,7 @@ const newsletterAudienceSchema = z.unknown().transform((value, ctx) => {
|
|
|
5861
6217
|
return z.NEVER;
|
|
5862
6218
|
});
|
|
5863
6219
|
function parseMailingListGlobalForm(value) {
|
|
5864
|
-
if (!isRecord$
|
|
6220
|
+
if (!isRecord$3(value)) return formError("shape");
|
|
5865
6221
|
const fields = parseGlobalFields(value.fields);
|
|
5866
6222
|
if (fields === null) return formError("fields");
|
|
5867
6223
|
if (typeof value.includeOptionalPhone !== "boolean") {
|
|
@@ -5882,7 +6238,7 @@ function parseMailingListGlobalForm(value) {
|
|
|
5882
6238
|
});
|
|
5883
6239
|
}
|
|
5884
6240
|
function parseMailingListSiteSetup(value) {
|
|
5885
|
-
if (!isRecord$
|
|
6241
|
+
if (!isRecord$3(value)) return setupError("shape");
|
|
5886
6242
|
const siteId = parseSiteId(value.siteId);
|
|
5887
6243
|
if (!siteId.ok) return setupError("siteId");
|
|
5888
6244
|
if (value.tag === "not_configured") {
|
|
@@ -5912,7 +6268,7 @@ function parseConfiguredSiteSetup(value, siteId) {
|
|
|
5912
6268
|
});
|
|
5913
6269
|
}
|
|
5914
6270
|
function parseConfiguredMailingListProvider(value) {
|
|
5915
|
-
if (!isRecord$
|
|
6271
|
+
if (!isRecord$3(value) || typeof value.provider !== "string") {
|
|
5916
6272
|
return setupError("provider");
|
|
5917
6273
|
}
|
|
5918
6274
|
switch (value.provider) {
|
|
@@ -5966,7 +6322,7 @@ function parseBrevoSetup(value) {
|
|
|
5966
6322
|
});
|
|
5967
6323
|
}
|
|
5968
6324
|
function parseNewsletterAudience(value) {
|
|
5969
|
-
if (!isRecord$
|
|
6325
|
+
if (!isRecord$3(value)) return err("invalid_newsletter_audience");
|
|
5970
6326
|
if (value.kind === "general" && Object.keys(value).length === 1) {
|
|
5971
6327
|
return ok({ kind: "general" });
|
|
5972
6328
|
}
|
|
@@ -5980,7 +6336,7 @@ function parseNewsletterAudience(value) {
|
|
|
5980
6336
|
});
|
|
5981
6337
|
}
|
|
5982
6338
|
function parseGlobalFields(value) {
|
|
5983
|
-
if (!isRecord$
|
|
6339
|
+
if (!isRecord$3(value) || typeof value.preset !== "string") return null;
|
|
5984
6340
|
switch (value.preset) {
|
|
5985
6341
|
case "emailOnly": return { preset: "emailOnly" };
|
|
5986
6342
|
case "emailName": return isRequirement(value.name) ? {
|
|
@@ -6005,11 +6361,11 @@ function parseGlobalFields(value) {
|
|
|
6005
6361
|
}
|
|
6006
6362
|
}
|
|
6007
6363
|
function parseToggleConfirmation(value) {
|
|
6008
|
-
if (!isRecord$
|
|
6364
|
+
if (!isRecord$3(value)) return null;
|
|
6009
6365
|
return value.tag === "on" || value.tag === "off" ? { tag: value.tag } : null;
|
|
6010
6366
|
}
|
|
6011
6367
|
function parseBrevoConfirmation(value) {
|
|
6012
|
-
if (!isRecord$
|
|
6368
|
+
if (!isRecord$3(value)) return null;
|
|
6013
6369
|
if (value.tag === "off") return { tag: "off" };
|
|
6014
6370
|
if (value.tag !== "on") return null;
|
|
6015
6371
|
const templateId = parseBrevoConfirmationTemplateId(value.templateId);
|
|
@@ -6046,7 +6402,7 @@ function parseOptionalString(value) {
|
|
|
6046
6402
|
function isRequirement(value) {
|
|
6047
6403
|
return value === "required" || value === "optional";
|
|
6048
6404
|
}
|
|
6049
|
-
function isRecord$
|
|
6405
|
+
function isRecord$3(value) {
|
|
6050
6406
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6051
6407
|
}
|
|
6052
6408
|
function formError(field) {
|
|
@@ -6169,7 +6525,7 @@ function assessMatchedChoices(matched, choices) {
|
|
|
6169
6525
|
//#endregion
|
|
6170
6526
|
//#region ../core/src/mailing-list-runtime.ts
|
|
6171
6527
|
function parseMailingListRuntimeContext(value) {
|
|
6172
|
-
if (!isRecord$
|
|
6528
|
+
if (!isRecord$2(value)) return invalidRuntimeContext();
|
|
6173
6529
|
if (value.tag === "not_configured") return ok({ tag: "not_configured" });
|
|
6174
6530
|
if (value.tag !== "configured") return invalidRuntimeContext();
|
|
6175
6531
|
return parseConfiguredRuntimeContext(value);
|
|
@@ -6217,7 +6573,7 @@ function parseBookingSignupOffer(value) {
|
|
|
6217
6573
|
tag: "unavailable",
|
|
6218
6574
|
reason: "disabled"
|
|
6219
6575
|
};
|
|
6220
|
-
if (!isRecord$
|
|
6576
|
+
if (!isRecord$2(value)) return null;
|
|
6221
6577
|
if (value.tag === "offered") return { tag: "offered" };
|
|
6222
6578
|
if (value.tag === "unavailable" && (value.reason === "disabled" || value.reason === "fields" || value.reason === "destination")) {
|
|
6223
6579
|
return {
|
|
@@ -6228,7 +6584,7 @@ function parseBookingSignupOffer(value) {
|
|
|
6228
6584
|
return null;
|
|
6229
6585
|
}
|
|
6230
6586
|
function parseRuntimeProvider(value) {
|
|
6231
|
-
if (!isRecord$
|
|
6587
|
+
if (!isRecord$2(value)) return null;
|
|
6232
6588
|
switch (value.provider) {
|
|
6233
6589
|
case "native": return parseNativeRuntimeProvider(value);
|
|
6234
6590
|
case "brevo": return parseBrevoRuntimeProvider(value);
|
|
@@ -6266,7 +6622,7 @@ function parseMailchimpRuntimeProvider(value) {
|
|
|
6266
6622
|
} : null;
|
|
6267
6623
|
}
|
|
6268
6624
|
function parseMailchimpAudience(value) {
|
|
6269
|
-
if (!isRecord$
|
|
6625
|
+
if (!isRecord$2(value) || !Array.isArray(value.interests)) return null;
|
|
6270
6626
|
const id = parseMailchimpAudienceId(value.id);
|
|
6271
6627
|
const name = parseName(value.name);
|
|
6272
6628
|
const interests = Array.from(value.interests, parseMailchimpInterest);
|
|
@@ -6277,7 +6633,7 @@ function parseMailchimpAudience(value) {
|
|
|
6277
6633
|
} : null;
|
|
6278
6634
|
}
|
|
6279
6635
|
function parseMailchimpInterest(value) {
|
|
6280
|
-
if (!isRecord$
|
|
6636
|
+
if (!isRecord$2(value)) return null;
|
|
6281
6637
|
const id = parseMailchimpInterestId(value.id);
|
|
6282
6638
|
const name = parseName(value.name);
|
|
6283
6639
|
const categoryName = parseName(value.categoryName);
|
|
@@ -6290,7 +6646,7 @@ function parseMailchimpInterest(value) {
|
|
|
6290
6646
|
function parseNamedItems(value, parseId) {
|
|
6291
6647
|
if (!Array.isArray(value)) return null;
|
|
6292
6648
|
const items = Array.from(value, (item) => {
|
|
6293
|
-
if (!isRecord$
|
|
6649
|
+
if (!isRecord$2(item)) return null;
|
|
6294
6650
|
const id = parseId(item.id);
|
|
6295
6651
|
const name = parseName(item.name);
|
|
6296
6652
|
return id !== null && name !== null ? {
|
|
@@ -6305,7 +6661,7 @@ function parseName(value) {
|
|
|
6305
6661
|
const name = value.trim();
|
|
6306
6662
|
return name.length > 0 ? name : null;
|
|
6307
6663
|
}
|
|
6308
|
-
function isRecord$
|
|
6664
|
+
function isRecord$2(value) {
|
|
6309
6665
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6310
6666
|
}
|
|
6311
6667
|
function invalidRuntimeContext() {
|
|
@@ -6579,11 +6935,11 @@ const PRIORITY_IDS = new Set([
|
|
|
6579
6935
|
"emailaddress"
|
|
6580
6936
|
]);
|
|
6581
6937
|
const MAX_COLUMNS = 5;
|
|
6582
|
-
function isRecord(value) {
|
|
6938
|
+
function isRecord$1(value) {
|
|
6583
6939
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6584
6940
|
}
|
|
6585
6941
|
function isSchemaField(value) {
|
|
6586
|
-
return isRecord(value) && typeof value.id === "string";
|
|
6942
|
+
return isRecord$1(value) && typeof value.id === "string";
|
|
6587
6943
|
}
|
|
6588
6944
|
function selectSubmissionPreviewFields(schemaFields, submissions) {
|
|
6589
6945
|
const fields = Array.isArray(schemaFields) ? schemaFields.filter(isSchemaField) : [];
|
|
@@ -6676,7 +7032,7 @@ function valueIsMeaningful(value) {
|
|
|
6676
7032
|
if (value === null || value === undefined) return false;
|
|
6677
7033
|
if (typeof value === "string") return value.trim().length > 0;
|
|
6678
7034
|
if (Array.isArray(value)) return value.length > 0;
|
|
6679
|
-
if (isRecord(value)) return Object.keys(value).length > 0;
|
|
7035
|
+
if (isRecord$1(value)) return Object.keys(value).length > 0;
|
|
6680
7036
|
return true;
|
|
6681
7037
|
}
|
|
6682
7038
|
function orderSubmissionFields(schemaFields, data) {
|
|
@@ -8471,4 +8827,32 @@ function resolvePublicSiteVisibility(input) {
|
|
|
8471
8827
|
}
|
|
8472
8828
|
|
|
8473
8829
|
//#endregion
|
|
8474
|
-
|
|
8830
|
+
//#region ../core/src/authored-values.ts
|
|
8831
|
+
/** Canonical authored equality: empty storage values and absent optional members agree. */
|
|
8832
|
+
function canonicalAuthoredValue(value) {
|
|
8833
|
+
if (value == null || value === "" || typeof value === "number" && Number.isNaN(value)) return null;
|
|
8834
|
+
if (Array.isArray(value)) return value.map(canonicalAuthoredValue);
|
|
8835
|
+
if (typeof value !== "object") return value;
|
|
8836
|
+
const entries = Object.entries(value).sort(([a], [b]) => a.localeCompare(b)).map(([key, member]) => [key, canonicalAuthoredValue(member)]).filter(([, member]) => member !== null);
|
|
8837
|
+
return entries.length === 0 ? null : Object.fromEntries(entries);
|
|
8838
|
+
}
|
|
8839
|
+
function authoredValuesEqual(left, right) {
|
|
8840
|
+
return JSON.stringify(canonicalAuthoredValue(left)) === JSON.stringify(canonicalAuthoredValue(right));
|
|
8841
|
+
}
|
|
8842
|
+
|
|
8843
|
+
//#endregion
|
|
8844
|
+
//#region ../core/src/record-guards.ts
|
|
8845
|
+
function isRecord(value) {
|
|
8846
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8847
|
+
}
|
|
8848
|
+
/**
|
|
8849
|
+
* Type guard for plain object records (excludes class instances like Error/Date).
|
|
8850
|
+
*/
|
|
8851
|
+
function isPlainRecord(value) {
|
|
8852
|
+
if (!isRecord(value)) return false;
|
|
8853
|
+
const proto = Object.getPrototypeOf(value);
|
|
8854
|
+
return proto === Object.prototype || proto === null;
|
|
8855
|
+
}
|
|
8856
|
+
|
|
8857
|
+
//#endregion
|
|
8858
|
+
export { inferSiteDateLocale as $, parseCurrencyCode as $t, assessMailingListTargeting as A, unsafeAsPositiveByteCount as An, resolveFlexibleBalanceInitialPaymentCents as At, parsePublicContactDetails as B, unsafeAsStoragePath as Bn, resolveExactOrFreePriceDisplay as Bt, parseManagementKey as C, unsafeAsEventOfferingId as Cn, clampConfiguredAmount as Ct, parseMailingListContentVersionId as D, unsafeAsOccurrenceId as Dn, omitZeroAmountFutureRows as Dt, parseMailingListBlockId as E, unsafeAsMediaAssetId as En, getBookingInstalmentProtectedDepositAmountCents as Et, parseMailingListPlacementTargeting as F, unsafeAsSiteFontId as Fn, isPublicEventPricingOptionDisplayable as Ft, isPresent as G, isNonNegativeWholeCents as Gt, assertAllowedPublicUrl as H, unsafeAsUserId as Hn, fromArray as Ht, DEFAULT_MAILING_LIST_TARGETING as I, unsafeAsSiteId as In, publicEventPricingCurrency as It, formatDateRange as J, toCents as Jt, selectCategoryView as K, parseNonNegativeCents as Kt, planMailingListChoicePresentation as L, unsafeAsSiteScopedStoragePath as Ln, publicEventPricingDisplay as Lt, parseMailingListProviderScope as M, unsafeAsPricingOptionId as Mn, parseEventPageSurfaceSubject as Mt, parseFooterCompositionV1 as N, unsafeAsProductId as Nn, formatBookingPriceDisplay as Nt, parseMailingListSignedSourceToken as O, unsafeAsOriginalFilename as On, splitAmountWithRemainderInFirst as Ot, footerNavigationLayouts as P, unsafeAsSafeDownloadFilename as Pn, formatEventPricing as Pt, formatTimeRange as Q, formatCurrencyAmount as Qt, isCanonicalRichTextDoc as R, unsafeAsStaffMemberId as Rn, publicEventPricingOptions as Rt, exposeSecret as S, unsafeAsEventInstanceId as Sn, addIntervalPreservingMonthAnchor as St, slugify as T, unsafeAsFileChecksumSha256 as Tn, getBookingInstalmentPlanIntervalCount as Tt, normalizeLocationAddressText as U, err as Un, mapNonEmptyArray as Ut, parseWeeklyOpeningHours as V, unsafeAsUploadSessionId as Vn, resolvePricingOptionsPriceDisplay as Vt, toLocationCoordinates as W, ok as Wn, mapReadonlyNonEmptyArray as Wt, formatDateTimeRange as X, unsafeAsNonNegativeCents as Xt, formatDateTime as Y, toNonNegativeCents as Yt, formatTime as Z, unsafeAsPositiveCents as Zt, nextLiveRunSessionStartMs as _, unsafeAsCheckoutLineId as _n, parseBookingTimeZone as _t, areConfiguredBookingVerticalConfigsEqual as a, parseDatedOfferingCapacityHoldId as an, getBookingLocalDateKey as at, resolveWholeSeriesRunLifecycle as b, unsafeAsDetectedMimeType as bn, isSettleableFlexibleBalanceContractStatus as bt, parseVerticalPresetId as c, parseMembershipId as cn, localScheduleTimePattern as ct, EVENT_PRESET_VALUES as d, parseSiteId as dn, parseUtcIsoDateTimeString as dt, assertNever as en, resolveBookingDisplayContext as et, ORDINARY_EVENT_PRESET_VALUES as f, parseSiteTermsVersionId as fn, resolveBookingBusinessTimeZone as ft, CANCELLED_SESSION_STATUS as g, unsafeAsBookingSessionId as gn, toUtcIsoDateTimeString as gt, publicReadFreshnessSeconds as h, unsafeAsBookingRequirementId as hn, toScheduledBookingDateTime as ht, NAVIGATION_LOCATIONS as i, parseDatedOfferingCapacityHoldAuditRef as in, formatLocalScheduleTime as it, DEFAULT_MAILING_LIST_SUCCESS_MESSAGE as j, unsafeAsPositiveSeconds as jn, deriveTotalTicketQuantity as jt, parseMailingListRuntimeContext as k, unsafeAsPassId as kn, resolveFlexibleBalanceDueAt as kt, resolveSiteVerticalBookingConfig as l, parsePageId as ln, parseBookingLocalDate as lt, WHOLE_SERIES_EVENT_PRESET_VALUES as m, unsafeAsAppointmentResourceId as mn, toBookingTimeZone as mt, resolveEventCatalogue as n, parseApiKeyId as nn, compareLocalScheduleDates as nt, canonicalizeConfiguredBookingVerticalConfig as o, parseEventSeriesId as on, getLocalScheduleDate as ot, SURFACE_EVENT_PRESET_VALUES as p, parseUserId as pn, resolveBookingTimeZoneId as pt, formatDate as q, parsePositiveCents as qt, EVENT_PRESET_VOCABULARY as r, parseCustomerId as rn, formatLocalScheduleDate as rt, parseVerticalId as s, parseMediaAssetId as sn, getLocalScheduleTime as st, authoredValuesEqual as t, formatDurationUnitLabel as tn, buildBookingUtcDateWindow as tt, DEFAULT_EVENT_TYPE_PRESETS as u, parseRetiredCourseId as un, parseLocalScheduleTime as ut, orderedLiveRunSessions as v, unsafeAsDeclaredMimeType as vn, validateBookingPaymentOptionKinds as vt, stableJsonStringify as w, unsafeAsEventSeriesId as wn, getBookingInstalmentDepositRefundability as wt, createSecret as x, unsafeAsEntitlementId as xn, isSettleableOrderInstalmentPlanStatus as xt, resolveWholeSeriesBookingPhase as y, unsafeAsDemoCapability as yn, isLiveOrderInstalmentPlanStatus as yt, formatOpeningHoursRows as z, unsafeAsStorageBucketName as zn, publicEventPricingType as zt };
|