@symbo.ls/brender 3.7.6 → 3.8.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.
@@ -40,6 +40,7 @@ var import_path = require("path");
40
40
  var import_fs = require("fs");
41
41
  var import_os = require("os");
42
42
  var import_crypto = require("crypto");
43
+ var import_module = require("module");
43
44
  var import_env = require("./env.js");
44
45
  var import_keys = require("./keys.js");
45
46
  var import_metadata = require("./metadata.js");
@@ -121,71 +122,219 @@ const safeJsonReplacer = () => {
121
122
  return value;
122
123
  };
123
124
  };
125
+ const _require = (0, import_module.createRequire)(import_meta.url);
126
+ const detectWorkspace = () => {
127
+ const brenderDir = (0, import_fs.realpathSync)(new URL(".", import_meta.url).pathname);
128
+ const monorepoRoot = (0, import_path.resolve)(brenderDir, "../..");
129
+ const isMonorepo = (0, import_fs.existsSync)((0, import_path.resolve)(monorepoRoot, "packages", "smbls", "src", "createDomql.js"));
130
+ if (isMonorepo) {
131
+ return { isMonorepo: true, monorepoRoot };
132
+ }
133
+ let smblsRoot;
134
+ try {
135
+ const smblsPkg = _require.resolve("smbls/package.json");
136
+ smblsRoot = (0, import_path.dirname)(smblsPkg);
137
+ } catch {
138
+ let dir = brenderDir;
139
+ while (dir !== (0, import_path.dirname)(dir)) {
140
+ const candidate = (0, import_path.resolve)(dir, "node_modules", "smbls");
141
+ if ((0, import_fs.existsSync)((0, import_path.resolve)(candidate, "package.json"))) {
142
+ smblsRoot = candidate;
143
+ break;
144
+ }
145
+ dir = (0, import_path.dirname)(dir);
146
+ }
147
+ }
148
+ return { isMonorepo: false, smblsRoot, brenderDir };
149
+ };
150
+ const resolvePackagePath = (ws, pkgName, ...subpath) => {
151
+ if (ws.isMonorepo) {
152
+ return (0, import_path.resolve)(ws.monorepoRoot, "packages", pkgName, ...subpath);
153
+ }
154
+ try {
155
+ const pkgJson = _require.resolve(`${pkgName}/package.json`);
156
+ return (0, import_path.resolve)((0, import_path.dirname)(pkgJson), ...subpath);
157
+ } catch {
158
+ }
159
+ const scopedNames = {
160
+ "domql": "domql",
161
+ "css-in-props": "css-in-props",
162
+ "attrs-in-props": "attrs-in-props"
163
+ };
164
+ if (scopedNames[pkgName]) {
165
+ try {
166
+ const pkgJson = _require.resolve(`${pkgName}/package.json`);
167
+ return (0, import_path.resolve)((0, import_path.dirname)(pkgJson), ...subpath);
168
+ } catch {
169
+ }
170
+ }
171
+ return null;
172
+ };
173
+ const resolvePluginPath = (ws, pluginName, ...subpath) => {
174
+ if (ws.isMonorepo) {
175
+ return (0, import_path.resolve)(ws.monorepoRoot, "plugins", pluginName, ...subpath);
176
+ }
177
+ try {
178
+ const pkgJson = _require.resolve(`@symbo.ls/${pluginName}/package.json`);
179
+ return (0, import_path.resolve)((0, import_path.dirname)(pkgJson), ...subpath);
180
+ } catch {
181
+ }
182
+ return null;
183
+ };
184
+ const resolveSymbolsPackage = (ws, pkg, ...subpath) => {
185
+ if (ws.isMonorepo) {
186
+ for (const dir of ["packages", "plugins"]) {
187
+ const src = (0, import_path.resolve)(ws.monorepoRoot, dir, pkg, ...subpath);
188
+ if ((0, import_fs.existsSync)(src)) return src;
189
+ }
190
+ return null;
191
+ }
192
+ try {
193
+ const pkgJson = _require.resolve(`@symbo.ls/${pkg}/package.json`);
194
+ return (0, import_path.resolve)((0, import_path.dirname)(pkgJson), ...subpath);
195
+ } catch {
196
+ }
197
+ return null;
198
+ };
199
+ const resolveDomqlPackage = (ws, pkg, ...subpath) => {
200
+ if (ws.isMonorepo) {
201
+ return (0, import_path.resolve)(ws.monorepoRoot, "packages", "domql", "packages", pkg, ...subpath);
202
+ }
203
+ try {
204
+ const pkgJson = _require.resolve(`@domql/${pkg}/package.json`);
205
+ return (0, import_path.resolve)((0, import_path.dirname)(pkgJson), ...subpath);
206
+ } catch {
207
+ }
208
+ return null;
209
+ };
124
210
  let _cachedCreateDomql = null;
125
211
  const bundleCreateDomql = async () => {
126
212
  if (_cachedCreateDomql) return _cachedCreateDomql;
127
- const brenderDir = (0, import_fs.realpathSync)(new URL(".", import_meta.url).pathname);
128
- const monorepoRoot = (0, import_path.resolve)(brenderDir, "../..");
129
- const entry = (0, import_path.resolve)(monorepoRoot, "packages", "smbls", "src", "createDomql.js");
213
+ const ws = detectWorkspace();
214
+ let entry;
215
+ if (ws.isMonorepo) {
216
+ entry = (0, import_path.resolve)(ws.monorepoRoot, "packages", "smbls", "src", "createDomql.js");
217
+ } else if (ws.smblsRoot) {
218
+ const srcEntry = (0, import_path.resolve)(ws.smblsRoot, "src", "createDomql.js");
219
+ const distEntry = (0, import_path.resolve)(ws.smblsRoot, "dist", "esm", "src", "createDomql.js");
220
+ entry = (0, import_fs.existsSync)(srcEntry) ? srcEntry : distEntry;
221
+ }
222
+ if (!entry || !(0, import_fs.existsSync)(entry)) {
223
+ throw new Error(`brender: cannot find createDomql.js (isMonorepo=${ws.isMonorepo}, entry=${entry})`);
224
+ }
130
225
  const esbuild = await import("esbuild");
131
226
  const outFile = (0, import_path.join)((0, import_os.tmpdir)(), `br_createDomql_${(0, import_crypto.randomBytes)(6).toString("hex")}.mjs`);
227
+ const tryResolve = (base) => {
228
+ if (!base) return null;
229
+ const src = (0, import_path.resolve)(base, "src", "index.js");
230
+ if ((0, import_fs.existsSync)(src)) return src;
231
+ const idx = (0, import_path.resolve)(base, "index.js");
232
+ if ((0, import_fs.existsSync)(idx)) return idx;
233
+ return null;
234
+ };
132
235
  const workspacePlugin = {
133
236
  name: "workspace-resolve",
134
237
  setup(build) {
135
238
  build.onResolve({ filter: /^smbls/ }, (args) => {
136
239
  const subpath = args.path.replace(/^smbls\/?/, "");
240
+ const smblsBase = ws.isMonorepo ? (0, import_path.resolve)(ws.monorepoRoot, "packages", "smbls") : ws.smblsRoot;
241
+ if (!smblsBase) return;
137
242
  if (!subpath) {
138
- const src = (0, import_path.resolve)(monorepoRoot, "packages", "smbls", "src", "index.js");
139
- if ((0, import_fs.existsSync)(src)) return { path: src };
243
+ const r = tryResolve(smblsBase);
244
+ if (r) return { path: r };
245
+ return;
140
246
  }
141
- const full = (0, import_path.resolve)(monorepoRoot, "packages", "smbls", subpath);
247
+ const full = (0, import_path.resolve)(smblsBase, subpath);
142
248
  if ((0, import_fs.existsSync)(full)) return { path: full };
143
249
  if ((0, import_fs.existsSync)(full + ".js")) return { path: full + ".js" };
144
250
  const idx = (0, import_path.resolve)(full, "index.js");
145
251
  if ((0, import_fs.existsSync)(idx)) return { path: idx };
146
252
  });
147
253
  build.onResolve({ filter: /^domql$/ }, (args) => {
148
- const src = (0, import_path.resolve)(monorepoRoot, "packages", "domql", "src", "index.js");
149
- if ((0, import_fs.existsSync)(src)) return { path: src };
150
- const dist = (0, import_path.resolve)(monorepoRoot, "packages", "domql", "index.js");
151
- if ((0, import_fs.existsSync)(dist)) return { path: dist };
254
+ if (ws.isMonorepo) {
255
+ const src = (0, import_path.resolve)(ws.monorepoRoot, "packages", "domql", "src", "index.js");
256
+ if ((0, import_fs.existsSync)(src)) return { path: src };
257
+ const dist = (0, import_path.resolve)(ws.monorepoRoot, "packages", "domql", "index.js");
258
+ if ((0, import_fs.existsSync)(dist)) return { path: dist };
259
+ } else {
260
+ try {
261
+ const pkgJson = _require.resolve("domql/package.json");
262
+ const r = tryResolve((0, import_path.dirname)(pkgJson));
263
+ if (r) return { path: r };
264
+ } catch {
265
+ }
266
+ }
152
267
  });
153
268
  build.onResolve({ filter: /^@symbo\.ls\// }, (args) => {
154
269
  const pkg = args.path.replace("@symbo.ls/", "");
155
270
  if (pkg === "sync") return { path: "sync-stub", namespace: "brender-stub" };
156
- for (const dir of ["packages", "plugins"]) {
157
- const src = (0, import_path.resolve)(monorepoRoot, dir, pkg, "src", "index.js");
158
- if ((0, import_fs.existsSync)(src)) return { path: src };
159
- const dist = (0, import_path.resolve)(monorepoRoot, dir, pkg, "index.js");
160
- if ((0, import_fs.existsSync)(dist)) return { path: dist };
271
+ if (ws.isMonorepo) {
272
+ for (const dir of ["packages", "plugins"]) {
273
+ const src = (0, import_path.resolve)(ws.monorepoRoot, dir, pkg, "src", "index.js");
274
+ if ((0, import_fs.existsSync)(src)) return { path: src };
275
+ const dist = (0, import_path.resolve)(ws.monorepoRoot, dir, pkg, "index.js");
276
+ if ((0, import_fs.existsSync)(dist)) return { path: dist };
277
+ }
278
+ const blank = (0, import_path.resolve)(ws.monorepoRoot, "packages", "default-config", "blank", "index.js");
279
+ if (pkg === "default-config" && (0, import_fs.existsSync)(blank)) return { path: blank };
280
+ } else {
281
+ const resolved = resolveSymbolsPackage(ws, pkg, "src", "index.js");
282
+ if (resolved && (0, import_fs.existsSync)(resolved)) return { path: resolved };
283
+ const resolvedIdx = resolveSymbolsPackage(ws, pkg, "index.js");
284
+ if (resolvedIdx && (0, import_fs.existsSync)(resolvedIdx)) return { path: resolvedIdx };
285
+ if (pkg === "default-config") {
286
+ const blank = resolveSymbolsPackage(ws, "default-config", "blank", "index.js");
287
+ if (blank && (0, import_fs.existsSync)(blank)) return { path: blank };
288
+ }
161
289
  }
162
- const blank = (0, import_path.resolve)(monorepoRoot, "packages", "default-config", "blank", "index.js");
163
- if (pkg === "default-config" && (0, import_fs.existsSync)(blank)) return { path: blank };
164
290
  });
165
291
  build.onResolve({ filter: /^@domql\// }, (args) => {
166
292
  const pkg = args.path.replace("@domql/", "");
167
- const src = (0, import_path.resolve)(monorepoRoot, "packages", "domql", "packages", pkg, "src", "index.js");
168
- if ((0, import_fs.existsSync)(src)) return { path: src };
169
- const dist = (0, import_path.resolve)(monorepoRoot, "packages", "domql", "packages", pkg, "index.js");
170
- if ((0, import_fs.existsSync)(dist)) return { path: dist };
293
+ if (ws.isMonorepo) {
294
+ const src = (0, import_path.resolve)(ws.monorepoRoot, "packages", "domql", "packages", pkg, "src", "index.js");
295
+ if ((0, import_fs.existsSync)(src)) return { path: src };
296
+ const dist = (0, import_path.resolve)(ws.monorepoRoot, "packages", "domql", "packages", pkg, "index.js");
297
+ if ((0, import_fs.existsSync)(dist)) return { path: dist };
298
+ } else {
299
+ const resolved = resolveDomqlPackage(ws, pkg, "src", "index.js");
300
+ if (resolved && (0, import_fs.existsSync)(resolved)) return { path: resolved };
301
+ const resolvedIdx = resolveDomqlPackage(ws, pkg, "index.js");
302
+ if (resolvedIdx && (0, import_fs.existsSync)(resolvedIdx)) return { path: resolvedIdx };
303
+ }
171
304
  });
172
305
  build.onResolve({ filter: /^css-in-props/ }, (args) => {
173
- const base = (0, import_path.resolve)(monorepoRoot, "packages", "css-in-props");
306
+ let base;
307
+ if (ws.isMonorepo) {
308
+ base = (0, import_path.resolve)(ws.monorepoRoot, "packages", "css-in-props");
309
+ } else {
310
+ try {
311
+ base = (0, import_path.dirname)(_require.resolve("css-in-props/package.json"));
312
+ } catch {
313
+ }
314
+ }
315
+ if (!base) return;
174
316
  const subpath = args.path.replace(/^css-in-props\/?/, "");
175
317
  if (subpath) {
176
318
  const full = (0, import_path.resolve)(base, subpath);
177
- const idx2 = (0, import_path.resolve)(full, "index.js");
178
- if ((0, import_fs.existsSync)(idx2)) return { path: idx2 };
319
+ const idx = (0, import_path.resolve)(full, "index.js");
320
+ if ((0, import_fs.existsSync)(idx)) return { path: idx };
179
321
  if ((0, import_fs.existsSync)(full + ".js")) return { path: full + ".js" };
180
322
  if ((0, import_fs.existsSync)(full)) return { path: full };
181
323
  }
182
- const src = (0, import_path.resolve)(base, "src", "index.js");
183
- if ((0, import_fs.existsSync)(src)) return { path: src };
184
- const idx = (0, import_path.resolve)(base, "index.js");
185
- if ((0, import_fs.existsSync)(idx)) return { path: idx };
324
+ const r = tryResolve(base);
325
+ if (r) return { path: r };
186
326
  });
187
327
  build.onResolve({ filter: /^@emotion\// }, (args) => {
188
- const nm = (0, import_path.resolve)(monorepoRoot, "node_modules", args.path);
328
+ let nm;
329
+ if (ws.isMonorepo) {
330
+ nm = (0, import_path.resolve)(ws.monorepoRoot, "node_modules", args.path);
331
+ } else {
332
+ try {
333
+ nm = (0, import_path.dirname)(_require.resolve(`${args.path}/package.json`));
334
+ } catch {
335
+ return;
336
+ }
337
+ }
189
338
  if ((0, import_fs.existsSync)(nm)) {
190
339
  const pkg = (0, import_path.resolve)(nm, "package.json");
191
340
  if ((0, import_fs.existsSync)(pkg)) {
@@ -258,7 +407,7 @@ const bundleCreateDomql = async () => {
258
407
  write: true,
259
408
  logLevel: "warning",
260
409
  plugins: [workspacePlugin],
261
- nodePaths: [(0, import_path.resolve)(monorepoRoot, "node_modules")],
410
+ nodePaths: ws.isMonorepo ? [(0, import_path.resolve)(ws.monorepoRoot, "node_modules")] : [(0, import_path.resolve)(ws.smblsRoot, "node_modules"), (0, import_path.resolve)(ws.smblsRoot, "..", "..", "node_modules")].filter((p) => (0, import_fs.existsSync)(p)),
262
411
  supported: { "import-attributes": false },
263
412
  external: [
264
413
  "fs",
@@ -638,26 +787,43 @@ const generateGlobalCSS = async (ds, config) => {
638
787
  globalThis.__BR_GLOBAL_CSS__ = result
639
788
  export default result
640
789
  `);
641
- const brenderDir = new URL(".", import_meta.url).pathname;
642
- const monorepoRoot = (0, import_path.resolve)(brenderDir, "../..");
790
+ const ws = detectWorkspace();
643
791
  const workspacePlugin = {
644
792
  name: "workspace-resolve",
645
793
  setup(build) {
646
794
  build.onResolve({ filter: /^@symbo\.ls\// }, (args) => {
647
795
  const pkg = args.path.replace("@symbo.ls/", "");
648
- for (const dir of ["packages", "plugins"]) {
649
- const src = (0, import_path.resolve)(monorepoRoot, dir, pkg, "src", "index.js");
650
- if (existsSync2(src)) return { path: src };
651
- const dist = (0, import_path.resolve)(monorepoRoot, dir, pkg, "index.js");
652
- if (existsSync2(dist)) return { path: dist };
796
+ if (ws.isMonorepo) {
797
+ for (const dir of ["packages", "plugins"]) {
798
+ const src = (0, import_path.resolve)(ws.monorepoRoot, dir, pkg, "src", "index.js");
799
+ if (existsSync2(src)) return { path: src };
800
+ const dist = (0, import_path.resolve)(ws.monorepoRoot, dir, pkg, "index.js");
801
+ if (existsSync2(dist)) return { path: dist };
802
+ }
803
+ const blank = (0, import_path.resolve)(ws.monorepoRoot, "packages", "default-config", "blank", "index.js");
804
+ if (pkg === "default-config" && existsSync2(blank)) return { path: blank };
805
+ } else {
806
+ const resolved = resolveSymbolsPackage(ws, pkg, "src", "index.js");
807
+ if (resolved && existsSync2(resolved)) return { path: resolved };
808
+ const resolvedIdx = resolveSymbolsPackage(ws, pkg, "index.js");
809
+ if (resolvedIdx && existsSync2(resolvedIdx)) return { path: resolvedIdx };
810
+ if (pkg === "default-config") {
811
+ const blank = resolveSymbolsPackage(ws, "default-config", "blank", "index.js");
812
+ if (blank && existsSync2(blank)) return { path: blank };
813
+ }
653
814
  }
654
- const blank = (0, import_path.resolve)(monorepoRoot, "packages", "default-config", "blank", "index.js");
655
- if (pkg === "default-config" && existsSync2(blank)) return { path: blank };
656
815
  });
657
816
  build.onResolve({ filter: /^@domql\// }, (args) => {
658
817
  const pkg = args.path.replace("@domql/", "");
659
- const src = (0, import_path.resolve)(monorepoRoot, "packages", "domql", "packages", pkg, "src", "index.js");
660
- if (existsSync2(src)) return { path: src };
818
+ if (ws.isMonorepo) {
819
+ const src = (0, import_path.resolve)(ws.monorepoRoot, "packages", "domql", "packages", pkg, "src", "index.js");
820
+ if (existsSync2(src)) return { path: src };
821
+ } else {
822
+ const resolved = resolveDomqlPackage(ws, pkg, "src", "index.js");
823
+ if (resolved && existsSync2(resolved)) return { path: resolved };
824
+ const resolvedIdx = resolveDomqlPackage(ws, pkg, "index.js");
825
+ if (resolvedIdx && existsSync2(resolvedIdx)) return { path: resolvedIdx };
826
+ }
661
827
  });
662
828
  }
663
829
  };
@@ -1,7 +1,8 @@
1
- import { resolve, join } from "path";
1
+ import { resolve, join, dirname } from "path";
2
2
  import { existsSync, writeFileSync, unlinkSync, readFileSync, realpathSync } from "fs";
3
3
  import { tmpdir } from "os";
4
4
  import { randomBytes } from "crypto";
5
+ import { createRequire } from "module";
5
6
  import { createEnv } from "./env.js";
6
7
  import { resetKeys, assignKeys, mapKeysToElements } from "./keys.js";
7
8
  import { extractMetadata, generateHeadHtml } from "./metadata.js";
@@ -82,71 +83,219 @@ const safeJsonReplacer = () => {
82
83
  return value;
83
84
  };
84
85
  };
86
+ const _require = createRequire(import.meta.url);
87
+ const detectWorkspace = () => {
88
+ const brenderDir = realpathSync(new URL(".", import.meta.url).pathname);
89
+ const monorepoRoot = resolve(brenderDir, "../..");
90
+ const isMonorepo = existsSync(resolve(monorepoRoot, "packages", "smbls", "src", "createDomql.js"));
91
+ if (isMonorepo) {
92
+ return { isMonorepo: true, monorepoRoot };
93
+ }
94
+ let smblsRoot;
95
+ try {
96
+ const smblsPkg = _require.resolve("smbls/package.json");
97
+ smblsRoot = dirname(smblsPkg);
98
+ } catch {
99
+ let dir = brenderDir;
100
+ while (dir !== dirname(dir)) {
101
+ const candidate = resolve(dir, "node_modules", "smbls");
102
+ if (existsSync(resolve(candidate, "package.json"))) {
103
+ smblsRoot = candidate;
104
+ break;
105
+ }
106
+ dir = dirname(dir);
107
+ }
108
+ }
109
+ return { isMonorepo: false, smblsRoot, brenderDir };
110
+ };
111
+ const resolvePackagePath = (ws, pkgName, ...subpath) => {
112
+ if (ws.isMonorepo) {
113
+ return resolve(ws.monorepoRoot, "packages", pkgName, ...subpath);
114
+ }
115
+ try {
116
+ const pkgJson = _require.resolve(`${pkgName}/package.json`);
117
+ return resolve(dirname(pkgJson), ...subpath);
118
+ } catch {
119
+ }
120
+ const scopedNames = {
121
+ "domql": "domql",
122
+ "css-in-props": "css-in-props",
123
+ "attrs-in-props": "attrs-in-props"
124
+ };
125
+ if (scopedNames[pkgName]) {
126
+ try {
127
+ const pkgJson = _require.resolve(`${pkgName}/package.json`);
128
+ return resolve(dirname(pkgJson), ...subpath);
129
+ } catch {
130
+ }
131
+ }
132
+ return null;
133
+ };
134
+ const resolvePluginPath = (ws, pluginName, ...subpath) => {
135
+ if (ws.isMonorepo) {
136
+ return resolve(ws.monorepoRoot, "plugins", pluginName, ...subpath);
137
+ }
138
+ try {
139
+ const pkgJson = _require.resolve(`@symbo.ls/${pluginName}/package.json`);
140
+ return resolve(dirname(pkgJson), ...subpath);
141
+ } catch {
142
+ }
143
+ return null;
144
+ };
145
+ const resolveSymbolsPackage = (ws, pkg, ...subpath) => {
146
+ if (ws.isMonorepo) {
147
+ for (const dir of ["packages", "plugins"]) {
148
+ const src = resolve(ws.monorepoRoot, dir, pkg, ...subpath);
149
+ if (existsSync(src)) return src;
150
+ }
151
+ return null;
152
+ }
153
+ try {
154
+ const pkgJson = _require.resolve(`@symbo.ls/${pkg}/package.json`);
155
+ return resolve(dirname(pkgJson), ...subpath);
156
+ } catch {
157
+ }
158
+ return null;
159
+ };
160
+ const resolveDomqlPackage = (ws, pkg, ...subpath) => {
161
+ if (ws.isMonorepo) {
162
+ return resolve(ws.monorepoRoot, "packages", "domql", "packages", pkg, ...subpath);
163
+ }
164
+ try {
165
+ const pkgJson = _require.resolve(`@domql/${pkg}/package.json`);
166
+ return resolve(dirname(pkgJson), ...subpath);
167
+ } catch {
168
+ }
169
+ return null;
170
+ };
85
171
  let _cachedCreateDomql = null;
86
172
  const bundleCreateDomql = async () => {
87
173
  if (_cachedCreateDomql) return _cachedCreateDomql;
88
- const brenderDir = realpathSync(new URL(".", import.meta.url).pathname);
89
- const monorepoRoot = resolve(brenderDir, "../..");
90
- const entry = resolve(monorepoRoot, "packages", "smbls", "src", "createDomql.js");
174
+ const ws = detectWorkspace();
175
+ let entry;
176
+ if (ws.isMonorepo) {
177
+ entry = resolve(ws.monorepoRoot, "packages", "smbls", "src", "createDomql.js");
178
+ } else if (ws.smblsRoot) {
179
+ const srcEntry = resolve(ws.smblsRoot, "src", "createDomql.js");
180
+ const distEntry = resolve(ws.smblsRoot, "dist", "esm", "src", "createDomql.js");
181
+ entry = existsSync(srcEntry) ? srcEntry : distEntry;
182
+ }
183
+ if (!entry || !existsSync(entry)) {
184
+ throw new Error(`brender: cannot find createDomql.js (isMonorepo=${ws.isMonorepo}, entry=${entry})`);
185
+ }
91
186
  const esbuild = await import("esbuild");
92
187
  const outFile = join(tmpdir(), `br_createDomql_${randomBytes(6).toString("hex")}.mjs`);
188
+ const tryResolve = (base) => {
189
+ if (!base) return null;
190
+ const src = resolve(base, "src", "index.js");
191
+ if (existsSync(src)) return src;
192
+ const idx = resolve(base, "index.js");
193
+ if (existsSync(idx)) return idx;
194
+ return null;
195
+ };
93
196
  const workspacePlugin = {
94
197
  name: "workspace-resolve",
95
198
  setup(build) {
96
199
  build.onResolve({ filter: /^smbls/ }, (args) => {
97
200
  const subpath = args.path.replace(/^smbls\/?/, "");
201
+ const smblsBase = ws.isMonorepo ? resolve(ws.monorepoRoot, "packages", "smbls") : ws.smblsRoot;
202
+ if (!smblsBase) return;
98
203
  if (!subpath) {
99
- const src = resolve(monorepoRoot, "packages", "smbls", "src", "index.js");
100
- if (existsSync(src)) return { path: src };
204
+ const r = tryResolve(smblsBase);
205
+ if (r) return { path: r };
206
+ return;
101
207
  }
102
- const full = resolve(monorepoRoot, "packages", "smbls", subpath);
208
+ const full = resolve(smblsBase, subpath);
103
209
  if (existsSync(full)) return { path: full };
104
210
  if (existsSync(full + ".js")) return { path: full + ".js" };
105
211
  const idx = resolve(full, "index.js");
106
212
  if (existsSync(idx)) return { path: idx };
107
213
  });
108
214
  build.onResolve({ filter: /^domql$/ }, (args) => {
109
- const src = resolve(monorepoRoot, "packages", "domql", "src", "index.js");
110
- if (existsSync(src)) return { path: src };
111
- const dist = resolve(monorepoRoot, "packages", "domql", "index.js");
112
- if (existsSync(dist)) return { path: dist };
215
+ if (ws.isMonorepo) {
216
+ const src = resolve(ws.monorepoRoot, "packages", "domql", "src", "index.js");
217
+ if (existsSync(src)) return { path: src };
218
+ const dist = resolve(ws.monorepoRoot, "packages", "domql", "index.js");
219
+ if (existsSync(dist)) return { path: dist };
220
+ } else {
221
+ try {
222
+ const pkgJson = _require.resolve("domql/package.json");
223
+ const r = tryResolve(dirname(pkgJson));
224
+ if (r) return { path: r };
225
+ } catch {
226
+ }
227
+ }
113
228
  });
114
229
  build.onResolve({ filter: /^@symbo\.ls\// }, (args) => {
115
230
  const pkg = args.path.replace("@symbo.ls/", "");
116
231
  if (pkg === "sync") return { path: "sync-stub", namespace: "brender-stub" };
117
- for (const dir of ["packages", "plugins"]) {
118
- const src = resolve(monorepoRoot, dir, pkg, "src", "index.js");
119
- if (existsSync(src)) return { path: src };
120
- const dist = resolve(monorepoRoot, dir, pkg, "index.js");
121
- if (existsSync(dist)) return { path: dist };
232
+ if (ws.isMonorepo) {
233
+ for (const dir of ["packages", "plugins"]) {
234
+ const src = resolve(ws.monorepoRoot, dir, pkg, "src", "index.js");
235
+ if (existsSync(src)) return { path: src };
236
+ const dist = resolve(ws.monorepoRoot, dir, pkg, "index.js");
237
+ if (existsSync(dist)) return { path: dist };
238
+ }
239
+ const blank = resolve(ws.monorepoRoot, "packages", "default-config", "blank", "index.js");
240
+ if (pkg === "default-config" && existsSync(blank)) return { path: blank };
241
+ } else {
242
+ const resolved = resolveSymbolsPackage(ws, pkg, "src", "index.js");
243
+ if (resolved && existsSync(resolved)) return { path: resolved };
244
+ const resolvedIdx = resolveSymbolsPackage(ws, pkg, "index.js");
245
+ if (resolvedIdx && existsSync(resolvedIdx)) return { path: resolvedIdx };
246
+ if (pkg === "default-config") {
247
+ const blank = resolveSymbolsPackage(ws, "default-config", "blank", "index.js");
248
+ if (blank && existsSync(blank)) return { path: blank };
249
+ }
122
250
  }
123
- const blank = resolve(monorepoRoot, "packages", "default-config", "blank", "index.js");
124
- if (pkg === "default-config" && existsSync(blank)) return { path: blank };
125
251
  });
126
252
  build.onResolve({ filter: /^@domql\// }, (args) => {
127
253
  const pkg = args.path.replace("@domql/", "");
128
- const src = resolve(monorepoRoot, "packages", "domql", "packages", pkg, "src", "index.js");
129
- if (existsSync(src)) return { path: src };
130
- const dist = resolve(monorepoRoot, "packages", "domql", "packages", pkg, "index.js");
131
- if (existsSync(dist)) return { path: dist };
254
+ if (ws.isMonorepo) {
255
+ const src = resolve(ws.monorepoRoot, "packages", "domql", "packages", pkg, "src", "index.js");
256
+ if (existsSync(src)) return { path: src };
257
+ const dist = resolve(ws.monorepoRoot, "packages", "domql", "packages", pkg, "index.js");
258
+ if (existsSync(dist)) return { path: dist };
259
+ } else {
260
+ const resolved = resolveDomqlPackage(ws, pkg, "src", "index.js");
261
+ if (resolved && existsSync(resolved)) return { path: resolved };
262
+ const resolvedIdx = resolveDomqlPackage(ws, pkg, "index.js");
263
+ if (resolvedIdx && existsSync(resolvedIdx)) return { path: resolvedIdx };
264
+ }
132
265
  });
133
266
  build.onResolve({ filter: /^css-in-props/ }, (args) => {
134
- const base = resolve(monorepoRoot, "packages", "css-in-props");
267
+ let base;
268
+ if (ws.isMonorepo) {
269
+ base = resolve(ws.monorepoRoot, "packages", "css-in-props");
270
+ } else {
271
+ try {
272
+ base = dirname(_require.resolve("css-in-props/package.json"));
273
+ } catch {
274
+ }
275
+ }
276
+ if (!base) return;
135
277
  const subpath = args.path.replace(/^css-in-props\/?/, "");
136
278
  if (subpath) {
137
279
  const full = resolve(base, subpath);
138
- const idx2 = resolve(full, "index.js");
139
- if (existsSync(idx2)) return { path: idx2 };
280
+ const idx = resolve(full, "index.js");
281
+ if (existsSync(idx)) return { path: idx };
140
282
  if (existsSync(full + ".js")) return { path: full + ".js" };
141
283
  if (existsSync(full)) return { path: full };
142
284
  }
143
- const src = resolve(base, "src", "index.js");
144
- if (existsSync(src)) return { path: src };
145
- const idx = resolve(base, "index.js");
146
- if (existsSync(idx)) return { path: idx };
285
+ const r = tryResolve(base);
286
+ if (r) return { path: r };
147
287
  });
148
288
  build.onResolve({ filter: /^@emotion\// }, (args) => {
149
- const nm = resolve(monorepoRoot, "node_modules", args.path);
289
+ let nm;
290
+ if (ws.isMonorepo) {
291
+ nm = resolve(ws.monorepoRoot, "node_modules", args.path);
292
+ } else {
293
+ try {
294
+ nm = dirname(_require.resolve(`${args.path}/package.json`));
295
+ } catch {
296
+ return;
297
+ }
298
+ }
150
299
  if (existsSync(nm)) {
151
300
  const pkg = resolve(nm, "package.json");
152
301
  if (existsSync(pkg)) {
@@ -219,7 +368,7 @@ const bundleCreateDomql = async () => {
219
368
  write: true,
220
369
  logLevel: "warning",
221
370
  plugins: [workspacePlugin],
222
- nodePaths: [resolve(monorepoRoot, "node_modules")],
371
+ nodePaths: ws.isMonorepo ? [resolve(ws.monorepoRoot, "node_modules")] : [resolve(ws.smblsRoot, "node_modules"), resolve(ws.smblsRoot, "..", "..", "node_modules")].filter((p) => existsSync(p)),
223
372
  supported: { "import-attributes": false },
224
373
  external: [
225
374
  "fs",
@@ -599,26 +748,43 @@ const generateGlobalCSS = async (ds, config) => {
599
748
  globalThis.__BR_GLOBAL_CSS__ = result
600
749
  export default result
601
750
  `);
602
- const brenderDir = new URL(".", import.meta.url).pathname;
603
- const monorepoRoot = resolve(brenderDir, "../..");
751
+ const ws = detectWorkspace();
604
752
  const workspacePlugin = {
605
753
  name: "workspace-resolve",
606
754
  setup(build) {
607
755
  build.onResolve({ filter: /^@symbo\.ls\// }, (args) => {
608
756
  const pkg = args.path.replace("@symbo.ls/", "");
609
- for (const dir of ["packages", "plugins"]) {
610
- const src = resolve(monorepoRoot, dir, pkg, "src", "index.js");
611
- if (existsSync2(src)) return { path: src };
612
- const dist = resolve(monorepoRoot, dir, pkg, "index.js");
613
- if (existsSync2(dist)) return { path: dist };
757
+ if (ws.isMonorepo) {
758
+ for (const dir of ["packages", "plugins"]) {
759
+ const src = resolve(ws.monorepoRoot, dir, pkg, "src", "index.js");
760
+ if (existsSync2(src)) return { path: src };
761
+ const dist = resolve(ws.monorepoRoot, dir, pkg, "index.js");
762
+ if (existsSync2(dist)) return { path: dist };
763
+ }
764
+ const blank = resolve(ws.monorepoRoot, "packages", "default-config", "blank", "index.js");
765
+ if (pkg === "default-config" && existsSync2(blank)) return { path: blank };
766
+ } else {
767
+ const resolved = resolveSymbolsPackage(ws, pkg, "src", "index.js");
768
+ if (resolved && existsSync2(resolved)) return { path: resolved };
769
+ const resolvedIdx = resolveSymbolsPackage(ws, pkg, "index.js");
770
+ if (resolvedIdx && existsSync2(resolvedIdx)) return { path: resolvedIdx };
771
+ if (pkg === "default-config") {
772
+ const blank = resolveSymbolsPackage(ws, "default-config", "blank", "index.js");
773
+ if (blank && existsSync2(blank)) return { path: blank };
774
+ }
614
775
  }
615
- const blank = resolve(monorepoRoot, "packages", "default-config", "blank", "index.js");
616
- if (pkg === "default-config" && existsSync2(blank)) return { path: blank };
617
776
  });
618
777
  build.onResolve({ filter: /^@domql\// }, (args) => {
619
778
  const pkg = args.path.replace("@domql/", "");
620
- const src = resolve(monorepoRoot, "packages", "domql", "packages", pkg, "src", "index.js");
621
- if (existsSync2(src)) return { path: src };
779
+ if (ws.isMonorepo) {
780
+ const src = resolve(ws.monorepoRoot, "packages", "domql", "packages", pkg, "src", "index.js");
781
+ if (existsSync2(src)) return { path: src };
782
+ } else {
783
+ const resolved = resolveDomqlPackage(ws, pkg, "src", "index.js");
784
+ if (resolved && existsSync2(resolved)) return { path: resolved };
785
+ const resolvedIdx = resolveDomqlPackage(ws, pkg, "index.js");
786
+ if (resolvedIdx && existsSync2(resolvedIdx)) return { path: resolvedIdx };
787
+ }
622
788
  });
623
789
  }
624
790
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@symbo.ls/brender",
3
- "version": "3.7.6",
3
+ "version": "3.8.0",
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.7.6",
39
+ "@symbo.ls/helmet": "^3.8.0",
40
40
  "linkedom": "^0.16.8"
41
41
  },
42
42
  "devDependencies": {
package/render.js CHANGED
@@ -1,7 +1,8 @@
1
- import { resolve, join } from 'path'
1
+ import { resolve, join, dirname } from 'path'
2
2
  import { existsSync, writeFileSync, unlinkSync, readFileSync, realpathSync } from 'fs'
3
3
  import { tmpdir } from 'os'
4
4
  import { randomBytes } from 'crypto'
5
+ import { createRequire } from 'module'
5
6
  import { createEnv } from './env.js'
6
7
  import { resetKeys, assignKeys, mapKeysToElements } from './keys.js'
7
8
  import { extractMetadata, generateHeadHtml } from './metadata.js'
@@ -100,6 +101,106 @@ const safeJsonReplacer = () => {
100
101
  }
101
102
  }
102
103
 
104
+ // ── Workspace detection ──────────────────────────────────────────────────────
105
+ // Detect whether brender is running inside the monorepo or as an installed
106
+ // npm package, and resolve paths accordingly.
107
+ const _require = createRequire(import.meta.url)
108
+
109
+ const detectWorkspace = () => {
110
+ const brenderDir = realpathSync(new URL('.', import.meta.url).pathname)
111
+ const monorepoRoot = resolve(brenderDir, '../..')
112
+
113
+ // Check if monorepo layout exists (packages/smbls/src/createDomql.js)
114
+ const isMonorepo = existsSync(resolve(monorepoRoot, 'packages', 'smbls', 'src', 'createDomql.js'))
115
+
116
+ if (isMonorepo) {
117
+ return { isMonorepo: true, monorepoRoot }
118
+ }
119
+
120
+ // npm install context — resolve packages from node_modules
121
+ // Find the smbls package root via require.resolve
122
+ let smblsRoot
123
+ try {
124
+ const smblsPkg = _require.resolve('smbls/package.json')
125
+ smblsRoot = dirname(smblsPkg)
126
+ } catch {
127
+ // Fallback: walk up from brenderDir looking for node_modules/smbls
128
+ let dir = brenderDir
129
+ while (dir !== dirname(dir)) {
130
+ const candidate = resolve(dir, 'node_modules', 'smbls')
131
+ if (existsSync(resolve(candidate, 'package.json'))) {
132
+ smblsRoot = candidate
133
+ break
134
+ }
135
+ dir = dirname(dir)
136
+ }
137
+ }
138
+
139
+ return { isMonorepo: false, smblsRoot, brenderDir }
140
+ }
141
+
142
+ // Resolve a package path — monorepo layout or node_modules
143
+ const resolvePackagePath = (ws, pkgName, ...subpath) => {
144
+ if (ws.isMonorepo) {
145
+ return resolve(ws.monorepoRoot, 'packages', pkgName, ...subpath)
146
+ }
147
+ // npm context: try require.resolve
148
+ try {
149
+ const pkgJson = _require.resolve(`${pkgName}/package.json`)
150
+ return resolve(dirname(pkgJson), ...subpath)
151
+ } catch {}
152
+ // Try scoped name
153
+ const scopedNames = {
154
+ 'domql': 'domql',
155
+ 'css-in-props': 'css-in-props',
156
+ 'attrs-in-props': 'attrs-in-props'
157
+ }
158
+ if (scopedNames[pkgName]) {
159
+ try {
160
+ const pkgJson = _require.resolve(`${pkgName}/package.json`)
161
+ return resolve(dirname(pkgJson), ...subpath)
162
+ } catch {}
163
+ }
164
+ return null
165
+ }
166
+
167
+ const resolvePluginPath = (ws, pluginName, ...subpath) => {
168
+ if (ws.isMonorepo) {
169
+ return resolve(ws.monorepoRoot, 'plugins', pluginName, ...subpath)
170
+ }
171
+ try {
172
+ const pkgJson = _require.resolve(`@symbo.ls/${pluginName}/package.json`)
173
+ return resolve(dirname(pkgJson), ...subpath)
174
+ } catch {}
175
+ return null
176
+ }
177
+
178
+ const resolveSymbolsPackage = (ws, pkg, ...subpath) => {
179
+ if (ws.isMonorepo) {
180
+ for (const dir of ['packages', 'plugins']) {
181
+ const src = resolve(ws.monorepoRoot, dir, pkg, ...subpath)
182
+ if (existsSync(src)) return src
183
+ }
184
+ return null
185
+ }
186
+ try {
187
+ const pkgJson = _require.resolve(`@symbo.ls/${pkg}/package.json`)
188
+ return resolve(dirname(pkgJson), ...subpath)
189
+ } catch {}
190
+ return null
191
+ }
192
+
193
+ const resolveDomqlPackage = (ws, pkg, ...subpath) => {
194
+ if (ws.isMonorepo) {
195
+ return resolve(ws.monorepoRoot, 'packages', 'domql', 'packages', pkg, ...subpath)
196
+ }
197
+ try {
198
+ const pkgJson = _require.resolve(`@domql/${pkg}/package.json`)
199
+ return resolve(dirname(pkgJson), ...subpath)
200
+ } catch {}
201
+ return null
202
+ }
203
+
103
204
  // ── Bundled import of createDomqlElement ──────────────────────────────────────
104
205
  // The smbls source tree uses extensionless/directory imports that Node.js ESM
105
206
  // cannot resolve natively. We bundle createDomql.js with esbuild (once, cached)
@@ -109,24 +210,52 @@ let _cachedCreateDomql = null
109
210
  const bundleCreateDomql = async () => {
110
211
  if (_cachedCreateDomql) return _cachedCreateDomql
111
212
 
112
- const brenderDir = realpathSync(new URL('.', import.meta.url).pathname)
113
- const monorepoRoot = resolve(brenderDir, '../..')
114
- const entry = resolve(monorepoRoot, 'packages', 'smbls', 'src', 'createDomql.js')
213
+ const ws = detectWorkspace()
214
+
215
+ // Resolve entry point
216
+ let entry
217
+ if (ws.isMonorepo) {
218
+ entry = resolve(ws.monorepoRoot, 'packages', 'smbls', 'src', 'createDomql.js')
219
+ } else if (ws.smblsRoot) {
220
+ // Prefer src/ (shipped in smbls package), fall back to dist
221
+ const srcEntry = resolve(ws.smblsRoot, 'src', 'createDomql.js')
222
+ const distEntry = resolve(ws.smblsRoot, 'dist', 'esm', 'src', 'createDomql.js')
223
+ entry = existsSync(srcEntry) ? srcEntry : distEntry
224
+ }
225
+
226
+ if (!entry || !existsSync(entry)) {
227
+ throw new Error(`brender: cannot find createDomql.js (isMonorepo=${ws.isMonorepo}, entry=${entry})`)
228
+ }
115
229
 
116
230
  const esbuild = await import('esbuild')
117
231
  const outFile = join(tmpdir(), `br_createDomql_${randomBytes(6).toString('hex')}.mjs`)
118
232
 
233
+ // Helper to find a file trying src/ then root index.js
234
+ const tryResolve = (base) => {
235
+ if (!base) return null
236
+ const src = resolve(base, 'src', 'index.js')
237
+ if (existsSync(src)) return src
238
+ const idx = resolve(base, 'index.js')
239
+ if (existsSync(idx)) return idx
240
+ return null
241
+ }
242
+
119
243
  const workspacePlugin = {
120
244
  name: 'workspace-resolve',
121
245
  setup (build) {
122
246
  // Resolve smbls bare import
123
247
  build.onResolve({ filter: /^smbls/ }, (args) => {
124
248
  const subpath = args.path.replace(/^smbls\/?/, '')
249
+ const smblsBase = ws.isMonorepo
250
+ ? resolve(ws.monorepoRoot, 'packages', 'smbls')
251
+ : ws.smblsRoot
252
+ if (!smblsBase) return
125
253
  if (!subpath) {
126
- const src = resolve(monorepoRoot, 'packages', 'smbls', 'src', 'index.js')
127
- if (existsSync(src)) return { path: src }
254
+ const r = tryResolve(smblsBase)
255
+ if (r) return { path: r }
256
+ return
128
257
  }
129
- const full = resolve(monorepoRoot, 'packages', 'smbls', subpath)
258
+ const full = resolve(smblsBase, subpath)
130
259
  if (existsSync(full)) return { path: full }
131
260
  if (existsSync(full + '.js')) return { path: full + '.js' }
132
261
  const idx = resolve(full, 'index.js')
@@ -134,35 +263,70 @@ const bundleCreateDomql = async () => {
134
263
  })
135
264
  // Resolve domql bare import
136
265
  build.onResolve({ filter: /^domql$/ }, (args) => {
137
- const src = resolve(monorepoRoot, 'packages', 'domql', 'src', 'index.js')
138
- if (existsSync(src)) return { path: src }
139
- const dist = resolve(monorepoRoot, 'packages', 'domql', 'index.js')
140
- if (existsSync(dist)) return { path: dist }
266
+ if (ws.isMonorepo) {
267
+ const src = resolve(ws.monorepoRoot, 'packages', 'domql', 'src', 'index.js')
268
+ if (existsSync(src)) return { path: src }
269
+ const dist = resolve(ws.monorepoRoot, 'packages', 'domql', 'index.js')
270
+ if (existsSync(dist)) return { path: dist }
271
+ } else {
272
+ try {
273
+ const pkgJson = _require.resolve('domql/package.json')
274
+ const r = tryResolve(dirname(pkgJson))
275
+ if (r) return { path: r }
276
+ } catch {}
277
+ }
141
278
  })
142
279
  // Resolve @symbo.ls/* packages (skip sync — stubbed above)
143
280
  build.onResolve({ filter: /^@symbo\.ls\// }, args => {
144
281
  const pkg = args.path.replace('@symbo.ls/', '')
145
282
  if (pkg === 'sync') return { path: 'sync-stub', namespace: 'brender-stub' }
146
- for (const dir of ['packages', 'plugins']) {
147
- const src = resolve(monorepoRoot, dir, pkg, 'src', 'index.js')
148
- if (existsSync(src)) return { path: src }
149
- const dist = resolve(monorepoRoot, dir, pkg, 'index.js')
150
- if (existsSync(dist)) return { path: dist }
283
+ if (ws.isMonorepo) {
284
+ for (const dir of ['packages', 'plugins']) {
285
+ const src = resolve(ws.monorepoRoot, dir, pkg, 'src', 'index.js')
286
+ if (existsSync(src)) return { path: src }
287
+ const dist = resolve(ws.monorepoRoot, dir, pkg, 'index.js')
288
+ if (existsSync(dist)) return { path: dist }
289
+ }
290
+ const blank = resolve(ws.monorepoRoot, 'packages', 'default-config', 'blank', 'index.js')
291
+ if (pkg === 'default-config' && existsSync(blank)) return { path: blank }
292
+ } else {
293
+ const resolved = resolveSymbolsPackage(ws, pkg, 'src', 'index.js')
294
+ if (resolved && existsSync(resolved)) return { path: resolved }
295
+ const resolvedIdx = resolveSymbolsPackage(ws, pkg, 'index.js')
296
+ if (resolvedIdx && existsSync(resolvedIdx)) return { path: resolvedIdx }
297
+ // default-config blank
298
+ if (pkg === 'default-config') {
299
+ const blank = resolveSymbolsPackage(ws, 'default-config', 'blank', 'index.js')
300
+ if (blank && existsSync(blank)) return { path: blank }
301
+ }
151
302
  }
152
- const blank = resolve(monorepoRoot, 'packages', 'default-config', 'blank', 'index.js')
153
- if (pkg === 'default-config' && existsSync(blank)) return { path: blank }
154
303
  })
155
304
  // Resolve @domql/* packages
156
305
  build.onResolve({ filter: /^@domql\// }, args => {
157
306
  const pkg = args.path.replace('@domql/', '')
158
- const src = resolve(monorepoRoot, 'packages', 'domql', 'packages', pkg, 'src', 'index.js')
159
- if (existsSync(src)) return { path: src }
160
- const dist = resolve(monorepoRoot, 'packages', 'domql', 'packages', pkg, 'index.js')
161
- if (existsSync(dist)) return { path: dist }
307
+ if (ws.isMonorepo) {
308
+ const src = resolve(ws.monorepoRoot, 'packages', 'domql', 'packages', pkg, 'src', 'index.js')
309
+ if (existsSync(src)) return { path: src }
310
+ const dist = resolve(ws.monorepoRoot, 'packages', 'domql', 'packages', pkg, 'index.js')
311
+ if (existsSync(dist)) return { path: dist }
312
+ } else {
313
+ const resolved = resolveDomqlPackage(ws, pkg, 'src', 'index.js')
314
+ if (resolved && existsSync(resolved)) return { path: resolved }
315
+ const resolvedIdx = resolveDomqlPackage(ws, pkg, 'index.js')
316
+ if (resolvedIdx && existsSync(resolvedIdx)) return { path: resolvedIdx }
317
+ }
162
318
  })
163
319
  // Resolve css-in-props
164
320
  build.onResolve({ filter: /^css-in-props/ }, args => {
165
- const base = resolve(monorepoRoot, 'packages', 'css-in-props')
321
+ let base
322
+ if (ws.isMonorepo) {
323
+ base = resolve(ws.monorepoRoot, 'packages', 'css-in-props')
324
+ } else {
325
+ try {
326
+ base = dirname(_require.resolve('css-in-props/package.json'))
327
+ } catch {}
328
+ }
329
+ if (!base) return
166
330
  const subpath = args.path.replace(/^css-in-props\/?/, '')
167
331
  if (subpath) {
168
332
  const full = resolve(base, subpath)
@@ -171,14 +335,21 @@ const bundleCreateDomql = async () => {
171
335
  if (existsSync(full + '.js')) return { path: full + '.js' }
172
336
  if (existsSync(full)) return { path: full }
173
337
  }
174
- const src = resolve(base, 'src', 'index.js')
175
- if (existsSync(src)) return { path: src }
176
- const idx = resolve(base, 'index.js')
177
- if (existsSync(idx)) return { path: idx }
338
+ const r = tryResolve(base)
339
+ if (r) return { path: r }
178
340
  })
179
- // Resolve @emotion/* from monorepo node_modules
341
+ // Resolve @emotion/* from node_modules
180
342
  build.onResolve({ filter: /^@emotion\// }, args => {
181
- const nm = resolve(monorepoRoot, 'node_modules', args.path)
343
+ let nm
344
+ if (ws.isMonorepo) {
345
+ nm = resolve(ws.monorepoRoot, 'node_modules', args.path)
346
+ } else {
347
+ try {
348
+ nm = dirname(_require.resolve(`${args.path}/package.json`))
349
+ } catch {
350
+ return
351
+ }
352
+ }
182
353
  if (existsSync(nm)) {
183
354
  const pkg = resolve(nm, 'package.json')
184
355
  if (existsSync(pkg)) {
@@ -263,7 +434,9 @@ const bundleCreateDomql = async () => {
263
434
  write: true,
264
435
  logLevel: 'warning',
265
436
  plugins: [workspacePlugin],
266
- nodePaths: [resolve(monorepoRoot, 'node_modules')],
437
+ nodePaths: ws.isMonorepo
438
+ ? [resolve(ws.monorepoRoot, 'node_modules')]
439
+ : [resolve(ws.smblsRoot, 'node_modules'), resolve(ws.smblsRoot, '..', '..', 'node_modules')].filter(p => existsSync(p)),
267
440
  supported: { 'import-attributes': false },
268
441
  external: [
269
442
  'fs', 'path', 'os', 'crypto', 'url', 'http', 'https', 'stream',
@@ -754,10 +927,8 @@ const generateGlobalCSS = async (ds, config) => {
754
927
  export default result
755
928
  `)
756
929
 
757
- // Resolve the monorepo root from the brender plugin location
758
- // so esbuild can find @symbo.ls/* packages
759
- const brenderDir = new URL('.', import.meta.url).pathname
760
- const monorepoRoot = resolve(brenderDir, '../..')
930
+ // Detect workspace layout (monorepo vs npm install)
931
+ const ws = detectWorkspace()
761
932
 
762
933
  // Workspace resolve plugin: maps @symbo.ls/* and @domql/* to source paths
763
934
  const workspacePlugin = {
@@ -765,21 +936,37 @@ const generateGlobalCSS = async (ds, config) => {
765
936
  setup (build) {
766
937
  build.onResolve({ filter: /^@symbo\.ls\// }, args => {
767
938
  const pkg = args.path.replace('@symbo.ls/', '')
768
- // Try packages/ then plugins/
769
- for (const dir of ['packages', 'plugins']) {
770
- const src = resolve(monorepoRoot, dir, pkg, 'src', 'index.js')
771
- if (existsSync(src)) return { path: src }
772
- const dist = resolve(monorepoRoot, dir, pkg, 'index.js')
773
- if (existsSync(dist)) return { path: dist }
939
+ if (ws.isMonorepo) {
940
+ for (const dir of ['packages', 'plugins']) {
941
+ const src = resolve(ws.monorepoRoot, dir, pkg, 'src', 'index.js')
942
+ if (existsSync(src)) return { path: src }
943
+ const dist = resolve(ws.monorepoRoot, dir, pkg, 'index.js')
944
+ if (existsSync(dist)) return { path: dist }
945
+ }
946
+ const blank = resolve(ws.monorepoRoot, 'packages', 'default-config', 'blank', 'index.js')
947
+ if (pkg === 'default-config' && existsSync(blank)) return { path: blank }
948
+ } else {
949
+ const resolved = resolveSymbolsPackage(ws, pkg, 'src', 'index.js')
950
+ if (resolved && existsSync(resolved)) return { path: resolved }
951
+ const resolvedIdx = resolveSymbolsPackage(ws, pkg, 'index.js')
952
+ if (resolvedIdx && existsSync(resolvedIdx)) return { path: resolvedIdx }
953
+ if (pkg === 'default-config') {
954
+ const blank = resolveSymbolsPackage(ws, 'default-config', 'blank', 'index.js')
955
+ if (blank && existsSync(blank)) return { path: blank }
956
+ }
774
957
  }
775
- // default-config special case
776
- const blank = resolve(monorepoRoot, 'packages', 'default-config', 'blank', 'index.js')
777
- if (pkg === 'default-config' && existsSync(blank)) return { path: blank }
778
958
  })
779
959
  build.onResolve({ filter: /^@domql\// }, args => {
780
960
  const pkg = args.path.replace('@domql/', '')
781
- const src = resolve(monorepoRoot, 'packages', 'domql', 'packages', pkg, 'src', 'index.js')
782
- if (existsSync(src)) return { path: src }
961
+ if (ws.isMonorepo) {
962
+ const src = resolve(ws.monorepoRoot, 'packages', 'domql', 'packages', pkg, 'src', 'index.js')
963
+ if (existsSync(src)) return { path: src }
964
+ } else {
965
+ const resolved = resolveDomqlPackage(ws, pkg, 'src', 'index.js')
966
+ if (resolved && existsSync(resolved)) return { path: resolved }
967
+ const resolvedIdx = resolveDomqlPackage(ws, pkg, 'index.js')
968
+ if (resolvedIdx && existsSync(resolvedIdx)) return { path: resolvedIdx }
969
+ }
783
970
  })
784
971
  }
785
972
  }