clientplane 0.0.0-reserved.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/bin/clientplane.js +818 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +885 -0
- package/package.json +33 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,885 @@
|
|
|
1
|
+
// ../cli/dist/commands/backfill.js
|
|
2
|
+
async function backfillCommand(input) {
|
|
3
|
+
const values = await input.readPublishedValues();
|
|
4
|
+
const lines = input.manifest.fields.filter((field) => Object.hasOwn(values, field.fieldId)).map((field) => `Update ${field.fieldId} fallback in ${field.sourceFilePath ?? "the source file"} to ${JSON.stringify(values[field.fieldId])}.`);
|
|
5
|
+
return {
|
|
6
|
+
appliesAutomatically: false,
|
|
7
|
+
instructions: lines.join("\n")
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// ../cli/dist/commands/scan.js
|
|
12
|
+
import { readFile } from "fs/promises";
|
|
13
|
+
|
|
14
|
+
// ../cli/dist/scan/next-source-scan.js
|
|
15
|
+
import ts from "typescript";
|
|
16
|
+
|
|
17
|
+
// ../shared/dist/actors.js
|
|
18
|
+
import { z } from "zod";
|
|
19
|
+
var ACTOR_TYPES = ["developer", "client", "agent", "system"];
|
|
20
|
+
var actorTypeSchema = z.enum(ACTOR_TYPES);
|
|
21
|
+
|
|
22
|
+
// ../shared/dist/assets.js
|
|
23
|
+
import { z as z2 } from "zod";
|
|
24
|
+
var ASSET_STAGES = ["staging", "final", "deleted"];
|
|
25
|
+
var ASSET_VISIBILITIES = ["private", "public", "deleted"];
|
|
26
|
+
var ASSET_USAGE_ENTITY_TYPES = [
|
|
27
|
+
"branding",
|
|
28
|
+
"draft",
|
|
29
|
+
"change_set",
|
|
30
|
+
"published_value"
|
|
31
|
+
];
|
|
32
|
+
var assetStageSchema = z2.enum(ASSET_STAGES);
|
|
33
|
+
var assetVisibilitySchema = z2.enum(ASSET_VISIBILITIES);
|
|
34
|
+
var assetUsageEntityTypeSchema = z2.enum(ASSET_USAGE_ENTITY_TYPES);
|
|
35
|
+
var brandingAccentColorSchema = z2.string().regex(/^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/);
|
|
36
|
+
|
|
37
|
+
// ../shared/dist/bridge-protocol.js
|
|
38
|
+
import { z as z5 } from "zod";
|
|
39
|
+
|
|
40
|
+
// ../shared/dist/field-id.js
|
|
41
|
+
import { z as z3 } from "zod";
|
|
42
|
+
var FIELD_ID_PATTERN = /^[a-z][a-z0-9_-]*(\.[a-z][a-z0-9_-]*)+$/;
|
|
43
|
+
var fieldIdSchema = z3.string().regex(FIELD_ID_PATTERN, "Invalid field id");
|
|
44
|
+
function isFieldId(value) {
|
|
45
|
+
return typeof value === "string" && fieldIdSchema.safeParse(value).success;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// ../shared/dist/field-types.js
|
|
49
|
+
import { z as z4 } from "zod";
|
|
50
|
+
var FIELD_TYPES = ["text", "longText", "image", "link"];
|
|
51
|
+
var fieldTypeSchema = z4.enum(FIELD_TYPES);
|
|
52
|
+
|
|
53
|
+
// ../shared/dist/bridge-protocol.js
|
|
54
|
+
var BRIDGE_PROTOCOL_VERSION = 1;
|
|
55
|
+
var BRIDGE_MESSAGE_TYPES = [
|
|
56
|
+
"clientplane:bridge:init",
|
|
57
|
+
"clientplane:bridge:ready",
|
|
58
|
+
"clientplane:bridge:fields",
|
|
59
|
+
"clientplane:bridge:select-field",
|
|
60
|
+
"clientplane:bridge:apply-preview-values",
|
|
61
|
+
"clientplane:bridge:test-preview-value",
|
|
62
|
+
"clientplane:bridge:ack",
|
|
63
|
+
"clientplane:bridge:error"
|
|
64
|
+
];
|
|
65
|
+
var bridgeMessageTypeSchema = z5.enum(BRIDGE_MESSAGE_TYPES);
|
|
66
|
+
var bridgeBaseSchema = z5.object({
|
|
67
|
+
version: z5.literal(BRIDGE_PROTOCOL_VERSION),
|
|
68
|
+
type: bridgeMessageTypeSchema,
|
|
69
|
+
siteId: z5.string().uuid(),
|
|
70
|
+
sessionId: z5.string().trim().min(1),
|
|
71
|
+
requestId: z5.string().trim().min(1),
|
|
72
|
+
sentAt: z5.string().datetime()
|
|
73
|
+
});
|
|
74
|
+
var bridgeRectSchema = z5.object({
|
|
75
|
+
x: z5.number(),
|
|
76
|
+
y: z5.number(),
|
|
77
|
+
width: z5.number().nonnegative(),
|
|
78
|
+
height: z5.number().nonnegative()
|
|
79
|
+
});
|
|
80
|
+
var bridgeFieldSchema = z5.object({
|
|
81
|
+
fieldId: fieldIdSchema,
|
|
82
|
+
fieldType: fieldTypeSchema,
|
|
83
|
+
route: z5.string().regex(/^\/.*/),
|
|
84
|
+
routeId: z5.string().trim().min(1).optional(),
|
|
85
|
+
sourcePath: z5.string().trim().min(1).optional(),
|
|
86
|
+
editTarget: fieldIdSchema,
|
|
87
|
+
manifestVersion: z5.string().trim().min(1).optional(),
|
|
88
|
+
rect: bridgeRectSchema,
|
|
89
|
+
editable: z5.boolean(),
|
|
90
|
+
label: z5.string().trim().min(1).optional()
|
|
91
|
+
});
|
|
92
|
+
var bridgeInitPayloadSchema = z5.object({
|
|
93
|
+
adminOrigin: z5.string().url(),
|
|
94
|
+
customerOrigin: z5.string().url(),
|
|
95
|
+
route: z5.string().regex(/^\/.*/)
|
|
96
|
+
});
|
|
97
|
+
var bridgeReadyPayloadSchema = z5.object({
|
|
98
|
+
route: z5.string().regex(/^\/.*/),
|
|
99
|
+
fieldCount: z5.number().int().nonnegative()
|
|
100
|
+
});
|
|
101
|
+
var bridgeFieldsPayloadSchema = z5.object({
|
|
102
|
+
route: z5.string().regex(/^\/.*/),
|
|
103
|
+
fields: z5.array(bridgeFieldSchema)
|
|
104
|
+
});
|
|
105
|
+
var bridgeSelectFieldPayloadSchema = z5.object({
|
|
106
|
+
fieldId: fieldIdSchema,
|
|
107
|
+
source: z5.enum(["runtime", "editor"]).default("runtime")
|
|
108
|
+
});
|
|
109
|
+
var previewTextValueSchema = z5.object({
|
|
110
|
+
fieldType: z5.enum(["text", "longText"]),
|
|
111
|
+
value: z5.string()
|
|
112
|
+
});
|
|
113
|
+
var previewLinkValueSchema = z5.object({
|
|
114
|
+
fieldType: z5.literal("link"),
|
|
115
|
+
value: z5.object({
|
|
116
|
+
href: z5.string().trim().min(1),
|
|
117
|
+
label: z5.string().trim().min(1).optional()
|
|
118
|
+
})
|
|
119
|
+
});
|
|
120
|
+
var previewImageValueSchema = z5.object({
|
|
121
|
+
fieldType: z5.literal("image"),
|
|
122
|
+
value: z5.object({
|
|
123
|
+
src: z5.string().trim().min(1),
|
|
124
|
+
alt: z5.string().trim().min(1)
|
|
125
|
+
})
|
|
126
|
+
});
|
|
127
|
+
var bridgePreviewValueSchema = z5.discriminatedUnion("fieldType", [
|
|
128
|
+
previewTextValueSchema,
|
|
129
|
+
previewLinkValueSchema,
|
|
130
|
+
previewImageValueSchema
|
|
131
|
+
]);
|
|
132
|
+
var bridgeApplyPreviewValuesPayloadSchema = z5.object({
|
|
133
|
+
values: z5.record(fieldIdSchema, bridgePreviewValueSchema)
|
|
134
|
+
});
|
|
135
|
+
var bridgeTestPreviewValuePayloadSchema = z5.object({
|
|
136
|
+
fieldIds: z5.array(fieldIdSchema).min(1)
|
|
137
|
+
});
|
|
138
|
+
var bridgeAckPayloadSchema = z5.object({
|
|
139
|
+
ackRequestId: z5.string().trim().min(1)
|
|
140
|
+
});
|
|
141
|
+
var bridgeErrorPayloadSchema = z5.object({
|
|
142
|
+
code: z5.string().trim().min(1),
|
|
143
|
+
message: z5.string().trim().min(1),
|
|
144
|
+
recoverable: z5.boolean().default(false)
|
|
145
|
+
});
|
|
146
|
+
var bridgeInitMessageSchema = bridgeBaseSchema.extend({
|
|
147
|
+
type: z5.literal("clientplane:bridge:init"),
|
|
148
|
+
payload: bridgeInitPayloadSchema
|
|
149
|
+
});
|
|
150
|
+
var bridgeReadyMessageSchema = bridgeBaseSchema.extend({
|
|
151
|
+
type: z5.literal("clientplane:bridge:ready"),
|
|
152
|
+
payload: bridgeReadyPayloadSchema
|
|
153
|
+
});
|
|
154
|
+
var bridgeFieldsMessageSchema = bridgeBaseSchema.extend({
|
|
155
|
+
type: z5.literal("clientplane:bridge:fields"),
|
|
156
|
+
payload: bridgeFieldsPayloadSchema
|
|
157
|
+
});
|
|
158
|
+
var bridgeSelectFieldMessageSchema = bridgeBaseSchema.extend({
|
|
159
|
+
type: z5.literal("clientplane:bridge:select-field"),
|
|
160
|
+
payload: bridgeSelectFieldPayloadSchema
|
|
161
|
+
});
|
|
162
|
+
var bridgeApplyPreviewValuesMessageSchema = bridgeBaseSchema.extend({
|
|
163
|
+
type: z5.literal("clientplane:bridge:apply-preview-values"),
|
|
164
|
+
payload: bridgeApplyPreviewValuesPayloadSchema
|
|
165
|
+
});
|
|
166
|
+
var bridgeTestPreviewValueMessageSchema = bridgeBaseSchema.extend({
|
|
167
|
+
type: z5.literal("clientplane:bridge:test-preview-value"),
|
|
168
|
+
payload: bridgeTestPreviewValuePayloadSchema
|
|
169
|
+
});
|
|
170
|
+
var bridgeAckMessageSchema = bridgeBaseSchema.extend({
|
|
171
|
+
type: z5.literal("clientplane:bridge:ack"),
|
|
172
|
+
payload: bridgeAckPayloadSchema
|
|
173
|
+
});
|
|
174
|
+
var bridgeErrorMessageSchema = bridgeBaseSchema.extend({
|
|
175
|
+
type: z5.literal("clientplane:bridge:error"),
|
|
176
|
+
payload: bridgeErrorPayloadSchema
|
|
177
|
+
});
|
|
178
|
+
var bridgeMessageSchema = z5.discriminatedUnion("type", [
|
|
179
|
+
bridgeInitMessageSchema,
|
|
180
|
+
bridgeReadyMessageSchema,
|
|
181
|
+
bridgeFieldsMessageSchema,
|
|
182
|
+
bridgeSelectFieldMessageSchema,
|
|
183
|
+
bridgeApplyPreviewValuesMessageSchema,
|
|
184
|
+
bridgeTestPreviewValueMessageSchema,
|
|
185
|
+
bridgeAckMessageSchema,
|
|
186
|
+
bridgeErrorMessageSchema
|
|
187
|
+
]);
|
|
188
|
+
|
|
189
|
+
// ../shared/dist/commands.js
|
|
190
|
+
import { z as z7 } from "zod";
|
|
191
|
+
|
|
192
|
+
// ../shared/dist/errors.js
|
|
193
|
+
import { z as z6 } from "zod";
|
|
194
|
+
var UI_ERROR_CATEGORIES = [
|
|
195
|
+
"client",
|
|
196
|
+
"developer",
|
|
197
|
+
"internal"
|
|
198
|
+
];
|
|
199
|
+
var uiErrorCategorySchema = z6.enum(UI_ERROR_CATEGORIES);
|
|
200
|
+
var commandErrorPayloadSchema = z6.object({
|
|
201
|
+
code: z6.string().min(1),
|
|
202
|
+
message: z6.string().min(1),
|
|
203
|
+
category: uiErrorCategorySchema,
|
|
204
|
+
details: z6.record(z6.string(), z6.unknown()).optional()
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
// ../shared/dist/commands.js
|
|
208
|
+
var commandSuccessSchema = z7.object({
|
|
209
|
+
ok: z7.literal(true),
|
|
210
|
+
data: z7.unknown()
|
|
211
|
+
});
|
|
212
|
+
var commandErrorSchema = z7.object({
|
|
213
|
+
ok: z7.literal(false),
|
|
214
|
+
error: commandErrorPayloadSchema
|
|
215
|
+
});
|
|
216
|
+
var commandResultSchema = z7.discriminatedUnion("ok", [
|
|
217
|
+
commandSuccessSchema,
|
|
218
|
+
commandErrorSchema
|
|
219
|
+
]);
|
|
220
|
+
|
|
221
|
+
// ../shared/dist/field-manifest.js
|
|
222
|
+
import { z as z8 } from "zod";
|
|
223
|
+
var FIELD_MANIFEST_CHANGE_TYPES = [
|
|
224
|
+
"new",
|
|
225
|
+
"changed",
|
|
226
|
+
"removed",
|
|
227
|
+
"rename_candidate"
|
|
228
|
+
];
|
|
229
|
+
var FIELD_MANIFEST_REVIEW_STATUSES = [
|
|
230
|
+
"pending",
|
|
231
|
+
"approved",
|
|
232
|
+
"rejected",
|
|
233
|
+
"needs_fix",
|
|
234
|
+
"resolved"
|
|
235
|
+
];
|
|
236
|
+
var FIELD_DEFINITION_STATUSES = [
|
|
237
|
+
"active",
|
|
238
|
+
"hidden",
|
|
239
|
+
"orphaned",
|
|
240
|
+
"archived"
|
|
241
|
+
];
|
|
242
|
+
var fieldManifestChangeTypeSchema = z8.enum(FIELD_MANIFEST_CHANGE_TYPES);
|
|
243
|
+
var fieldManifestReviewStatusSchema = z8.enum(FIELD_MANIFEST_REVIEW_STATUSES);
|
|
244
|
+
var fieldDefinitionStatusSchema = z8.enum(FIELD_DEFINITION_STATUSES);
|
|
245
|
+
var manifestRouteSchema = z8.object({
|
|
246
|
+
path: z8.string().regex(/^\/.*/),
|
|
247
|
+
label: z8.string().trim().min(1).optional()
|
|
248
|
+
});
|
|
249
|
+
var fieldManifestFieldSchema = z8.object({
|
|
250
|
+
fieldId: fieldIdSchema,
|
|
251
|
+
fieldType: fieldTypeSchema,
|
|
252
|
+
fallback: z8.unknown().optional(),
|
|
253
|
+
label: z8.string().trim().min(1).optional(),
|
|
254
|
+
description: z8.string().trim().min(1).optional(),
|
|
255
|
+
required: z8.boolean().optional(),
|
|
256
|
+
maxLength: z8.number().int().positive().optional(),
|
|
257
|
+
routeHint: z8.string().regex(/^\/.*/).optional(),
|
|
258
|
+
routeId: z8.string().trim().min(1).optional(),
|
|
259
|
+
sourcePath: z8.string().trim().min(1).optional(),
|
|
260
|
+
editTarget: fieldIdSchema.optional(),
|
|
261
|
+
lastSeenRoute: z8.string().regex(/^\/.*/).optional(),
|
|
262
|
+
positionHint: z8.record(z8.string(), z8.unknown()).optional(),
|
|
263
|
+
domSelectorHint: z8.string().trim().min(1).optional(),
|
|
264
|
+
source: z8.enum(["component", "function", "runtime"]).default("component"),
|
|
265
|
+
sourceFilePath: z8.string().trim().min(1).optional(),
|
|
266
|
+
sourceExportName: z8.string().trim().min(1).optional(),
|
|
267
|
+
componentHint: z8.string().trim().min(1).optional(),
|
|
268
|
+
validation: z8.record(z8.string(), z8.unknown()).optional(),
|
|
269
|
+
metadata: z8.record(z8.string(), z8.unknown()).optional(),
|
|
270
|
+
warnings: z8.array(z8.string().trim().min(1)).default([]),
|
|
271
|
+
suggestions: z8.array(z8.string().trim().min(1)).default([])
|
|
272
|
+
});
|
|
273
|
+
var fieldManifestSchema = z8.object({
|
|
274
|
+
version: z8.literal(1),
|
|
275
|
+
siteId: z8.string().uuid().optional(),
|
|
276
|
+
fields: z8.array(fieldManifestFieldSchema),
|
|
277
|
+
routes: z8.array(manifestRouteSchema).default([])
|
|
278
|
+
}).superRefine((manifest, context) => {
|
|
279
|
+
const seen = /* @__PURE__ */ new Set();
|
|
280
|
+
for (const field of manifest.fields) {
|
|
281
|
+
if (seen.has(field.fieldId)) {
|
|
282
|
+
context.addIssue({
|
|
283
|
+
code: "custom",
|
|
284
|
+
path: ["fields"],
|
|
285
|
+
message: `Duplicate field id: ${field.fieldId}`
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
seen.add(field.fieldId);
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
// ../shared/dist/fallback-portal.js
|
|
293
|
+
import { z as z9 } from "zod";
|
|
294
|
+
var FALLBACK_PORTAL_SLUG_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
295
|
+
var fallbackPortalSlugSchema = z9.string().regex(FALLBACK_PORTAL_SLUG_PATTERN, "Invalid fallback portal slug");
|
|
296
|
+
|
|
297
|
+
// ../shared/dist/entitlements.js
|
|
298
|
+
import { z as z10 } from "zod";
|
|
299
|
+
var entitlementSnapshotSchema = z10.object({
|
|
300
|
+
planKey: z10.string().trim().min(1),
|
|
301
|
+
sitesLimit: z10.number().int().positive(),
|
|
302
|
+
clientAccountsPerSiteLimit: z10.number().int().positive(),
|
|
303
|
+
customAdminDomainsEnabled: z10.boolean(),
|
|
304
|
+
agentMcpEnabled: z10.boolean(),
|
|
305
|
+
emailNotificationsEnabled: z10.boolean()
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
// ../shared/dist/image-value.js
|
|
309
|
+
import { z as z11 } from "zod";
|
|
310
|
+
var SUPPORTED_IMAGE_CONTENT_TYPES = [
|
|
311
|
+
"image/jpeg",
|
|
312
|
+
"image/png",
|
|
313
|
+
"image/webp",
|
|
314
|
+
"image/avif"
|
|
315
|
+
];
|
|
316
|
+
var maxImageUploadBytes = 10 * 1024 * 1024;
|
|
317
|
+
var largeImageWarningBytes = 2 * 1024 * 1024;
|
|
318
|
+
var imageContentTypeSchema = z11.enum(SUPPORTED_IMAGE_CONTENT_TYPES);
|
|
319
|
+
var imageCropSchema = z11.object({
|
|
320
|
+
x: z11.number().min(0).max(100),
|
|
321
|
+
y: z11.number().min(0).max(100),
|
|
322
|
+
zoom: z11.number().min(1).max(4),
|
|
323
|
+
aspectRatio: z11.number().positive().max(10)
|
|
324
|
+
});
|
|
325
|
+
var imageValueSchema = z11.object({
|
|
326
|
+
src: z11.string().trim().min(1),
|
|
327
|
+
alt: z11.string().trim().min(1).max(300),
|
|
328
|
+
width: z11.number().int().positive().optional(),
|
|
329
|
+
height: z11.number().int().positive().optional(),
|
|
330
|
+
crop: imageCropSchema.optional(),
|
|
331
|
+
assetId: z11.string().uuid().optional(),
|
|
332
|
+
finalStorageProvider: z11.enum([
|
|
333
|
+
"repo_static_assets",
|
|
334
|
+
"repo_handoff",
|
|
335
|
+
"site_owned_storage",
|
|
336
|
+
"clientplane_managed_fallback"
|
|
337
|
+
]).optional()
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
// ../shared/dist/readiness.js
|
|
341
|
+
import { z as z12 } from "zod";
|
|
342
|
+
var READINESS_CHECK_KEYS = [
|
|
343
|
+
"agent_instructions_installed",
|
|
344
|
+
"manual_setup_confirmed",
|
|
345
|
+
"runtime_package_connected",
|
|
346
|
+
"secure_server_access_configured",
|
|
347
|
+
"manifest_synced",
|
|
348
|
+
"approved_field_exists",
|
|
349
|
+
"pending_manifest_changes_clear",
|
|
350
|
+
"preview_bridge_working",
|
|
351
|
+
"admin_access_url_selected",
|
|
352
|
+
"default_publishing_mode_selected"
|
|
353
|
+
];
|
|
354
|
+
var READINESS_STATUSES = [
|
|
355
|
+
"pending",
|
|
356
|
+
"passing",
|
|
357
|
+
"failing",
|
|
358
|
+
"warning"
|
|
359
|
+
];
|
|
360
|
+
var readinessCheckKeySchema = z12.enum(READINESS_CHECK_KEYS);
|
|
361
|
+
var readinessStatusSchema = z12.enum(READINESS_STATUSES);
|
|
362
|
+
|
|
363
|
+
// ../shared/dist/site.js
|
|
364
|
+
import { z as z13 } from "zod";
|
|
365
|
+
var SITE_STATUSES = [
|
|
366
|
+
"setup",
|
|
367
|
+
"client_ready",
|
|
368
|
+
"disabled",
|
|
369
|
+
"archived"
|
|
370
|
+
];
|
|
371
|
+
var siteStatusSchema = z13.enum(SITE_STATUSES);
|
|
372
|
+
var websiteUrlSchema = z13.string().trim().url().refine((value) => value.startsWith("https://") || value.startsWith("http://"), "Website URL must use http or https");
|
|
373
|
+
|
|
374
|
+
// ../cli/dist/scan/next-source-scan.js
|
|
375
|
+
var editableComponentNames = /* @__PURE__ */ new Set([
|
|
376
|
+
"EditableImage",
|
|
377
|
+
"EditableText",
|
|
378
|
+
"EditableLongText",
|
|
379
|
+
"EditableLink"
|
|
380
|
+
]);
|
|
381
|
+
var functionTypeByName = {
|
|
382
|
+
text: "text",
|
|
383
|
+
longText: "longText",
|
|
384
|
+
link: "link",
|
|
385
|
+
image: "image"
|
|
386
|
+
};
|
|
387
|
+
function scanNextSourceFiles(files) {
|
|
388
|
+
const fields = [];
|
|
389
|
+
const hardErrors = [];
|
|
390
|
+
const warnings = [];
|
|
391
|
+
const suggestions = [];
|
|
392
|
+
for (const file of files) {
|
|
393
|
+
scanSourceFile(file, fields, hardErrors);
|
|
394
|
+
}
|
|
395
|
+
validateScannedFields(fields, hardErrors, warnings, suggestions);
|
|
396
|
+
const manifest = fieldManifestSchema.parse({
|
|
397
|
+
version: 1,
|
|
398
|
+
fields: uniqueFields(fields).filter((field) => isFieldId(field.fieldId)),
|
|
399
|
+
routes: createRoutes(fields)
|
|
400
|
+
});
|
|
401
|
+
return {
|
|
402
|
+
manifest,
|
|
403
|
+
hardErrors,
|
|
404
|
+
warnings,
|
|
405
|
+
suggestions
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
function uniqueFields(fields) {
|
|
409
|
+
const seen = /* @__PURE__ */ new Set();
|
|
410
|
+
const unique = [];
|
|
411
|
+
for (const field of fields) {
|
|
412
|
+
if (seen.has(field.fieldId)) {
|
|
413
|
+
continue;
|
|
414
|
+
}
|
|
415
|
+
seen.add(field.fieldId);
|
|
416
|
+
unique.push(field);
|
|
417
|
+
}
|
|
418
|
+
return unique;
|
|
419
|
+
}
|
|
420
|
+
function scanSourceFile(file, fields, hardErrors) {
|
|
421
|
+
const fieldsInFile = [];
|
|
422
|
+
const attrFieldIds = /* @__PURE__ */ new Set();
|
|
423
|
+
const attrRouteRefs = /* @__PURE__ */ new Set();
|
|
424
|
+
const sourceFile = ts.createSourceFile(file.filePath, file.sourceText, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);
|
|
425
|
+
function visit(node) {
|
|
426
|
+
if (ts.isJsxSelfClosingElement(node) || ts.isJsxOpeningElement(node)) {
|
|
427
|
+
const componentName = getJsxTagName(node.tagName);
|
|
428
|
+
if (editableComponentNames.has(componentName)) {
|
|
429
|
+
hardErrors.push({
|
|
430
|
+
code: "field_scan.value_first_required",
|
|
431
|
+
message: "Clientplane MVP uses value-first APIs. Replace this field with clientplane.route(...) or a field value call.",
|
|
432
|
+
filePath: file.filePath
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
if (ts.isCallExpression(node)) {
|
|
437
|
+
collectAttrsCall(node, attrFieldIds, attrRouteRefs);
|
|
438
|
+
const extractedFields = extractFunctionFields(node, file);
|
|
439
|
+
for (const field of extractedFields) {
|
|
440
|
+
fieldsInFile.push(field);
|
|
441
|
+
fields.push(field);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
ts.forEachChild(node, visit);
|
|
445
|
+
}
|
|
446
|
+
visit(sourceFile);
|
|
447
|
+
markMissingAttrsWarnings(fieldsInFile, attrFieldIds, attrRouteRefs);
|
|
448
|
+
}
|
|
449
|
+
function extractFunctionFields(node, file) {
|
|
450
|
+
if (!ts.isPropertyAccessExpression(node.expression)) {
|
|
451
|
+
return [];
|
|
452
|
+
}
|
|
453
|
+
if (node.expression.expression.getText() !== "clientplane") {
|
|
454
|
+
return [];
|
|
455
|
+
}
|
|
456
|
+
const functionName = node.expression.name.text;
|
|
457
|
+
if (functionName === "route") {
|
|
458
|
+
return extractRouteFields(node, file);
|
|
459
|
+
}
|
|
460
|
+
const fieldType = functionTypeByName[functionName];
|
|
461
|
+
if (!fieldType) {
|
|
462
|
+
return [];
|
|
463
|
+
}
|
|
464
|
+
const fieldId = staticExpressionValue(node.arguments[0]);
|
|
465
|
+
if (typeof fieldId !== "string") {
|
|
466
|
+
return [];
|
|
467
|
+
}
|
|
468
|
+
const input = {
|
|
469
|
+
fieldId,
|
|
470
|
+
fieldType,
|
|
471
|
+
fallback: staticExpressionValue(node.arguments[1]),
|
|
472
|
+
source: "function",
|
|
473
|
+
sourceFilePath: file.filePath,
|
|
474
|
+
sourceExportName: functionName,
|
|
475
|
+
editTarget: fieldId
|
|
476
|
+
};
|
|
477
|
+
const routeHint = inferRouteHint(file.filePath);
|
|
478
|
+
const options = staticExpressionValue(node.arguments[2]);
|
|
479
|
+
const fieldOptions = options && typeof options === "object" && !Array.isArray(options) ? options : {};
|
|
480
|
+
assignIfDefined(input, "routeHint", routeHint);
|
|
481
|
+
assignIfDefined(input, "label", stringValue(fieldOptions.label));
|
|
482
|
+
assignIfDefined(input, "description", stringValue(fieldOptions.description));
|
|
483
|
+
assignIfDefined(input, "required", booleanValue(fieldOptions.required));
|
|
484
|
+
assignIfDefined(input, "maxLength", numberValue(fieldOptions.maxLength));
|
|
485
|
+
return [createField(input)];
|
|
486
|
+
}
|
|
487
|
+
function extractRouteFields(node, file) {
|
|
488
|
+
const routeId = staticExpressionValue(node.arguments[0]);
|
|
489
|
+
const fallbacks = staticExpressionValue(node.arguments[1]);
|
|
490
|
+
const options = staticExpressionValue(node.arguments[2]);
|
|
491
|
+
if (typeof routeId !== "string" || !fallbacks || typeof fallbacks !== "object" || Array.isArray(fallbacks)) {
|
|
492
|
+
return [];
|
|
493
|
+
}
|
|
494
|
+
const routeVariableName = getAssignedVariableName(node);
|
|
495
|
+
const fieldsConfig = options && typeof options === "object" && !Array.isArray(options) ? options.fields : void 0;
|
|
496
|
+
const routeHint = inferRouteHint(file.filePath);
|
|
497
|
+
const fields = [];
|
|
498
|
+
for (const [key, fallback] of Object.entries(fallbacks)) {
|
|
499
|
+
const config = fieldsConfig && typeof fieldsConfig === "object" && !Array.isArray(fieldsConfig) ? fieldsConfig[key] : void 0;
|
|
500
|
+
if (!config || typeof config !== "object" || Array.isArray(config)) {
|
|
501
|
+
continue;
|
|
502
|
+
}
|
|
503
|
+
const fieldConfig = config;
|
|
504
|
+
const fieldId = stringValue(fieldConfig.id);
|
|
505
|
+
const fieldType = fieldTypeValue(fieldConfig.type);
|
|
506
|
+
if (!fieldId || !fieldType) {
|
|
507
|
+
continue;
|
|
508
|
+
}
|
|
509
|
+
const input = {
|
|
510
|
+
fieldId,
|
|
511
|
+
fieldType,
|
|
512
|
+
fallback,
|
|
513
|
+
source: "function",
|
|
514
|
+
sourceFilePath: file.filePath,
|
|
515
|
+
sourceExportName: "route",
|
|
516
|
+
routeId,
|
|
517
|
+
sourcePath: `$.${key}`,
|
|
518
|
+
editTarget: fieldId,
|
|
519
|
+
routeFieldKey: key
|
|
520
|
+
};
|
|
521
|
+
assignIfDefined(input, "routeVariableName", routeVariableName);
|
|
522
|
+
assignIfDefined(input, "routeHint", routeHint);
|
|
523
|
+
assignIfDefined(input, "label", stringValue(fieldConfig.label));
|
|
524
|
+
assignIfDefined(input, "description", stringValue(fieldConfig.description));
|
|
525
|
+
assignIfDefined(input, "required", booleanValue(fieldConfig.required));
|
|
526
|
+
assignIfDefined(input, "maxLength", numberValue(fieldConfig.maxLength));
|
|
527
|
+
fields.push(createField(input));
|
|
528
|
+
}
|
|
529
|
+
return fields;
|
|
530
|
+
}
|
|
531
|
+
function createField(input) {
|
|
532
|
+
const field = {
|
|
533
|
+
fieldId: input.fieldId,
|
|
534
|
+
fieldType: input.fieldType,
|
|
535
|
+
fallback: input.fallback,
|
|
536
|
+
source: input.source,
|
|
537
|
+
sourceFilePath: input.sourceFilePath,
|
|
538
|
+
warnings: [],
|
|
539
|
+
suggestions: []
|
|
540
|
+
};
|
|
541
|
+
assignIfDefined(field, "label", input.label);
|
|
542
|
+
assignIfDefined(field, "description", input.description);
|
|
543
|
+
assignIfDefined(field, "required", input.required);
|
|
544
|
+
assignIfDefined(field, "maxLength", input.maxLength);
|
|
545
|
+
assignIfDefined(field, "sourceExportName", input.sourceExportName);
|
|
546
|
+
assignIfDefined(field, "componentHint", input.componentHint);
|
|
547
|
+
assignIfDefined(field, "routeHint", input.routeHint);
|
|
548
|
+
assignIfDefined(field, "routeId", input.routeId);
|
|
549
|
+
assignIfDefined(field, "sourcePath", input.sourcePath);
|
|
550
|
+
assignIfDefined(field, "editTarget", input.editTarget);
|
|
551
|
+
assignIfDefined(field, "routeVariableName", input.routeVariableName);
|
|
552
|
+
assignIfDefined(field, "routeFieldKey", input.routeFieldKey);
|
|
553
|
+
if (field.fieldType === "text" && field.maxLength === void 0) {
|
|
554
|
+
field.warnings.push("field_scan.text_max_length_missing");
|
|
555
|
+
}
|
|
556
|
+
if (isPositionalFieldReference(field.fieldId) || isPositionalFieldReference(field.sourcePath)) {
|
|
557
|
+
field.warnings.push("field_scan.positional_repeating_id");
|
|
558
|
+
}
|
|
559
|
+
return field;
|
|
560
|
+
}
|
|
561
|
+
function collectAttrsCall(node, attrFieldIds, attrRouteRefs) {
|
|
562
|
+
if (!ts.isPropertyAccessExpression(node.expression)) {
|
|
563
|
+
return;
|
|
564
|
+
}
|
|
565
|
+
if (node.expression.expression.getText() !== "clientplane" || node.expression.name.text !== "attrs") {
|
|
566
|
+
return;
|
|
567
|
+
}
|
|
568
|
+
const firstArg = node.arguments[0];
|
|
569
|
+
const secondArg = staticExpressionValue(node.arguments[1]);
|
|
570
|
+
const directFieldId = staticExpressionValue(firstArg);
|
|
571
|
+
if (typeof directFieldId === "string") {
|
|
572
|
+
attrFieldIds.add(directFieldId);
|
|
573
|
+
return;
|
|
574
|
+
}
|
|
575
|
+
if (firstArg && ts.isIdentifier(firstArg) && typeof secondArg === "string") {
|
|
576
|
+
attrRouteRefs.add(`${firstArg.text}:${secondArg}`);
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
function markMissingAttrsWarnings(fields, attrFieldIds, attrRouteRefs) {
|
|
580
|
+
for (const field of fields) {
|
|
581
|
+
if (field.fieldType !== "text" && field.fieldType !== "longText") {
|
|
582
|
+
continue;
|
|
583
|
+
}
|
|
584
|
+
const hasDirectAttrs = attrFieldIds.has(field.fieldId);
|
|
585
|
+
const hasRouteAttrs = field.routeVariableName && field.routeFieldKey ? attrRouteRefs.has(`${field.routeVariableName}:${field.routeFieldKey}`) : false;
|
|
586
|
+
if (!hasDirectAttrs && !hasRouteAttrs) {
|
|
587
|
+
field.warnings.push("field_scan.attrs_missing");
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
function validateScannedFields(fields, hardErrors, warnings, suggestions) {
|
|
592
|
+
const seen = /* @__PURE__ */ new Map();
|
|
593
|
+
for (const field of fields) {
|
|
594
|
+
if (!isFieldId(field.fieldId)) {
|
|
595
|
+
hardErrors.push({
|
|
596
|
+
code: "field_scan.invalid_field_id",
|
|
597
|
+
message: `Invalid field id: ${field.fieldId}`,
|
|
598
|
+
fieldId: field.fieldId,
|
|
599
|
+
filePath: field.sourceFilePath ?? "unknown"
|
|
600
|
+
});
|
|
601
|
+
}
|
|
602
|
+
const existing = seen.get(field.fieldId);
|
|
603
|
+
if (existing) {
|
|
604
|
+
hardErrors.push({
|
|
605
|
+
code: "field_scan.duplicate_id",
|
|
606
|
+
message: `Duplicate field id: ${field.fieldId}`,
|
|
607
|
+
fieldId: field.fieldId,
|
|
608
|
+
filePath: field.sourceFilePath ?? "unknown"
|
|
609
|
+
});
|
|
610
|
+
if (existing.fieldType !== field.fieldType) {
|
|
611
|
+
hardErrors.push({
|
|
612
|
+
code: "field_scan.type_conflict",
|
|
613
|
+
message: `Field id ${field.fieldId} is used with multiple types.`,
|
|
614
|
+
fieldId: field.fieldId,
|
|
615
|
+
filePath: field.sourceFilePath ?? "unknown"
|
|
616
|
+
});
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
seen.set(field.fieldId, field);
|
|
620
|
+
for (const warning of field.warnings) {
|
|
621
|
+
warnings.push({
|
|
622
|
+
code: warning,
|
|
623
|
+
message: getScanIssueMessage(warning),
|
|
624
|
+
fieldId: field.fieldId,
|
|
625
|
+
filePath: field.sourceFilePath ?? "unknown"
|
|
626
|
+
});
|
|
627
|
+
}
|
|
628
|
+
for (const suggestion of field.suggestions) {
|
|
629
|
+
suggestions.push({
|
|
630
|
+
code: suggestion,
|
|
631
|
+
message: getScanIssueMessage(suggestion),
|
|
632
|
+
fieldId: field.fieldId,
|
|
633
|
+
filePath: field.sourceFilePath ?? "unknown"
|
|
634
|
+
});
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
function getScanIssueMessage(code) {
|
|
639
|
+
if (code === "field_scan.attrs_missing") {
|
|
640
|
+
return "Field renders a value but has no DOM discovery attrs. Add clientplane.attrs(...) to the nearest stable element so the visual editor can select it.";
|
|
641
|
+
}
|
|
642
|
+
if (code === "field_scan.positional_repeating_id") {
|
|
643
|
+
return "Repeating content needs stable Clientplane field IDs for the MVP. Replace positional array/index field ids with stable item ids such as services.haircut.price.";
|
|
644
|
+
}
|
|
645
|
+
if (code === "field_scan.animation_wrapper") {
|
|
646
|
+
return 'Put clientplane.attrs(...) on the stable wrapper and make the animation respect data-clientplane-editor="true" or useClientplaneEditorMode().';
|
|
647
|
+
}
|
|
648
|
+
return code;
|
|
649
|
+
}
|
|
650
|
+
function staticExpressionValue(expression) {
|
|
651
|
+
if (!expression) {
|
|
652
|
+
return void 0;
|
|
653
|
+
}
|
|
654
|
+
if (ts.isStringLiteral(expression) || ts.isNoSubstitutionTemplateLiteral(expression)) {
|
|
655
|
+
return expression.text;
|
|
656
|
+
}
|
|
657
|
+
if (ts.isNumericLiteral(expression)) {
|
|
658
|
+
return Number(expression.text);
|
|
659
|
+
}
|
|
660
|
+
if (expression.kind === ts.SyntaxKind.TrueKeyword) {
|
|
661
|
+
return true;
|
|
662
|
+
}
|
|
663
|
+
if (expression.kind === ts.SyntaxKind.FalseKeyword) {
|
|
664
|
+
return false;
|
|
665
|
+
}
|
|
666
|
+
if (ts.isObjectLiteralExpression(expression)) {
|
|
667
|
+
return readObjectLiteral(expression);
|
|
668
|
+
}
|
|
669
|
+
return void 0;
|
|
670
|
+
}
|
|
671
|
+
function readObjectLiteral(expression) {
|
|
672
|
+
const value = {};
|
|
673
|
+
for (const property of expression.properties) {
|
|
674
|
+
if (!ts.isPropertyAssignment(property)) {
|
|
675
|
+
continue;
|
|
676
|
+
}
|
|
677
|
+
const name = getPropertyName(property.name);
|
|
678
|
+
if (!name) {
|
|
679
|
+
continue;
|
|
680
|
+
}
|
|
681
|
+
value[name] = staticExpressionValue(property.initializer);
|
|
682
|
+
}
|
|
683
|
+
return value;
|
|
684
|
+
}
|
|
685
|
+
function getPropertyName(name) {
|
|
686
|
+
if (ts.isIdentifier(name) || ts.isStringLiteral(name)) {
|
|
687
|
+
return name.text;
|
|
688
|
+
}
|
|
689
|
+
return null;
|
|
690
|
+
}
|
|
691
|
+
function getAssignedVariableName(node) {
|
|
692
|
+
let current = node;
|
|
693
|
+
while (ts.isAwaitExpression(current.parent)) {
|
|
694
|
+
current = current.parent;
|
|
695
|
+
}
|
|
696
|
+
if (ts.isVariableDeclaration(current.parent) && ts.isIdentifier(current.parent.name)) {
|
|
697
|
+
return current.parent.name.text;
|
|
698
|
+
}
|
|
699
|
+
return void 0;
|
|
700
|
+
}
|
|
701
|
+
function getJsxTagName(tagName) {
|
|
702
|
+
return tagName.getText();
|
|
703
|
+
}
|
|
704
|
+
function stringValue(value) {
|
|
705
|
+
return typeof value === "string" ? value : void 0;
|
|
706
|
+
}
|
|
707
|
+
function fieldTypeValue(value) {
|
|
708
|
+
if (value === "text" || value === "longText" || value === "image" || value === "link") {
|
|
709
|
+
return value;
|
|
710
|
+
}
|
|
711
|
+
return void 0;
|
|
712
|
+
}
|
|
713
|
+
function numberValue(value) {
|
|
714
|
+
return typeof value === "number" ? value : void 0;
|
|
715
|
+
}
|
|
716
|
+
function booleanValue(value) {
|
|
717
|
+
return typeof value === "boolean" ? value : void 0;
|
|
718
|
+
}
|
|
719
|
+
function assignIfDefined(object, key, value) {
|
|
720
|
+
if (value !== void 0) {
|
|
721
|
+
object[key] = value;
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
function inferRouteHint(filePath) {
|
|
725
|
+
const normalized = filePath.replaceAll("\\", "/");
|
|
726
|
+
const appIndex = normalized.indexOf("app/");
|
|
727
|
+
if (appIndex === -1 || !normalized.endsWith("page.tsx")) {
|
|
728
|
+
return void 0;
|
|
729
|
+
}
|
|
730
|
+
const route = normalized.slice(appIndex + 4, -"page.tsx".length).split("/").filter((segment) => segment && !segment.startsWith("(")).join("/");
|
|
731
|
+
return route ? `/${route}` : "/";
|
|
732
|
+
}
|
|
733
|
+
function isPositionalFieldReference(value) {
|
|
734
|
+
return value ? /\[\d+\]|\.\d+(?:\.|$)/.test(value) : false;
|
|
735
|
+
}
|
|
736
|
+
function createRoutes(fields) {
|
|
737
|
+
const paths = /* @__PURE__ */ new Set();
|
|
738
|
+
for (const field of fields) {
|
|
739
|
+
if (field.routeHint) {
|
|
740
|
+
paths.add(field.routeHint);
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
return [...paths].map((path) => ({ path }));
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
// ../cli/dist/commands/scan.js
|
|
747
|
+
async function scanCommand(filePaths) {
|
|
748
|
+
const files = await Promise.all(filePaths.map(async (filePath) => ({
|
|
749
|
+
filePath,
|
|
750
|
+
sourceText: await readFile(filePath, "utf8")
|
|
751
|
+
})));
|
|
752
|
+
return scanNextSourceFiles(files);
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
// ../cli/dist/commands/check.js
|
|
756
|
+
async function checkCommand(filePaths) {
|
|
757
|
+
const result = await scanCommand(filePaths);
|
|
758
|
+
return {
|
|
759
|
+
ok: result.hardErrors.length === 0,
|
|
760
|
+
hardErrorCount: result.hardErrors.length,
|
|
761
|
+
warningCount: result.warnings.length,
|
|
762
|
+
warnings: result.warnings
|
|
763
|
+
};
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
// ../cli/dist/commands/export.js
|
|
767
|
+
async function exportCommand(input) {
|
|
768
|
+
return {
|
|
769
|
+
kind: "json",
|
|
770
|
+
values: await input.readPublishedValues()
|
|
771
|
+
};
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
// ../cli/dist/config/project-config.js
|
|
775
|
+
import { access, readFile as readFile2, writeFile } from "fs/promises";
|
|
776
|
+
import { join } from "path";
|
|
777
|
+
import { z as z14 } from "zod";
|
|
778
|
+
var clientplaneProjectConfigSchema = z14.object({
|
|
779
|
+
apiBaseUrl: z14.string().url(),
|
|
780
|
+
siteId: z14.string().trim().min(1),
|
|
781
|
+
workspaceId: z14.string().trim().min(1),
|
|
782
|
+
publicSiteKey: z14.string().trim().min(1),
|
|
783
|
+
manifestPath: z14.string().trim().min(1).default("clientplane.manifest.json")
|
|
784
|
+
});
|
|
785
|
+
async function readProjectPackageJson(projectDir) {
|
|
786
|
+
return JSON.parse(await readFile2(join(projectDir, "package.json"), "utf8"));
|
|
787
|
+
}
|
|
788
|
+
async function detectNextProject(projectDir) {
|
|
789
|
+
const packageJson = await readProjectPackageJson(projectDir).catch(() => null);
|
|
790
|
+
if (packageJson?.dependencies?.next || packageJson?.devDependencies?.next) {
|
|
791
|
+
return true;
|
|
792
|
+
}
|
|
793
|
+
for (const fileName of ["next.config.js", "next.config.mjs", "next.config.ts"]) {
|
|
794
|
+
try {
|
|
795
|
+
await access(join(projectDir, fileName));
|
|
796
|
+
return true;
|
|
797
|
+
} catch {
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
return false;
|
|
801
|
+
}
|
|
802
|
+
async function writeProjectConfig(projectDir, config) {
|
|
803
|
+
const parsed = clientplaneProjectConfigSchema.parse(config);
|
|
804
|
+
const path = join(projectDir, "clientplane.config.json");
|
|
805
|
+
await writeFile(path, `${JSON.stringify(parsed, null, 2)}
|
|
806
|
+
`, "utf8");
|
|
807
|
+
return path;
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
// ../cli/dist/config/credentials.js
|
|
811
|
+
import { mkdir, writeFile as writeFile2 } from "fs/promises";
|
|
812
|
+
import { dirname, join as join2 } from "path";
|
|
813
|
+
import { z as z15 } from "zod";
|
|
814
|
+
var localCredentialsSchema = z15.object({
|
|
815
|
+
apiBaseUrl: z15.string().url(),
|
|
816
|
+
accessToken: z15.string().trim().min(1)
|
|
817
|
+
});
|
|
818
|
+
async function writeLocalCredentials(projectDir, credentials, options = {}) {
|
|
819
|
+
const path = join2(projectDir, ".clientplane/credentials.json");
|
|
820
|
+
if (await options.isTrackedFile?.(path)) {
|
|
821
|
+
throw new Error("Refusing to write Clientplane credentials into a tracked file.");
|
|
822
|
+
}
|
|
823
|
+
await mkdir(dirname(path), { recursive: true });
|
|
824
|
+
await writeFile2(path, `${JSON.stringify(localCredentialsSchema.parse(credentials), null, 2)}
|
|
825
|
+
`, "utf8");
|
|
826
|
+
return path;
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
// ../cli/dist/commands/init.js
|
|
830
|
+
async function initCommand(input) {
|
|
831
|
+
if (!input.setupToken.trim()) {
|
|
832
|
+
throw new Error("A Clientplane setup token is required.");
|
|
833
|
+
}
|
|
834
|
+
if (!await detectNextProject(input.projectDir)) {
|
|
835
|
+
throw new Error("Clientplane init currently supports Next.js projects.");
|
|
836
|
+
}
|
|
837
|
+
const configPath = await writeProjectConfig(input.projectDir, {
|
|
838
|
+
apiBaseUrl: input.apiBaseUrl,
|
|
839
|
+
siteId: input.siteId,
|
|
840
|
+
workspaceId: input.workspaceId,
|
|
841
|
+
publicSiteKey: input.publicSiteKey,
|
|
842
|
+
manifestPath: "clientplane.manifest.json"
|
|
843
|
+
});
|
|
844
|
+
const credentialsPath = await writeLocalCredentials(input.projectDir, {
|
|
845
|
+
apiBaseUrl: input.apiBaseUrl,
|
|
846
|
+
accessToken: input.projectConnectionToken
|
|
847
|
+
}, input.isTrackedFile ? { isTrackedFile: input.isTrackedFile } : {});
|
|
848
|
+
return {
|
|
849
|
+
configPath,
|
|
850
|
+
credentialsPath,
|
|
851
|
+
nextSteps: [
|
|
852
|
+
"npm install @clientplane/runtime-next",
|
|
853
|
+
"clientplane check",
|
|
854
|
+
"clientplane scan",
|
|
855
|
+
"clientplane sync"
|
|
856
|
+
]
|
|
857
|
+
};
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
// ../cli/dist/commands/sync.js
|
|
861
|
+
async function syncCommand(input) {
|
|
862
|
+
return fetch(`${input.config.apiBaseUrl}/api/cli/field-manifest/sync`, {
|
|
863
|
+
method: "POST",
|
|
864
|
+
headers: {
|
|
865
|
+
authorization: `Bearer ${input.config.accessToken}`,
|
|
866
|
+
"content-type": "application/json"
|
|
867
|
+
},
|
|
868
|
+
body: JSON.stringify({
|
|
869
|
+
siteId: input.config.siteId,
|
|
870
|
+
manifest: input.manifest
|
|
871
|
+
})
|
|
872
|
+
});
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
// ../cli/dist/manifest/write-manifest.js
|
|
876
|
+
import { mkdir as mkdir2, writeFile as writeFile3 } from "fs/promises";
|
|
877
|
+
import { dirname as dirname2, join as join3 } from "path";
|
|
878
|
+
export {
|
|
879
|
+
backfillCommand,
|
|
880
|
+
checkCommand,
|
|
881
|
+
exportCommand,
|
|
882
|
+
initCommand,
|
|
883
|
+
scanCommand,
|
|
884
|
+
syncCommand
|
|
885
|
+
};
|