@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/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,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";
|