@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.
- package/dist/Designation.d.ts.map +1 -1
- package/dist/Designation.js +56 -2
- package/dist/Designation.js.map +1 -1
- package/package.json +12 -12
- package/src/Designation.ts +70 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Designation.d.ts","sourceRoot":"","sources":["../src/Designation.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,
|
|
1
|
+
{"version":3,"file":"Designation.d.ts","sourceRoot":"","sources":["../src/Designation.ts"],"names":[],"mappings":"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"}
|
package/dist/Designation.js
CHANGED
|
@@ -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
|
-
|
|
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();
|
package/dist/Designation.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Designation.js","sourceRoot":"","sources":["../src/Designation.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,SAAS,EACT,UAAU,GAOX,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,SAAS,EAAE,eAAe,EAAoB,MAAM,gCAAgC,CAAC;
|
|
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.
|
|
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/
|
|
46
|
-
"@fougere/
|
|
47
|
-
"@fougere/
|
|
48
|
-
"@fougere/
|
|
49
|
-
"@fougere/
|
|
50
|
-
"@fougere/transport-http": "0.12.
|
|
51
|
-
"@fougere/
|
|
52
|
-
"@fougere/
|
|
53
|
-
"@fougere/
|
|
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.
|
|
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.
|
|
63
|
+
"@fougere/adapter-graphql": "^0.12.1-alpha.0"
|
|
64
64
|
},
|
|
65
65
|
"peerDependenciesMeta": {
|
|
66
66
|
"@fougere/adapter-graphql": {
|
package/src/Designation.ts
CHANGED
|
@@ -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
|
-
|
|
75
|
+
async function postCall(
|
|
72
76
|
fetcher: Fetcher,
|
|
73
77
|
call: FrondCall,
|
|
74
78
|
invocation: InvocationContext,
|
|
75
|
-
endpoint: string
|
|
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. */
|