@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.
- package/LICENSE +661 -0
- package/README.md +12 -0
- package/lib/fixtures.js +411 -0
- package/lib/index.js +335 -0
- package/lib/types/contract-version.d.ts +2 -0
- package/lib/types/fixtures.d.ts +22 -0
- package/lib/types/index.d.ts +1 -0
- package/lib/types/schema.d.ts +10490 -0
- package/package.json +45 -0
package/lib/fixtures.js
ADDED
|
@@ -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
|
+
};
|