@webstudio-is/protocol 0.271.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.
@@ -0,0 +1,411 @@
1
+ // src/schema.ts
2
+ import { Asset, Page } from "@webstudio-is/sdk/schema";
3
+ import { SerializedBuildSchema } from "@webstudio-is/project-build/schema";
4
+ import { wsAuthConfigSchema } from "@webstudio-is/wsauth/schema";
5
+ import { z as z2 } from "zod";
6
+
7
+ // package.json
8
+ var package_default = {
9
+ name: "@webstudio-is/protocol",
10
+ version: "0.271.0",
11
+ description: "Webstudio data exchange protocol contracts",
12
+ author: "Webstudio <github@webstudio.is>",
13
+ homepage: "https://webstudio.is",
14
+ type: "module",
15
+ scripts: {
16
+ build: "rm -rf lib && esbuild src/index.ts src/fixtures.ts --outdir=lib --bundle --format=esm --packages=external",
17
+ dts: "tsc --project tsconfig.dts.json",
18
+ test: "vitest run",
19
+ typecheck: "tsgo --noEmit"
20
+ },
21
+ dependencies: {
22
+ "@webstudio-is/project-build": "workspace:*",
23
+ "@webstudio-is/sdk": "workspace:*",
24
+ "@webstudio-is/wsauth": "workspace:*",
25
+ zod: "^3.24.2"
26
+ },
27
+ devDependencies: {
28
+ "@webstudio-is/tsconfig": "workspace:*",
29
+ vitest: "^3.1.2"
30
+ },
31
+ exports: {
32
+ ".": {
33
+ webstudio: "./src/index.ts",
34
+ types: "./lib/types/index.d.ts",
35
+ import: "./lib/index.js",
36
+ default: "./src/index.ts"
37
+ },
38
+ "./fixtures": {
39
+ webstudio: "./src/fixtures.ts",
40
+ types: "./lib/types/fixtures.d.ts",
41
+ import: "./lib/fixtures.js",
42
+ default: "./src/fixtures.ts"
43
+ }
44
+ },
45
+ files: [
46
+ "lib/*",
47
+ "!*.{test,stories}.*"
48
+ ],
49
+ license: "AGPL-3.0-or-later",
50
+ private: false,
51
+ sideEffects: false
52
+ };
53
+
54
+ // src/contract-version.ts
55
+ import { z } from "zod";
56
+ var getFunctionContract = (value) => {
57
+ if (typeof value !== "function") {
58
+ return;
59
+ }
60
+ const contractFunction = value;
61
+ if (contractFunction.contract !== void 0) {
62
+ return { contract: contractFunction.contract };
63
+ }
64
+ return { contract: "unversioned-function" };
65
+ };
66
+ var getSchemaContract = (schema, seen = /* @__PURE__ */ new Map()) => {
67
+ const schemaId = seen.get(schema);
68
+ if (schemaId !== void 0) {
69
+ return { type: "ref", id: schemaId };
70
+ }
71
+ seen.set(schema, seen.size);
72
+ const definition = schema._def;
73
+ switch (definition.typeName) {
74
+ case z.ZodFirstPartyTypeKind.ZodArray:
75
+ return {
76
+ type: "array",
77
+ value: getSchemaContract(definition.type, seen),
78
+ checks: {
79
+ exactLength: definition.exactLength,
80
+ maxLength: definition.maxLength,
81
+ minLength: definition.minLength
82
+ }
83
+ };
84
+ case z.ZodFirstPartyTypeKind.ZodBoolean:
85
+ return {
86
+ type: "boolean"
87
+ };
88
+ case z.ZodFirstPartyTypeKind.ZodDefault:
89
+ return {
90
+ type: "default",
91
+ value: getSchemaContract(definition.innerType, seen)
92
+ };
93
+ case z.ZodFirstPartyTypeKind.ZodDiscriminatedUnion:
94
+ return {
95
+ type: "discriminatedUnion",
96
+ discriminator: definition.discriminator,
97
+ options: definition.options.map(
98
+ (option) => getSchemaContract(option, seen)
99
+ )
100
+ };
101
+ case z.ZodFirstPartyTypeKind.ZodEffects:
102
+ return {
103
+ type: "effects",
104
+ effect: definition.effect.type,
105
+ source: getFunctionContract(
106
+ definition.effect.refinement ?? definition.effect.transform
107
+ ),
108
+ value: getSchemaContract(definition.schema, seen)
109
+ };
110
+ case z.ZodFirstPartyTypeKind.ZodEnum:
111
+ return {
112
+ type: "enum",
113
+ values: definition.values
114
+ };
115
+ case z.ZodFirstPartyTypeKind.ZodLiteral:
116
+ return {
117
+ type: "literal",
118
+ value: definition.value
119
+ };
120
+ case z.ZodFirstPartyTypeKind.ZodLazy:
121
+ return {
122
+ type: "lazy",
123
+ value: getSchemaContract(definition.getter(), seen)
124
+ };
125
+ case z.ZodFirstPartyTypeKind.ZodMap:
126
+ return {
127
+ type: "map",
128
+ key: getSchemaContract(definition.keyType, seen),
129
+ value: getSchemaContract(definition.valueType, seen)
130
+ };
131
+ case z.ZodFirstPartyTypeKind.ZodNativeEnum:
132
+ return {
133
+ type: "nativeEnum",
134
+ values: definition.values
135
+ };
136
+ case z.ZodFirstPartyTypeKind.ZodNever:
137
+ return {
138
+ type: "never"
139
+ };
140
+ case z.ZodFirstPartyTypeKind.ZodNull:
141
+ return {
142
+ type: "null"
143
+ };
144
+ case z.ZodFirstPartyTypeKind.ZodNullable:
145
+ return {
146
+ type: "nullable",
147
+ value: getSchemaContract(definition.innerType, seen)
148
+ };
149
+ case z.ZodFirstPartyTypeKind.ZodNumber:
150
+ return {
151
+ type: "number",
152
+ checks: definition.checks
153
+ };
154
+ case z.ZodFirstPartyTypeKind.ZodObject:
155
+ return {
156
+ type: "object",
157
+ unknownKeys: definition.unknownKeys,
158
+ catchall: getSchemaContract(definition.catchall, seen),
159
+ shape: Object.fromEntries(
160
+ Object.entries(definition.shape()).sort(([left], [right]) => left.localeCompare(right)).map(([key, value]) => [
161
+ key,
162
+ getSchemaContract(value, seen)
163
+ ])
164
+ )
165
+ };
166
+ case z.ZodFirstPartyTypeKind.ZodOptional:
167
+ return {
168
+ type: "optional",
169
+ value: getSchemaContract(definition.innerType, seen)
170
+ };
171
+ case z.ZodFirstPartyTypeKind.ZodRecord:
172
+ return {
173
+ type: "record",
174
+ key: getSchemaContract(definition.keyType, seen),
175
+ value: getSchemaContract(definition.valueType, seen)
176
+ };
177
+ case z.ZodFirstPartyTypeKind.ZodString:
178
+ return {
179
+ type: "string",
180
+ checks: definition.checks
181
+ };
182
+ case z.ZodFirstPartyTypeKind.ZodTuple:
183
+ return {
184
+ type: "tuple",
185
+ items: definition.items.map(
186
+ (item) => getSchemaContract(item, seen)
187
+ ),
188
+ rest: definition.rest === null ? void 0 : getSchemaContract(definition.rest, seen)
189
+ };
190
+ case z.ZodFirstPartyTypeKind.ZodUndefined:
191
+ return {
192
+ type: "undefined"
193
+ };
194
+ case z.ZodFirstPartyTypeKind.ZodUnknown:
195
+ return {
196
+ type: "unknown"
197
+ };
198
+ case z.ZodFirstPartyTypeKind.ZodUnion:
199
+ return {
200
+ type: "union",
201
+ options: definition.options.map(
202
+ (option) => getSchemaContract(option, seen)
203
+ )
204
+ };
205
+ default:
206
+ throw new Error(
207
+ `Unsupported schema contract type: ${definition.typeName}`
208
+ );
209
+ }
210
+ };
211
+ var stableStringify = (value) => {
212
+ if (value === void 0) {
213
+ return "undefined";
214
+ }
215
+ if (value instanceof RegExp) {
216
+ return stableStringify({
217
+ source: value.source,
218
+ flags: value.flags
219
+ });
220
+ }
221
+ if (Array.isArray(value)) {
222
+ return `[${value.map(stableStringify).join(",")}]`;
223
+ }
224
+ if (value !== null && typeof value === "object") {
225
+ return `{${Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, item]) => `${JSON.stringify(key)}:${stableStringify(item)}`).join(",")}}`;
226
+ }
227
+ return JSON.stringify(value);
228
+ };
229
+ var createContractVersion = (schema, version, additionalSchemas = []) => {
230
+ const bundlePackageVersion = version.replace(/-webstudio-version$/, "");
231
+ let hash = 2166136261;
232
+ for (const char of stableStringify({
233
+ additionalSchemas: additionalSchemas.map(
234
+ (schema2) => getSchemaContract(schema2)
235
+ ),
236
+ schema: getSchemaContract(schema)
237
+ })) {
238
+ hash ^= char.charCodeAt(0);
239
+ hash = Math.imul(hash, 16777619);
240
+ }
241
+ return `bundle-${bundlePackageVersion}-${(hash >>> 0).toString(16).padStart(8, "0")}`;
242
+ };
243
+
244
+ // src/schema.ts
245
+ var assetFileDataPattern = /^[A-Za-z0-9+/]*={0,2}$/;
246
+ var isAssetFileDataString = (value) => {
247
+ if (value.length % 4 !== 0) {
248
+ return false;
249
+ }
250
+ if (assetFileDataPattern.test(value) === false) {
251
+ return false;
252
+ }
253
+ const paddingIndex = value.indexOf("=");
254
+ return paddingIndex === -1 || paddingIndex >= value.length - 2;
255
+ };
256
+ var assertAssetFileDataString = Object.assign(
257
+ (value, context) => {
258
+ if (isAssetFileDataString(value)) {
259
+ return;
260
+ }
261
+ context.addIssue({
262
+ code: z2.ZodIssueCode.custom,
263
+ message: "Invalid asset file data"
264
+ });
265
+ },
266
+ {
267
+ contract: {
268
+ encoding: "base64",
269
+ length: "multiple-of-4",
270
+ padding: "only-last-two-characters",
271
+ pattern: assetFileDataPattern
272
+ }
273
+ }
274
+ );
275
+ var assetFileNameSchema = z2.string().min(1).regex(/^(?!\.{1,2}$)[^/\\]+$/);
276
+ var assetFileDataSchema = z2.object({
277
+ name: assetFileNameSchema,
278
+ data: z2.string().superRefine(assertAssetFileDataString)
279
+ });
280
+ var projectBundleSchema = z2.object({
281
+ page: Page,
282
+ pages: z2.array(Page),
283
+ build: SerializedBuildSchema,
284
+ assets: z2.array(Asset),
285
+ origin: z2.string().optional()
286
+ });
287
+ var publishedProjectBundleSchema = projectBundleSchema.extend({
288
+ bundleVersion: z2.union([z2.string(), z2.number()]).optional(),
289
+ user: z2.object({ email: z2.string().nullable() }).optional(),
290
+ projectDomain: z2.string(),
291
+ projectTitle: z2.string()
292
+ });
293
+ var importProjectBundleInputSchema = z2.object({
294
+ projectId: z2.string(),
295
+ data: publishedProjectBundleSchema,
296
+ assetFiles: z2.array(assetFileDataSchema).optional(),
297
+ ignoreVersionCheck: z2.boolean().optional()
298
+ });
299
+ var importProjectBundleResultSchema = z2.object({
300
+ version: z2.number()
301
+ });
302
+ var checkProjectBuildPermissionInputSchema = z2.object({
303
+ projectId: z2.string()
304
+ });
305
+ var bundleVersion = createContractVersion(
306
+ publishedProjectBundleSchema,
307
+ package_default.version,
308
+ [wsAuthConfigSchema]
309
+ );
310
+
311
+ // src/fixtures.ts
312
+ var createPageFixture = (overrides = {}) => ({
313
+ id: "home",
314
+ name: "Home",
315
+ path: "",
316
+ title: "Home",
317
+ meta: {},
318
+ rootInstanceId: "root",
319
+ ...overrides
320
+ });
321
+ var createImageAssetFixture = (overrides = {}) => ({
322
+ id: "asset-1",
323
+ projectId: "source-project",
324
+ name: "image.png",
325
+ type: "image",
326
+ createdAt: "2024-01-01T00:00:00.000Z",
327
+ format: "png",
328
+ size: 100,
329
+ meta: { width: 100, height: 100 },
330
+ ...overrides
331
+ });
332
+ var createSerializedBuildFixture = ({
333
+ pages,
334
+ ...overrides
335
+ } = {}) => {
336
+ const page = createPageFixture();
337
+ return {
338
+ id: "build-1",
339
+ projectId: "source-project",
340
+ version: 1,
341
+ createdAt: "2024-01-01T00:00:00.000Z",
342
+ updatedAt: "2024-01-01T00:00:00.000Z",
343
+ pages: {
344
+ homePageId: page.id,
345
+ rootFolderId: "root-folder",
346
+ pages: [page],
347
+ folders: [
348
+ {
349
+ id: "root-folder",
350
+ name: "Root",
351
+ slug: "",
352
+ children: [page.id]
353
+ }
354
+ ],
355
+ ...pages
356
+ },
357
+ breakpoints: [],
358
+ styles: [],
359
+ styleSources: [],
360
+ styleSourceSelections: [],
361
+ props: [],
362
+ instances: [],
363
+ dataSources: [],
364
+ resources: [],
365
+ ...overrides
366
+ };
367
+ };
368
+ var createPublishedProjectBundleFixture = (options = {}) => {
369
+ const {
370
+ assets,
371
+ build,
372
+ buildPages,
373
+ page: pageOverrides,
374
+ pages,
375
+ ...overrides
376
+ } = options;
377
+ const page = createPageFixture(pageOverrides);
378
+ return {
379
+ bundleVersion,
380
+ origin: "https://example.com",
381
+ projectDomain: "example",
382
+ projectTitle: "Example",
383
+ page,
384
+ pages: "pages" in options ? pages : [page],
385
+ assets: "assets" in options ? assets : [],
386
+ build: createSerializedBuildFixture({
387
+ ...build,
388
+ pages: {
389
+ homePageId: page.id,
390
+ pages: [page],
391
+ folders: [
392
+ {
393
+ id: "root-folder",
394
+ name: "Root",
395
+ slug: "",
396
+ children: [page.id]
397
+ }
398
+ ],
399
+ ...build?.pages,
400
+ ...buildPages
401
+ }
402
+ }),
403
+ ...overrides
404
+ };
405
+ };
406
+ export {
407
+ createImageAssetFixture,
408
+ createPageFixture,
409
+ createPublishedProjectBundleFixture,
410
+ createSerializedBuildFixture
411
+ };