@fougere/cli 0.9.2-alpha.0 → 0.10.0-alpha.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 (67) hide show
  1. package/app/commands/CheckCommand.ts +3 -2
  2. package/app/commands/ExplainCommand.ts +15 -1
  3. package/app/commands/GraphCommand.ts +25 -1
  4. package/app/commands/LoadCommand.ts +44 -0
  5. package/app/commands/ServeCommand.ts +1 -1
  6. package/dist/bridge.d.ts.map +1 -1
  7. package/dist/bridge.js +24 -4
  8. package/dist/bridge.js.map +1 -1
  9. package/dist/machine.d.ts +1 -1
  10. package/dist/machine.js +1 -1
  11. package/dist/runner.d.ts +9 -1
  12. package/dist/runner.d.ts.map +1 -1
  13. package/dist/runner.js +13 -6
  14. package/dist/runner.js.map +1 -1
  15. package/dist/typescript/{EntityTypes.d.ts → EntityTypes/EntityTypes.d.ts} +1 -4
  16. package/dist/typescript/EntityTypes/EntityTypes.d.ts.map +1 -0
  17. package/dist/typescript/{EntityTypes.js → EntityTypes/EntityTypes.js} +1 -1
  18. package/dist/typescript/EntityTypes/EntityTypes.js.map +1 -0
  19. package/dist/typescript/EntityTypes/EntityTypesOptions.d.ts +5 -0
  20. package/dist/typescript/EntityTypes/EntityTypesOptions.d.ts.map +1 -0
  21. package/dist/typescript/EntityTypes/EntityTypesOptions.js +2 -0
  22. package/dist/typescript/EntityTypes/EntityTypesOptions.js.map +1 -0
  23. package/dist/typescript/FacadeTypes/FacadeTypes.d.ts +9 -0
  24. package/dist/typescript/FacadeTypes/FacadeTypes.d.ts.map +1 -0
  25. package/dist/typescript/{FacadeTypes.js → FacadeTypes/FacadeTypes.js} +1 -1
  26. package/dist/typescript/FacadeTypes/FacadeTypes.js.map +1 -0
  27. package/dist/typescript/FacadeTypes/FacadeTypesOptions.d.ts +6 -0
  28. package/dist/typescript/FacadeTypes/FacadeTypesOptions.d.ts.map +1 -0
  29. package/dist/typescript/FacadeTypes/FacadeTypesOptions.js +2 -0
  30. package/dist/typescript/FacadeTypes/FacadeTypesOptions.js.map +1 -0
  31. package/dist/typescript/FacadeTypes/OpDescriptor.d.ts +8 -0
  32. package/dist/typescript/FacadeTypes/OpDescriptor.d.ts.map +1 -0
  33. package/dist/typescript/FacadeTypes/OpDescriptor.js +2 -0
  34. package/dist/typescript/FacadeTypes/OpDescriptor.js.map +1 -0
  35. package/fronds/analysis/entities/Load.ts +8 -0
  36. package/fronds/analysis/handlers/BuildHandler.ts +25 -2
  37. package/fronds/analysis/handlers/CheckHandler.ts +39 -30
  38. package/fronds/analysis/handlers/DevtoolsHandler.ts +12 -2
  39. package/fronds/analysis/handlers/ExplainHandler.ts +6 -0
  40. package/fronds/analysis/handlers/GraphHandler.ts +6 -3
  41. package/fronds/analysis/handlers/LoadHandler.ts +43 -0
  42. package/fronds/scaffold/handlers/BuildFrondHandler.ts +1 -1
  43. package/fronds/scaffold/handlers/SyncHandler.ts +57 -18
  44. package/fronds/scaffold/services/ProjectWriter.ts +61 -3
  45. package/package.json +15 -8
  46. package/src/bridge.ts +27 -4
  47. package/src/machine.ts +1 -1
  48. package/src/runner.ts +13 -6
  49. package/src/typescript/{EntityTypes.ts → EntityTypes/EntityTypes.ts} +2 -6
  50. package/src/typescript/EntityTypes/EntityTypesOptions.ts +4 -0
  51. package/src/typescript/{FacadeTypes.ts → FacadeTypes/FacadeTypes.ts} +3 -15
  52. package/src/typescript/FacadeTypes/FacadeTypesOptions.ts +5 -0
  53. package/src/typescript/FacadeTypes/OpDescriptor.ts +8 -0
  54. package/templates/blog/fronds/blog/entities/Post.ts +1 -1
  55. package/templates/flat/CLAUDE.md +3 -3
  56. package/templates/frond/CLAUDE.md +3 -3
  57. package/templates/workspace/CLAUDE.md +3 -3
  58. package/dist/typescript/EntityTypes.d.ts.map +0 -1
  59. package/dist/typescript/EntityTypes.js.map +0 -1
  60. package/dist/typescript/FacadeTypes.d.ts +0 -19
  61. package/dist/typescript/FacadeTypes.d.ts.map +0 -1
  62. package/dist/typescript/FacadeTypes.js.map +0 -1
  63. package/templates/apps/nuxt/app/app.vue +0 -25
  64. package/templates/apps/nuxt/app/pages/index.vue +0 -33
  65. package/templates/apps/nuxt/nuxt.config.ts +0 -6
  66. package/templates/apps/nuxt/package.json +0 -19
  67. package/templates/apps/nuxt/tsconfig.json +0 -3
@@ -1,4 +1,5 @@
1
- import type { CheckResult, Finding } from '../../fronds/analysis/handlers/CheckHandler.js';
1
+ import type { CheckResult } from '../../fronds/analysis/handlers/CheckHandler.js';
2
+ import type { Diagnostic } from '@fougere/core';
2
3
  import type { App } from '@fougere/core';
3
4
  import { createAppRunner } from '@fougere/core';
4
5
  import type { ui as createUi } from '../../src/ui.js';
@@ -45,7 +46,7 @@ export default class CheckCommand {
45
46
  }
46
47
  }
47
48
 
48
- function render(f: Finding): string {
49
+ function render(f: Diagnostic): string {
49
50
  const mark = f.severity === 'blocking' ? pc.red('✗') : pc.yellow('⚠');
50
51
  const where = relative(process.cwd(), f.filePath) || f.filePath;
51
52
  const what = f.subject ? ` ${f.subject}` : '';
@@ -19,7 +19,7 @@ export default class ExplainCommand {
19
19
  const operation = (raw.operation as string | undefined)?.trim();
20
20
 
21
21
  // No operation named — the question is what this project serves at all. The same
22
- // model answers both, so the door is the one that was asked, never a guess.
22
+ // model answers both, so the facade is the one that was asked, never a guess.
23
23
  if (names || !operation) return this.listing(raw, names);
24
24
 
25
25
  const result = await this.ask('execute', raw) as ExplainResult;
@@ -88,12 +88,26 @@ export function renderExplain(result: ExplainResult): string {
88
88
  `${pc.dim('Surfaces:')} ${result.exposure.surfaces.join(', ') || '—'}`,
89
89
  `${pc.dim('Adapters:')} ${result.exposure.adapters.join(', ') || '—'}`,
90
90
  `${pc.dim('Placement:')} ${result.placement.frond} / ${result.placement.runtime}${result.placement.remote ? ` (${result.placement.remote})` : ''}`,
91
+ // Where the work GOES, under where it answers. The hop count is what a sampling rate, a
92
+ // histogram's bounds and a load threshold are all a function of — each hard-coded today.
93
+ `${pc.dim('Reach:')} ${renderReach(result.reach)}`,
91
94
  );
92
95
 
93
96
  if (result.handler.file) lines.push(`${pc.dim('Source:')} ${result.handler.file}`);
94
97
  return lines.join('\n');
95
98
  }
96
99
 
100
+ /** What this op reaches, and the part of it that costs a round trip. */
101
+ function renderReach(reach: ExplainResult['reach']): string {
102
+ if (reach.fronds.length === 0) return pc.dim('nothing outside its own frond');
103
+
104
+ const named = reach.fronds
105
+ .map((one) => (one.runtime === 'remote' ? pc.yellow(one.frond) : pc.cyan(one.frond)))
106
+ .join(', ');
107
+
108
+ return `${named} ${pc.dim(`— ${reach.hops} hop(s)`)}`;
109
+ }
110
+
97
111
  export function renderListing(listing: ExplainListing): string {
98
112
  const lines = [pc.bold('Fronds')];
99
113
  if (listing.fronds.length === 0) lines.push(' —');
@@ -1,5 +1,5 @@
1
1
  import type { GraphResult } from '../../fronds/analysis/handlers/GraphHandler.js';
2
- import type { EntityNode, DomainCluster, App } from '@fougere/core';
2
+ import type { DeclaredTopology, EntityNode, DomainCluster, App } from '@fougere/core';
3
3
  import { createAppRunner } from '@fougere/core';
4
4
  import type { ui as createUi } from '../../src/ui.js';
5
5
  import pc from 'picocolors';
@@ -25,6 +25,7 @@ export default class GraphCommand {
25
25
  }
26
26
 
27
27
  this.ui.step(`${pc.bold(String(result.totalEntities))} entities, ${pc.bold(String(result.totalRefs))} refs, ${pc.bold(String(result.fronds.length))} frond(s)`);
28
+ this.ui.note(renderFronds(result.declared), 'Fronds');
28
29
  this.ui.note(renderGraph(result.nodes), 'Entity Graph');
29
30
 
30
31
  const min = (raw.minEntities as number) ?? 6;
@@ -39,6 +40,29 @@ export default class GraphCommand {
39
40
  }
40
41
  }
41
42
 
43
+ /**
44
+ * Where each frond runs, and which reaches which. Read from `remotes:` and from what handlers
45
+ * ask for — never from a call, so this says the same thing with nothing running.
46
+ */
47
+ function renderFronds(declared: DeclaredTopology): string {
48
+ const reached = new Map<string, string[]>();
49
+ for (const edge of declared.edges) {
50
+ reached.set(edge.from, [...(reached.get(edge.from) ?? []), edge.to]);
51
+ }
52
+
53
+ const width = Math.max(0, ...declared.fronds.map((one) => one.frond.length));
54
+
55
+ return declared.fronds.map((one) => {
56
+ const name = pc.bold(one.frond.padEnd(width));
57
+ const where = one.placement === 'local' ? pc.dim('local ') : pc.yellow('remote');
58
+ const at = one.at ? ` ${pc.dim(one.at)}` : '';
59
+ const calls = reached.get(one.frond);
60
+ const out = calls ? ` ${pc.dim('→')} ${calls.map((to) => pc.cyan(to)).join(', ')}` : '';
61
+
62
+ return ` ${name} ${where}${at}${out}`;
63
+ }).join('\n');
64
+ }
65
+
42
66
  function renderGraph(nodes: Map<string, EntityNode>): string {
43
67
  return [...nodes.entries()].map(([name, node]) => {
44
68
  const refs = node.refs.length > 0
@@ -0,0 +1,44 @@
1
+ import type { App } from '@fougere/core';
2
+ import { createAppRunner } from '@fougere/core';
3
+ import type { LoadScenario } from '../../fronds/analysis/handlers/LoadHandler.js';
4
+ import type { ui as createUi } from '../../src/ui.js';
5
+ import pc from 'picocolors';
6
+ import { machineWanted, printMachine } from '../../src/machine.js';
7
+
8
+ type Ui = ReturnType<typeof createUi>;
9
+
10
+ /**
11
+ * The command the generated header has been naming all along.
12
+ *
13
+ * What it writes is derived — the operations from what the project serves, a body for each from
14
+ * the entity's own fields, the envelope from the one function that states it. What it cannot
15
+ * derive is what the load IS: the weights, the stages and the thresholds are facts about your
16
+ * users, and the file says so where they sit.
17
+ */
18
+ export default class LoadCommand {
19
+ constructor(private app: App, private ui: Ui) {}
20
+
21
+ async run(raw: Record<string, unknown>) {
22
+ const result = await createAppRunner(this.app)(
23
+ { entity: 'load', op: 'execute' },
24
+ { params: {}, query: {}, input: raw, state: {} },
25
+ ) as LoadScenario;
26
+
27
+ if (machineWanted(raw)) return printMachine(result);
28
+
29
+ if (result.operations.length === 0) {
30
+ this.ui.warn('No operation answers the default facade — nothing to put under load.');
31
+ return;
32
+ }
33
+
34
+ if (!result.file) {
35
+ process.stdout.write(result.script);
36
+ return;
37
+ }
38
+
39
+ this.ui.step(`${pc.bold(String(result.operations.length))} operation(s) against ${pc.dim(result.facade)}`);
40
+ this.ui.note(result.operations.map((one) => ` ${one}`).join('\n'), 'Under load');
41
+ this.ui.info(`${pc.dim('Written to')} ${result.file} ${pc.dim('— edit the weights, the stages and the thresholds.')}`);
42
+ this.ui.info(`${pc.dim('Then:')} k6 run ${result.file}`);
43
+ }
44
+ }
@@ -1,7 +1,7 @@
1
1
  import { createLocalRunner, identityFromEnv } from '@fougere/core';
2
2
  import { watchPathsOf } from '@fougere/compiler';
3
3
  import { installLoader } from '../../src/loader.js';
4
- import type { Conventions } from '@fougere/core';
4
+
5
5
  import { bootApp } from '@fougere/defaults';
6
6
  import { serve } from '@fougere/transport-http';
7
7
  import { watch } from 'node:fs';
@@ -1 +1 @@
1
- {"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AACA,6BAA6B;AAC7B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAE9C,OAAO,KAAK,EAAE,OAAO,EAAU,MAAM,OAAO,CAAC;AAM7C,6DAA6D;AAC7D,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CA4CpD"}
1
+ {"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AACA,6BAA6B;AAC7B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAE9C,OAAO,KAAK,EAAE,OAAO,EAAU,MAAM,OAAO,CAAC;AA0B7C,6DAA6D;AAC7D,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CA+CpD"}
package/dist/bridge.js CHANGED
@@ -3,22 +3,42 @@ import { Shapes, Visibility } from '@fougere/schema';
3
3
  function toKebab(name) {
4
4
  return name.replace(/[A-Z]/g, (c) => '-' + c.toLowerCase());
5
5
  }
6
+ /**
7
+ * What a caller supplies: the fields the axes admit, or the PRIMARY when they admit nothing.
8
+ *
9
+ * `Visibility.input` answers who may WRITE a field, and a primary is the server's — right for a
10
+ * form, wrong for an operation whose whole input is `Product.pick('id')`. That contract asks the
11
+ * caller to NAME a row, and the axes leave it with no argument at all: `product:archive abc-9`
12
+ * answered `Unexpected argument`.
13
+ *
14
+ * Only when nothing else remains, so `create` over a full entity is untouched — its input holds
15
+ * twelve writable fields and the primary stays the server's.
16
+ */
17
+ function suppliedIn(fields) {
18
+ const written = Visibility.of(fields).input;
19
+ if (Object.keys(written).length > 0)
20
+ return written;
21
+ return Object.fromEntries(Object.entries(fields).filter(([, field]) => Role.of(field).isPrimary));
22
+ }
6
23
  /** Convert an Entity's fields into citty args definition. */
7
24
  export function entityToArgs(fields) {
8
25
  const args = {};
9
26
  let positionalIndex = 0;
10
- // Axes-derived ingress membership; the CLI additionally skips ALL relations
11
- // (a ref is not a flag — supplying related rows is not a CLI gesture).
12
- for (const [key, field] of Object.entries(Visibility.of(fields).input)) {
27
+ // The CLI additionally skips ALL relations: a ref is not a flag — supplying related rows is
28
+ // not a CLI gesture.
29
+ for (const [key, field] of Object.entries(suppliedIn(fields))) {
13
30
  if (Role.of(field).isRelation)
14
31
  continue;
15
32
  // A `default(v)` travels as the create rule `{ value }` — citty shows it.
16
33
  const defaultValue = Lifecycle.of(field).literal?.value;
17
34
  const { base: shape, nullable } = Shapes.of(field.shape);
18
35
  const type = Shapes.typeOf(field.shape);
36
+ // Naming a row is required by definition: a generator fills a primary the server writes,
37
+ // never one a caller hands in to designate.
38
+ const designates = Role.of(field).isPrimary;
19
39
  const common = {
20
40
  description: field.meta?.description,
21
- required: !nullable && Lifecycle.of(field).requiredAtCreate,
41
+ required: designates || (!nullable && Lifecycle.of(field).requiredAtCreate),
22
42
  };
23
43
  // A closed set is citty's `enum`: the shape already names the legal values, so the
24
44
  // refusal and the `--help` listing come from the declaration rather than a check
@@ -1 +1 @@
1
- {"version":3,"file":"bridge.js","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"bridge.js","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"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"}
package/dist/machine.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /** A command's machine output — the one shape a pipe reads. */
2
2
  export declare function machineWanted(raw: Record<string, unknown>): boolean;
3
3
  /**
4
- * A `Map` serializes to `{}`, so the door converts it rather than each command flattening its own
4
+ * A `Map` serializes to `{}`, so the facade converts it rather than each command flattening its own
5
5
  * result: `GraphResult.nodes` is a Map, and `graph --json` would have printed a report with an
6
6
  * empty graph in it.
7
7
  */
package/dist/machine.js CHANGED
@@ -3,7 +3,7 @@ export function machineWanted(raw) {
3
3
  return raw.json === true || typeof raw.names === 'string';
4
4
  }
5
5
  /**
6
- * A `Map` serializes to `{}`, so the door converts it rather than each command flattening its own
6
+ * A `Map` serializes to `{}`, so the facade converts it rather than each command flattening its own
7
7
  * result: `GraphResult.nodes` is a Map, and `graph --json` would have printed a report with an
8
8
  * empty graph in it.
9
9
  */
package/dist/runner.d.ts CHANGED
@@ -3,5 +3,13 @@
3
3
  * via citty.
4
4
  */
5
5
  import type { App } from '@fougere/core';
6
- export declare function run(app: App): Promise<void>;
6
+ /**
7
+ * Every operation of an app, as a terminal command.
8
+ *
9
+ * `root` is where the PRESENTATION classes are looked for — `app/commands/`, one per command
10
+ * that wants to print something of its own. It defaults to this package, which is how
11
+ * `npx fougere` finds its fifteen; a project passes its own and gets the same treatment for
12
+ * the operations it declares, with no class at all where a default rendering will do.
13
+ */
14
+ export declare function run(app: App, root?: string): Promise<void>;
7
15
  //# sourceMappingURL=runner.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AAwCzC,wBAAsB,GAAG,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAgGjD"}
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AAwCzC;;;;;;;GAOG;AACH,wBAAsB,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,SAA0C,GAAG,OAAO,CAAC,IAAI,CAAC,CA+FjG"}
package/dist/runner.js CHANGED
@@ -13,9 +13,9 @@ function toCamel(kebab) {
13
13
  return kebab.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
14
14
  }
15
15
  /** Scan app/commands/ for command classes. */
16
- async function loadAppCommands(cliRoot, loader) {
16
+ async function loadAppCommands(root, loader) {
17
17
  const map = new Map();
18
- const dir = join(cliRoot, 'app', 'commands');
18
+ const dir = join(root, 'app', 'commands');
19
19
  const files = await readdir(dir, { withFileTypes: true }).catch(() => []);
20
20
  for (const f of files) {
21
21
  if (!f.isFile() || !(f.name.endsWith('.ts') || f.name.endsWith('.js')))
@@ -29,13 +29,20 @@ async function loadAppCommands(cliRoot, loader) {
29
29
  }
30
30
  return map;
31
31
  }
32
- export async function run(app) {
32
+ /**
33
+ * Every operation of an app, as a terminal command.
34
+ *
35
+ * `root` is where the PRESENTATION classes are looked for — `app/commands/`, one per command
36
+ * that wants to print something of its own. It defaults to this package, which is how
37
+ * `npx fougere` finds its fifteen; a project passes its own and gets the same treatment for
38
+ * the operations it declares, with no class at all where a default rendering will do.
39
+ */
40
+ export async function run(app, root = new URL('..', import.meta.url).pathname) {
33
41
  const terminal = ui();
34
- const cliRoot = new URL('..', import.meta.url).pathname;
35
42
  const { createJiti } = await import('jiti');
36
43
  const jiti = createJiti(import.meta.url, { interopDefault: true });
37
44
  const loader = (path) => jiti.import(path);
38
- const appCommands = await loadAppCommands(cliRoot, loader);
45
+ const appCommands = await loadAppCommands(root, loader);
39
46
  const subCommands = {};
40
47
  for (const frond of app.fronds) {
41
48
  const handlerMap = new Map(frond.handlers.map((h) => [h.address, h]));
@@ -69,7 +76,7 @@ export async function run(app) {
69
76
  meta: {
70
77
  name: cmdName,
71
78
  // `--help` reads the operation's own doc sentence, which the scan already
72
- // carries for every door (`OperationContract.description`). A table here
79
+ // carries for every facade (`OperationContract.description`). A table here
73
80
  // would be the same fact written twice, and it drifted: it described `add`
74
81
  // and `doctor`, which do not exist, and had nothing for `call` or `serve`.
75
82
  description: handlerEntry.operations.get('execute')?.description,
@@ -1 +1 @@
1
- {"version":3,"file":"runner.js","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,5 @@
1
1
  import { type SchemaDescriptor } from '@fougere/schema';
2
- export interface EntityTypesOptions {
3
- name?: string;
4
- exported?: boolean;
5
- }
2
+ import type { EntityTypesOptions } from './EntityTypesOptions.js';
6
3
  export declare class EntityTypes {
7
4
  private readonly descriptor;
8
5
  private constructor();
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EntityTypes.d.ts","sourceRoot":"","sources":["../../../src/typescript/EntityTypes/EntityTypes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoC,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAE1F,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAsDlE,qBAAa,WAAW;IACF,OAAO,CAAC,QAAQ,CAAC,UAAU;IAA/C,OAAO,eAA8D;IAErE,MAAM,CAAC,EAAE,CAAC,UAAU,EAAE,gBAAgB,GAAG,WAAW,CAEnD;IAED,MAAM,CAAC,OAAO,GAAE,kBAAuB,GAAG,MAAM,CAS/C;CACF"}
@@ -1,5 +1,5 @@
1
1
  import { upperFirst } from '@fougere/schema';
2
- import { docCommentOf, propertyKey } from './syntax.js';
2
+ import { docCommentOf, propertyKey } from '../syntax.js';
3
3
  /** So a nullable field lands as a union. */
4
4
  function typeOf(field) {
5
5
  const types = Array.isArray(field.type) ? field.type : field.type ? [field.type] : [];
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EntityTypes.js","sourceRoot":"","sources":["../../../src/typescript/EntityTypes/EntityTypes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export interface EntityTypesOptions {
2
+ name?: string;
3
+ exported?: boolean;
4
+ }
5
+ //# sourceMappingURL=EntityTypesOptions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EntityTypesOptions.d.ts","sourceRoot":"","sources":["../../../src/typescript/EntityTypes/EntityTypesOptions.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=EntityTypesOptions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EntityTypesOptions.js","sourceRoot":"","sources":["../../../src/typescript/EntityTypes/EntityTypesOptions.ts"],"names":[],"mappings":""}
@@ -0,0 +1,9 @@
1
+ import type { FacadeTypesOptions } from './FacadeTypesOptions.js';
2
+ import type { OpDescriptor } from './OpDescriptor.js';
3
+ export declare class FacadeTypes {
4
+ private readonly operations;
5
+ private constructor();
6
+ static of(operations: readonly OpDescriptor[]): FacadeTypes;
7
+ render(options?: FacadeTypesOptions): string;
8
+ }
9
+ //# sourceMappingURL=FacadeTypes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FacadeTypes.d.ts","sourceRoot":"","sources":["../../../src/typescript/FacadeTypes/FacadeTypes.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AActD,qBAAa,WAAW;IACF,OAAO,CAAC,QAAQ,CAAC,UAAU;IAA/C,OAAO,eAAqE;IAE5E,MAAM,CAAC,EAAE,CAAC,UAAU,EAAE,SAAS,YAAY,EAAE,GAAG,WAAW,CAE1D;IAED,MAAM,CAAC,OAAO,GAAE,kBAAuB,GAAG,MAAM,CAW/C;CACF"}
@@ -1,4 +1,4 @@
1
- import { docCommentOf, propertyKey } from './syntax.js';
1
+ import { docCommentOf, propertyKey } from '../syntax.js';
2
2
  /** So a consumer sees the cardinality in the type, not in a doc line. */
3
3
  function returnTypeOf(op, rowType) {
4
4
  switch (op.cardinality) {
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FacadeTypes.js","sourceRoot":"","sources":["../../../src/typescript/FacadeTypes/FacadeTypes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAIzD,yEAAyE;AACzE,SAAS,YAAY,CAAC,EAAgB,EAAE,OAAe;IACrD,QAAQ,EAAE,CAAC,WAAW,EAAE,CAAC;QACvB,KAAK,MAAM,EAAE,OAAO,GAAG,OAAO,IAAI,CAAC;QACnC,KAAK,MAAM,EAAE,OAAO,GAAG,OAAO,gEAAgE,CAAC;QAC/F,KAAK,OAAO,EAAE,OAAO,GAAG,OAAO,cAAc,CAAC;QAC9C,KAAK,KAAK,EAAE,OAAO,OAAO,CAAC;QAC3B,KAAK,MAAM,EAAE,OAAO,SAAS,CAAC;QAC9B,SAAS,OAAO,SAAS,CAAC;IAC5B,CAAC;AACH,CAAC;AAED,MAAM,OAAO,WAAW;IACe,UAAU;IAA/C,YAAqC,UAAmC;0BAAnC,UAAU;IAA4B,CAAC;IAE5E,MAAM,CAAC,EAAE,CAAC,UAAmC;QAC3C,OAAO,IAAI,WAAW,CAAC,UAAU,CAAC,CAAC;IACrC,CAAC;IAED,MAAM,CAAC,OAAO,GAAuB,EAAE;QACrC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,QAAQ,CAAC;QACtC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,KAAK,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;QAC7D,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,SAAS,CAAC;QAC7C,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE;YAChD,MAAM,GAAG,GAAG,YAAY,CAAC,SAAS,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;YACtD,OAAO,GAAG,GAAG,KAAK,WAAW,CAAC,SAAS,CAAC,IAAI,CAAC,sCAAsC,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,IAAI,CAAC;QAC1H,CAAC,CAAC,CAAC;QAEH,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,GAAG,QAAQ,aAAa,IAAI,KAAK,CAAC;QACnE,OAAO,GAAG,QAAQ,aAAa,IAAI,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;IACpE,CAAC;CACF"}
@@ -0,0 +1,6 @@
1
+ export interface FacadeTypesOptions {
2
+ name?: string;
3
+ exported?: boolean;
4
+ rowType?: string;
5
+ }
6
+ //# sourceMappingURL=FacadeTypesOptions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FacadeTypesOptions.d.ts","sourceRoot":"","sources":["../../../src/typescript/FacadeTypes/FacadeTypesOptions.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=FacadeTypesOptions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FacadeTypesOptions.js","sourceRoot":"","sources":["../../../src/typescript/FacadeTypes/FacadeTypesOptions.ts"],"names":[],"mappings":""}
@@ -0,0 +1,8 @@
1
+ import type { SchemaDescriptor } from '@fougere/schema';
2
+ export interface OpDescriptor {
3
+ name: string;
4
+ description?: string;
5
+ output?: SchemaDescriptor;
6
+ cardinality?: 'one' | 'maybe' | 'many' | 'page' | 'none';
7
+ }
8
+ //# sourceMappingURL=OpDescriptor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OpDescriptor.d.ts","sourceRoot":"","sources":["../../../src/typescript/FacadeTypes/OpDescriptor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAExD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,WAAW,CAAC,EAAE,KAAK,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;CAC1D"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=OpDescriptor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OpDescriptor.js","sourceRoot":"","sources":["../../../src/typescript/FacadeTypes/OpDescriptor.ts"],"names":[],"mappings":""}
@@ -0,0 +1,8 @@
1
+ import { entity, bool, text } from '@fougere/schema';
2
+
3
+ export default class Load extends entity({
4
+ root: text({ description: 'Project root directory (default: cwd)' }),
5
+ facade: text({ description: 'Where the calls go (default: http://127.0.0.1:3000/_fougere/call)' }),
6
+ out: text({ description: 'Where to write it, or empty to print it on stdout (default: <root>/load.js)' }),
7
+ json: bool({ default: false, description: 'Print the scenario as JSON, with nothing else on stdout' }),
8
+ }) {}
@@ -1,6 +1,7 @@
1
1
  import { mkdir, writeFile } from 'node:fs/promises';
2
- import { dirname, relative, resolve } from 'node:path';
3
- import { emitScan } from '@fougere/compiler';
2
+ import { loadConfig } from '@fougere/core/node';
3
+ import { dirname, join, relative, resolve } from 'node:path';
4
+ import { emitFacade, emitNames, emitScan } from '@fougere/compiler';
4
5
  import ProjectScan from '../services/ProjectScan.js';
5
6
  import type Build from '../entities/Build.js';
6
7
 
@@ -12,12 +13,20 @@ import type Build from '../entities/Build.js';
12
13
  * This is the same scan the next build performs again, so it is gitignored.
13
14
  */
14
15
  export const DEFAULT_OUT = '.fougere/scan.generated.ts';
16
+ /** Types only, beside the module — what lets a client narrow a refusal it might meet. */
17
+ export const FACADE_OUT = 'facade.generated.ts';
18
+ /** Types only — what a config may NAME, so a string cannot designate a class that is not there. */
19
+ export const NAMES_OUT = 'names.generated.d.ts';
15
20
 
16
21
  export interface BuildReport {
17
22
  /** Absolute, so a caller can print it or read it back. */
18
23
  out: string;
19
24
  /** Relative to the project root — what a human recognizes. */
20
25
  path: string;
26
+ /** Where the facades were written — one export per address, the page's facade in. */
27
+ facade: string;
28
+ /** Where the names went — the unions a config is judged against. */
29
+ names: string;
21
30
  fronds: string[];
22
31
  entities: number;
23
32
  handlers: number;
@@ -52,9 +61,23 @@ export default class BuildHandler {
52
61
  await mkdir(dirname(out), { recursive: true });
53
62
  await writeFile(out, emitScan(scan, { outFile: out }));
54
63
 
64
+ // The same scan, projected a third way. It holds no value and reaches no bundle: what a
65
+ // client cannot otherwise know is which refusals one facade can answer, because TypeScript
66
+ // records nothing about what a function throws.
67
+ const facade = join(dirname(out), FACADE_OUT);
68
+ await writeFile(facade, emitFacade(scan, { outFile: facade }));
69
+
70
+ // And a fourth, for the only place a name is still written as a string: a config file. The
71
+ // sources are the config's own keys, which no scan can find.
72
+ const config = await loadConfig(scan.root).catch(() => ({}) as Awaited<ReturnType<typeof loadConfig>>);
73
+ const names = join(dirname(out), NAMES_OUT);
74
+ await writeFile(names, emitNames(scan, { sources: Object.keys(config.sources ?? {}) }));
75
+
55
76
  return {
56
77
  out,
57
78
  path: relative(scan.root, out),
79
+ facade: relative(scan.root, facade),
80
+ names: relative(scan.root, names),
58
81
  fronds: scan.fronds.map((frond) => frond.name),
59
82
  entities: scan.fronds.reduce((total, frond) => total + frond.entities.length, 0),
60
83
  handlers: scan.fronds.reduce((total, frond) => total + frond.handlers.length, 0),
@@ -4,33 +4,19 @@ import {
4
4
  buildGraph,
5
5
  clusterEntities,
6
6
  resolveEffectiveOperations,
7
- type ScanDiagnostic,
7
+ type Diagnostic,
8
8
  } from '@fougere/core';
9
9
  import { adaptersOf, crossFrondImports, handlerDeclarations, outsideConventions } from '@fougere/compiler';
10
10
  import { resolveConventions } from '@fougere/core';
11
11
  import ProjectScan from '../services/ProjectScan.js';
12
-
13
- /** One thing that does not hold, in the terms of whoever has to fix it. */
14
- export interface Finding {
15
- severity: 'blocking' | 'warning';
16
- /** Stable rule name — the same vocabulary a scan diagnostic uses. */
17
- code: string;
18
- /** Where to go and look. */
19
- filePath: string;
20
- /**
21
- * What the finding is ABOUT — `PostHandler.whoNull(user)` — when the rule holds it
22
- * as a fact rather than inside its sentence. Two ops of one handler breaking the
23
- * same rule read as one repeated line without it.
24
- */
25
- subject?: string;
26
- /** What is wrong, and what it costs. One sentence. */
27
- message: string;
28
- }
12
+ import { statSync } from 'node:fs';
13
+ import { dirname, join } from 'node:path';
14
+ import { FACADE_OUT, DEFAULT_OUT } from './BuildHandler.js';
29
15
 
30
16
  export interface CheckResult {
31
17
  fronds: number;
32
18
  handlers: number;
33
- findings: Finding[];
19
+ findings: Diagnostic[];
34
20
  }
35
21
 
36
22
  /** Shared with `fougere graph` — one threshold, so the two never disagree. */
@@ -63,7 +49,7 @@ export default class CheckHandler {
63
49
  remotes: config.remotes,
64
50
  adapters: config.adapters,
65
51
  });
66
- const findings: Finding[] = model.diagnostics.map(asFinding);
52
+ const findings: Diagnostic[] = [...model.diagnostics];
67
53
  const handlers = fronds.reduce((count, frond) => count + frond.handlers.length, 0);
68
54
 
69
55
  /**
@@ -121,7 +107,7 @@ export default class CheckHandler {
121
107
 
122
108
  /**
123
109
  * A `pattern` that backtracks super-linearly. The pattern is fixed at declaration and
124
- * the string tested against it is not: whoever calls the door chooses it, so the cost
110
+ * the string tested against it is not: whoever calls the facade chooses it, so the cost
125
111
  * of one match is theirs to set. Judged HERE because a regex says the same thing on
126
112
  * every run — checking it per row would pay for a verdict that never changes.
127
113
  *
@@ -191,17 +177,40 @@ export default class CheckHandler {
191
177
  });
192
178
  }
193
179
 
180
+ findings.push(...facadeFindings(root, fronds));
181
+
194
182
  return { fronds: fronds.length, handlers, findings };
195
183
  }
196
184
  }
197
185
 
198
- /** A scan diagnostic IS a finding — same vocabulary, so the renderer has one shape. */
199
- function asFinding(d: ScanDiagnostic): Finding {
200
- return {
201
- severity: d.severity,
202
- code: d.code,
203
- filePath: d.filePath,
204
- subject: d.subject,
205
- message: d.message,
206
- };
186
+ /**
187
+ * A facade module older than the handlers it was read off.
188
+ *
189
+ * An ABSENT module needs no finding: a page importing one fails to resolve, loudly, and a
190
+ * backend project never imports one at all — warning there would fire on every project that
191
+ * does not want a facade, which is most of them.
192
+ *
193
+ * A STALE one is the silent case. The import resolves, the operations are the old ones, and a
194
+ * renamed op compiles against a name nothing serves any more. An mtime is the whole check.
195
+ */
196
+ function facadeFindings(root: string, fronds: readonly { handlers: readonly { filePath: string }[] }[]): Diagnostic[] {
197
+ const facade = join(root, dirname(DEFAULT_OUT), FACADE_OUT);
198
+ const written = statSync(facade, { throwIfNoEntry: false })?.mtimeMs;
199
+ if (written === undefined) return [];
200
+
201
+ const newer = fronds
202
+ .flatMap((frond) => frond.handlers)
203
+ .filter((handler) => (statSync(handler.filePath, { throwIfNoEntry: false })?.mtimeMs ?? 0) > written);
204
+
205
+ if (newer.length === 0) return [];
206
+
207
+ return [{
208
+ severity: 'warning',
209
+ code: 'facade-stale',
210
+ filePath: facade,
211
+ subject: `${newer.length} handler${newer.length > 1 ? 's' : ''}`,
212
+ message: 'The facade module is older than the handlers it was read off, so a page checks its '
213
+ + 'calls against operations that may no longer exist. Run `fougere build`.',
214
+ }];
207
215
  }
216
+