@symbo.ls/brender 3.8.2 → 3.8.7
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/cjs/render.js +80 -6
- package/dist/esm/render.js +80 -6
- package/package.json +2 -2
- package/render.js +69 -2
package/dist/cjs/render.js
CHANGED
|
@@ -49,6 +49,17 @@ var import_prefetch = require("./prefetch.js");
|
|
|
49
49
|
var import_linkedom = require("linkedom");
|
|
50
50
|
var import_create_instance = __toESM(require("@emotion/css/create-instance"), 1);
|
|
51
51
|
const import_meta = {};
|
|
52
|
+
let _funcqlPlugin = null;
|
|
53
|
+
const getFuncqlPlugin = async () => {
|
|
54
|
+
if (_funcqlPlugin) return _funcqlPlugin;
|
|
55
|
+
try {
|
|
56
|
+
const mod = await import("@domql/funcql");
|
|
57
|
+
_funcqlPlugin = mod.funcqlPlugin;
|
|
58
|
+
return _funcqlPlugin;
|
|
59
|
+
} catch {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
52
63
|
const ssrResolve = (map, key) => {
|
|
53
64
|
if (!map || !key) return void 0;
|
|
54
65
|
if (map[key] !== void 0) return map[key];
|
|
@@ -122,8 +133,17 @@ const safeJsonReplacer = () => {
|
|
|
122
133
|
return value;
|
|
123
134
|
};
|
|
124
135
|
};
|
|
125
|
-
|
|
136
|
+
let _brenderRequire = null;
|
|
137
|
+
try {
|
|
138
|
+
if (import_meta.url) {
|
|
139
|
+
_brenderRequire = (0, import_module.createRequire)(import_meta.url);
|
|
140
|
+
}
|
|
141
|
+
} catch {
|
|
142
|
+
}
|
|
126
143
|
const detectWorkspace = () => {
|
|
144
|
+
if (!import_meta.url || !_brenderRequire) {
|
|
145
|
+
return { isMonorepo: false, monorepoRoot: null, resolvePackage: (pkg) => pkg };
|
|
146
|
+
}
|
|
127
147
|
const brenderDir = (0, import_fs.realpathSync)(new URL(".", import_meta.url).pathname);
|
|
128
148
|
const monorepoRoot = (0, import_path.resolve)(brenderDir, "../..");
|
|
129
149
|
const isMonorepo = (0, import_fs.existsSync)((0, import_path.resolve)(monorepoRoot, "packages", "smbls", "src", "createDomql.js"));
|
|
@@ -220,6 +240,15 @@ let _cachedCreateDomql = null;
|
|
|
220
240
|
const bundleCreateDomql = async () => {
|
|
221
241
|
if (_cachedCreateDomql) return _cachedCreateDomql;
|
|
222
242
|
const ws = detectWorkspace();
|
|
243
|
+
if (!_brenderRequire) {
|
|
244
|
+
try {
|
|
245
|
+
const mod2 = await import("./dist/createDomql.bundled.mjs");
|
|
246
|
+
_cachedCreateDomql = mod2;
|
|
247
|
+
return mod2;
|
|
248
|
+
} catch (err) {
|
|
249
|
+
throw new Error(`brender: pre-bundled createDomql not available in bundled runtime: ${err.message}`);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
223
252
|
let entry;
|
|
224
253
|
if (ws.isMonorepo) {
|
|
225
254
|
entry = (0, import_path.resolve)(ws.monorepoRoot, "packages", "smbls", "src", "createDomql.js");
|
|
@@ -381,6 +410,14 @@ const bundleCreateDomql = async () => {
|
|
|
381
410
|
);
|
|
382
411
|
return { contents, loader: "js" };
|
|
383
412
|
});
|
|
413
|
+
build.onLoad({ filter: /fetch\/adapters\/supabase\.js$/ }, () => {
|
|
414
|
+
return {
|
|
415
|
+
contents: `export const setup = async () => null;
|
|
416
|
+
export const supabaseAdapter = () => ({name:'supabase'});
|
|
417
|
+
`,
|
|
418
|
+
loader: "js"
|
|
419
|
+
};
|
|
420
|
+
});
|
|
384
421
|
build.onLoad({ filter: /.*/, namespace: "brender-stub" }, () => {
|
|
385
422
|
return { contents: "export const SyncComponent = {}; export const Inspect = {}; export const Notifications = {}; export default {}", loader: "js" };
|
|
386
423
|
});
|
|
@@ -455,9 +492,13 @@ const bundleCreateDomql = async () => {
|
|
|
455
492
|
]
|
|
456
493
|
});
|
|
457
494
|
const mod = await import(`file://${outFile}`);
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
495
|
+
if (!process.env.BRENDER_DEBUG) {
|
|
496
|
+
try {
|
|
497
|
+
(0, import_fs.unlinkSync)(outFile);
|
|
498
|
+
} catch {
|
|
499
|
+
}
|
|
500
|
+
} else {
|
|
501
|
+
console.log("[brender] Bundle saved:", outFile);
|
|
461
502
|
}
|
|
462
503
|
_cachedCreateDomql = mod;
|
|
463
504
|
return mod;
|
|
@@ -525,6 +566,22 @@ const UIKIT_STUBS = {
|
|
|
525
566
|
},
|
|
526
567
|
Text: { tag: "span" }
|
|
527
568
|
};
|
|
569
|
+
const buildPathRegistry = (element, path = "") => {
|
|
570
|
+
if (!element || !element.__ref) return {};
|
|
571
|
+
const registry = {};
|
|
572
|
+
const brKey = element.__ref.__brKey;
|
|
573
|
+
if (brKey) registry[path === "" ? "__root" : path] = brKey;
|
|
574
|
+
if (element.__ref.__children) {
|
|
575
|
+
for (const childKey of element.__ref.__children) {
|
|
576
|
+
const child = element[childKey];
|
|
577
|
+
if (child && child.__ref) {
|
|
578
|
+
const childPath = path === "" ? childKey : `${path}.${childKey}`;
|
|
579
|
+
Object.assign(registry, buildPathRegistry(child, childPath));
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
return registry;
|
|
584
|
+
};
|
|
528
585
|
const render = async (data, options = {}) => {
|
|
529
586
|
const { route = "/", pathname, state: stateOverrides, context: contextOverrides, prefetch = false } = options;
|
|
530
587
|
const locationPath = pathname || route;
|
|
@@ -651,12 +708,20 @@ const render = async (data, options = {}) => {
|
|
|
651
708
|
// Caller overrides
|
|
652
709
|
...contextOverrides || {}
|
|
653
710
|
};
|
|
711
|
+
const funcql = await getFuncqlPlugin();
|
|
712
|
+
if (funcql) {
|
|
713
|
+
ctx.plugins = ctx.plugins || [];
|
|
714
|
+
if (!ctx.plugins.some((p) => p.name === "funcql")) {
|
|
715
|
+
ctx.plugins.push(funcql);
|
|
716
|
+
}
|
|
717
|
+
}
|
|
654
718
|
(0, import_keys.resetKeys)();
|
|
655
719
|
const element = await createDomqlElement(app, ctx);
|
|
656
720
|
const flushDelay = prefetch ? 2e3 : 50;
|
|
657
721
|
await new Promise((r) => setTimeout(r, flushDelay));
|
|
658
722
|
(0, import_keys.assignKeys)(body);
|
|
659
723
|
const registry = (0, import_keys.mapKeysToElements)(element);
|
|
724
|
+
const brRegistry = buildPathRegistry(element);
|
|
660
725
|
const metadata = (0, import_metadata.extractMetadata)(data, route, element, element?.state);
|
|
661
726
|
const emotionCSS = [];
|
|
662
727
|
const emotionInstance = ctx.emotion || element && element.context && element.context.emotion;
|
|
@@ -707,7 +772,7 @@ const render = async (data, options = {}) => {
|
|
|
707
772
|
else delete globalThis.document;
|
|
708
773
|
if (_prevLoc !== void 0) globalThis.location = _prevLoc;
|
|
709
774
|
else delete globalThis.location;
|
|
710
|
-
return { html, metadata, registry, element, emotionCSS, document, window, ssrTranslations, prefetchedPages };
|
|
775
|
+
return { html, metadata, registry, brRegistry, element, emotionCSS, document, window, ssrTranslations, prefetchedPages };
|
|
711
776
|
};
|
|
712
777
|
const renderElement = async (elementDef, options = {}) => {
|
|
713
778
|
const { context = {} } = options;
|
|
@@ -753,6 +818,11 @@ const generateGlobalCSS = async (ds, config) => {
|
|
|
753
818
|
const { existsSync: existsSync2, writeFileSync: writeFileSync2, unlinkSync: unlinkSync2 } = await import("fs");
|
|
754
819
|
const { tmpdir: tmpdir2 } = await import("os");
|
|
755
820
|
const { randomBytes: randomBytes2 } = await import("crypto");
|
|
821
|
+
try {
|
|
822
|
+
tmpdir2();
|
|
823
|
+
} catch {
|
|
824
|
+
return {};
|
|
825
|
+
}
|
|
756
826
|
const esbuild = await import("esbuild");
|
|
757
827
|
const dsJson = JSON.stringify(ds || {}, safeJsonReplacer());
|
|
758
828
|
const cfgJson = JSON.stringify(config || {}, safeJsonReplacer());
|
|
@@ -970,6 +1040,7 @@ const renderRoute = async (data, options = {}) => {
|
|
|
970
1040
|
fontLinks: generateFontLinks(ds),
|
|
971
1041
|
metadata: result.metadata || (0, import_metadata.extractMetadata)(data, route),
|
|
972
1042
|
brKeyCount: result.registry ? Object.keys(result.registry).length : 0,
|
|
1043
|
+
brRegistry: result.brRegistry || {},
|
|
973
1044
|
ssrTranslations: result.ssrTranslations,
|
|
974
1045
|
prefetchedState,
|
|
975
1046
|
activeLang
|
|
@@ -1019,7 +1090,10 @@ const renderPage = async (data, route = "/", options = {}) => {
|
|
|
1019
1090
|
`;
|
|
1020
1091
|
}
|
|
1021
1092
|
}
|
|
1022
|
-
|
|
1093
|
+
const brRegistryJson = result.brRegistry && Object.keys(result.brRegistry).length ? JSON.stringify(result.brRegistry) : null;
|
|
1094
|
+
const brRegistryScript = brRegistryJson ? `<script>window.__BR_REGISTRY__=${brRegistryJson}<\/script>
|
|
1095
|
+
` : "";
|
|
1096
|
+
isrBody = `${translationSeed}${brRegistryScript}<script>window.__BRENDER__=true<\/script>
|
|
1023
1097
|
<script type="module" src="${prefix}${isr.clientScript}"><\/script>`;
|
|
1024
1098
|
} else {
|
|
1025
1099
|
isrBody = `<script type="module">
|
package/dist/esm/render.js
CHANGED
|
@@ -8,6 +8,17 @@ import { resetKeys, assignKeys, mapKeysToElements } from "./keys.js";
|
|
|
8
8
|
import { extractMetadata, generateHeadHtml } from "./metadata.js";
|
|
9
9
|
import { hydrate } from "./hydrate.js";
|
|
10
10
|
import { prefetchPageData, injectPrefetchedState, fetchSSRTranslations } from "./prefetch.js";
|
|
11
|
+
let _funcqlPlugin = null;
|
|
12
|
+
const getFuncqlPlugin = async () => {
|
|
13
|
+
if (_funcqlPlugin) return _funcqlPlugin;
|
|
14
|
+
try {
|
|
15
|
+
const mod = await import("@domql/funcql");
|
|
16
|
+
_funcqlPlugin = mod.funcqlPlugin;
|
|
17
|
+
return _funcqlPlugin;
|
|
18
|
+
} catch {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
};
|
|
11
22
|
import { parseHTML } from "linkedom";
|
|
12
23
|
import createEmotionInstance from "@emotion/css/create-instance";
|
|
13
24
|
const ssrResolve = (map, key) => {
|
|
@@ -83,8 +94,17 @@ const safeJsonReplacer = () => {
|
|
|
83
94
|
return value;
|
|
84
95
|
};
|
|
85
96
|
};
|
|
86
|
-
|
|
97
|
+
let _brenderRequire = null;
|
|
98
|
+
try {
|
|
99
|
+
if (import.meta.url) {
|
|
100
|
+
_brenderRequire = createRequire(import.meta.url);
|
|
101
|
+
}
|
|
102
|
+
} catch {
|
|
103
|
+
}
|
|
87
104
|
const detectWorkspace = () => {
|
|
105
|
+
if (!import.meta.url || !_brenderRequire) {
|
|
106
|
+
return { isMonorepo: false, monorepoRoot: null, resolvePackage: (pkg) => pkg };
|
|
107
|
+
}
|
|
88
108
|
const brenderDir = realpathSync(new URL(".", import.meta.url).pathname);
|
|
89
109
|
const monorepoRoot = resolve(brenderDir, "../..");
|
|
90
110
|
const isMonorepo = existsSync(resolve(monorepoRoot, "packages", "smbls", "src", "createDomql.js"));
|
|
@@ -181,6 +201,15 @@ let _cachedCreateDomql = null;
|
|
|
181
201
|
const bundleCreateDomql = async () => {
|
|
182
202
|
if (_cachedCreateDomql) return _cachedCreateDomql;
|
|
183
203
|
const ws = detectWorkspace();
|
|
204
|
+
if (!_brenderRequire) {
|
|
205
|
+
try {
|
|
206
|
+
const mod2 = await import("./dist/createDomql.bundled.mjs");
|
|
207
|
+
_cachedCreateDomql = mod2;
|
|
208
|
+
return mod2;
|
|
209
|
+
} catch (err) {
|
|
210
|
+
throw new Error(`brender: pre-bundled createDomql not available in bundled runtime: ${err.message}`);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
184
213
|
let entry;
|
|
185
214
|
if (ws.isMonorepo) {
|
|
186
215
|
entry = resolve(ws.monorepoRoot, "packages", "smbls", "src", "createDomql.js");
|
|
@@ -342,6 +371,14 @@ const bundleCreateDomql = async () => {
|
|
|
342
371
|
);
|
|
343
372
|
return { contents, loader: "js" };
|
|
344
373
|
});
|
|
374
|
+
build.onLoad({ filter: /fetch\/adapters\/supabase\.js$/ }, () => {
|
|
375
|
+
return {
|
|
376
|
+
contents: `export const setup = async () => null;
|
|
377
|
+
export const supabaseAdapter = () => ({name:'supabase'});
|
|
378
|
+
`,
|
|
379
|
+
loader: "js"
|
|
380
|
+
};
|
|
381
|
+
});
|
|
345
382
|
build.onLoad({ filter: /.*/, namespace: "brender-stub" }, () => {
|
|
346
383
|
return { contents: "export const SyncComponent = {}; export const Inspect = {}; export const Notifications = {}; export default {}", loader: "js" };
|
|
347
384
|
});
|
|
@@ -416,9 +453,13 @@ const bundleCreateDomql = async () => {
|
|
|
416
453
|
]
|
|
417
454
|
});
|
|
418
455
|
const mod = await import(`file://${outFile}`);
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
456
|
+
if (!process.env.BRENDER_DEBUG) {
|
|
457
|
+
try {
|
|
458
|
+
unlinkSync(outFile);
|
|
459
|
+
} catch {
|
|
460
|
+
}
|
|
461
|
+
} else {
|
|
462
|
+
console.log("[brender] Bundle saved:", outFile);
|
|
422
463
|
}
|
|
423
464
|
_cachedCreateDomql = mod;
|
|
424
465
|
return mod;
|
|
@@ -486,6 +527,22 @@ const UIKIT_STUBS = {
|
|
|
486
527
|
},
|
|
487
528
|
Text: { tag: "span" }
|
|
488
529
|
};
|
|
530
|
+
const buildPathRegistry = (element, path = "") => {
|
|
531
|
+
if (!element || !element.__ref) return {};
|
|
532
|
+
const registry = {};
|
|
533
|
+
const brKey = element.__ref.__brKey;
|
|
534
|
+
if (brKey) registry[path === "" ? "__root" : path] = brKey;
|
|
535
|
+
if (element.__ref.__children) {
|
|
536
|
+
for (const childKey of element.__ref.__children) {
|
|
537
|
+
const child = element[childKey];
|
|
538
|
+
if (child && child.__ref) {
|
|
539
|
+
const childPath = path === "" ? childKey : `${path}.${childKey}`;
|
|
540
|
+
Object.assign(registry, buildPathRegistry(child, childPath));
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
return registry;
|
|
545
|
+
};
|
|
489
546
|
const render = async (data, options = {}) => {
|
|
490
547
|
const { route = "/", pathname, state: stateOverrides, context: contextOverrides, prefetch = false } = options;
|
|
491
548
|
const locationPath = pathname || route;
|
|
@@ -612,12 +669,20 @@ const render = async (data, options = {}) => {
|
|
|
612
669
|
// Caller overrides
|
|
613
670
|
...contextOverrides || {}
|
|
614
671
|
};
|
|
672
|
+
const funcql = await getFuncqlPlugin();
|
|
673
|
+
if (funcql) {
|
|
674
|
+
ctx.plugins = ctx.plugins || [];
|
|
675
|
+
if (!ctx.plugins.some((p) => p.name === "funcql")) {
|
|
676
|
+
ctx.plugins.push(funcql);
|
|
677
|
+
}
|
|
678
|
+
}
|
|
615
679
|
resetKeys();
|
|
616
680
|
const element = await createDomqlElement(app, ctx);
|
|
617
681
|
const flushDelay = prefetch ? 2e3 : 50;
|
|
618
682
|
await new Promise((r) => setTimeout(r, flushDelay));
|
|
619
683
|
assignKeys(body);
|
|
620
684
|
const registry = mapKeysToElements(element);
|
|
685
|
+
const brRegistry = buildPathRegistry(element);
|
|
621
686
|
const metadata = extractMetadata(data, route, element, element?.state);
|
|
622
687
|
const emotionCSS = [];
|
|
623
688
|
const emotionInstance = ctx.emotion || element && element.context && element.context.emotion;
|
|
@@ -668,7 +733,7 @@ const render = async (data, options = {}) => {
|
|
|
668
733
|
else delete globalThis.document;
|
|
669
734
|
if (_prevLoc !== void 0) globalThis.location = _prevLoc;
|
|
670
735
|
else delete globalThis.location;
|
|
671
|
-
return { html, metadata, registry, element, emotionCSS, document, window, ssrTranslations, prefetchedPages };
|
|
736
|
+
return { html, metadata, registry, brRegistry, element, emotionCSS, document, window, ssrTranslations, prefetchedPages };
|
|
672
737
|
};
|
|
673
738
|
const renderElement = async (elementDef, options = {}) => {
|
|
674
739
|
const { context = {} } = options;
|
|
@@ -714,6 +779,11 @@ const generateGlobalCSS = async (ds, config) => {
|
|
|
714
779
|
const { existsSync: existsSync2, writeFileSync: writeFileSync2, unlinkSync: unlinkSync2 } = await import("fs");
|
|
715
780
|
const { tmpdir: tmpdir2 } = await import("os");
|
|
716
781
|
const { randomBytes: randomBytes2 } = await import("crypto");
|
|
782
|
+
try {
|
|
783
|
+
tmpdir2();
|
|
784
|
+
} catch {
|
|
785
|
+
return {};
|
|
786
|
+
}
|
|
717
787
|
const esbuild = await import("esbuild");
|
|
718
788
|
const dsJson = JSON.stringify(ds || {}, safeJsonReplacer());
|
|
719
789
|
const cfgJson = JSON.stringify(config || {}, safeJsonReplacer());
|
|
@@ -931,6 +1001,7 @@ const renderRoute = async (data, options = {}) => {
|
|
|
931
1001
|
fontLinks: generateFontLinks(ds),
|
|
932
1002
|
metadata: result.metadata || extractMetadata(data, route),
|
|
933
1003
|
brKeyCount: result.registry ? Object.keys(result.registry).length : 0,
|
|
1004
|
+
brRegistry: result.brRegistry || {},
|
|
934
1005
|
ssrTranslations: result.ssrTranslations,
|
|
935
1006
|
prefetchedState,
|
|
936
1007
|
activeLang
|
|
@@ -980,7 +1051,10 @@ const renderPage = async (data, route = "/", options = {}) => {
|
|
|
980
1051
|
`;
|
|
981
1052
|
}
|
|
982
1053
|
}
|
|
983
|
-
|
|
1054
|
+
const brRegistryJson = result.brRegistry && Object.keys(result.brRegistry).length ? JSON.stringify(result.brRegistry) : null;
|
|
1055
|
+
const brRegistryScript = brRegistryJson ? `<script>window.__BR_REGISTRY__=${brRegistryJson}<\/script>
|
|
1056
|
+
` : "";
|
|
1057
|
+
isrBody = `${translationSeed}${brRegistryScript}<script>window.__BRENDER__=true<\/script>
|
|
984
1058
|
<script type="module" src="${prefix}${isr.clientScript}"><\/script>`;
|
|
985
1059
|
} else {
|
|
986
1060
|
isrBody = `<script type="module">
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@symbo.ls/brender",
|
|
3
|
-
"version": "3.8.
|
|
3
|
+
"version": "3.8.7",
|
|
4
4
|
"license": "CC-BY-NC-4.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./dist/esm/index.js",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"dev:rita": "node examples/serve-rita.js"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@symbo.ls/helmet": "^3.8.
|
|
39
|
+
"@symbo.ls/helmet": "^3.8.7",
|
|
40
40
|
"linkedom": "^0.16.8"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
package/render.js
CHANGED
|
@@ -8,6 +8,20 @@ import { resetKeys, assignKeys, mapKeysToElements } from './keys.js'
|
|
|
8
8
|
import { extractMetadata, generateHeadHtml } from './metadata.js'
|
|
9
9
|
import { hydrate } from './hydrate.js'
|
|
10
10
|
import { prefetchPageData, injectPrefetchedState, fetchSSRTranslations } from './prefetch.js'
|
|
11
|
+
|
|
12
|
+
// funcql plugin — enables evaluation of funcql schemas as property values
|
|
13
|
+
// during SSR. Async-imported to avoid polluting non-funcql codepaths.
|
|
14
|
+
let _funcqlPlugin = null
|
|
15
|
+
const getFuncqlPlugin = async () => {
|
|
16
|
+
if (_funcqlPlugin) return _funcqlPlugin
|
|
17
|
+
try {
|
|
18
|
+
const mod = await import('@domql/funcql')
|
|
19
|
+
_funcqlPlugin = mod.funcqlPlugin
|
|
20
|
+
return _funcqlPlugin
|
|
21
|
+
} catch {
|
|
22
|
+
return null
|
|
23
|
+
}
|
|
24
|
+
}
|
|
11
25
|
import { parseHTML } from 'linkedom'
|
|
12
26
|
import createEmotionInstance from '@emotion/css/create-instance'
|
|
13
27
|
|
|
@@ -104,9 +118,23 @@ const safeJsonReplacer = () => {
|
|
|
104
118
|
// ── Workspace detection ──────────────────────────────────────────────────────
|
|
105
119
|
// Detect whether brender is running inside the monorepo or as an installed
|
|
106
120
|
// npm package, and resolve paths accordingly.
|
|
107
|
-
|
|
121
|
+
// Guard createRequire for bundled environments (e.g. Cloudflare Workers)
|
|
122
|
+
// where import.meta.url may be undefined after bundling.
|
|
123
|
+
let _brenderRequire = null
|
|
124
|
+
try {
|
|
125
|
+
if (import.meta.url) {
|
|
126
|
+
_brenderRequire = createRequire(import.meta.url)
|
|
127
|
+
}
|
|
128
|
+
} catch {
|
|
129
|
+
// Bundled runtime — filesystem-based resolution not available
|
|
130
|
+
}
|
|
108
131
|
|
|
109
132
|
const detectWorkspace = () => {
|
|
133
|
+
// In bundled environments (CF Workers), import.meta.url may be undefined.
|
|
134
|
+
// Return a minimal workspace config that skips filesystem-based resolution.
|
|
135
|
+
if (!import.meta.url || !_brenderRequire) {
|
|
136
|
+
return { isMonorepo: false, monorepoRoot: null, resolvePackage: (pkg) => pkg }
|
|
137
|
+
}
|
|
110
138
|
const brenderDir = realpathSync(new URL('.', import.meta.url).pathname)
|
|
111
139
|
const monorepoRoot = resolve(brenderDir, '../..')
|
|
112
140
|
|
|
@@ -232,6 +260,18 @@ const bundleCreateDomql = async () => {
|
|
|
232
260
|
|
|
233
261
|
const ws = detectWorkspace()
|
|
234
262
|
|
|
263
|
+
// In bundled environments (CF Workers), use the pre-bundled createDomql.
|
|
264
|
+
// Generated by: node scripts/prebundle-createDomql.js (or during npm prepublish)
|
|
265
|
+
if (!_brenderRequire) {
|
|
266
|
+
try {
|
|
267
|
+
const mod = await import('./dist/createDomql.bundled.mjs')
|
|
268
|
+
_cachedCreateDomql = mod
|
|
269
|
+
return mod
|
|
270
|
+
} catch (err) {
|
|
271
|
+
throw new Error(`brender: pre-bundled createDomql not available in bundled runtime: ${err.message}`)
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
235
275
|
// Resolve entry point
|
|
236
276
|
let entry
|
|
237
277
|
if (ws.isMonorepo) {
|
|
@@ -412,6 +452,15 @@ const bundleCreateDomql = async () => {
|
|
|
412
452
|
)
|
|
413
453
|
return { contents, loader: 'js' }
|
|
414
454
|
})
|
|
455
|
+
// Stub the Supabase adapter during brender — the prefetch system handles
|
|
456
|
+
// data fetching separately via its own Supabase client. The DOMQL fetch
|
|
457
|
+
// plugin's on.create handler shouldn't fire during SSR.
|
|
458
|
+
build.onLoad({ filter: /fetch\/adapters\/supabase\.js$/ }, () => {
|
|
459
|
+
return {
|
|
460
|
+
contents: `export const setup = async () => null;\nexport const supabaseAdapter = () => ({name:'supabase'});\n`,
|
|
461
|
+
loader: 'js'
|
|
462
|
+
}
|
|
463
|
+
})
|
|
415
464
|
// No-op: globals.js keeps window = globalThis
|
|
416
465
|
// We set globalThis.document/location before import to make it SSR-safe
|
|
417
466
|
// Stub loader for brender-stub namespace (used for @symbo.ls/sync etc.)
|
|
@@ -470,7 +519,12 @@ const bundleCreateDomql = async () => {
|
|
|
470
519
|
})
|
|
471
520
|
|
|
472
521
|
const mod = await import(`file://${outFile}`)
|
|
473
|
-
|
|
522
|
+
// Keep temp file in debug mode for inspection
|
|
523
|
+
if (!process.env.BRENDER_DEBUG) {
|
|
524
|
+
try { unlinkSync(outFile) } catch {}
|
|
525
|
+
} else {
|
|
526
|
+
console.log('[brender] Bundle saved:', outFile)
|
|
527
|
+
}
|
|
474
528
|
|
|
475
529
|
_cachedCreateDomql = mod
|
|
476
530
|
return mod
|
|
@@ -758,6 +812,15 @@ export const render = async (data, options = {}) => {
|
|
|
758
812
|
...(contextOverrides || {})
|
|
759
813
|
}
|
|
760
814
|
|
|
815
|
+
// Add funcql plugin if available (enables funcql schema evaluation in exec())
|
|
816
|
+
const funcql = await getFuncqlPlugin()
|
|
817
|
+
if (funcql) {
|
|
818
|
+
ctx.plugins = ctx.plugins || []
|
|
819
|
+
if (!ctx.plugins.some(p => p.name === 'funcql')) {
|
|
820
|
+
ctx.plugins.push(funcql)
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
|
|
761
824
|
resetKeys()
|
|
762
825
|
|
|
763
826
|
const element = await createDomqlElement(app, ctx)
|
|
@@ -937,6 +1000,10 @@ const generateGlobalCSS = async (ds, config) => {
|
|
|
937
1000
|
const { existsSync, writeFileSync, unlinkSync } = await import('fs')
|
|
938
1001
|
const { tmpdir } = await import('os')
|
|
939
1002
|
const { randomBytes } = await import('crypto')
|
|
1003
|
+
|
|
1004
|
+
// Guard: skip if filesystem APIs aren't available (e.g. CF Workers)
|
|
1005
|
+
try { tmpdir() } catch { return {} }
|
|
1006
|
+
|
|
940
1007
|
const esbuild = await import('esbuild')
|
|
941
1008
|
|
|
942
1009
|
// Write a temporary script that imports scratch, runs set(), and
|