@siteoshq/cli 1.3.0 → 1.5.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/README.md +50 -0
- package/dist/cli.js +514 -40
- package/dist/cli.js.map +1 -1
- package/package.json +3 -1
package/dist/cli.js
CHANGED
|
@@ -2936,6 +2936,8 @@ function isCliExitCode(value) {
|
|
|
2936
2936
|
import { readFile as readFile5 } from "fs/promises";
|
|
2937
2937
|
import path12 from "path";
|
|
2938
2938
|
import { z as z10 } from "zod";
|
|
2939
|
+
import { Ajv } from "ajv";
|
|
2940
|
+
import addFormats from "ajv-formats";
|
|
2939
2941
|
|
|
2940
2942
|
// src/siteos-forms-api.ts
|
|
2941
2943
|
import { z as z9 } from "zod";
|
|
@@ -2971,12 +2973,82 @@ var formDefinitionSyncResponseSchema = z9.object({
|
|
|
2971
2973
|
success: z9.literal(true),
|
|
2972
2974
|
version: z9.number().int().positive()
|
|
2973
2975
|
}).strict();
|
|
2976
|
+
var definitionSchema = z9.object({
|
|
2977
|
+
id: opaqueIdentifierSchema,
|
|
2978
|
+
environmentId: opaqueIdentifierSchema,
|
|
2979
|
+
formKey: opaqueIdentifierSchema,
|
|
2980
|
+
name: z9.string(),
|
|
2981
|
+
sourcePagePath: z9.string().nullable(),
|
|
2982
|
+
activeVersion: z9.number().int().positive(),
|
|
2983
|
+
activeVersionId: opaqueIdentifierSchema,
|
|
2984
|
+
status: z9.enum(["active", "inactive"]),
|
|
2985
|
+
submissionCount: z9.number().int().nonnegative(),
|
|
2986
|
+
lastSubmittedAt: z9.string().datetime({ offset: true }).nullable(),
|
|
2987
|
+
createdAt: z9.string().datetime({ offset: true }),
|
|
2988
|
+
updatedAt: z9.string().datetime({ offset: true })
|
|
2989
|
+
});
|
|
2990
|
+
var definitionListSchema = z9.object({
|
|
2991
|
+
definitions: z9.array(definitionSchema)
|
|
2992
|
+
});
|
|
2993
|
+
var definitionContextSchema = z9.object({
|
|
2994
|
+
definition: definitionSchema,
|
|
2995
|
+
revision: z9.number().int().positive(),
|
|
2996
|
+
canManage: z9.boolean(),
|
|
2997
|
+
project: z9.object({ id: opaqueIdentifierSchema, name: z9.string() }),
|
|
2998
|
+
environment: z9.object({
|
|
2999
|
+
id: opaqueIdentifierSchema,
|
|
3000
|
+
name: z9.string(),
|
|
3001
|
+
slug: z9.string()
|
|
3002
|
+
})
|
|
3003
|
+
});
|
|
3004
|
+
var definitionChangeResponseSchema = z9.object({
|
|
3005
|
+
deleted: z9.boolean(),
|
|
3006
|
+
formId: opaqueIdentifierSchema
|
|
3007
|
+
});
|
|
2974
3008
|
var formSubmissionResponseSchema = z9.object({
|
|
2975
3009
|
formId: opaqueIdentifierSchema,
|
|
2976
3010
|
receivedAt: z9.string().datetime({ offset: true }),
|
|
2977
3011
|
submissionId: opaqueIdentifierSchema,
|
|
2978
3012
|
success: z9.literal(true)
|
|
2979
3013
|
}).strict();
|
|
3014
|
+
var formsSubmissionStatusSchema = z9.enum([
|
|
3015
|
+
"new",
|
|
3016
|
+
"read",
|
|
3017
|
+
"archived",
|
|
3018
|
+
"spam"
|
|
3019
|
+
]);
|
|
3020
|
+
var submissionSummarySchema = z9.object({
|
|
3021
|
+
id: opaqueIdentifierSchema,
|
|
3022
|
+
formId: opaqueIdentifierSchema,
|
|
3023
|
+
normalized: z9.record(
|
|
3024
|
+
z9.union([z9.string(), z9.number(), z9.boolean(), z9.null()])
|
|
3025
|
+
),
|
|
3026
|
+
status: formsSubmissionStatusSchema,
|
|
3027
|
+
submittedAt: z9.string().datetime({ offset: true })
|
|
3028
|
+
});
|
|
3029
|
+
var submissionDetailSchema = submissionSummarySchema.extend({
|
|
3030
|
+
payload: z9.record(z9.unknown()),
|
|
3031
|
+
fields: z9.array(
|
|
3032
|
+
z9.object({
|
|
3033
|
+
key: z9.string(),
|
|
3034
|
+
label: z9.string().optional(),
|
|
3035
|
+
kind: z9.string().optional(),
|
|
3036
|
+
displayRole: z9.enum(["primary", "secondary"]).optional(),
|
|
3037
|
+
multiple: z9.boolean().optional(),
|
|
3038
|
+
options: z9.array(z9.object({ value: z9.string(), label: z9.string() })).optional()
|
|
3039
|
+
})
|
|
3040
|
+
),
|
|
3041
|
+
version: z9.number().int().positive(),
|
|
3042
|
+
versionId: opaqueIdentifierSchema
|
|
3043
|
+
});
|
|
3044
|
+
var submissionPageSchema = z9.object({
|
|
3045
|
+
submissions: z9.array(submissionSummarySchema),
|
|
3046
|
+
total: z9.number().int().nonnegative(),
|
|
3047
|
+
nextCursor: z9.string().nullable()
|
|
3048
|
+
});
|
|
3049
|
+
var submissionDetailResponseSchema = z9.object({
|
|
3050
|
+
submission: submissionDetailSchema
|
|
3051
|
+
});
|
|
2980
3052
|
var formsCredentialMetadataSchema = z9.object({
|
|
2981
3053
|
createdAt: z9.string().datetime({ offset: true }),
|
|
2982
3054
|
id: z9.string().trim().min(1).max(255),
|
|
@@ -2993,6 +3065,9 @@ var formsCredentialExchangeSchema = formsCredentialMetadataSchema.extend({
|
|
|
2993
3065
|
token: z9.string().regex(/^pfs_[A-Za-z0-9_-]{22}$/)
|
|
2994
3066
|
});
|
|
2995
3067
|
var formsErrorCodeSchema = z9.enum([
|
|
3068
|
+
"AUTHENTICATION_REQUIRED",
|
|
3069
|
+
"FORBIDDEN",
|
|
3070
|
+
"CONFLICT",
|
|
2996
3071
|
"INVALID_REQUEST",
|
|
2997
3072
|
"INVALID_INPUT",
|
|
2998
3073
|
"VALIDATION_FAILED",
|
|
@@ -3000,6 +3075,8 @@ var formsErrorCodeSchema = z9.enum([
|
|
|
3000
3075
|
"UNAUTHORIZED",
|
|
3001
3076
|
"IDENTITY_REQUIRED",
|
|
3002
3077
|
"NOT_ALLOWED",
|
|
3078
|
+
"FORM_ARCHIVED",
|
|
3079
|
+
"FORM_DELETED",
|
|
3003
3080
|
"NOT_FOUND",
|
|
3004
3081
|
"PROJECT_NOT_FOUND",
|
|
3005
3082
|
"PROJECT_CONFLICT",
|
|
@@ -3012,6 +3089,9 @@ var formsErrorCodeSchema = z9.enum([
|
|
|
3012
3089
|
"INTERNAL_ERROR"
|
|
3013
3090
|
]);
|
|
3014
3091
|
var safeFormsErrorMessages = {
|
|
3092
|
+
AUTHENTICATION_REQUIRED: "Sign in to SiteOS before reading Forms submissions.",
|
|
3093
|
+
FORBIDDEN: "Forms management access is denied.",
|
|
3094
|
+
CONFLICT: "The resource changed or this idempotency key belongs to different data. Read the current state before retrying.",
|
|
3015
3095
|
INVALID_REQUEST: "The Forms request is invalid.",
|
|
3016
3096
|
INVALID_INPUT: "Invalid input data.",
|
|
3017
3097
|
VALIDATION_FAILED: "Validation failed.",
|
|
@@ -3019,6 +3099,8 @@ var safeFormsErrorMessages = {
|
|
|
3019
3099
|
UNAUTHORIZED: "Forms management authorization is invalid.",
|
|
3020
3100
|
IDENTITY_REQUIRED: "Forms browser identity is required.",
|
|
3021
3101
|
NOT_ALLOWED: "Forms management access is denied.",
|
|
3102
|
+
FORM_ARCHIVED: "This form is archived. Restore it explicitly before syncing or sending new submissions.",
|
|
3103
|
+
FORM_DELETED: "This form was permanently deleted. Use a new form key for a new form.",
|
|
3022
3104
|
NOT_FOUND: "The requested resource was not found.",
|
|
3023
3105
|
PROJECT_NOT_FOUND: "The Forms Project was not found.",
|
|
3024
3106
|
PROJECT_CONFLICT: "The Forms Project already exists.",
|
|
@@ -3051,9 +3133,83 @@ function resolveSiteOSFormsBaseUrl(env = process.env) {
|
|
|
3051
3133
|
env[SITEOS_FORMS_BASE_URL_ENV]?.trim() || DEFAULT_SITEOS_FORMS_BASE_URL
|
|
3052
3134
|
);
|
|
3053
3135
|
}
|
|
3136
|
+
var deploymentResponseSchema = z9.object({
|
|
3137
|
+
environmentId: opaqueIdentifierSchema,
|
|
3138
|
+
forms: z9.array(
|
|
3139
|
+
z9.object({
|
|
3140
|
+
formKey: opaqueIdentifierSchema,
|
|
3141
|
+
formId: opaqueIdentifierSchema,
|
|
3142
|
+
contractVersion: z9.string().regex(/^sha256:[a-f0-9]{64}$/),
|
|
3143
|
+
versionId: opaqueIdentifierSchema,
|
|
3144
|
+
version: z9.number().int().positive()
|
|
3145
|
+
})
|
|
3146
|
+
)
|
|
3147
|
+
});
|
|
3054
3148
|
function createSiteOSFormsApiClient(options) {
|
|
3055
3149
|
const apiBaseUrl = normalizeFormsOrigin(options.apiBaseUrl);
|
|
3150
|
+
const inboxPath = (input) => `/api/v1/forms/environments/${encodeURIComponent(input.environmentId)}/forms/${encodeURIComponent(input.formId)}/submissions`;
|
|
3151
|
+
const definitionPath = (input) => `/api/v1/forms/environments/${encodeURIComponent(input.environmentId)}/forms/${encodeURIComponent(input.formId)}`;
|
|
3152
|
+
const keyCollection = (input) => options.deploymentKeys ? `${environmentItemPath(input)}/deployment-keys` : credentialCollectionPath(input);
|
|
3056
3153
|
return {
|
|
3154
|
+
publishDefinitions: (input) => requestJson2({
|
|
3155
|
+
apiBaseUrl,
|
|
3156
|
+
fetchImpl: options.fetchImpl,
|
|
3157
|
+
method: "POST",
|
|
3158
|
+
path: "/api/forms/deployments",
|
|
3159
|
+
body: { definitions: input.definitions },
|
|
3160
|
+
headers: { "x-siteos-forms-deployment-key": input.credential },
|
|
3161
|
+
responseSchema: deploymentResponseSchema
|
|
3162
|
+
}),
|
|
3163
|
+
listDefinitions: (input) => requestJson2({
|
|
3164
|
+
apiBaseUrl,
|
|
3165
|
+
fetchImpl: options.fetchImpl,
|
|
3166
|
+
headers: managementHeaders(input),
|
|
3167
|
+
method: "GET",
|
|
3168
|
+
path: `/api/v1/forms/environments/${encodeURIComponent(input.environmentId)}/definitions?status=${input.status}`,
|
|
3169
|
+
responseSchema: definitionListSchema
|
|
3170
|
+
}),
|
|
3171
|
+
readDefinition: (input) => requestJson2({
|
|
3172
|
+
apiBaseUrl,
|
|
3173
|
+
fetchImpl: options.fetchImpl,
|
|
3174
|
+
headers: managementHeaders(input),
|
|
3175
|
+
method: "GET",
|
|
3176
|
+
path: definitionPath(input),
|
|
3177
|
+
responseSchema: definitionContextSchema
|
|
3178
|
+
}),
|
|
3179
|
+
changeDefinition: (input) => requestJson2({
|
|
3180
|
+
apiBaseUrl,
|
|
3181
|
+
fetchImpl: options.fetchImpl,
|
|
3182
|
+
headers: managementHeaders(input),
|
|
3183
|
+
method: "PATCH",
|
|
3184
|
+
path: definitionPath(input),
|
|
3185
|
+
body: input.change,
|
|
3186
|
+
responseSchema: definitionChangeResponseSchema
|
|
3187
|
+
}),
|
|
3188
|
+
listSubmissions: (input) => requestJson2({
|
|
3189
|
+
apiBaseUrl,
|
|
3190
|
+
fetchImpl: options.fetchImpl,
|
|
3191
|
+
headers: managementHeaders(input),
|
|
3192
|
+
method: "GET",
|
|
3193
|
+
path: `${inboxPath(input)}?${input.filters}`,
|
|
3194
|
+
responseSchema: submissionPageSchema
|
|
3195
|
+
}),
|
|
3196
|
+
readSubmission: (input) => requestJson2({
|
|
3197
|
+
apiBaseUrl,
|
|
3198
|
+
fetchImpl: options.fetchImpl,
|
|
3199
|
+
headers: managementHeaders(input),
|
|
3200
|
+
method: "GET",
|
|
3201
|
+
path: `${inboxPath(input)}/${encodeURIComponent(input.submissionId)}`,
|
|
3202
|
+
responseSchema: submissionDetailResponseSchema
|
|
3203
|
+
}),
|
|
3204
|
+
updateSubmissionStatus: (input) => requestJson2({
|
|
3205
|
+
apiBaseUrl,
|
|
3206
|
+
fetchImpl: options.fetchImpl,
|
|
3207
|
+
headers: managementHeaders(input),
|
|
3208
|
+
method: "PATCH",
|
|
3209
|
+
path: `${inboxPath(input)}/${encodeURIComponent(input.submissionId)}`,
|
|
3210
|
+
body: { status: input.status, expectedStatus: input.expectedStatus },
|
|
3211
|
+
responseSchema: submissionDetailResponseSchema
|
|
3212
|
+
}),
|
|
3057
3213
|
createProject: (input) => requestJson2({
|
|
3058
3214
|
apiBaseUrl,
|
|
3059
3215
|
body: { name: input.name, slug: input.slug },
|
|
@@ -3078,8 +3234,10 @@ function createSiteOSFormsApiClient(options) {
|
|
|
3078
3234
|
fetchImpl: options.fetchImpl,
|
|
3079
3235
|
headers: managementHeaders(input),
|
|
3080
3236
|
method: "POST",
|
|
3081
|
-
path:
|
|
3082
|
-
responseSchema: formsCredentialExchangeSchema
|
|
3237
|
+
path: keyCollection(input),
|
|
3238
|
+
responseSchema: options.deploymentKeys ? formsCredentialExchangeSchema.extend({
|
|
3239
|
+
token: z9.string().regex(/^pfd_[A-Za-z0-9_-]{43}$/)
|
|
3240
|
+
}) : formsCredentialExchangeSchema
|
|
3083
3241
|
}),
|
|
3084
3242
|
listEnvironments: (input) => requestJson2({
|
|
3085
3243
|
apiBaseUrl,
|
|
@@ -3102,7 +3260,7 @@ function createSiteOSFormsApiClient(options) {
|
|
|
3102
3260
|
fetchImpl: options.fetchImpl,
|
|
3103
3261
|
headers: managementHeaders(input),
|
|
3104
3262
|
method: "GET",
|
|
3105
|
-
path:
|
|
3263
|
+
path: keyCollection(input),
|
|
3106
3264
|
responseSchema: formsCredentialListSchema
|
|
3107
3265
|
}),
|
|
3108
3266
|
revokeCredential: (input) => requestJson2({
|
|
@@ -3110,7 +3268,7 @@ function createSiteOSFormsApiClient(options) {
|
|
|
3110
3268
|
fetchImpl: options.fetchImpl,
|
|
3111
3269
|
headers: managementHeaders(input),
|
|
3112
3270
|
method: "DELETE",
|
|
3113
|
-
path: credentialItemPath(input),
|
|
3271
|
+
path: options.deploymentKeys ? `${keyCollection(input)}/${encodeURIComponent(input.credentialId)}` : credentialItemPath(input),
|
|
3114
3272
|
responseSchema: formsCredentialMetadataSchema
|
|
3115
3273
|
}),
|
|
3116
3274
|
rotateCredential: (input) => requestJson2({
|
|
@@ -3120,7 +3278,9 @@ function createSiteOSFormsApiClient(options) {
|
|
|
3120
3278
|
headers: managementHeaders(input),
|
|
3121
3279
|
method: "POST",
|
|
3122
3280
|
path: credentialRotatePath(input),
|
|
3123
|
-
responseSchema: formsCredentialExchangeSchema
|
|
3281
|
+
responseSchema: options.deploymentKeys ? formsCredentialExchangeSchema.extend({
|
|
3282
|
+
token: z9.string().regex(/^pfd_[A-Za-z0-9_-]{43}$/)
|
|
3283
|
+
}) : formsCredentialExchangeSchema
|
|
3124
3284
|
}),
|
|
3125
3285
|
submitForm: (input) => requestJson2({
|
|
3126
3286
|
apiBaseUrl,
|
|
@@ -3154,7 +3314,9 @@ async function requestJson2(options) {
|
|
|
3154
3314
|
...options.body === void 0 ? {} : { "Content-Type": "application/json" },
|
|
3155
3315
|
...options.headers
|
|
3156
3316
|
},
|
|
3157
|
-
method: options.method
|
|
3317
|
+
method: options.method,
|
|
3318
|
+
redirect: "error",
|
|
3319
|
+
signal: AbortSignal.timeout(3e4)
|
|
3158
3320
|
});
|
|
3159
3321
|
} catch {
|
|
3160
3322
|
throw new SiteOSFormsApiError({
|
|
@@ -3247,7 +3409,7 @@ import {
|
|
|
3247
3409
|
} from "fs/promises";
|
|
3248
3410
|
import path11 from "path";
|
|
3249
3411
|
var SITEOS_FORMS_SUBMISSION_CREDENTIAL_ENV = "SITEOS_FORMS_SUBMISSION_CREDENTIAL";
|
|
3250
|
-
var
|
|
3412
|
+
var SITEOS_FORMS_DEPLOYMENT_KEY_ENV = "SITEOS_FORMS_DEPLOYMENT_KEY";
|
|
3251
3413
|
var SiteOSFormsCredentialStorageError = class extends Error {
|
|
3252
3414
|
code;
|
|
3253
3415
|
constructor(code) {
|
|
@@ -3259,6 +3421,8 @@ var SiteOSFormsCredentialStorageError = class extends Error {
|
|
|
3259
3421
|
}
|
|
3260
3422
|
};
|
|
3261
3423
|
async function prepareSiteOSFormsCredentialInstallation(options) {
|
|
3424
|
+
const variable = options.deployment ? SITEOS_FORMS_DEPLOYMENT_KEY_ENV : SITEOS_FORMS_SUBMISSION_CREDENTIAL_ENV;
|
|
3425
|
+
const credentialPattern = options.deployment ? /^pfd_[A-Za-z0-9_-]{43}$/ : /^pfs_[A-Za-z0-9_-]{22}$/;
|
|
3262
3426
|
const projectRoot = path11.resolve(options.projectRoot);
|
|
3263
3427
|
const dotenvPath = path11.join(projectRoot, ".env");
|
|
3264
3428
|
try {
|
|
@@ -3285,7 +3449,7 @@ async function prepareSiteOSFormsCredentialInstallation(options) {
|
|
|
3285
3449
|
}
|
|
3286
3450
|
const currentContent = await readSafeDotenv(dotenvPath);
|
|
3287
3451
|
await writeCredentialAtomically({
|
|
3288
|
-
content: setCredential(currentContent, credential),
|
|
3452
|
+
content: setCredential(currentContent, credential, variable),
|
|
3289
3453
|
dotenvPath,
|
|
3290
3454
|
projectRoot
|
|
3291
3455
|
});
|
|
@@ -3323,7 +3487,10 @@ async function readSafeDotenv(dotenvPath) {
|
|
|
3323
3487
|
);
|
|
3324
3488
|
}
|
|
3325
3489
|
const content = dotenvStats ? await readFile4(dotenvPath, "utf8") : "";
|
|
3326
|
-
if (
|
|
3490
|
+
if ([
|
|
3491
|
+
SITEOS_FORMS_SUBMISSION_CREDENTIAL_ENV,
|
|
3492
|
+
SITEOS_FORMS_DEPLOYMENT_KEY_ENV
|
|
3493
|
+
].some((variable) => countCredentialEntries(content, variable) > 1)) {
|
|
3327
3494
|
throw new SiteOSFormsCredentialStorageError(
|
|
3328
3495
|
"FORMS_CREDENTIAL_STORAGE_INVALID"
|
|
3329
3496
|
);
|
|
@@ -3351,21 +3518,16 @@ async function writeCredentialAtomically(options) {
|
|
|
3351
3518
|
await rm3(temporaryPath, { force: true }).catch(() => void 0);
|
|
3352
3519
|
}
|
|
3353
3520
|
}
|
|
3354
|
-
function setCredential(content, credential) {
|
|
3355
|
-
const assignment = `${
|
|
3356
|
-
const existing = new RegExp(
|
|
3357
|
-
`^${SITEOS_FORMS_SUBMISSION_CREDENTIAL_ENV}=[^\\r\\n]*(?=\\r?$)`,
|
|
3358
|
-
"m"
|
|
3359
|
-
);
|
|
3521
|
+
function setCredential(content, credential, variable) {
|
|
3522
|
+
const assignment = `${variable}=${credential}`;
|
|
3523
|
+
const existing = new RegExp(`^${variable}=[^\\r\\n]*(?=\\r?$)`, "m");
|
|
3360
3524
|
if (existing.test(content)) return content.replace(existing, assignment);
|
|
3361
3525
|
const newline = content.includes("\r\n") ? "\r\n" : "\n";
|
|
3362
3526
|
if (content.length === 0) return `${assignment}${newline}`;
|
|
3363
3527
|
return `${content}${content.endsWith("\n") ? "" : newline}${assignment}${newline}`;
|
|
3364
3528
|
}
|
|
3365
|
-
function countCredentialEntries(content) {
|
|
3366
|
-
return content.split(/\r?\n/u).filter(
|
|
3367
|
-
(line) => line.startsWith(`${SITEOS_FORMS_SUBMISSION_CREDENTIAL_ENV}=`)
|
|
3368
|
-
).length;
|
|
3529
|
+
function countCredentialEntries(content, variable) {
|
|
3530
|
+
return content.split(/\r?\n/u).filter((line) => line.startsWith(`${variable}=`)).length;
|
|
3369
3531
|
}
|
|
3370
3532
|
function isDotenvIgnored(projectRoot) {
|
|
3371
3533
|
return new Promise((resolve, reject) => {
|
|
@@ -3407,25 +3569,40 @@ var SLUG_FLAG = "--slug";
|
|
|
3407
3569
|
var CREDENTIAL_FLAG = "--credential";
|
|
3408
3570
|
var REPLACE_FLAG = "--replace";
|
|
3409
3571
|
var normalizedFieldOptionSchema = z10.object({
|
|
3410
|
-
label: z10.string().trim().min(1),
|
|
3411
|
-
value: z10.string().trim().min(1)
|
|
3572
|
+
label: z10.string().trim().min(1).max(255),
|
|
3573
|
+
value: z10.string().trim().min(1).max(255)
|
|
3412
3574
|
});
|
|
3413
3575
|
var normalizedFieldSchema = z10.object({
|
|
3414
|
-
key: z10.string().trim().min(1),
|
|
3415
|
-
kind: z10.string().trim().min(1).optional(),
|
|
3416
|
-
label: z10.string().trim().min(1).optional(),
|
|
3576
|
+
key: z10.string().trim().min(1).max(255),
|
|
3577
|
+
kind: z10.string().trim().min(1).max(64).optional(),
|
|
3578
|
+
label: z10.string().trim().min(1).max(255).optional(),
|
|
3417
3579
|
displayRole: z10.enum(["primary", "secondary"]).optional(),
|
|
3418
3580
|
multiple: z10.boolean().optional(),
|
|
3419
|
-
options: z10.array(normalizedFieldOptionSchema).optional()
|
|
3420
|
-
}).
|
|
3581
|
+
options: z10.array(normalizedFieldOptionSchema).max(500).optional()
|
|
3582
|
+
}).strict();
|
|
3421
3583
|
var definitionSyncInputSchema = z10.object({
|
|
3422
|
-
formKey: z10.string().trim().min(1),
|
|
3423
|
-
name: z10.string().trim().min(1),
|
|
3424
|
-
normalizedFieldsJson: z10.array(normalizedFieldSchema).min(1),
|
|
3584
|
+
formKey: z10.string().trim().min(1).max(255),
|
|
3585
|
+
name: z10.string().trim().min(1).max(255),
|
|
3586
|
+
normalizedFieldsJson: z10.array(normalizedFieldSchema).min(1).max(500),
|
|
3425
3587
|
schemaJson: z10.record(z10.unknown()),
|
|
3426
|
-
sourceExportId: z10.string().trim().min(1).optional(),
|
|
3427
|
-
sourcePagePath: z10.string().trim().min(1).optional()
|
|
3428
|
-
}).
|
|
3588
|
+
sourceExportId: z10.string().trim().min(1).max(255).optional(),
|
|
3589
|
+
sourcePagePath: z10.string().trim().min(1).max(2048).optional()
|
|
3590
|
+
}).strict().superRefine((definition, context) => {
|
|
3591
|
+
const ajv = new Ajv({
|
|
3592
|
+
allErrors: true,
|
|
3593
|
+
removeAdditional: false,
|
|
3594
|
+
strict: true
|
|
3595
|
+
});
|
|
3596
|
+
addFormats.default(ajv);
|
|
3597
|
+
try {
|
|
3598
|
+
ajv.compile(definition.schemaJson);
|
|
3599
|
+
} catch {
|
|
3600
|
+
context.addIssue({
|
|
3601
|
+
code: z10.ZodIssueCode.custom,
|
|
3602
|
+
message: "schemaJson must be an executable JSON Schema supported by SiteOS Forms.",
|
|
3603
|
+
path: ["schemaJson"]
|
|
3604
|
+
});
|
|
3605
|
+
}
|
|
3429
3606
|
const fields = definition.normalizedFieldsJson;
|
|
3430
3607
|
const duplicateKeys = fields.map((field) => field.key).filter((key, index, keys) => keys.indexOf(key) !== index);
|
|
3431
3608
|
for (const key of new Set(duplicateKeys)) {
|
|
@@ -3506,6 +3683,11 @@ var FORMS_HELP = `Usage:
|
|
|
3506
3683
|
siteos forms environment create --slug <slug> --name <name> [--json]
|
|
3507
3684
|
siteos forms definition sync --environment <slug> --input <path> [--json]
|
|
3508
3685
|
siteos forms definition sync --environment <slug> --manifest <path> [--json]
|
|
3686
|
+
siteos forms definition list --environment <slug> [--status <active|inactive|all>] [--json]
|
|
3687
|
+
siteos forms definition read --environment <slug> --form <form-id> [--json]
|
|
3688
|
+
siteos forms definition archive --environment <slug> --form <form-id> --expected-revision <revision> [--json]
|
|
3689
|
+
siteos forms definition restore --environment <slug> --form <form-id> --expected-revision <revision> [--json]
|
|
3690
|
+
siteos forms definition delete --environment <slug> --form <form-id> [--apply --confirm <form-key> --expected-revision <revision> --expected-submissions <count>] [--json]
|
|
3509
3691
|
siteos forms definition check --input <path> [--json]
|
|
3510
3692
|
siteos forms definition check --manifest <path> [--json]
|
|
3511
3693
|
siteos forms credential list --environment <slug> [--json]
|
|
@@ -3513,6 +3695,13 @@ var FORMS_HELP = `Usage:
|
|
|
3513
3695
|
siteos forms credential rotate --environment <slug> --install [--name <name>] [--json]
|
|
3514
3696
|
siteos forms credential revoke --environment <slug> --credential <credential-id> [--json]
|
|
3515
3697
|
siteos forms credentials issue --environment <slug> [--name <name>] [--json]
|
|
3698
|
+
siteos forms submissions list --environment <slug> --form <form-id> [--query <text>] [--status <status>] [--from <ISO>] [--to <ISO>] [--limit <1-100>] [--cursor <cursor>] [--json]
|
|
3699
|
+
siteos forms submissions read --environment <slug> --form <form-id> --submission <id> [--json]
|
|
3700
|
+
siteos forms submissions status --environment <slug> --form <form-id> --submission <id> --status <new|read|archived|spam> --expected-status <status> [--json]
|
|
3701
|
+
siteos forms deploy --manifest <path> [--json]
|
|
3702
|
+
siteos forms deployment-key issue --environment <slug> --install [--name <name>] [--json]
|
|
3703
|
+
siteos forms deployment-key list --environment <slug> [--json]
|
|
3704
|
+
siteos forms deployment-key revoke --environment <slug> --credential <id> [--json]
|
|
3516
3705
|
siteos forms submit --input <path> [--json]
|
|
3517
3706
|
|
|
3518
3707
|
Manage SiteOS Forms Environments, definitions, credentials, and submission smoke tests.`;
|
|
@@ -3524,6 +3713,8 @@ async function runFormsCommand(options) {
|
|
|
3524
3713
|
stdout: FORMS_HELP
|
|
3525
3714
|
};
|
|
3526
3715
|
}
|
|
3716
|
+
if (args2[0] === "deploy")
|
|
3717
|
+
return runDeployment({ ...options, args: args2.slice(1) });
|
|
3527
3718
|
if (args2[0] !== "submit" && args2[0] !== "project") {
|
|
3528
3719
|
try {
|
|
3529
3720
|
args2 = await commonEnvironmentArguments(options, "forms", args2);
|
|
@@ -3534,6 +3725,8 @@ async function runFormsCommand(options) {
|
|
|
3534
3725
|
};
|
|
3535
3726
|
}
|
|
3536
3727
|
}
|
|
3728
|
+
if (args2[0] === "submissions")
|
|
3729
|
+
return runSubmissionsCommand({ ...options, args: args2.slice(1) });
|
|
3537
3730
|
if (args2[0] === "definition") {
|
|
3538
3731
|
return runDefinitionCommand({
|
|
3539
3732
|
...options,
|
|
@@ -3558,6 +3751,13 @@ async function runFormsCommand(options) {
|
|
|
3558
3751
|
args: args2.slice(1)
|
|
3559
3752
|
});
|
|
3560
3753
|
}
|
|
3754
|
+
if (args2[0] === "deployment-key") {
|
|
3755
|
+
return runCredentialCommand({
|
|
3756
|
+
...options,
|
|
3757
|
+
args: args2.slice(1),
|
|
3758
|
+
deployment: true
|
|
3759
|
+
});
|
|
3760
|
+
}
|
|
3561
3761
|
if (args2[0] === "credential") {
|
|
3562
3762
|
return runCredentialCommand({
|
|
3563
3763
|
...options,
|
|
@@ -3577,6 +3777,96 @@ async function runFormsCommand(options) {
|
|
|
3577
3777
|
}
|
|
3578
3778
|
return usageError2("Unknown SiteOS forms command.");
|
|
3579
3779
|
}
|
|
3780
|
+
async function runSubmissionsCommand(options) {
|
|
3781
|
+
const action = options.args[0];
|
|
3782
|
+
if (!action || !["list", "read", "status"].includes(action))
|
|
3783
|
+
return usageError2("Unknown Forms submissions command.");
|
|
3784
|
+
const parsed = parseFlags(options.args.slice(1), {
|
|
3785
|
+
allowed: /* @__PURE__ */ new Set([
|
|
3786
|
+
"--environment",
|
|
3787
|
+
"--form",
|
|
3788
|
+
"--json",
|
|
3789
|
+
...action === "list" ? ["--query", "--status", "--from", "--to", "--limit", "--cursor"] : [
|
|
3790
|
+
"--submission",
|
|
3791
|
+
...action === "status" ? ["--status", "--expected-status"] : []
|
|
3792
|
+
]
|
|
3793
|
+
]),
|
|
3794
|
+
boolean: /* @__PURE__ */ new Set(["--json"]),
|
|
3795
|
+
rejectDuplicates: true
|
|
3796
|
+
});
|
|
3797
|
+
if (!parsed.ok) return usageError2(parsed.error);
|
|
3798
|
+
if (parsed.positionals.length)
|
|
3799
|
+
return usageError2("Unexpected positional arguments.");
|
|
3800
|
+
const value = (key) => readStringFlag(parsed.flags, `--${key}`);
|
|
3801
|
+
const environmentSlug = value("environment");
|
|
3802
|
+
const formId = value("form");
|
|
3803
|
+
const submissionId = value("submission");
|
|
3804
|
+
if (!environmentSlug || !isValidEnvironmentSlug(environmentSlug) || !formId || formId.length > 255)
|
|
3805
|
+
return usageError2("Provide a valid --environment and --form.");
|
|
3806
|
+
if (action !== "list" && (!submissionId || submissionId.length > 255))
|
|
3807
|
+
return usageError2("Provide --submission.");
|
|
3808
|
+
const status = formsSubmissionStatusSchema.safeParse(value("status"));
|
|
3809
|
+
const expected = formsSubmissionStatusSchema.safeParse(
|
|
3810
|
+
value("expected-status")
|
|
3811
|
+
);
|
|
3812
|
+
if (value("status") && !status.success || action === "status" && (!status.success || !expected.success))
|
|
3813
|
+
return usageError2(
|
|
3814
|
+
"Use new, read, archived or spam for --status and --expected-status."
|
|
3815
|
+
);
|
|
3816
|
+
const filters = new URLSearchParams();
|
|
3817
|
+
for (const key of ["query", "status", "from", "to", "limit", "cursor"]) {
|
|
3818
|
+
const item = value(key);
|
|
3819
|
+
if (item) filters.set(key, item);
|
|
3820
|
+
}
|
|
3821
|
+
const limit = Number(value("limit") ?? 50);
|
|
3822
|
+
if (!Number.isInteger(limit) || limit < 1 || limit > 100)
|
|
3823
|
+
return usageError2("--limit must be between 1 and 100.");
|
|
3824
|
+
if ((value("query")?.length ?? 0) > 200 || (value("cursor")?.length ?? 0) > 2048)
|
|
3825
|
+
return usageError2("The query or cursor is too long.");
|
|
3826
|
+
for (const key of ["from", "to"])
|
|
3827
|
+
if (value(key) && !z10.string().datetime({ offset: true }).safeParse(value(key)).success)
|
|
3828
|
+
return usageError2(
|
|
3829
|
+
`--${key} must be an ISO timestamp including a timezone.`
|
|
3830
|
+
);
|
|
3831
|
+
if (value("from") && value("to") && Date.parse(value("from")) >= Date.parse(value("to")))
|
|
3832
|
+
return usageError2("--from must be earlier than --to (exclusive).");
|
|
3833
|
+
const context = await loadFormsManagementContext(
|
|
3834
|
+
options,
|
|
3835
|
+
"forms:workspace:write"
|
|
3836
|
+
);
|
|
3837
|
+
if (!context.ok) return context.error;
|
|
3838
|
+
try {
|
|
3839
|
+
const { environments } = await context.client.listEnvironments({
|
|
3840
|
+
grant: context.grant,
|
|
3841
|
+
projectId: context.project.id
|
|
3842
|
+
});
|
|
3843
|
+
requireEnvironmentProjectConvergence(environments, context.project.id);
|
|
3844
|
+
const environment = environments.find(
|
|
3845
|
+
(item) => item.slug === environmentSlug
|
|
3846
|
+
);
|
|
3847
|
+
if (!environment)
|
|
3848
|
+
return usageError2(
|
|
3849
|
+
"The selected Forms Environment does not exist. Run forms environment list."
|
|
3850
|
+
);
|
|
3851
|
+
const input = {
|
|
3852
|
+
grant: context.grant,
|
|
3853
|
+
environmentId: environment.id,
|
|
3854
|
+
formId
|
|
3855
|
+
};
|
|
3856
|
+
const response = action === "list" ? await context.client.listSubmissions({ ...input, filters }) : action === "read" ? await context.client.readSubmission({
|
|
3857
|
+
...input,
|
|
3858
|
+
submissionId
|
|
3859
|
+
}) : await context.client.updateSubmissionStatus({
|
|
3860
|
+
...input,
|
|
3861
|
+
submissionId,
|
|
3862
|
+
status: status.data,
|
|
3863
|
+
expectedStatus: expected.data
|
|
3864
|
+
});
|
|
3865
|
+
return { exitCode: 0, stdout: stringifySafeJson(response) };
|
|
3866
|
+
} catch (error) {
|
|
3867
|
+
return formatApiError(error);
|
|
3868
|
+
}
|
|
3869
|
+
}
|
|
3580
3870
|
async function runProjectCommand(options) {
|
|
3581
3871
|
const action = options.args[0];
|
|
3582
3872
|
if (!action || !["create", "list", "status", "use"].includes(action)) {
|
|
@@ -3803,6 +4093,11 @@ async function runCredentialCommand(options) {
|
|
|
3803
4093
|
if (!action || !["issue", "list", "revoke", "rotate"].includes(action)) {
|
|
3804
4094
|
return usageError2("Unknown SiteOS forms credential command.");
|
|
3805
4095
|
}
|
|
4096
|
+
if (options.deployment && action === "rotate")
|
|
4097
|
+
return usageError2(
|
|
4098
|
+
"Issue a new deployment key, update the release secret, then revoke the old key."
|
|
4099
|
+
);
|
|
4100
|
+
const variable = options.deployment ? SITEOS_FORMS_DEPLOYMENT_KEY_ENV : SITEOS_FORMS_SUBMISSION_CREDENTIAL_ENV;
|
|
3806
4101
|
const parsed = parseCredentialFlags(action, options.args.slice(1));
|
|
3807
4102
|
if (!parsed.ok) return parsed.error;
|
|
3808
4103
|
const context = await loadCredentialManagementContext({
|
|
@@ -3874,7 +4169,7 @@ Environment: ${parsed.environmentSlug}`
|
|
|
3874
4169
|
credential,
|
|
3875
4170
|
environment: parsed.environmentSlug,
|
|
3876
4171
|
installed: {
|
|
3877
|
-
variable
|
|
4172
|
+
variable
|
|
3878
4173
|
},
|
|
3879
4174
|
operation: action === "issue" ? "issued" : "rotated"
|
|
3880
4175
|
};
|
|
@@ -3884,7 +4179,7 @@ Environment: ${parsed.environmentSlug}`
|
|
|
3884
4179
|
`SiteOS Forms credential ${output.operation} and installed.`,
|
|
3885
4180
|
`Credential: ${credential.id}`,
|
|
3886
4181
|
`Environment: ${parsed.environmentSlug}`,
|
|
3887
|
-
`Variable: ${
|
|
4182
|
+
`Variable: ${variable}`
|
|
3888
4183
|
].join("\n")
|
|
3889
4184
|
};
|
|
3890
4185
|
} catch (error) {
|
|
@@ -3895,14 +4190,21 @@ async function loadCredentialManagementContext(options) {
|
|
|
3895
4190
|
try {
|
|
3896
4191
|
const local = await readLocalCommonProject(options);
|
|
3897
4192
|
const rootDir = local?.rootDir ?? (await requireFormsProjectReference(options.cwd ?? process.cwd())).rootDir;
|
|
3898
|
-
const installation = options.install ? await (options.prepareCredentialInstallation ?? prepareSiteOSFormsCredentialInstallation)({
|
|
4193
|
+
const installation = options.install ? await (options.prepareCredentialInstallation ?? prepareSiteOSFormsCredentialInstallation)({
|
|
4194
|
+
projectRoot: rootDir,
|
|
4195
|
+
...options.deployment ? { deployment: true } : {}
|
|
4196
|
+
}) : void 0;
|
|
3899
4197
|
const context = await loadFormsManagementContext(
|
|
3900
4198
|
options,
|
|
3901
4199
|
"forms:credential:manage"
|
|
3902
4200
|
);
|
|
3903
4201
|
if (!context.ok) return context;
|
|
3904
4202
|
return {
|
|
3905
|
-
client:
|
|
4203
|
+
client: options.deployment ? createSiteOSFormsApiClient({
|
|
4204
|
+
apiBaseUrl: context.apiBaseUrl,
|
|
4205
|
+
fetchImpl: options.fetchImpl ?? fetch,
|
|
4206
|
+
deploymentKeys: true
|
|
4207
|
+
}) : context.client,
|
|
3906
4208
|
grant: context.grant,
|
|
3907
4209
|
...installation ? { installation } : {},
|
|
3908
4210
|
ok: true,
|
|
@@ -4017,6 +4319,10 @@ async function requireFormsProjectReference(cwd) {
|
|
|
4017
4319
|
return reference;
|
|
4018
4320
|
}
|
|
4019
4321
|
async function runDefinitionCommand(options) {
|
|
4322
|
+
if (["list", "read", "archive", "restore", "delete"].includes(
|
|
4323
|
+
options.args[0] ?? ""
|
|
4324
|
+
))
|
|
4325
|
+
return runDefinitionLifecycle(options);
|
|
4020
4326
|
if (options.args[0] === "sync") {
|
|
4021
4327
|
return runDefinitionSync({
|
|
4022
4328
|
...options,
|
|
@@ -4031,6 +4337,125 @@ async function runDefinitionCommand(options) {
|
|
|
4031
4337
|
}
|
|
4032
4338
|
return usageError2("Unknown SiteOS forms definition command.");
|
|
4033
4339
|
}
|
|
4340
|
+
async function runDefinitionLifecycle(options) {
|
|
4341
|
+
const action = options.args[0];
|
|
4342
|
+
const parsed = parseFlags(options.args.slice(1), {
|
|
4343
|
+
allowed: /* @__PURE__ */ new Set([
|
|
4344
|
+
"--environment",
|
|
4345
|
+
"--json",
|
|
4346
|
+
...action === "list" ? ["--status"] : ["--form"],
|
|
4347
|
+
...["archive", "restore", "delete"].includes(action) ? ["--expected-revision"] : [],
|
|
4348
|
+
...action === "delete" ? ["--apply", "--confirm", "--expected-submissions"] : []
|
|
4349
|
+
]),
|
|
4350
|
+
boolean: /* @__PURE__ */ new Set(["--json", "--apply"]),
|
|
4351
|
+
rejectDuplicates: true
|
|
4352
|
+
});
|
|
4353
|
+
if (!parsed.ok) return usageError2(parsed.error);
|
|
4354
|
+
if (parsed.positionals.length)
|
|
4355
|
+
return usageError2("Unexpected positional arguments.");
|
|
4356
|
+
const value = (key) => readStringFlag(parsed.flags, `--${key}`);
|
|
4357
|
+
const environmentSlug = value("environment");
|
|
4358
|
+
const formId = value("form");
|
|
4359
|
+
if (!environmentSlug || !isValidEnvironmentSlug(environmentSlug) || action !== "list" && (!formId || formId.length > 255))
|
|
4360
|
+
return usageError2("Provide a valid --environment and --form.");
|
|
4361
|
+
const status = value("status") ?? "active";
|
|
4362
|
+
if (!["active", "inactive", "all"].includes(status))
|
|
4363
|
+
return usageError2("Use active, inactive or all for --status.");
|
|
4364
|
+
const apply = parsed.flags.get("--apply") === true;
|
|
4365
|
+
const revision = Number(value("expected-revision"));
|
|
4366
|
+
const count = Number(value("expected-submissions"));
|
|
4367
|
+
const confirmKey = value("confirm");
|
|
4368
|
+
if ((action === "archive" || action === "restore" || apply) && (!Number.isSafeInteger(revision) || revision < 1))
|
|
4369
|
+
return usageError2(
|
|
4370
|
+
"Read the form first, then provide its --expected-revision."
|
|
4371
|
+
);
|
|
4372
|
+
if (apply && (!confirmKey || confirmKey.length > 255 || !Number.isSafeInteger(count) || count < 0))
|
|
4373
|
+
return usageError2(
|
|
4374
|
+
"Deletion requires --confirm with the exact form key and --expected-submissions from the preview."
|
|
4375
|
+
);
|
|
4376
|
+
if (action === "delete" && !apply && ["confirm", "expected-revision", "expected-submissions"].some(
|
|
4377
|
+
(key) => value(key) !== void 0
|
|
4378
|
+
))
|
|
4379
|
+
return usageError2(
|
|
4380
|
+
"Delete is a read-only preview. Add --apply with all confirmation values to delete."
|
|
4381
|
+
);
|
|
4382
|
+
const context = await loadFormsManagementContext(
|
|
4383
|
+
options,
|
|
4384
|
+
"forms:workspace:write"
|
|
4385
|
+
);
|
|
4386
|
+
if (!context.ok) return context.error;
|
|
4387
|
+
try {
|
|
4388
|
+
const { environments } = await context.client.listEnvironments({
|
|
4389
|
+
grant: context.grant,
|
|
4390
|
+
projectId: context.project.id
|
|
4391
|
+
});
|
|
4392
|
+
requireEnvironmentProjectConvergence(environments, context.project.id);
|
|
4393
|
+
const environment = environments.find(
|
|
4394
|
+
(item) => item.slug === environmentSlug
|
|
4395
|
+
);
|
|
4396
|
+
if (!environment)
|
|
4397
|
+
return usageError2(
|
|
4398
|
+
"The selected Forms Environment does not exist. Run forms environment list."
|
|
4399
|
+
);
|
|
4400
|
+
const input = {
|
|
4401
|
+
grant: context.grant,
|
|
4402
|
+
environmentId: environment.id,
|
|
4403
|
+
formId: formId ?? ""
|
|
4404
|
+
};
|
|
4405
|
+
if (action === "list")
|
|
4406
|
+
return {
|
|
4407
|
+
exitCode: 0,
|
|
4408
|
+
stdout: stringifySafeJson(
|
|
4409
|
+
await context.client.listDefinitions({
|
|
4410
|
+
...input,
|
|
4411
|
+
status
|
|
4412
|
+
})
|
|
4413
|
+
)
|
|
4414
|
+
};
|
|
4415
|
+
if (action === "read" || action === "delete" && !apply) {
|
|
4416
|
+
const preview = await context.client.readDefinition(input);
|
|
4417
|
+
if (preview.project.id !== context.project.id || preview.environment.id !== environment.id || preview.definition.id !== formId || preview.definition.environmentId !== environment.id)
|
|
4418
|
+
throw new SiteOSFormsApiError({
|
|
4419
|
+
code: "INVALID_RESPONSE",
|
|
4420
|
+
message: "The form does not match the selected Project and Environment."
|
|
4421
|
+
});
|
|
4422
|
+
return {
|
|
4423
|
+
exitCode: 0,
|
|
4424
|
+
stdout: stringifySafeJson(
|
|
4425
|
+
action === "read" ? preview : {
|
|
4426
|
+
...preview,
|
|
4427
|
+
action: "delete",
|
|
4428
|
+
applied: false,
|
|
4429
|
+
warning: "Permanently removes this form, all versions and all submitted answers. This cannot be undone. The form key remains reserved.",
|
|
4430
|
+
confirmation: {
|
|
4431
|
+
confirmKey: preview.definition.formKey,
|
|
4432
|
+
expectedRevision: preview.revision,
|
|
4433
|
+
expectedSubmissionCount: preview.definition.submissionCount
|
|
4434
|
+
}
|
|
4435
|
+
}
|
|
4436
|
+
)
|
|
4437
|
+
};
|
|
4438
|
+
}
|
|
4439
|
+
const response = await context.client.changeDefinition({
|
|
4440
|
+
...input,
|
|
4441
|
+
change: action === "delete" ? {
|
|
4442
|
+
action,
|
|
4443
|
+
confirmKey,
|
|
4444
|
+
expectedRevision: revision,
|
|
4445
|
+
expectedSubmissionCount: count
|
|
4446
|
+
} : {
|
|
4447
|
+
action,
|
|
4448
|
+
expectedRevision: revision
|
|
4449
|
+
}
|
|
4450
|
+
});
|
|
4451
|
+
return {
|
|
4452
|
+
exitCode: 0,
|
|
4453
|
+
stdout: stringifySafeJson({ ...response, action, applied: true })
|
|
4454
|
+
};
|
|
4455
|
+
} catch (error) {
|
|
4456
|
+
return formatApiError(error);
|
|
4457
|
+
}
|
|
4458
|
+
}
|
|
4034
4459
|
async function runDefinitionSync(options) {
|
|
4035
4460
|
const parsed = parseDefinitionSourceFlags(options.args, {
|
|
4036
4461
|
environmentRequired: true,
|
|
@@ -4713,8 +5138,8 @@ function formatApiError(error) {
|
|
|
4713
5138
|
error.status ? `Status: ${error.status}` : void 0,
|
|
4714
5139
|
`Code: ${error.code}`,
|
|
4715
5140
|
error.message,
|
|
4716
|
-
error.status === 404 && error.code === "NOT_FOUND" ? "
|
|
4717
|
-
error.status === 409 && error.code === "PROJECT_FORM_SUBMISSION_EXISTS" ? "The submission idempotency key was already used.
|
|
5141
|
+
error.status === 404 && error.code === "NOT_FOUND" ? "Verify the selected Project, Environment and form ID. The server must support this command." : void 0,
|
|
5142
|
+
error.status === 409 && error.code === "PROJECT_FORM_SUBMISSION_EXISTS" ? "The submission idempotency key was already used. Keep it for an unchanged retry and check the existing receipt before sending again." : void 0
|
|
4718
5143
|
].filter((line) => Boolean(line));
|
|
4719
5144
|
return {
|
|
4720
5145
|
exitCode: 1,
|
|
@@ -4883,6 +5308,55 @@ function createFormsUiOutput(input) {
|
|
|
4883
5308
|
url
|
|
4884
5309
|
};
|
|
4885
5310
|
}
|
|
5311
|
+
async function runDeployment(options) {
|
|
5312
|
+
const parsed = parseDefinitionSourceFlags(options.args, {
|
|
5313
|
+
environmentRequired: false,
|
|
5314
|
+
usage: "Usage: siteos forms deploy --manifest <path> [--json]"
|
|
5315
|
+
});
|
|
5316
|
+
if (!parsed.ok) return parsed.error;
|
|
5317
|
+
const loaded = await loadFormDefinitions({
|
|
5318
|
+
cwd: options.cwd,
|
|
5319
|
+
source: parsed.source
|
|
5320
|
+
});
|
|
5321
|
+
if (!loaded.ok) return loaded.error;
|
|
5322
|
+
const env = options.env ?? process.env;
|
|
5323
|
+
const credential = env[SITEOS_FORMS_DEPLOYMENT_KEY_ENV]?.trim();
|
|
5324
|
+
const apiBaseUrl = env.SITEOS_FORMS_PUBLIC_URL?.trim();
|
|
5325
|
+
if (!credential || !/^pfd_[A-Za-z0-9_-]{43}$/.test(credential) || !apiBaseUrl)
|
|
5326
|
+
return {
|
|
5327
|
+
exitCode: 1,
|
|
5328
|
+
stderr: "Configure SITEOS_FORMS_PUBLIC_URL and SITEOS_FORMS_DEPLOYMENT_KEY in the release environment."
|
|
5329
|
+
};
|
|
5330
|
+
try {
|
|
5331
|
+
const client = createSiteOSFormsApiClient({
|
|
5332
|
+
apiBaseUrl,
|
|
5333
|
+
fetchImpl: options.fetchImpl ?? fetch
|
|
5334
|
+
});
|
|
5335
|
+
const result = await client.publishDefinitions({
|
|
5336
|
+
credential,
|
|
5337
|
+
definitions: loaded.definitions.map((item) => item.value)
|
|
5338
|
+
});
|
|
5339
|
+
const expected = new Map(
|
|
5340
|
+
loaded.definitions.map((item) => [
|
|
5341
|
+
item.value.formKey,
|
|
5342
|
+
item.value.sourceExportId
|
|
5343
|
+
])
|
|
5344
|
+
);
|
|
5345
|
+
if (result.forms.length !== expected.size || new Set(result.forms.map((item) => item.formKey)).size !== expected.size || result.forms.some(
|
|
5346
|
+
(item) => !expected.has(item.formKey) || expected.get(item.formKey) !== item.contractVersion
|
|
5347
|
+
))
|
|
5348
|
+
return {
|
|
5349
|
+
exitCode: 1,
|
|
5350
|
+
stderr: "The published Forms versions do not match this build."
|
|
5351
|
+
};
|
|
5352
|
+
return {
|
|
5353
|
+
exitCode: 0,
|
|
5354
|
+
stdout: parsed.json ? stringifySafeJson(result) : `Published ${result.forms.length} Forms contracts for Environment ${result.environmentId}.`
|
|
5355
|
+
};
|
|
5356
|
+
} catch (error) {
|
|
5357
|
+
return formatApiError(error);
|
|
5358
|
+
}
|
|
5359
|
+
}
|
|
4886
5360
|
|
|
4887
5361
|
// src/package-metadata.ts
|
|
4888
5362
|
import { readFileSync } from "fs";
|
|
@@ -4927,7 +5401,7 @@ var projectSchema = z11.object({
|
|
|
4927
5401
|
}).strict();
|
|
4928
5402
|
var projectListSchema = z11.object({ projects: z11.array(projectSchema) }).strict();
|
|
4929
5403
|
var projectResponseSchema = z11.object({ project: projectSchema }).strict();
|
|
4930
|
-
var
|
|
5404
|
+
var deploymentResponseSchema2 = z11.object({
|
|
4931
5405
|
checks: z11.array(
|
|
4932
5406
|
z11.object({
|
|
4933
5407
|
checkId: z11.string().min(1),
|
|
@@ -5032,7 +5506,7 @@ function createPulseApiClient(input) {
|
|
|
5032
5506
|
grant: options.grant,
|
|
5033
5507
|
method: "POST",
|
|
5034
5508
|
path: "/api/cli/v1/deployments",
|
|
5035
|
-
schema:
|
|
5509
|
+
schema: deploymentResponseSchema2
|
|
5036
5510
|
});
|
|
5037
5511
|
}
|
|
5038
5512
|
};
|