proteum 2.1.9-8 → 2.2.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.
Files changed (35) hide show
  1. package/README.md +11 -8
  2. package/agents/project/AGENTS.md +7 -7
  3. package/agents/project/CODING_STYLE.md +1 -1
  4. package/agents/project/client/AGENTS.md +1 -1
  5. package/agents/project/client/pages/AGENTS.md +10 -10
  6. package/agents/project/optimizations.md +5 -6
  7. package/agents/project/root/AGENTS.md +7 -7
  8. package/cli/commands/migrate.ts +51 -0
  9. package/cli/compiler/artifacts/manifest.ts +4 -4
  10. package/cli/compiler/artifacts/routing.ts +2 -2
  11. package/cli/compiler/common/generatedRouteModules.ts +31 -38
  12. package/cli/context.ts +1 -1
  13. package/cli/migrate/pageContract.ts +516 -0
  14. package/cli/presentation/commands.ts +27 -1
  15. package/cli/runtime/commands.ts +25 -0
  16. package/cli/scaffold/templates.ts +4 -2
  17. package/client/dev/profiler/index.tsx +1 -2
  18. package/client/services/router/index.tsx +6 -22
  19. package/common/dev/console.ts +1 -0
  20. package/common/dev/diagnostics.ts +4 -4
  21. package/common/dev/inspection.ts +1 -1
  22. package/common/dev/proteumManifest.ts +4 -4
  23. package/common/dev/requestTrace.ts +0 -1
  24. package/common/router/contracts.ts +8 -11
  25. package/common/router/index.ts +2 -2
  26. package/common/router/pageData.ts +72 -0
  27. package/common/router/register.ts +10 -46
  28. package/common/router/response/page.ts +28 -16
  29. package/package.json +5 -1
  30. package/server/services/router/index.ts +48 -14
  31. package/server/services/router/request/api.ts +1 -1
  32. package/server/services/router/response/index.ts +0 -27
  33. package/types/global/vendors.d.ts +12 -0
  34. package/types/vendors.d.ts +12 -0
  35. package/common/router/pageSetup.ts +0 -51
package/README.md CHANGED
@@ -26,7 +26,7 @@ Proteum combines:
26
26
 
27
27
  ## Core Principles
28
28
 
29
- - **Server-first by default.** Put data loading in the page setup function and keep client code focused on UI.
29
+ - **Server-first by default.** Put data loading in the page data function and keep client code focused on UI.
30
30
  - **Explicit request entrypoints.** Controllers are classes. Request access is explicit through `this.request`.
31
31
  - **Local validation.** Validate handler input inside the handler with `this.input(schema)`.
32
32
  - **Deterministic generation.** Proteum owns `.proteum/` and regenerates it from source.
@@ -71,7 +71,7 @@ Important files:
71
71
  - `process.env` / optional `.env`: `PORT`, `ENV_*`, `URL`, `URL_INTERNAL`, any app-chosen variables referenced by `proteum.config.ts`, and `TRACE_*` environment variables loaded by the app
72
72
  - `server/config/*.ts`: plain typed config exports consumed by the explicit app bootstrap
73
73
  - `server/index.ts`: default-exported `Application` subclass that instantiates root services and router plugins
74
- - `client/pages/**`: SSR page entrypoints registered through `Router.page(...)`
74
+ - `client/pages/**`: SSR page entrypoints registered through `Router.page(path, options, data, render)`
75
75
  - `server/controllers/**`: request handlers that extend `Controller`
76
76
  - `commands/**`: dev-only internal commands that extend `Commands`
77
77
  - `server/services/**`: business logic that extends `Service`
@@ -194,9 +194,11 @@ import Router from '@/client/router';
194
194
 
195
195
  Router.page(
196
196
  '/',
197
+ {
198
+ auth: false,
199
+ layout: false,
200
+ },
197
201
  ({ Plans, Stats }) => ({
198
- _auth: false,
199
- _layout: false,
200
202
  plans: Plans.getPlans(),
201
203
  stats: Stats.general(),
202
204
  }),
@@ -209,9 +211,10 @@ Router.page(
209
211
  What happens here:
210
212
 
211
213
  - the first argument is the route path
212
- - the optional setup function runs on the server for SSR data loading
213
- - keys prefixed with `_` become route options such as `_auth`, `_layout`, `_static`, or `_redirectLogged`
214
- - every other returned key becomes page data
214
+ - the second argument is the explicit route-options object
215
+ - the third argument is the page data function or `null`
216
+ - route behavior such as `auth`, `layout`, `static`, or `redirectLogged` lives in the options object
217
+ - every key returned from the data function becomes page data
215
218
  - the renderer receives the resolved data and the generated controller/service context
216
219
 
217
220
  ## Example: Controller
@@ -518,7 +521,7 @@ If you are an LLM or automation agent, start here:
518
521
  4. Read `.proteum/manifest.json` or run `proteum explain --json`.
519
522
  5. Inspect `server/controllers/**` for request entrypoints.
520
523
  6. Inspect `server/services/**` for business logic.
521
- 7. Inspect `client/pages/**` for SSR routes and page setup contracts.
524
+ 7. Inspect `client/pages/**` for SSR routes and page data contracts.
522
525
  8. If the task touches a protected route or controller in dev and login UX is not the feature under test, use `proteum session <email> --role <role>` before Playwright or direct HTTP calls.
523
526
 
524
527
  For implementation rules in a real Proteum app, treat the local `AGENTS.md` files plus `proteum explain`, `proteum doctor`, `proteum diagnose`, `proteum perf`, and `proteum trace` as the task contract. This README is the framework overview, not the project-local instruction layer.
@@ -136,14 +136,14 @@ Coding style source of truth: root-level `CODING_STYLE.md`.
136
136
 
137
137
  - Proteum scans page files for top-level `Router.page(...)` and `Router.error(...)` calls.
138
138
  - File path controls chunk identity and layout discovery; route path comes from the explicit `Router.page(...)` string.
139
- - Supported page signatures are `Router.page(path, render)`, `Router.page(path, setup, render)`, `Router.page(path, options, render)`, and `Router.page(path, options, setup, render)`.
140
- - For new work, prefer `Router.page(path, setup, render)` or `Router.page(path, options, setup, render)`.
141
- - `setup` returns one flat object. Reserved keys like `_auth`, `_layout`, `_static`, and `_redirectLogged` are route options; all other keys are SSR data.
142
- - Controller fetchers and promises returned from `setup` resolve before render.
143
- - `render` consumes resolved setup data and uses generated controller methods from render args or `@/client/context`.
144
- - Use `api.reload(...)` or `api.set(...)` only when intentionally mutating active page setup state.
139
+ - The only supported page signature is `Router.page(path, options, data, render)`.
140
+ - `options` is always required. `data` is the only nullable argument and must be `null` when the page has no SSR data loader.
141
+ - `data` returns one flat object. Route-option keys such as `auth`, `layout`, `static`, and `_static` are forbidden in page data and must live in `options`.
142
+ - Controller fetchers and promises returned from `data` resolve before render.
143
+ - `render` consumes resolved page data and uses generated controller methods from render args or `@/client/context`.
144
+ - Use `api.reload(...)` or `api.set(...)` only when intentionally mutating active page data state.
145
145
  - Error pages use `Router.error(code, options, render)` in `client/pages/_messages/**`.
146
- - Prefer `proteum create page ...` for new page boilerplate, then review the explicit route path and setup payload.
146
+ - Prefer `proteum create page ...` for new page boilerplate, then review the explicit route path, options object, and data payload.
147
147
 
148
148
  ### Manual Routes
149
149
 
@@ -17,7 +17,7 @@ This file is the source of truth for codex coding style instructions in Proteum-
17
17
  - Keep short arrow functions and short returned object literals compact when they are easy to scan.
18
18
  - Keep JSX multiline only when it is clearly more readable; otherwise keep short JSX compact.
19
19
  - Avoid staircase formatting and unnecessary blank lines inside short callbacks.
20
- - Keep `Router.page(...)` and `Router.error(...)` registrations in the compact inline-call shape when possible, for example `Router.page('/path', setup, render);`.
20
+ - Keep `Router.page(...)` and `Router.error(...)` registrations in the compact inline-call shape when possible, for example `Router.page('/path', {}, null, render);`.
21
21
 
22
22
  ## File organization
23
23
 
@@ -3,7 +3,7 @@
3
3
  This is the canonical client-area contract for Proteum-based projects.
4
4
  Role: keep only client-area rules here.
5
5
  Keep here: client component, hook, design-system, accessibility, and client-context usage rules that apply beyond a single page.
6
- Do not put here: page `setup` and route-registration details, server/service rules, or generic project workflow already covered by broader ancestor `AGENTS.md` files.
6
+ Do not put here: page `data` and route-registration details, server/service rules, or generic project workflow already covered by broader ancestor `AGENTS.md` files.
7
7
 
8
8
  Optimization source of truth: root-level `optimizations.md`.
9
9
  Diagnostics source of truth: root-level `diagnostics.md`.
@@ -2,7 +2,7 @@
2
2
 
3
3
  This is the canonical page-file contract for Proteum-based projects.
4
4
  Role: keep only page-file rules here.
5
- Keep here: `Router.page(...)` registration, SSR `setup` and `render` contracts, page payload shape, and page-local typing rules.
5
+ Keep here: `Router.page(...)` registration, SSR `data` and `render` contracts, page payload shape, and page-local typing rules.
6
6
  Do not put here: generic component rules, server/service implementation details, or app-wide workflow already covered by broader AGENTS files.
7
7
 
8
8
  Optimization source of truth: root-level `optimizations.md`.
@@ -13,19 +13,19 @@ Coding style source of truth: root-level `CODING_STYLE.md`.
13
13
 
14
14
  - Proteum scans page files for top-level `Router.page(...)` and `Router.error(...)` calls.
15
15
  - File path controls chunk identity and layout discovery; route path comes from the explicit `Router.page(...)` string.
16
- - Supported page signatures are `Router.page(path, render)`, `Router.page(path, setup, render)`, `Router.page(path, options, render)`, and `Router.page(path, options, setup, render)`.
17
- - Prefer `Router.page(path, setup, render)` for normal SSR pages.
18
- - Use `Router.page(path, options, setup, render)` when a separate route-options object makes the call clearer.
16
+ - The only supported page signature is `Router.page(path, options, data, render)`.
17
+ - `options` is always required and must be an object.
18
+ - `data` is the only nullable argument. Pass `null` when the page does not need SSR data.
19
19
  - Keep the `Router.page(...)` call compact instead of exploding each outer argument onto its own line.
20
20
  - Keep route registration at top level. Do not hide it behind helper abstractions.
21
21
 
22
- ## Setup And Render
22
+ ## Data And Render
23
23
 
24
- - `setup` returns one flat object.
25
- - `_`-prefixed keys like `_auth`, `_layout`, `_static`, and `_redirectLogged` are route options.
26
- - Every other key is SSR data and should be consumed from `render`.
27
- - Controller fetchers and promises returned from `setup` resolve before render.
28
- - If a page needs route data, return it from `setup` and read it in `render`.
24
+ - Route behavior belongs in the explicit `options` object, not in page data.
25
+ - `data` returns one flat object or `null` is passed as the third argument when no page data is needed.
26
+ - Returning route-option keys such as `auth`, `layout`, `static`, `redirectLogged`, or their `_`-prefixed variants from `data` is a contract error.
27
+ - Controller fetchers and promises returned from `data` resolve before render.
28
+ - If a page needs route data, return it from `data` and read it in `render`.
29
29
 
30
30
  ## Page Rules
31
31
 
@@ -22,12 +22,11 @@ When tradeoffs exist inside optimization work, optimize in this order:
22
22
 
23
23
  ## SSR And Page Size
24
24
 
25
- - SSR page data belongs in page `setup`, not in `api.fetch(...)`.
26
- - Prefer `Router.page(path, setup, render)` for normal SSR pages.
27
- - `setup` returns one flat object.
28
- - `_`-prefixed keys are route options. Every other key is SSR data and should be consumed from `render`.
29
- - If a page needs route data, return it from `setup` and read it in `render`.
30
- - Controller fetchers and promises returned from `setup` resolve before render.
25
+ - SSR page data belongs in the explicit `Router.page(path, options, data, render)` `data` function, not in `api.fetch(...)`.
26
+ - `options` carries route behavior. `data` returns one flat object or is `null` when the page has no SSR data loader.
27
+ - Route-option keys and `_`-prefixed route-option aliases are forbidden in page data and must live in `options`.
28
+ - If a page needs route data, return it from `data` and read it in `render`.
29
+ - Controller fetchers and promises returned from `data` resolve before render.
31
30
  - Never use `api.fetch(...)` in page files for SSR loading.
32
31
  - Synchronous or SSR data calls must return only the strictly necessary data for the current render path to minimize SSR payload size.
33
32
  - If an existing controller or data method returns a broader shape than the SSR path needs, create a dedicated proxy controller method with a narrower typed contract instead of reusing the oversized payload.
@@ -128,14 +128,14 @@ Coding style source of truth: root-level `CODING_STYLE.md`.
128
128
 
129
129
  - Proteum scans page files for top-level `Router.page(...)` and `Router.error(...)` calls.
130
130
  - File path controls chunk identity and layout discovery; route path comes from the explicit `Router.page(...)` string.
131
- - Supported page signatures are `Router.page(path, render)`, `Router.page(path, setup, render)`, `Router.page(path, options, render)`, and `Router.page(path, options, setup, render)`.
132
- - For new work, prefer `Router.page(path, setup, render)` or `Router.page(path, options, setup, render)`.
133
- - `setup` returns one flat object. Reserved keys like `_auth`, `_layout`, `_static`, and `_redirectLogged` are route options; all other keys are SSR data.
134
- - Controller fetchers and promises returned from `setup` resolve before render.
135
- - `render` consumes resolved setup data and uses generated controller methods from render args or `@/client/context`.
136
- - Use `api.reload(...)` or `api.set(...)` only when intentionally mutating active page setup state.
131
+ - The only supported page signature is `Router.page(path, options, data, render)`.
132
+ - `options` is always required. `data` is the only nullable argument and must be `null` when the page has no SSR data loader.
133
+ - `data` returns one flat object. Route-option keys such as `auth`, `layout`, `static`, and `_static` are forbidden in page data and must live in `options`.
134
+ - Controller fetchers and promises returned from `data` resolve before render.
135
+ - `render` consumes resolved page data and uses generated controller methods from render args or `@/client/context`.
136
+ - Use `api.reload(...)` or `api.set(...)` only when intentionally mutating active page data state.
137
137
  - Error pages use `Router.error(code, options, render)` in `client/pages/_messages/**`.
138
- - Prefer `proteum create page ...` for new page boilerplate, then review the explicit route path and setup payload.
138
+ - Prefer `proteum create page ...` for new page boilerplate, then review the explicit route path, options object, and data payload.
139
139
 
140
140
  ### Manual Routes
141
141
 
@@ -0,0 +1,51 @@
1
+ import path from 'path';
2
+
3
+ import cli from '..';
4
+ import { runPageContractMigration } from '../migrate/pageContract';
5
+
6
+ const printHuman = (summary: ReturnType<typeof runPageContractMigration>) => {
7
+ console.log(`Proteum migrate page-contract`);
8
+ console.log(`App root: ${summary.appRoot}`);
9
+ console.log(`Scanned files: ${summary.scannedFiles}`);
10
+ console.log(`Changed files: ${summary.changedFiles.length}${summary.dryRun ? ' (dry run)' : ''}`);
11
+
12
+ if (summary.changedFiles.length > 0) {
13
+ console.log('');
14
+ console.log('Rewritten files:');
15
+ for (const filepath of summary.changedFiles) {
16
+ console.log(`- ${path.relative(summary.appRoot, filepath)}`);
17
+ }
18
+ }
19
+
20
+ if (summary.manualFixes.length > 0) {
21
+ console.log('');
22
+ console.log('Manual fixes required:');
23
+ for (const fix of summary.manualFixes) {
24
+ console.log(
25
+ `- ${path.relative(summary.appRoot, fix.filepath)}:${fix.line}:${fix.column} ${fix.routeLabel} :: ${fix.reason}`,
26
+ );
27
+ }
28
+ }
29
+ };
30
+
31
+ export const run = async (): Promise<void> => {
32
+ const action = String(cli.args.action || '').trim();
33
+ if (action !== 'page-contract') {
34
+ throw new Error(`Unsupported migrate action "${action}". Expected "page-contract".`);
35
+ }
36
+
37
+ const summary = runPageContractMigration({
38
+ appRoot: String(cli.args.workdir || process.cwd()),
39
+ dryRun: cli.args.dryRun === true,
40
+ });
41
+
42
+ if (cli.args.json === true) {
43
+ console.log(JSON.stringify(summary, null, 2));
44
+ } else {
45
+ printHuman(summary);
46
+ }
47
+
48
+ if (summary.manualFixes.length > 0) {
49
+ throw new Error(`Page-contract migration requires manual fixes in ${summary.manualFixes.length} location(s).`);
50
+ }
51
+ };
@@ -4,7 +4,7 @@ import path from 'path';
4
4
  import app from '../../app';
5
5
  import cli from '../..';
6
6
  import { inspectProteumEnv } from '../../../common/env/proteumEnv';
7
- import { reservedRouteSetupKeys, routeSetupOptionKeys } from '../../../common/router/pageSetup';
7
+ import { reservedRouteOptionKeys, routeOptionKeys } from '../../../common/router/pageData';
8
8
  import { getProjectInstructionGitignoreEntries } from '../../utils/agents';
9
9
  import {
10
10
  TProteumManifest,
@@ -303,7 +303,7 @@ export const writeCurrentProteumManifest = ({
303
303
  });
304
304
 
305
305
  const manifest: TProteumManifest = {
306
- version: 9,
306
+ version: 10,
307
307
  app: {
308
308
  root: normalizeAbsolutePath(app.paths.root),
309
309
  coreRoot: normalizeAbsolutePath(cli.paths.core.root),
@@ -338,8 +338,8 @@ export const writeCurrentProteumManifest = ({
338
338
  },
339
339
  },
340
340
  conventions: {
341
- routeSetupOptionKeys: [...routeSetupOptionKeys],
342
- reservedRouteSetupKeys: [...reservedRouteSetupKeys],
341
+ routeOptionKeys: [...routeOptionKeys],
342
+ reservedRouteOptionKeys: [...reservedRouteOptionKeys],
343
343
  },
344
344
  env: {
345
345
  source: 'process.env',
@@ -59,7 +59,7 @@ const buildClientRouteManifestEntry = (filepath: string): TProteumManifestRoute
59
59
  invalidOptionKeys: definition.invalidOptionKeys,
60
60
  reservedOptionKeys: definition.reservedOptionKeys,
61
61
  optionsRaw: definition.optionsRaw,
62
- hasSetup: definition.hasSetup,
62
+ hasData: definition.hasData,
63
63
  chunkId: pageChunk.chunkId,
64
64
  chunkFilepath: normalizePath(pageChunk.filepath),
65
65
  scope: 'app',
@@ -83,7 +83,7 @@ const buildServerRouteManifestEntries = (filepath: string) =>
83
83
  invalidOptionKeys: definition.invalidOptionKeys,
84
84
  reservedOptionKeys: definition.reservedOptionKeys,
85
85
  optionsRaw: definition.optionsRaw,
86
- hasSetup: definition.hasSetup,
86
+ hasData: definition.hasData,
87
87
  scope: 'app',
88
88
  }));
89
89
 
@@ -2,7 +2,7 @@ import fs from 'fs-extra';
2
2
  import path from 'path';
3
3
  import ts from 'typescript';
4
4
 
5
- import { getRouteSetupOptionKey } from '../../../common/router/pageSetup';
5
+ import { getRouteOptionKey } from '../../../common/router/pageData';
6
6
  import writeIfChanged from '../writeIfChanged';
7
7
 
8
8
  type TRouteSide = 'client' | 'server';
@@ -33,7 +33,7 @@ export type TIndexedRouteDefinition = {
33
33
  invalidOptionKeys: string[];
34
34
  reservedOptionKeys: string[];
35
35
  optionsRaw?: string;
36
- hasSetup: boolean;
36
+ hasData: boolean;
37
37
  };
38
38
 
39
39
  type TGeneratedClientRouteModuleOptions = { chunkId: string };
@@ -206,7 +206,7 @@ const getRouteOptionMetadata = (node: ts.ObjectLiteralExpression | undefined) =>
206
206
 
207
207
  for (const optionKey of optionKeys) {
208
208
  try {
209
- const normalizedOptionKey = getRouteSetupOptionKey(optionKey);
209
+ const normalizedOptionKey = getRouteOptionKey(optionKey);
210
210
 
211
211
  if (normalizedOptionKey) {
212
212
  normalizedOptionKeys.push(normalizedOptionKey);
@@ -438,29 +438,33 @@ const buildDestructuring = (importedServices: TImportedService[]) => {
438
438
  const getClientRouteSignature = (sourceFile: ts.SourceFile, definition: TRouteDefinition) => {
439
439
  const [, ...routeArgs] = [...definition.args];
440
440
 
441
- if (routeArgs.length === 1) {
442
- return { hasSetup: false, renderArg: routeArgs[0] };
443
- }
444
-
445
- if (routeArgs.length === 2) {
446
- if (ts.isObjectLiteralExpression(routeArgs[0])) {
447
- return { hasSetup: false, optionsArg: routeArgs[0], renderArg: routeArgs[1] };
441
+ if (definition.methodName === 'error') {
442
+ if (routeArgs.length === 2) {
443
+ return {
444
+ hasData: false,
445
+ optionsExpression: routeArgs[0],
446
+ optionsArg: ts.isObjectLiteralExpression(routeArgs[0]) ? routeArgs[0] : undefined,
447
+ renderArg: routeArgs[1],
448
+ };
448
449
  }
449
450
 
450
- return { hasSetup: true, setupArg: routeArgs[0], renderArg: routeArgs[1] };
451
+ throw new Error(
452
+ `Unsupported client error route signature in ${sourceFile.fileName}. Expected Router.error(code, options, render).`,
453
+ );
451
454
  }
452
455
 
453
- if (routeArgs.length === 3 && ts.isObjectLiteralExpression(routeArgs[0])) {
456
+ if (routeArgs.length === 3) {
454
457
  return {
455
- hasSetup: true,
456
- optionsArg: routeArgs[0],
457
- setupArg: routeArgs[1],
458
+ hasData: routeArgs[1].kind !== ts.SyntaxKind.NullKeyword,
459
+ optionsExpression: routeArgs[0],
460
+ optionsArg: ts.isObjectLiteralExpression(routeArgs[0]) ? routeArgs[0] : undefined,
461
+ dataArg: routeArgs[1],
458
462
  renderArg: routeArgs[2],
459
463
  };
460
464
  }
461
465
 
462
466
  throw new Error(
463
- `Unsupported client route signature in ${sourceFile.fileName}. Expected Router.page/error with 2-4 arguments.`,
467
+ `Unsupported client page route signature in ${sourceFile.fileName}. Expected Router.page(path, options, data, render).`,
464
468
  );
465
469
  };
466
470
 
@@ -469,30 +473,23 @@ const buildClientRegisterArgs = (
469
473
  definition: TRouteDefinition,
470
474
  clientRoute: TGeneratedClientRouteModuleOptions,
471
475
  ) => {
472
- const { optionsArg, setupArg, renderArg } = getClientRouteSignature(sourceFile, definition);
476
+ const { optionsExpression, renderArg } = getClientRouteSignature(sourceFile, definition);
473
477
  const sourceLocation = getNodeLocation(sourceFile, definition.callExpression);
474
478
  const injectedOptions = buildInjectedRouteMetadata(sourceFile.fileName, sourceLocation, [
475
479
  `id: ${JSON.stringify(clientRoute.chunkId)}`,
476
480
  ]);
477
481
 
478
- if (!optionsArg && !setupArg) {
479
- return [injectedOptions, getNodeText(sourceFile, renderArg)];
480
- }
481
-
482
- if (optionsArg && !setupArg) {
482
+ if (definition.methodName === 'error') {
483
483
  return [
484
- `{ ...(${getNodeText(sourceFile, optionsArg)}), ...${injectedOptions} }`,
484
+ `{ ...(${getNodeText(sourceFile, optionsExpression)}), ...${injectedOptions} }`,
485
485
  getNodeText(sourceFile, renderArg),
486
486
  ];
487
487
  }
488
488
 
489
- if (!optionsArg && setupArg) {
490
- return [injectedOptions, getNodeText(sourceFile, setupArg), getNodeText(sourceFile, renderArg)];
491
- }
492
-
489
+ const { dataArg } = getClientRouteSignature(sourceFile, definition);
493
490
  return [
494
- `{ ...(${getNodeText(sourceFile, optionsArg!)}), ...${injectedOptions} }`,
495
- getNodeText(sourceFile, setupArg!),
491
+ `{ ...(${getNodeText(sourceFile, optionsExpression)}), ...${injectedOptions} }`,
492
+ getNodeText(sourceFile, dataArg!),
496
493
  getNodeText(sourceFile, renderArg),
497
494
  ];
498
495
  };
@@ -604,10 +601,8 @@ export const indexRouteDefinitions = ({ side, sourceFilepath }: { side: TRouteSi
604
601
  normalizedOptionKeys: optionMetadata.normalizedOptionKeys,
605
602
  invalidOptionKeys: optionMetadata.invalidOptionKeys,
606
603
  reservedOptionKeys: optionMetadata.reservedOptionKeys,
607
- optionsRaw: clientSignature.optionsArg
608
- ? getNodeText(sourceFile, clientSignature.optionsArg)
609
- : undefined,
610
- hasSetup: clientSignature.hasSetup,
604
+ optionsRaw: getNodeText(sourceFile, clientSignature.optionsExpression),
605
+ hasData: false,
611
606
  }
612
607
  : {
613
608
  methodName: definition.methodName,
@@ -627,10 +622,8 @@ export const indexRouteDefinitions = ({ side, sourceFilepath }: { side: TRouteSi
627
622
  normalizedOptionKeys: optionMetadata.normalizedOptionKeys,
628
623
  invalidOptionKeys: optionMetadata.invalidOptionKeys,
629
624
  reservedOptionKeys: optionMetadata.reservedOptionKeys,
630
- optionsRaw: clientSignature.optionsArg
631
- ? getNodeText(sourceFile, clientSignature.optionsArg)
632
- : undefined,
633
- hasSetup: clientSignature.hasSetup,
625
+ optionsRaw: getNodeText(sourceFile, clientSignature.optionsExpression),
626
+ hasData: clientSignature.hasData,
634
627
  };
635
628
  }
636
629
 
@@ -659,7 +652,7 @@ export const indexRouteDefinitions = ({ side, sourceFilepath }: { side: TRouteSi
659
652
  invalidOptionKeys: optionMetadata.invalidOptionKeys,
660
653
  reservedOptionKeys: optionMetadata.reservedOptionKeys,
661
654
  optionsRaw: optionsArg ? getNodeText(sourceFile, optionsArg) : undefined,
662
- hasSetup: false,
655
+ hasData: false,
663
656
  };
664
657
  });
665
658
  };
package/cli/context.ts CHANGED
@@ -27,7 +27,7 @@ export class CLIContext {
27
27
  const workdir =
28
28
  typeof args.workdir === 'string' && args.workdir.trim().length > 0 ? args.workdir.trim() : process.cwd();
29
29
 
30
- this.args = { workdir, ...args, workdir };
30
+ this.args = { ...args, workdir };
31
31
  this.paths = new Paths(workdir, this.paths.core.root);
32
32
  this.paths.applyAliases();
33
33
  this.verbose = this.args.verbose === true;