@bleedingdev/modern-js-plugin-tanstack 3.5.0-ultramodern.29 → 3.5.0-ultramodern.30

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.
@@ -304,8 +304,13 @@ ${canonicalRoutesAugmentation}`;
304
304
  ]);
305
305
  process.env.MODERN_ARGV = 'node modern build';
306
306
  process.env.NODE_ENV = process.env.NODE_ENV || 'production';
307
+ const { findExists, CONFIG_FILE_EXTENSIONS } = utils;
308
+ const configFileBase = external_node_path_default().resolve(opts.appDirectory, 'modern.config');
309
+ const resolvedConfigFile = findExists(CONFIG_FILE_EXTENSIONS.map((extension)=>`${configFileBase}${extension}`));
310
+ if (!resolvedConfigFile) throw new Error(`[plugin-tanstack] Unable to locate a Modern.js config file (modern.config.{${CONFIG_FILE_EXTENSIONS.map((extension)=>extension.slice(1)).join(',')}}) in ${opts.appDirectory}. TanStack route generation requires the app config to resolve its plugins.`);
307
311
  const runOptions = await createRunOptions({
308
312
  cwd: opts.appDirectory,
313
+ configFile: configFileBase,
309
314
  version: opts.version || process.env.MODERN_JS_VERSION || '0.0.0-routes-generate',
310
315
  internalPlugins: utils.INTERNAL_RUNTIME_PLUGINS
311
316
  });
@@ -246,8 +246,13 @@ async function generateTanstackRouteArtifacts(opts) {
246
246
  ]);
247
247
  process.env.MODERN_ARGV = 'node modern build';
248
248
  process.env.NODE_ENV = process.env.NODE_ENV || 'production';
249
+ const { findExists, CONFIG_FILE_EXTENSIONS } = utils;
250
+ const configFileBase = node_path.resolve(opts.appDirectory, 'modern.config');
251
+ const resolvedConfigFile = findExists(CONFIG_FILE_EXTENSIONS.map((extension)=>`${configFileBase}${extension}`));
252
+ if (!resolvedConfigFile) throw new Error(`[plugin-tanstack] Unable to locate a Modern.js config file (modern.config.{${CONFIG_FILE_EXTENSIONS.map((extension)=>extension.slice(1)).join(',')}}) in ${opts.appDirectory}. TanStack route generation requires the app config to resolve its plugins.`);
249
253
  const runOptions = await createRunOptions({
250
254
  cwd: opts.appDirectory,
255
+ configFile: configFileBase,
251
256
  version: opts.version || process.env.MODERN_JS_VERSION || '0.0.0-routes-generate',
252
257
  internalPlugins: utils.INTERNAL_RUNTIME_PLUGINS
253
258
  });
@@ -250,8 +250,13 @@ async function generateTanstackRouteArtifacts(opts) {
250
250
  ]);
251
251
  process.env.MODERN_ARGV = 'node modern build';
252
252
  process.env.NODE_ENV = process.env.NODE_ENV || 'production';
253
+ const { findExists, CONFIG_FILE_EXTENSIONS } = utils;
254
+ const configFileBase = node_path.resolve(opts.appDirectory, 'modern.config');
255
+ const resolvedConfigFile = findExists(CONFIG_FILE_EXTENSIONS.map((extension)=>`${configFileBase}${extension}`));
256
+ if (!resolvedConfigFile) throw new Error(`[plugin-tanstack] Unable to locate a Modern.js config file (modern.config.{${CONFIG_FILE_EXTENSIONS.map((extension)=>extension.slice(1)).join(',')}}) in ${opts.appDirectory}. TanStack route generation requires the app config to resolve its plugins.`);
253
257
  const runOptions = await createRunOptions({
254
258
  cwd: opts.appDirectory,
259
+ configFile: configFileBase,
255
260
  version: opts.version || process.env.MODERN_JS_VERSION || '0.0.0-routes-generate',
256
261
  internalPlugins: utils.INTERNAL_RUNTIME_PLUGINS
257
262
  });
package/package.json CHANGED
@@ -18,7 +18,7 @@
18
18
  "modern.js",
19
19
  "tanstack-router"
20
20
  ],
21
- "version": "3.5.0-ultramodern.29",
21
+ "version": "3.5.0-ultramodern.30",
22
22
  "engines": {
23
23
  "node": ">=20"
24
24
  },
@@ -77,14 +77,14 @@
77
77
  "@swc/helpers": "^0.5.23",
78
78
  "@tanstack/react-router": "1.170.16",
79
79
  "@tanstack/router-core": "1.171.13",
80
- "@modern-js/plugin": "npm:@bleedingdev/modern-js-plugin@3.5.0-ultramodern.29",
81
- "@modern-js/types": "npm:@bleedingdev/modern-js-types@3.5.0-ultramodern.29",
82
- "@modern-js/utils": "npm:@bleedingdev/modern-js-utils@3.5.0-ultramodern.29",
83
- "@modern-js/runtime-utils": "npm:@bleedingdev/modern-js-runtime-utils@3.5.0-ultramodern.29"
80
+ "@modern-js/plugin": "npm:@bleedingdev/modern-js-plugin@3.5.0-ultramodern.30",
81
+ "@modern-js/runtime-utils": "npm:@bleedingdev/modern-js-runtime-utils@3.5.0-ultramodern.30",
82
+ "@modern-js/types": "npm:@bleedingdev/modern-js-types@3.5.0-ultramodern.30",
83
+ "@modern-js/utils": "npm:@bleedingdev/modern-js-utils@3.5.0-ultramodern.30"
84
84
  },
85
85
  "peerDependencies": {
86
- "@modern-js/app-tools": "3.5.0-ultramodern.29",
87
- "@modern-js/runtime": "3.5.0-ultramodern.29",
86
+ "@modern-js/app-tools": "3.5.0-ultramodern.30",
87
+ "@modern-js/runtime": "3.5.0-ultramodern.30",
88
88
  "react": "^19.2.7",
89
89
  "react-dom": "^19.2.7"
90
90
  },
@@ -99,8 +99,8 @@
99
99
  "@typescript/native-preview": "7.0.0-dev.20260628.1",
100
100
  "react": "^19.2.7",
101
101
  "react-dom": "^19.2.7",
102
- "@modern-js/app-tools": "npm:@bleedingdev/modern-js-app-tools@3.5.0-ultramodern.29",
103
- "@modern-js/runtime": "npm:@bleedingdev/modern-js-runtime@3.5.0-ultramodern.29",
102
+ "@modern-js/app-tools": "npm:@bleedingdev/modern-js-app-tools@3.5.0-ultramodern.30",
103
+ "@modern-js/runtime": "npm:@bleedingdev/modern-js-runtime@3.5.0-ultramodern.30",
104
104
  "@scripts/rstest-config": "2.66.0"
105
105
  },
106
106
  "sideEffects": [
package/src/cli/index.ts CHANGED
@@ -541,8 +541,37 @@ export async function generateTanstackRouteArtifacts(opts: {
541
541
  // not feed that check.
542
542
  process.env.MODERN_ARGV = 'node modern build';
543
543
  process.env.NODE_ENV = process.env.NODE_ENV || 'production';
544
+
545
+ // Resolve the app's Modern.js config file ourselves and pass it as an
546
+ // absolute base path. `createRunOptions` otherwise defaults its config lookup
547
+ // to `process.cwd()` (not `cwd`/appDirectory), so headless invocations that
548
+ // run from a different directory than the app — e.g. the create CLI spawning
549
+ // this from the workspace root — find no config, and `findExists` returns
550
+ // `false`. That `false` then flows into `cli.init` -> `getConfigFilePath` ->
551
+ // `path.isAbsolute(false)`, throwing the opaque
552
+ // `The "path" argument must be of type string. Received type boolean (false)`.
553
+ // Passing an absolute base is resolution-based: cwd no longer matters, and the
554
+ // downstream `getConfigFile` still appends the correct extension.
555
+ const { findExists, CONFIG_FILE_EXTENSIONS } = utils as {
556
+ findExists: (paths: string[]) => string | false;
557
+ CONFIG_FILE_EXTENSIONS: string[];
558
+ };
559
+ const configFileBase = path.resolve(opts.appDirectory, 'modern.config');
560
+ const resolvedConfigFile = findExists(
561
+ CONFIG_FILE_EXTENSIONS.map(extension => `${configFileBase}${extension}`),
562
+ );
563
+ if (!resolvedConfigFile) {
564
+ throw new Error(
565
+ `[plugin-tanstack] Unable to locate a Modern.js config file (modern.config.{${CONFIG_FILE_EXTENSIONS.map(
566
+ extension => extension.slice(1),
567
+ ).join(',')}}) in ${opts.appDirectory}. ` +
568
+ 'TanStack route generation requires the app config to resolve its plugins.',
569
+ );
570
+ }
571
+
544
572
  const runOptions = await createRunOptions({
545
573
  cwd: opts.appDirectory,
574
+ configFile: configFileBase,
546
575
  version:
547
576
  opts.version || process.env.MODERN_JS_VERSION || '0.0.0-routes-generate',
548
577
  internalPlugins: (utils as { INTERNAL_RUNTIME_PLUGINS: unknown })
@@ -2,8 +2,10 @@
2
2
  // export-shape test in cli.test.ts would pass even if the body were
3
3
  // reverted, so this file pins the actual prepare-only drive contract —
4
4
  // createRunOptions against the app dir, cli.init with build-command
5
- // semantics, and the MODERN_ARGV gate that makes analyze.onPrepare fire
6
- // generateEntryCode.
5
+ // semantics, the MODERN_ARGV gate that makes analyze.onPrepare fire
6
+ // generateEntryCode, and the absolute config-file resolution that keeps
7
+ // headless runs (cwd != appDirectory) from feeding `false` into node's
8
+ // path APIs.
7
9
  const createRunOptionsMock = rstest.fn(async (options: unknown) => ({
8
10
  mockRunOptions: true,
9
11
  received: options,
@@ -20,16 +22,37 @@ rstest.mock('@modern-js/plugin/cli', () => ({
20
22
  cli: { init: cliInitMock },
21
23
  }));
22
24
 
25
+ import fs from 'node:fs';
26
+ import os from 'node:os';
27
+ import path from 'node:path';
23
28
  import { INTERNAL_RUNTIME_PLUGINS } from '@modern-js/utils';
24
29
  import { generateTanstackRouteArtifacts } from '../../src/cli';
25
30
 
31
+ function makeAppDir(withConfig: boolean): string {
32
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'tanstack-routes-gen-'));
33
+ if (withConfig) {
34
+ fs.writeFileSync(
35
+ path.join(dir, 'modern.config.ts'),
36
+ 'export default {};\n',
37
+ 'utf-8',
38
+ );
39
+ }
40
+ return dir;
41
+ }
42
+
26
43
  describe('generateTanstackRouteArtifacts (headless routes-generate)', () => {
44
+ beforeEach(() => {
45
+ createRunOptionsMock.mockClear();
46
+ cliInitMock.mockClear();
47
+ });
48
+
27
49
  it('drives a prepare-only cli.init with build-command semantics', async () => {
28
50
  const previousArgv = process.env.MODERN_ARGV;
51
+ const appDirectory = makeAppDir(true);
29
52
 
30
53
  try {
31
54
  await generateTanstackRouteArtifacts({
32
- appDirectory: '/workspace/apps/shell',
55
+ appDirectory,
33
56
  version: '9.9.9-test',
34
57
  });
35
58
 
@@ -38,10 +61,18 @@ describe('generateTanstackRouteArtifacts (headless routes-generate)', () => {
38
61
  string,
39
62
  unknown
40
63
  >;
41
- expect(runOptionsArg.cwd).toBe('/workspace/apps/shell');
64
+ expect(runOptionsArg.cwd).toBe(appDirectory);
42
65
  expect(runOptionsArg.version).toBe('9.9.9-test');
43
66
  expect(runOptionsArg.internalPlugins).toBe(INTERNAL_RUNTIME_PLUGINS);
44
67
 
68
+ // The config file is resolved to an absolute base path against the app
69
+ // directory (not process.cwd()). Without this, a headless run from a
70
+ // different cwd finds no config, `findExists` returns `false`, and that
71
+ // boolean reaches `path.isAbsolute` deep inside plugin/cli.
72
+ expect(runOptionsArg.configFile).toBe(
73
+ path.resolve(appDirectory, 'modern.config'),
74
+ );
75
+
45
76
  expect(cliInitMock).toHaveBeenCalledTimes(1);
46
77
  const initArg = cliInitMock.mock.calls[0][0] as Record<string, unknown>;
47
78
  expect(initArg.command).toBe('build');
@@ -51,6 +82,7 @@ describe('generateTanstackRouteArtifacts (headless routes-generate)', () => {
51
82
  // is what lets analyze.onPrepare fire generateEntryCode headlessly.
52
83
  expect(process.env.MODERN_ARGV).toBe('node modern build');
53
84
  } finally {
85
+ fs.rmSync(appDirectory, { force: true, recursive: true });
54
86
  if (previousArgv === undefined) {
55
87
  delete process.env.MODERN_ARGV;
56
88
  } else {
@@ -58,4 +90,17 @@ describe('generateTanstackRouteArtifacts (headless routes-generate)', () => {
58
90
  }
59
91
  }
60
92
  });
93
+
94
+ it('throws a clear error (never a boolean path crash) when no config file exists', async () => {
95
+ const appDirectory = makeAppDir(false);
96
+
97
+ try {
98
+ await expect(
99
+ generateTanstackRouteArtifacts({ appDirectory }),
100
+ ).rejects.toThrow(/Unable to locate a Modern\.js config file/u);
101
+ expect(createRunOptionsMock).not.toHaveBeenCalled();
102
+ } finally {
103
+ fs.rmSync(appDirectory, { force: true, recursive: true });
104
+ }
105
+ });
61
106
  });