@archie/devtools 0.0.12 → 0.0.15

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/index.d.mts CHANGED
@@ -15,12 +15,12 @@ interface ArchieDevToolsOptions {
15
15
  interface ArchieDevToolsPlugin {
16
16
  name: string;
17
17
  enforce?: 'pre' | 'post';
18
- config?: () => {
19
- resolve: {
20
- dedupe: string[];
21
- };
22
- };
18
+ config?: () => object;
23
19
  configResolved?: (config: ResolvedConfig) => void;
20
+ transform?: (code: string, id: string) => Promise<{
21
+ code: string;
22
+ map?: object | null;
23
+ } | null | undefined>;
24
24
  resolveId?: (id: string) => string | null;
25
25
  load?: (id: string) => string | null;
26
26
  api?: {
package/dist/index.d.ts CHANGED
@@ -15,12 +15,12 @@ interface ArchieDevToolsOptions {
15
15
  interface ArchieDevToolsPlugin {
16
16
  name: string;
17
17
  enforce?: 'pre' | 'post';
18
- config?: () => {
19
- resolve: {
20
- dedupe: string[];
21
- };
22
- };
18
+ config?: () => object;
23
19
  configResolved?: (config: ResolvedConfig) => void;
20
+ transform?: (code: string, id: string) => Promise<{
21
+ code: string;
22
+ map?: object | null;
23
+ } | null | undefined>;
24
24
  resolveId?: (id: string) => string | null;
25
25
  load?: (id: string) => string | null;
26
26
  api?: {
package/dist/index.js CHANGED
@@ -234,6 +234,11 @@ function babelPluginEditorMeta({ types: t }, opts = {}) {
234
234
  }
235
235
  return "";
236
236
  }
237
+ function isHostLikeMemberExpressionName(name) {
238
+ if (!t.isJSXMemberExpression(name)) return false;
239
+ const propertyName = name.property.name;
240
+ return propertyName[0] === propertyName[0].toLowerCase();
241
+ }
237
242
  function computeNodeId(file, line, col, componentName) {
238
243
  return `${file}:${line}:${col}:${componentName}`;
239
244
  }
@@ -257,7 +262,7 @@ function babelPluginEditorMeta({ types: t }, opts = {}) {
257
262
  const loc = opening.loc?.start;
258
263
  if (loc) {
259
264
  const tag = getJSXTagName(opening);
260
- return computeNodeId(file, loc.line, loc.column, tag);
265
+ return computeNodeId(file, loc.line, loc.column + 1, tag);
261
266
  }
262
267
  return null;
263
268
  }
@@ -405,9 +410,10 @@ function babelPluginEditorMeta({ types: t }, opts = {}) {
405
410
  const root = state.file.opts.root ?? "";
406
411
  const file = root ? nodePath.relative(root, filename) : filename;
407
412
  const line = loc.line;
408
- const col = loc.column;
413
+ const col = loc.column + 1;
409
414
  const componentName = getJSXTagName(path.node);
410
415
  if (!componentName) return;
416
+ const isHostLikeMemberExpression = isHostLikeMemberExpressionName(path.node.name);
411
417
  const isHostElement = componentName[0] === componentName[0].toLowerCase();
412
418
  sanitizeSpreadAttributes(path.node.attributes);
413
419
  if (hasTruthyAsChildProp(path.node.attributes)) {
@@ -430,7 +436,7 @@ function babelPluginEditorMeta({ types: t }, opts = {}) {
430
436
  const decl = bp.parentPath;
431
437
  if (decl?.isImportDeclaration()) {
432
438
  const src = decl.node.source.value;
433
- if (isPackageImport(src)) return;
439
+ if (isPackageImport(src) && !isHostLikeMemberExpression) return;
434
440
  }
435
441
  }
436
442
  const programScope = path.scope.getProgramParent();
@@ -485,7 +491,9 @@ function archieDevTools(options = {}) {
485
491
  const log = (...args) => {
486
492
  if (debug) console.log("[Archie DevTools]", ...args);
487
493
  };
494
+ let babelCore = null;
488
495
  let includeHostSourceRef = false;
496
+ const transformedByHook = /* @__PURE__ */ new Set();
489
497
  const plugin = {
490
498
  name: "vite-plugin-archie-devtools",
491
499
  enforce: "pre",
@@ -493,12 +501,42 @@ function archieDevTools(options = {}) {
493
501
  return {
494
502
  resolve: {
495
503
  dedupe: ["react", "react-dom"]
504
+ },
505
+ optimizeDeps: {
506
+ exclude: ["@archie/devtools/client"]
496
507
  }
497
508
  };
498
509
  },
499
510
  configResolved(config) {
500
511
  includeHostSourceRef = !config.isProduction;
501
512
  },
513
+ async transform(code, id) {
514
+ if (!/\.[jt]sx$/.test(id) || /node_modules/.test(id)) return null;
515
+ try {
516
+ const babel = babelCore ?? (babelCore = await import("@babel/core"));
517
+ const isTS = /\.tsx$/.test(id);
518
+ const result = await babel.transformAsync(code, {
519
+ filename: id,
520
+ plugins: [
521
+ (b) => babelPluginEditorMeta(b, { includeHostSourceRef }),
522
+ ...dndPages.test(id) ? [(b) => babelPluginDndAuto(b, { importSource: INTERNAL_DND_SCOPE_IMPORT_SOURCE })] : []
523
+ ],
524
+ parserOpts: {
525
+ plugins: isTS ? ["jsx", "typescript"] : ["jsx"],
526
+ sourceType: "module"
527
+ },
528
+ sourceMaps: true,
529
+ configFile: false,
530
+ babelrc: false
531
+ });
532
+ if (!result?.code) return null;
533
+ transformedByHook.add(id);
534
+ return { code: result.code, map: result.map };
535
+ } catch (err) {
536
+ log("Babel transform failed for:", id, err);
537
+ return null;
538
+ }
539
+ },
502
540
  resolveId(id) {
503
541
  if (id === INTERNAL_DND_SCOPE_IMPORT_SOURCE) {
504
542
  return RESOLVED_DND_SCOPE_MODULE_ID;
@@ -513,14 +551,14 @@ function archieDevTools(options = {}) {
513
551
  },
514
552
  api: {
515
553
  reactBabel(babelOptions, context) {
516
- if (!/node_modules/.test(context.id)) {
554
+ if (!/node_modules/.test(context.id) && !transformedByHook.has(context.id)) {
517
555
  babelOptions.plugins.push(
518
556
  (babel) => babelPluginEditorMeta(babel, {
519
557
  includeHostSourceRef
520
558
  })
521
559
  );
522
560
  }
523
- if (dndPages.test(context.id)) {
561
+ if (dndPages.test(context.id) && !transformedByHook.has(context.id)) {
524
562
  log("Applying DnD transform to:", context.id);
525
563
  babelOptions.plugins.push(
526
564
  (babel) => babelPluginDndAuto(babel, {
package/dist/index.mjs CHANGED
@@ -200,6 +200,11 @@ function babelPluginEditorMeta({ types: t }, opts = {}) {
200
200
  }
201
201
  return "";
202
202
  }
203
+ function isHostLikeMemberExpressionName(name) {
204
+ if (!t.isJSXMemberExpression(name)) return false;
205
+ const propertyName = name.property.name;
206
+ return propertyName[0] === propertyName[0].toLowerCase();
207
+ }
203
208
  function computeNodeId(file, line, col, componentName) {
204
209
  return `${file}:${line}:${col}:${componentName}`;
205
210
  }
@@ -223,7 +228,7 @@ function babelPluginEditorMeta({ types: t }, opts = {}) {
223
228
  const loc = opening.loc?.start;
224
229
  if (loc) {
225
230
  const tag = getJSXTagName(opening);
226
- return computeNodeId(file, loc.line, loc.column, tag);
231
+ return computeNodeId(file, loc.line, loc.column + 1, tag);
227
232
  }
228
233
  return null;
229
234
  }
@@ -371,9 +376,10 @@ function babelPluginEditorMeta({ types: t }, opts = {}) {
371
376
  const root = state.file.opts.root ?? "";
372
377
  const file = root ? nodePath.relative(root, filename) : filename;
373
378
  const line = loc.line;
374
- const col = loc.column;
379
+ const col = loc.column + 1;
375
380
  const componentName = getJSXTagName(path.node);
376
381
  if (!componentName) return;
382
+ const isHostLikeMemberExpression = isHostLikeMemberExpressionName(path.node.name);
377
383
  const isHostElement = componentName[0] === componentName[0].toLowerCase();
378
384
  sanitizeSpreadAttributes(path.node.attributes);
379
385
  if (hasTruthyAsChildProp(path.node.attributes)) {
@@ -396,7 +402,7 @@ function babelPluginEditorMeta({ types: t }, opts = {}) {
396
402
  const decl = bp.parentPath;
397
403
  if (decl?.isImportDeclaration()) {
398
404
  const src = decl.node.source.value;
399
- if (isPackageImport(src)) return;
405
+ if (isPackageImport(src) && !isHostLikeMemberExpression) return;
400
406
  }
401
407
  }
402
408
  const programScope = path.scope.getProgramParent();
@@ -451,7 +457,9 @@ function archieDevTools(options = {}) {
451
457
  const log = (...args) => {
452
458
  if (debug) console.log("[Archie DevTools]", ...args);
453
459
  };
460
+ let babelCore = null;
454
461
  let includeHostSourceRef = false;
462
+ const transformedByHook = /* @__PURE__ */ new Set();
455
463
  const plugin = {
456
464
  name: "vite-plugin-archie-devtools",
457
465
  enforce: "pre",
@@ -459,12 +467,42 @@ function archieDevTools(options = {}) {
459
467
  return {
460
468
  resolve: {
461
469
  dedupe: ["react", "react-dom"]
470
+ },
471
+ optimizeDeps: {
472
+ exclude: ["@archie/devtools/client"]
462
473
  }
463
474
  };
464
475
  },
465
476
  configResolved(config) {
466
477
  includeHostSourceRef = !config.isProduction;
467
478
  },
479
+ async transform(code, id) {
480
+ if (!/\.[jt]sx$/.test(id) || /node_modules/.test(id)) return null;
481
+ try {
482
+ const babel = babelCore ?? (babelCore = await import("@babel/core"));
483
+ const isTS = /\.tsx$/.test(id);
484
+ const result = await babel.transformAsync(code, {
485
+ filename: id,
486
+ plugins: [
487
+ (b) => babelPluginEditorMeta(b, { includeHostSourceRef }),
488
+ ...dndPages.test(id) ? [(b) => babelPluginDndAuto(b, { importSource: INTERNAL_DND_SCOPE_IMPORT_SOURCE })] : []
489
+ ],
490
+ parserOpts: {
491
+ plugins: isTS ? ["jsx", "typescript"] : ["jsx"],
492
+ sourceType: "module"
493
+ },
494
+ sourceMaps: true,
495
+ configFile: false,
496
+ babelrc: false
497
+ });
498
+ if (!result?.code) return null;
499
+ transformedByHook.add(id);
500
+ return { code: result.code, map: result.map };
501
+ } catch (err) {
502
+ log("Babel transform failed for:", id, err);
503
+ return null;
504
+ }
505
+ },
468
506
  resolveId(id) {
469
507
  if (id === INTERNAL_DND_SCOPE_IMPORT_SOURCE) {
470
508
  return RESOLVED_DND_SCOPE_MODULE_ID;
@@ -479,14 +517,14 @@ function archieDevTools(options = {}) {
479
517
  },
480
518
  api: {
481
519
  reactBabel(babelOptions, context) {
482
- if (!/node_modules/.test(context.id)) {
520
+ if (!/node_modules/.test(context.id) && !transformedByHook.has(context.id)) {
483
521
  babelOptions.plugins.push(
484
522
  (babel) => babelPluginEditorMeta(babel, {
485
523
  includeHostSourceRef
486
524
  })
487
525
  );
488
526
  }
489
- if (dndPages.test(context.id)) {
527
+ if (dndPages.test(context.id) && !transformedByHook.has(context.id)) {
490
528
  log("Applying DnD transform to:", context.id);
491
529
  babelOptions.plugins.push(
492
530
  (babel) => babelPluginDndAuto(babel, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@archie/devtools",
3
- "version": "0.0.12",
3
+ "version": "0.0.15",
4
4
  "description": "DevTools for Archie generated applications - Route synchronization and editor communication",
5
5
  "repository": {
6
6
  "type": "git",
@@ -47,29 +47,29 @@
47
47
  "author": "8base",
48
48
  "license": "UNLICENSED",
49
49
  "devDependencies": {
50
- "@babel/core": "^7.29.0",
51
- "@babel/types": "^7.29.0",
52
- "@dnd-kit/core": "^6.3.1",
53
- "@dnd-kit/sortable": "^10.0.0",
54
- "@dnd-kit/utilities": "^3.2.2",
55
- "@remix-run/router": "^1.0.0",
56
- "@types/babel__core": "^7.20.5",
57
- "@types/react": "^19.0.0",
58
- "@types/react-dom": "^19.0.0",
59
- "happy-dom": "^20.5.0",
60
- "lucide-react": "^0.577.0",
61
- "react": "^19.0.0",
62
- "react-dom": "^19.0.0",
63
- "react-router-dom": "^7.0.0",
64
- "tsup": "^8.0.0",
65
- "typescript": "^5.0.0",
66
- "vite": "^5.0.0 || ^6.0.0 || ^7.0.0",
67
- "vitest": "^2.1.9",
68
- "zustand": "^5.0.11"
50
+ "@babel/core": "7.29.0",
51
+ "@babel/types": "7.29.0",
52
+ "@dnd-kit/core": "6.3.1",
53
+ "@dnd-kit/sortable": "10.0.0",
54
+ "@dnd-kit/utilities": "3.2.2",
55
+ "@remix-run/router": "1.23.2",
56
+ "@types/babel__core": "7.20.5",
57
+ "@types/react": "19.2.14",
58
+ "@types/react-dom": "19.2.3",
59
+ "happy-dom": "20.8.9",
60
+ "lucide-react": "0.577.0",
61
+ "react": "19.2.4",
62
+ "react-dom": "19.2.4",
63
+ "react-router-dom": "7.14.0",
64
+ "tsup": "8.5.1",
65
+ "typescript": "5.9.3",
66
+ "vite": "7.3.2",
67
+ "vitest": "4.1.3",
68
+ "zustand": "5.0.12"
69
69
  },
70
70
  "peerDependencies": {
71
71
  "react": ">=18.0.0",
72
72
  "react-dom": ">=18.0.0",
73
73
  "react-router-dom": ">=6.4.0"
74
74
  }
75
- }
75
+ }