@fougere/app 0.12.0-alpha.0 → 0.12.1-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.
@@ -1 +1 @@
1
- {"version":3,"file":"Designation.d.ts","sourceRoot":"","sources":["../src/Designation.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Designation.d.ts","sourceRoot":"","sources":["../src/Designation.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
- import { FougereError, ErrorCode, lowerFirst, } from '@fougere/core/contract';
1
+ import { FougereError, ErrorCode, RPC_ENTITY, assertIdentityCard, decoded, lowerFirst, } from '@fougere/core/contract';
2
2
  import { frameCall, unframeResponse } from '@fougere/transport-http/client';
3
+ import { Card } from '@fougere/schema';
3
4
  /**
4
5
  * One facade, built from its address alone — what a project that never generated `@fronds/facade`
5
6
  * has, and what a test writes when it stands one up by hand.
@@ -42,13 +43,66 @@ export function invocationOf(input) {
42
43
  export function queryKeyOf(entityKey, op, input) {
43
44
  return `fougere:${entityKey}.${op}:${JSON.stringify(input ?? {})}`;
44
45
  }
45
- export async function sendCall(fetcher, call, invocation, endpoint = CALL_ENDPOINT) {
46
+ async function postCall(fetcher, call, invocation, endpoint) {
46
47
  const response = await fetcher(endpoint, {
47
48
  method: 'POST',
48
49
  body: frameCall(call, invocation, nextId++),
49
50
  });
50
51
  return unframeResponse(response, call);
51
52
  }
53
+ /**
54
+ * The schemas this browser reads a row back through, asked ONCE per endpoint.
55
+ *
56
+ * `date-time` means a `Date` on both sides, and a page held the string: three of this repo's own
57
+ * pages wrote `day(iso?: string)` and called `new Date(iso)` by hand, against the type their
58
+ * composable handed them. A server-side caller has the schema by construction — a browser has
59
+ * to ask for it, and the card already carries it (645 bytes for a seven-field entity).
60
+ *
61
+ * An app serving no card decodes nothing, which is what a page had before this existed.
62
+ */
63
+ const schemas = new Map();
64
+ /** A card read as the schemas it carries, indexed the way a call names its facade. */
65
+ function schemasIn(answer, endpoint) {
66
+ const found = new Map();
67
+ const card = assertIdentityCard(answer, `The app at ${endpoint}`);
68
+ for (const frond of card.fronds) {
69
+ for (const facade of frond.facades) {
70
+ if (facade.schema)
71
+ found.set(facade.name, Card.fromDescriptor(facade.schema).toSchema());
72
+ }
73
+ }
74
+ return found;
75
+ }
76
+ /**
77
+ * Learned from a card that went past on its own, so an app already asking for one — the admin
78
+ * panel asks before it draws a resource — pays for a single discovery rather than two.
79
+ */
80
+ function learn(answer, endpoint) {
81
+ try {
82
+ schemas.set(endpoint, Promise.resolve(schemasIn(answer, endpoint)));
83
+ }
84
+ catch { /* not a card: whatever else `rpc` answered */ }
85
+ }
86
+ function schemasOf(fetcher, endpoint) {
87
+ const asked = schemas.get(endpoint) ?? (async () => {
88
+ try {
89
+ return schemasIn(await postCall(fetcher, { entity: RPC_ENTITY, op: 'discover' }, invocationOf(), endpoint), endpoint);
90
+ }
91
+ catch { /* unreachable, or an app that publishes no card */ }
92
+ return new Map();
93
+ })();
94
+ schemas.set(endpoint, asked);
95
+ return asked;
96
+ }
97
+ export async function sendCall(fetcher, call, invocation, endpoint = CALL_ENDPOINT) {
98
+ const answer = await postCall(fetcher, call, invocation, endpoint);
99
+ if (call.entity === RPC_ENTITY) {
100
+ if (call.op === 'discover')
101
+ learn(answer, endpoint);
102
+ return answer;
103
+ }
104
+ return decoded((await schemasOf(fetcher, endpoint)).get(call.entity), answer);
105
+ }
52
106
  // ── The link ─────────────────────────────────────
53
107
  /** Mounted queries per entity — the command side of the link reads this. */
54
108
  const mounted = new Map();
@@ -1 +1 @@
1
- {"version":3,"file":"Designation.js","sourceRoot":"","sources":["../src/Designation.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Designation.js","sourceRoot":"","sources":["../src/Designation.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fougere/app",
3
- "version": "0.12.0-alpha.0",
3
+ "version": "0.12.1-alpha.0",
4
4
  "description": "The host-independent half of a Fougere app: boot, call envelope, REST table, form contract.",
5
5
  "keywords": [
6
6
  "fougere",
@@ -42,25 +42,25 @@
42
42
  ],
43
43
  "dependencies": {
44
44
  "jiti": "^2.6.1",
45
- "@fougere/schema": "0.12.0-alpha.0",
46
- "@fougere/core": "0.12.0-alpha.0",
47
- "@fougere/defaults": "0.12.0-alpha.0",
48
- "@fougere/container": "0.12.0-alpha.0",
49
- "@fougere/compiler": "0.12.0-alpha.0",
50
- "@fougere/transport-http": "0.12.0-alpha.0",
51
- "@fougere/http": "0.12.0-alpha.0",
52
- "@fougere/adapter-memory": "0.12.0-alpha.0",
53
- "@fougere/adapter-rest": "0.12.0-alpha.0"
45
+ "@fougere/core": "0.12.1-alpha.0",
46
+ "@fougere/adapter-rest": "0.12.1-alpha.0",
47
+ "@fougere/schema": "0.12.1-alpha.0",
48
+ "@fougere/defaults": "0.12.1-alpha.0",
49
+ "@fougere/http": "0.12.1-alpha.0",
50
+ "@fougere/transport-http": "0.12.1-alpha.0",
51
+ "@fougere/adapter-memory": "0.12.1-alpha.0",
52
+ "@fougere/compiler": "0.12.1-alpha.0",
53
+ "@fougere/container": "0.12.1-alpha.0"
54
54
  },
55
55
  "devDependencies": {
56
56
  "vitest": "^4.1.0",
57
- "@fougere/adapter-graphql": "0.12.0-alpha.0"
57
+ "@fougere/adapter-graphql": "0.12.1-alpha.0"
58
58
  },
59
59
  "publishConfig": {
60
60
  "access": "public"
61
61
  },
62
62
  "peerDependencies": {
63
- "@fougere/adapter-graphql": "^0.12.0-alpha.0"
63
+ "@fougere/adapter-graphql": "^0.12.1-alpha.0"
64
64
  },
65
65
  "peerDependenciesMeta": {
66
66
  "@fougere/adapter-graphql": {
@@ -1,6 +1,9 @@
1
1
  import {
2
2
  FougereError,
3
3
  ErrorCode,
4
+ RPC_ENTITY,
5
+ assertIdentityCard,
6
+ decoded,
4
7
  lowerFirst,
5
8
  type InvocationContext,
6
9
  type FrondCall,
@@ -13,6 +16,7 @@ import { frameCall, unframeResponse, type RpcResponse } from '@fougere/transport
13
16
  import type { EntityClass } from './EntityClass.js';
14
17
  import type { CallInput } from './CallInput.js';
15
18
  import type { Fetcher } from './Fetcher.js';
19
+ import { Card, type SchemaView, type SchemaDescriptor } from '@fougere/schema';
16
20
 
17
21
  /**
18
22
  * One facade, built from its address alone — what a project that never generated `@fronds/facade`
@@ -68,19 +72,83 @@ export function queryKeyOf(entityKey: string, op: string, input?: CallInput): st
68
72
  return `fougere:${entityKey}.${op}:${JSON.stringify(input ?? {})}`;
69
73
  }
70
74
 
71
- export async function sendCall(
75
+ async function postCall(
72
76
  fetcher: Fetcher,
73
77
  call: FrondCall,
74
78
  invocation: InvocationContext,
75
- endpoint: string = CALL_ENDPOINT,
79
+ endpoint: string,
76
80
  ): Promise<unknown> {
77
81
  const response = await fetcher<RpcResponse>(endpoint, {
78
82
  method: 'POST',
79
83
  body: frameCall(call, invocation, nextId++),
80
84
  });
85
+
81
86
  return unframeResponse(response, call);
82
87
  }
83
88
 
89
+ /**
90
+ * The schemas this browser reads a row back through, asked ONCE per endpoint.
91
+ *
92
+ * `date-time` means a `Date` on both sides, and a page held the string: three of this repo's own
93
+ * pages wrote `day(iso?: string)` and called `new Date(iso)` by hand, against the type their
94
+ * composable handed them. A server-side caller has the schema by construction — a browser has
95
+ * to ask for it, and the card already carries it (645 bytes for a seven-field entity).
96
+ *
97
+ * An app serving no card decodes nothing, which is what a page had before this existed.
98
+ */
99
+ const schemas = new Map<string, Promise<Map<string, SchemaView>>>();
100
+
101
+ /** A card read as the schemas it carries, indexed the way a call names its facade. */
102
+ function schemasIn(answer: unknown, endpoint: string): Map<string, SchemaView> {
103
+ const found = new Map<string, SchemaView>();
104
+ const card = assertIdentityCard(answer, `The app at ${endpoint}`);
105
+ for (const frond of card.fronds) {
106
+ for (const facade of frond.facades) {
107
+ if (facade.schema) found.set(facade.name, Card.fromDescriptor(facade.schema as SchemaDescriptor).toSchema());
108
+ }
109
+ }
110
+
111
+ return found;
112
+ }
113
+
114
+ /**
115
+ * Learned from a card that went past on its own, so an app already asking for one — the admin
116
+ * panel asks before it draws a resource — pays for a single discovery rather than two.
117
+ */
118
+ function learn(answer: unknown, endpoint: string): void {
119
+ try { schemas.set(endpoint, Promise.resolve(schemasIn(answer, endpoint))); }
120
+ catch { /* not a card: whatever else `rpc` answered */ }
121
+ }
122
+
123
+ function schemasOf(fetcher: Fetcher, endpoint: string): Promise<Map<string, SchemaView>> {
124
+ const asked = schemas.get(endpoint) ?? (async () => {
125
+ try {
126
+ return schemasIn(await postCall(fetcher, { entity: RPC_ENTITY, op: 'discover' }, invocationOf(), endpoint), endpoint);
127
+ } catch { /* unreachable, or an app that publishes no card */ }
128
+
129
+ return new Map<string, SchemaView>();
130
+ })();
131
+ schemas.set(endpoint, asked);
132
+
133
+ return asked;
134
+ }
135
+
136
+ export async function sendCall(
137
+ fetcher: Fetcher,
138
+ call: FrondCall,
139
+ invocation: InvocationContext,
140
+ endpoint: string = CALL_ENDPOINT,
141
+ ): Promise<unknown> {
142
+ const answer = await postCall(fetcher, call, invocation, endpoint);
143
+ if (call.entity === RPC_ENTITY) {
144
+ if (call.op === 'discover') learn(answer, endpoint);
145
+
146
+ return answer;
147
+ }
148
+
149
+ return decoded((await schemasOf(fetcher, endpoint)).get(call.entity), answer);
150
+ }
151
+
84
152
  // ── The link ─────────────────────────────────────
85
153
 
86
154
  /** Mounted queries per entity — the command side of the link reads this. */