@valbuild/react 0.15.0 → 0.17.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/ValUI-3e00aae3.cjs.prod.js +104 -0
- package/dist/ValUI-64e3e5f2.browser.esm.js +102 -0
- package/dist/ValUI-9ac161d2.cjs.dev.js +104 -0
- package/dist/ValUI-d33998d0.esm.js +102 -0
- package/dist/declarations/src/ValProvider.d.ts +1 -1
- package/dist/declarations/src/ValStore.d.ts +8 -9
- package/dist/declarations/src/index.d.ts +1 -2
- package/dist/declarations/src/stega/index.d.ts +1 -3
- package/dist/declarations/src/stega/{stegaEncode.d.ts → transform.d.ts} +8 -5
- package/dist/{defineProperty-12b5bd29.esm.js → defineProperty-034d0378.browser.esm.js} +1 -1
- package/dist/{defineProperty-a4bf59bc.worker.esm.js → defineProperty-18559492.worker.esm.js} +1 -1
- package/dist/{defineProperty-f319cb47.browser.esm.js → defineProperty-b209a901.esm.js} +1 -1
- package/dist/{slicedToArray-d846e1d2.esm.js → slicedToArray-0cbb3d34.browser.esm.js} +13 -10
- package/dist/{slicedToArray-9e7d1407.worker.esm.js → slicedToArray-5a51fd33.worker.esm.js} +13 -10
- package/dist/{slicedToArray-b7cf26e0.cjs.dev.js → slicedToArray-5bddfa58.cjs.prod.js} +14 -11
- package/dist/slicedToArray-7b1713a7.cjs.dev.js +59 -0
- package/dist/{slicedToArray-1a246338.browser.esm.js → slicedToArray-b4fb91fa.esm.js} +13 -10
- package/dist/typeof-16c77f45.cjs.prod.js +13 -0
- package/dist/typeof-1de657a3.cjs.dev.js +13 -0
- package/dist/typeof-52fabea9.browser.esm.js +11 -0
- package/dist/typeof-5c86a240.esm.js +11 -0
- package/dist/typeof-8854ace1.worker.esm.js +11 -0
- package/dist/valbuild-react.browser.esm.js +618 -24
- package/dist/valbuild-react.cjs.dev.js +621 -28
- package/dist/valbuild-react.cjs.prod.js +621 -28
- package/dist/valbuild-react.esm.js +618 -24
- package/dist/valbuild-react.worker.esm.js +616 -24
- package/jsx-dev-runtime/dist/valbuild-react-jsx-dev-runtime.browser.esm.js +2 -2
- package/jsx-dev-runtime/dist/valbuild-react-jsx-dev-runtime.cjs.dev.js +3 -3
- package/jsx-dev-runtime/dist/valbuild-react-jsx-dev-runtime.cjs.prod.js +3 -3
- package/jsx-dev-runtime/dist/valbuild-react-jsx-dev-runtime.esm.js +2 -2
- package/jsx-dev-runtime/dist/valbuild-react-jsx-dev-runtime.worker.esm.js +2 -2
- package/jsx-runtime/dist/valbuild-react-jsx-runtime.browser.esm.js +2 -2
- package/jsx-runtime/dist/valbuild-react-jsx-runtime.cjs.dev.js +3 -3
- package/jsx-runtime/dist/valbuild-react-jsx-runtime.cjs.prod.js +3 -3
- package/jsx-runtime/dist/valbuild-react-jsx-runtime.esm.js +2 -2
- package/jsx-runtime/dist/valbuild-react-jsx-runtime.worker.esm.js +2 -2
- package/package.json +3 -3
- package/src/ValProvider.tsx +2 -3
- package/src/ValStore.ts +90 -40
- package/src/ValUI.tsx +49 -338
- package/src/index.ts +1 -2
- package/src/stega/autoTagJSX.ts +1 -1
- package/src/stega/index.ts +6 -3
- package/src/stega/transform.test.ts +145 -0
- package/src/stega/transform.ts +220 -0
- package/stega/dist/valbuild-react-stega.browser.esm.js +131 -46
- package/stega/dist/valbuild-react-stega.cjs.dev.js +134 -49
- package/stega/dist/valbuild-react-stega.cjs.prod.js +134 -49
- package/stega/dist/valbuild-react-stega.esm.js +131 -46
- package/stega/dist/valbuild-react-stega.worker.esm.js +109 -45
- package/dist/ValProvider-2eb6c2f2.esm.js +0 -701
- package/dist/ValProvider-74eef393.cjs.js +0 -7
- package/dist/ValProvider-74eef393.cjs.prod.js +0 -715
- package/dist/ValProvider-c677e164.browser.esm.js +0 -701
- package/dist/ValProvider-cb5a2161.worker.esm.js +0 -696
- package/dist/ValProvider-f647e355.cjs.dev.js +0 -715
- package/dist/ValUI-0c2671a7.cjs.prod.js +0 -382
- package/dist/ValUI-334ef1d0.cjs.dev.js +0 -382
- package/dist/ValUI-bb1d1ed6.browser.esm.js +0 -380
- package/dist/ValUI-bf82178a.esm.js +0 -380
- package/dist/declarations/src/ValApi.d.ts +0 -12
- package/dist/declarations/src/hooks/useVal.d.ts +0 -3
- package/dist/declarations/src/stega/fetchVal.d.ts +0 -3
- package/dist/declarations/src/stega/hooks/useVal.d.ts +0 -3
- package/dist/objectSpread2-30cc2856.browser.esm.js +0 -25
- package/dist/objectSpread2-61fbd9a9.cjs.dev.js +0 -27
- package/dist/objectSpread2-7b752a35.cjs.prod.js +0 -27
- package/dist/objectSpread2-d5a1fe1c.esm.js +0 -25
- package/dist/slicedToArray-0eb0bcdb.cjs.prod.js +0 -56
- package/dist/unsupportedIterableToArray-51bb61c2.esm.js +0 -16
- package/dist/unsupportedIterableToArray-738344ef.worker.esm.js +0 -16
- package/dist/unsupportedIterableToArray-9e97e24a.cjs.dev.js +0 -18
- package/dist/unsupportedIterableToArray-afbea1dd.cjs.prod.js +0 -18
- package/dist/unsupportedIterableToArray-d3087ed5.browser.esm.js +0 -16
- package/src/AuthStatus.tsx +0 -13
- package/src/ValApi.ts +0 -65
- package/src/hooks/useVal.test.tsx +0 -57
- package/src/hooks/useVal.ts +0 -35
- package/src/stega/fetchVal.ts +0 -16
- package/src/stega/hooks/useVal.ts +0 -14
- package/src/stega/stegaEncode.ts +0 -84
package/src/ValUI.tsx
CHANGED
@@ -1,353 +1,64 @@
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
2
|
+
import { Internal } from "@valbuild/core";
|
3
|
+
import { Style, ValOverlay } from "@valbuild/ui";
|
2
4
|
import { useEffect, useState } from "react";
|
3
|
-
import { ValApi } from "./ValApi";
|
4
|
-
import { ValStore } from "./ValStore";
|
5
|
-
import { Inputs, Style, ValOverlay } from "@valbuild/ui";
|
6
|
-
import {
|
7
|
-
FileSource,
|
8
|
-
FILE_REF_PROP,
|
9
|
-
Internal,
|
10
|
-
RichText,
|
11
|
-
SourcePath,
|
12
|
-
VAL_EXTENSION,
|
13
|
-
} from "@valbuild/core";
|
14
|
-
import { PatchJSON } from "@valbuild/core/patch";
|
15
|
-
import { ImageMetadata } from "@valbuild/core/src/schema/image";
|
16
|
-
import { AuthStatus } from "./AuthStatus";
|
17
5
|
import { ShadowRoot } from "./ShadowRoot";
|
6
|
+
import { useValApi } from "./ValProvider";
|
18
7
|
|
19
|
-
export
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
const [selectedSources, setSelectedSources] = useState<string[]>([]);
|
26
|
-
const [editMode, setEditMode] = useState(false);
|
27
|
-
const [editFormPosition, setEditFormPosition] = useState<{
|
28
|
-
left: number;
|
29
|
-
top: number;
|
30
|
-
} | null>(null);
|
31
|
-
|
32
|
-
const [authentication, setAuthentication] = useState<AuthStatus>({
|
33
|
-
status: "not-asked",
|
34
|
-
});
|
35
|
-
|
36
|
-
useEffect(() => {
|
37
|
-
if (editMode) {
|
38
|
-
valStore.updateAll();
|
39
|
-
}
|
40
|
-
}, [editMode]);
|
8
|
+
export default function ValUI() {
|
9
|
+
const [isClient, setIsClient] = useState(false);
|
10
|
+
const [enabled, setEnabled] = useState(false);
|
11
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
12
|
+
const [isDraftMode, setDraftMode] = useState(false); // TODO: if enabled, but not in draft mode: show something
|
13
|
+
const api = useValApi();
|
41
14
|
useEffect(() => {
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
passive: true,
|
47
|
-
};
|
48
|
-
if (editMode) {
|
49
|
-
// highlight val element by appending a new style
|
50
|
-
styleElement = document.createElement("style");
|
51
|
-
styleElement.id = "val-edit-highlight";
|
52
|
-
styleElement.innerHTML = `
|
53
|
-
.val-edit-mode >* [data-val-path] {
|
54
|
-
outline: #ffff00 solid 1px;
|
55
|
-
cursor: pointer;
|
56
|
-
}
|
57
|
-
`;
|
58
|
-
document.body.appendChild(styleElement);
|
59
|
-
|
60
|
-
// capture event clicks on data-val-path elements
|
61
|
-
openValFormListener = (e: MouseEvent) => {
|
62
|
-
if (e.target instanceof Element) {
|
63
|
-
let parent = e.target;
|
64
|
-
while (parent && parent !== document.body) {
|
65
|
-
if (parent.getAttribute("data-val-path")) {
|
66
|
-
break;
|
67
|
-
}
|
68
|
-
if (parent.parentElement) {
|
69
|
-
parent = parent.parentElement;
|
70
|
-
} else {
|
71
|
-
break;
|
72
|
-
}
|
73
|
-
}
|
74
|
-
const valSources = parent?.getAttribute("data-val-path");
|
75
|
-
if (valSources) {
|
76
|
-
e.stopPropagation();
|
77
|
-
setSelectedSources(
|
78
|
-
valSources.split(
|
79
|
-
","
|
80
|
-
) /* TODO: just split on commas will not work if path contains , */
|
81
|
-
);
|
82
|
-
setEditFormPosition({
|
83
|
-
left: e.pageX,
|
84
|
-
top: e.pageY,
|
85
|
-
});
|
86
|
-
// } else if (!isValElement(e.target)) {
|
87
|
-
// console.log("click outside", e.target);
|
88
|
-
// setEditFormPosition(null);
|
89
|
-
// setSelectedSources([]);
|
90
|
-
}
|
91
|
-
}
|
92
|
-
};
|
93
|
-
document.addEventListener(
|
94
|
-
"click",
|
95
|
-
openValFormListener,
|
96
|
-
editButtonClickOptions
|
15
|
+
setIsClient(true);
|
16
|
+
try {
|
17
|
+
const valEnabled = document.cookie?.includes(
|
18
|
+
`${Internal.VAL_ENABLE_COOKIE_NAME}=true`
|
97
19
|
);
|
20
|
+
setEnabled(valEnabled);
|
21
|
+
} catch (e) {
|
22
|
+
console.warn("Could not read Val enabled state", e);
|
98
23
|
}
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
}
|
107
|
-
styleElement?.remove();
|
108
|
-
};
|
109
|
-
}, [editMode]);
|
110
|
-
useEffect(() => {
|
111
|
-
if (editMode) {
|
112
|
-
document.body.classList.add("val-edit-mode");
|
113
|
-
} else {
|
114
|
-
document.body.classList.remove("val-edit-mode");
|
115
|
-
}
|
116
|
-
|
117
|
-
if (editMode) {
|
118
|
-
if (authentication.status !== "authenticated") {
|
119
|
-
valApi
|
120
|
-
.getSession()
|
121
|
-
.then(async (res) => {
|
122
|
-
if (res.status === 401) {
|
123
|
-
setAuthentication({
|
124
|
-
status: "unauthenticated",
|
125
|
-
});
|
126
|
-
} else if (res.ok) {
|
127
|
-
const data = await res.json();
|
128
|
-
if (data.mode === "local") {
|
129
|
-
setAuthentication({ status: "local" });
|
130
|
-
} else if (data.mode === "proxy") {
|
131
|
-
setAuthentication({
|
132
|
-
status: "authenticated",
|
133
|
-
});
|
134
|
-
} else {
|
135
|
-
setAuthentication({
|
136
|
-
status: "error",
|
137
|
-
message: "Unknown authentication mode",
|
138
|
-
});
|
139
|
-
}
|
140
|
-
} else {
|
141
|
-
let message = "Unknown error";
|
142
|
-
try {
|
143
|
-
message = await res.text();
|
144
|
-
} catch {
|
145
|
-
// ignore
|
146
|
-
}
|
147
|
-
setAuthentication({
|
148
|
-
status: "error",
|
149
|
-
message,
|
150
|
-
});
|
151
|
-
}
|
152
|
-
})
|
153
|
-
.catch((err) => {
|
154
|
-
console.error("Failed to fetch session", err);
|
155
|
-
setAuthentication({
|
156
|
-
status: "error",
|
157
|
-
message: "Unknown authentication mode",
|
158
|
-
});
|
159
|
-
});
|
160
|
-
}
|
161
|
-
} else {
|
162
|
-
if (authentication.status === "error") {
|
163
|
-
setAuthentication({
|
164
|
-
status: "not-asked",
|
165
|
-
});
|
166
|
-
}
|
24
|
+
try {
|
25
|
+
const valDraftMode = document.cookie?.includes(
|
26
|
+
`${Internal.VAL_DRAFT_MODE_COOKIE}=true`
|
27
|
+
);
|
28
|
+
setDraftMode(valDraftMode);
|
29
|
+
} catch (e) {
|
30
|
+
console.warn("Could not read Val draft mode", e);
|
167
31
|
}
|
168
|
-
}, [editMode, authentication.status]);
|
169
|
-
|
170
|
-
const [showEditButton, setShowEditButton] = useState(false);
|
171
|
-
useEffect(() => {
|
172
|
-
setShowEditButton(true);
|
173
32
|
}, []);
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
typeof serializedModule.source === "string"
|
185
|
-
) {
|
186
|
-
input = {
|
187
|
-
status: "completed",
|
188
|
-
type: "text",
|
189
|
-
data: serializedModule.source,
|
190
|
-
};
|
191
|
-
} else if (
|
192
|
-
serializedModule.schema.type === "richtext" &&
|
193
|
-
typeof serializedModule.source === "object"
|
194
|
-
) {
|
195
|
-
input = {
|
196
|
-
status: "completed",
|
197
|
-
type: "richtext",
|
198
|
-
data: serializedModule.source as RichText, // TODO: validate
|
199
|
-
};
|
200
|
-
} else if (
|
201
|
-
serializedModule.schema.type === "image" &&
|
202
|
-
serializedModule.source &&
|
203
|
-
typeof serializedModule.source === "object" &&
|
204
|
-
FILE_REF_PROP in serializedModule.source &&
|
205
|
-
typeof serializedModule.source[FILE_REF_PROP] === "string" &&
|
206
|
-
VAL_EXTENSION in serializedModule.source &&
|
207
|
-
typeof serializedModule.source[VAL_EXTENSION] === "string"
|
208
|
-
) {
|
209
|
-
input = {
|
210
|
-
status: "completed",
|
211
|
-
type: "image",
|
212
|
-
data: Internal.convertImageSource(
|
213
|
-
serializedModule.source as FileSource<ImageMetadata>
|
214
|
-
),
|
215
|
-
};
|
216
|
-
}
|
217
|
-
console.log("input path", path);
|
218
|
-
console.log("serialized path", serializedModule.path);
|
219
|
-
if (!input) {
|
220
|
-
throw new Error(
|
221
|
-
`Unsupported module type: ${serializedModule.schema.type}`
|
222
|
-
);
|
223
|
-
}
|
224
|
-
setInputs((inputs) => {
|
225
|
-
return {
|
226
|
-
...inputs,
|
227
|
-
[serializedModule.path]: input,
|
228
|
-
} as Inputs;
|
229
|
-
});
|
230
|
-
});
|
231
|
-
}
|
232
|
-
}, [selectedSources.join(",")]);
|
233
|
-
if (!showEditButton) {
|
33
|
+
if (isClient && !enabled && process.env.NODE_ENV === "development") {
|
34
|
+
console.log(
|
35
|
+
`Val is disabled. Enable it by going here ${window.origin}${
|
36
|
+
api.host
|
37
|
+
}/enable?redirect_to=${encodeURIComponent(
|
38
|
+
window.location.href
|
39
|
+
)}. NOTE: this message appears because NODE_ENV is set to development.`
|
40
|
+
);
|
41
|
+
}
|
42
|
+
if (!isClient || !enabled) {
|
234
43
|
return null;
|
235
44
|
}
|
236
45
|
return (
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
<Style />
|
250
|
-
<div data-mode="dark">
|
251
|
-
<ValOverlay
|
252
|
-
editMode={editMode}
|
253
|
-
setEditMode={setEditMode}
|
254
|
-
closeValWindow={() => {
|
255
|
-
setEditFormPosition(null);
|
256
|
-
setSelectedSources([]);
|
257
|
-
setInputs({});
|
258
|
-
}}
|
259
|
-
valWindow={
|
260
|
-
(editFormPosition && {
|
261
|
-
position: editFormPosition,
|
262
|
-
inputs,
|
263
|
-
onSubmit: (inputs) => {
|
264
|
-
Promise.all(
|
265
|
-
Object.entries(inputs).map(([path, input]) => {
|
266
|
-
if (input.status === "completed") {
|
267
|
-
const [moduleId, modulePath] =
|
268
|
-
Internal.splitModuleIdAndModulePath(path as SourcePath);
|
269
|
-
if (input.type === "text") {
|
270
|
-
const patch: PatchJSON = [
|
271
|
-
{
|
272
|
-
value: input.data,
|
273
|
-
op: "replace",
|
274
|
-
path: `/${modulePath
|
275
|
-
.split(".")
|
276
|
-
.map((p) => JSON.parse(p))
|
277
|
-
.join("/")}`,
|
278
|
-
},
|
279
|
-
];
|
280
|
-
return valApi.patchModuleContent(moduleId, patch);
|
281
|
-
} else if (input.type === "image") {
|
282
|
-
const pathParts = modulePath
|
283
|
-
.split(".")
|
284
|
-
.map((p) => JSON.parse(p));
|
285
|
-
|
286
|
-
if (!input?.data || !("src" in input.data)) {
|
287
|
-
// TODO: We probably need to have an Output type that is different from the Input: we have a union of both cases in Input right now, and we believe we do not want that
|
288
|
-
console.warn(
|
289
|
-
"No .src on input provided - this might mean no changes was made"
|
290
|
-
);
|
291
|
-
return;
|
292
|
-
}
|
293
|
-
const patch: PatchJSON = [
|
294
|
-
{
|
295
|
-
value: input.data.src,
|
296
|
-
op: "replace",
|
297
|
-
path: `/${pathParts.slice(0, -1).join("/")}/$${
|
298
|
-
pathParts[pathParts.length - 1]
|
299
|
-
}`,
|
300
|
-
},
|
301
|
-
];
|
302
|
-
if (input.data.metadata) {
|
303
|
-
if (input.data.addMetadata) {
|
304
|
-
patch.push({
|
305
|
-
value: input.data.metadata,
|
306
|
-
op: "add",
|
307
|
-
path: `/${pathParts.join("/")}/metadata`,
|
308
|
-
});
|
309
|
-
} else {
|
310
|
-
patch.push({
|
311
|
-
value: input.data.metadata,
|
312
|
-
op: "replace",
|
313
|
-
path: `/${pathParts.join("/")}/metadata`,
|
314
|
-
});
|
315
|
-
}
|
316
|
-
}
|
317
|
-
console.log("patch", patch);
|
318
|
-
return valApi.patchModuleContent(moduleId, patch);
|
319
|
-
} else if (input.type === "richtext") {
|
320
|
-
const patch: PatchJSON = [
|
321
|
-
{
|
322
|
-
value: input.data,
|
323
|
-
op: "replace",
|
324
|
-
path: `/${modulePath
|
325
|
-
.split(".")
|
326
|
-
.map((p) => JSON.parse(p))
|
327
|
-
.join("/")}`,
|
328
|
-
},
|
329
|
-
];
|
330
|
-
return valApi.patchModuleContent(moduleId, patch);
|
331
|
-
}
|
332
|
-
throw new Error(
|
333
|
-
`Unsupported input type: ${(input as any).type}`
|
334
|
-
);
|
335
|
-
} else {
|
336
|
-
console.error("Submitted incomplete input, ignoring...");
|
337
|
-
return Promise.resolve();
|
338
|
-
}
|
339
|
-
})
|
340
|
-
).then(() => {
|
341
|
-
setEditFormPosition(null);
|
342
|
-
setSelectedSources([]);
|
343
|
-
setInputs({});
|
344
|
-
});
|
345
|
-
},
|
346
|
-
}) ??
|
347
|
-
undefined
|
348
|
-
}
|
46
|
+
<>
|
47
|
+
<ShadowRoot>
|
48
|
+
{/* TODO: */}
|
49
|
+
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
50
|
+
<link
|
51
|
+
rel="preconnect"
|
52
|
+
href="https://fonts.gstatic.com"
|
53
|
+
crossOrigin="anonymous"
|
54
|
+
/>
|
55
|
+
<link
|
56
|
+
href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;1,400&family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,400;1,700&display=swap"
|
57
|
+
rel="stylesheet"
|
349
58
|
/>
|
350
|
-
|
351
|
-
|
59
|
+
<Style />
|
60
|
+
<ValOverlay api={api} />
|
61
|
+
</ShadowRoot>
|
62
|
+
</>
|
352
63
|
);
|
353
64
|
}
|
package/src/index.ts
CHANGED
@@ -1,4 +1,3 @@
|
|
1
1
|
// NOTE: the exports of this file needs to be kept in sync with ValQuickJSRuntime
|
2
|
-
export { ValProvider } from "./ValProvider";
|
3
|
-
export { useVal } from "./hooks/useVal";
|
2
|
+
export { ValProvider, useValStore, useValApi } from "./ValProvider";
|
4
3
|
export { ValRichText } from "./ValRichText";
|
package/src/stega/autoTagJSX.ts
CHANGED
@@ -30,9 +30,9 @@ const addValPathIfFound = (type: any, props: any) => {
|
|
30
30
|
) {
|
31
31
|
const valPath = encodedBits?.data?.valPath;
|
32
32
|
if (valPath) {
|
33
|
-
console.log("Found encoded valPath", valPath);
|
34
33
|
valSources.push(valPath);
|
35
34
|
props[key] = vercelStegaSplit(value).cleaned;
|
35
|
+
props[`data-val-attr-${key}`] = valPath;
|
36
36
|
}
|
37
37
|
}
|
38
38
|
}
|
package/src/stega/index.ts
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
// NOTE: the exports of this file needs to be kept in sync with ValQuickJSRuntime
|
2
2
|
export { autoTagJSX } from "./autoTagJSX";
|
3
|
-
export {
|
4
|
-
|
5
|
-
|
3
|
+
export {
|
4
|
+
transform,
|
5
|
+
getModuleIds,
|
6
|
+
type ValEncodedString,
|
7
|
+
type StegaOfSource,
|
8
|
+
} from "./transform";
|
@@ -0,0 +1,145 @@
|
|
1
|
+
import { getModuleIds, transform } from "./transform";
|
2
|
+
import { initVal } from "@valbuild/core";
|
3
|
+
import { vercelStegaDecode, vercelStegaSplit } from "@vercel/stega";
|
4
|
+
|
5
|
+
const { s, val } = initVal();
|
6
|
+
|
7
|
+
describe("stega transform", () => {
|
8
|
+
test("basic", () => {
|
9
|
+
const schema = s.array(
|
10
|
+
s.object({
|
11
|
+
image: s.image(),
|
12
|
+
text: s.richtext(),
|
13
|
+
n: s.number(),
|
14
|
+
b: s.boolean(),
|
15
|
+
})
|
16
|
+
);
|
17
|
+
|
18
|
+
const valModule = val.content("/test", schema, [
|
19
|
+
{
|
20
|
+
image: val.file("/public/test1.png", {
|
21
|
+
sha256: "1231",
|
22
|
+
width: 100,
|
23
|
+
height: 100,
|
24
|
+
}),
|
25
|
+
text: val.richtext("Test1"),
|
26
|
+
n: 1,
|
27
|
+
b: true,
|
28
|
+
},
|
29
|
+
{
|
30
|
+
image: val.file("/public/test2.png", {
|
31
|
+
sha256: "1232",
|
32
|
+
width: 100,
|
33
|
+
height: 100,
|
34
|
+
}),
|
35
|
+
text: val.richtext("Test2"),
|
36
|
+
n: 2,
|
37
|
+
b: false,
|
38
|
+
},
|
39
|
+
]);
|
40
|
+
const transformed = transform(valModule, {});
|
41
|
+
|
42
|
+
expect(transformed).toHaveLength(2);
|
43
|
+
|
44
|
+
expect(vercelStegaDecode(transformed[0].image.url)).toStrictEqual({
|
45
|
+
data: {
|
46
|
+
valPath: '/test.0."image"',
|
47
|
+
},
|
48
|
+
origin: "val.build",
|
49
|
+
});
|
50
|
+
expect(vercelStegaDecode(transformed[1].image.url)).toStrictEqual({
|
51
|
+
data: {
|
52
|
+
valPath: '/test.1."image"',
|
53
|
+
},
|
54
|
+
origin: "val.build",
|
55
|
+
});
|
56
|
+
//
|
57
|
+
expect(vercelStegaSplit(transformed[0].image.url).cleaned).toStrictEqual(
|
58
|
+
"/test1.png?sha256=1231"
|
59
|
+
);
|
60
|
+
expect(vercelStegaSplit(transformed[1].image.url).cleaned).toStrictEqual(
|
61
|
+
"/test2.png?sha256=1232"
|
62
|
+
);
|
63
|
+
|
64
|
+
expect(transformed[0].text.valPath).toStrictEqual('/test.0."text"');
|
65
|
+
expect(transformed[1].text.valPath).toStrictEqual('/test.1."text"');
|
66
|
+
});
|
67
|
+
|
68
|
+
test("get modules", () => {
|
69
|
+
const schema = s.array(s.string());
|
70
|
+
|
71
|
+
expect(
|
72
|
+
getModuleIds({
|
73
|
+
foo: [
|
74
|
+
{ test: val.content("/test1", schema, ["one", "two"]) },
|
75
|
+
{ test: val.content("/test2", schema, ["one", "two"]) },
|
76
|
+
],
|
77
|
+
test: val.content("/test3", schema, ["one", "two"]),
|
78
|
+
})
|
79
|
+
).toStrictEqual(["/test1", "/test2", "/test3"]);
|
80
|
+
});
|
81
|
+
|
82
|
+
test("basic transform with get modules", () => {
|
83
|
+
const schema = s.array(s.string());
|
84
|
+
const transformed = transform(
|
85
|
+
val.content("/test1", schema, ["one", "two"]),
|
86
|
+
{
|
87
|
+
getModule: (moduleId) => {
|
88
|
+
if (moduleId === "/test1") {
|
89
|
+
return ["1", "2"];
|
90
|
+
}
|
91
|
+
},
|
92
|
+
}
|
93
|
+
);
|
94
|
+
|
95
|
+
expect(vercelStegaSplit(transformed[0]).cleaned).toStrictEqual("1");
|
96
|
+
expect(vercelStegaDecode(transformed[0])).toStrictEqual({
|
97
|
+
data: {
|
98
|
+
valPath: "/test1.0",
|
99
|
+
},
|
100
|
+
origin: "val.build",
|
101
|
+
});
|
102
|
+
});
|
103
|
+
|
104
|
+
test("transform with get modules", () => {
|
105
|
+
const schema = s.array(s.string());
|
106
|
+
const transformed = transform(
|
107
|
+
{
|
108
|
+
foo: [
|
109
|
+
{ test: val.content("/test1", schema, ["one", "two"]) },
|
110
|
+
{ test: val.content("/test2", schema, ["one", "two"]) },
|
111
|
+
],
|
112
|
+
test: val.content("/test3", schema, ["one", "two"]),
|
113
|
+
},
|
114
|
+
{
|
115
|
+
getModule: (moduleId) => {
|
116
|
+
if (moduleId === "/test2") {
|
117
|
+
return ["1", "2"];
|
118
|
+
}
|
119
|
+
},
|
120
|
+
}
|
121
|
+
);
|
122
|
+
|
123
|
+
expect(vercelStegaSplit(transformed.foo[0].test[0]).cleaned).toStrictEqual(
|
124
|
+
"one"
|
125
|
+
);
|
126
|
+
expect(vercelStegaDecode(transformed.foo[0].test[0])).toStrictEqual({
|
127
|
+
data: {
|
128
|
+
valPath: "/test1.0",
|
129
|
+
},
|
130
|
+
origin: "val.build",
|
131
|
+
});
|
132
|
+
|
133
|
+
//
|
134
|
+
|
135
|
+
expect(vercelStegaSplit(transformed.foo[1].test[0]).cleaned).toStrictEqual(
|
136
|
+
"1"
|
137
|
+
);
|
138
|
+
expect(vercelStegaDecode(transformed.foo[1].test[0])).toStrictEqual({
|
139
|
+
data: {
|
140
|
+
valPath: "/test2.0",
|
141
|
+
},
|
142
|
+
origin: "val.build",
|
143
|
+
});
|
144
|
+
});
|
145
|
+
});
|