@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/lib/index.js ADDED
@@ -0,0 +1,335 @@
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 isAssetFileName = (value) => assetFileNameSchema.safeParse(value).success;
277
+ var assetFileDataSchema = z2.object({
278
+ name: assetFileNameSchema,
279
+ data: z2.string().superRefine(assertAssetFileDataString)
280
+ });
281
+ var projectBundleSchema = z2.object({
282
+ page: Page,
283
+ pages: z2.array(Page),
284
+ build: SerializedBuildSchema,
285
+ assets: z2.array(Asset),
286
+ origin: z2.string().optional()
287
+ });
288
+ var publishedProjectBundleSchema = projectBundleSchema.extend({
289
+ bundleVersion: z2.union([z2.string(), z2.number()]).optional(),
290
+ user: z2.object({ email: z2.string().nullable() }).optional(),
291
+ projectDomain: z2.string(),
292
+ projectTitle: z2.string()
293
+ });
294
+ var importProjectBundleInputSchema = z2.object({
295
+ projectId: z2.string(),
296
+ data: publishedProjectBundleSchema,
297
+ assetFiles: z2.array(assetFileDataSchema).optional(),
298
+ ignoreVersionCheck: z2.boolean().optional()
299
+ });
300
+ var importProjectBundleResultSchema = z2.object({
301
+ version: z2.number()
302
+ });
303
+ var checkProjectBuildPermissionInputSchema = z2.object({
304
+ projectId: z2.string()
305
+ });
306
+ var bundleVersion = createContractVersion(
307
+ publishedProjectBundleSchema,
308
+ package_default.version,
309
+ [wsAuthConfigSchema]
310
+ );
311
+ var getBundleVersion = (data) => {
312
+ if (typeof data !== "object" || data === null) {
313
+ return;
314
+ }
315
+ const version = data.bundleVersion;
316
+ return typeof version === "number" || typeof version === "string" ? version : void 0;
317
+ };
318
+ var getBundleVersionMismatchMessage = ({
319
+ ignoreVersionCheckHint,
320
+ receivedVersion
321
+ }) => `Project bundle format is incompatible. Expected version ${bundleVersion}, received ${receivedVersion ?? "missing"}. Sync with a compatible API/CLI version and retry, or ${ignoreVersionCheckHint}.`;
322
+ export {
323
+ assetFileDataPattern,
324
+ assetFileDataSchema,
325
+ bundleVersion,
326
+ checkProjectBuildPermissionInputSchema,
327
+ getBundleVersion,
328
+ getBundleVersionMismatchMessage,
329
+ importProjectBundleInputSchema,
330
+ importProjectBundleResultSchema,
331
+ isAssetFileDataString,
332
+ isAssetFileName,
333
+ projectBundleSchema,
334
+ publishedProjectBundleSchema
335
+ };
@@ -0,0 +1,2 @@
1
+ import { z } from "zod";
2
+ export declare const createContractVersion: (schema: z.ZodTypeAny, version: string, additionalSchemas?: z.ZodTypeAny[]) => `bundle-${string}-${string}`;
@@ -0,0 +1,22 @@
1
+ import type { Asset, Page } from "@webstudio-is/sdk/schema";
2
+ import { type PublishedProjectBundle } from "./schema";
3
+ type SerializedBuild = PublishedProjectBundle["build"];
4
+ type SerializedPages = SerializedBuild["pages"];
5
+ type ImageAsset = Extract<Asset, {
6
+ type: "image";
7
+ }>;
8
+ type SerializedBuildFixtureOptions = Partial<Omit<SerializedBuild, "pages">> & {
9
+ pages?: Partial<SerializedPages>;
10
+ };
11
+ export declare const createPageFixture: (overrides?: Partial<Page>) => Page;
12
+ export declare const createImageAssetFixture: (overrides?: Partial<ImageAsset>) => ImageAsset;
13
+ export declare const createSerializedBuildFixture: ({ pages, ...overrides }?: SerializedBuildFixtureOptions) => SerializedBuild;
14
+ type PublishedProjectBundleFixtureOptions = Partial<Omit<PublishedProjectBundle, "assets" | "build" | "page" | "pages">> & {
15
+ build?: SerializedBuildFixtureOptions;
16
+ buildPages?: Partial<SerializedPages>;
17
+ page?: Partial<Page>;
18
+ assets?: Asset[];
19
+ pages?: Page[];
20
+ };
21
+ export declare const createPublishedProjectBundleFixture: (options?: PublishedProjectBundleFixtureOptions) => PublishedProjectBundle;
22
+ export {};
@@ -0,0 +1 @@
1
+ export * from "./schema";