@fougere/core 0.19.0-alpha.0 → 0.20.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 (65) hide show
  1. package/dist/EffectiveOperationModel.js +3 -6
  2. package/dist/EffectiveOperationModel.js.map +1 -1
  3. package/dist/EffectiveOperationOptions.d.ts +1 -1
  4. package/dist/EffectiveOperationOptions.d.ts.map +1 -1
  5. package/dist/FougereConfig.d.ts +10 -16
  6. package/dist/FougereConfig.d.ts.map +1 -1
  7. package/dist/FougereConfig.js.map +1 -1
  8. package/dist/FougereProtocols.d.ts +9 -0
  9. package/dist/FougereProtocols.d.ts.map +1 -0
  10. package/dist/FougereProtocols.js +2 -0
  11. package/dist/FougereProtocols.js.map +1 -0
  12. package/dist/FougereSources.d.ts +9 -0
  13. package/dist/FougereSources.d.ts.map +1 -0
  14. package/dist/FougereSources.js +2 -0
  15. package/dist/FougereSources.js.map +1 -0
  16. package/dist/Protocol.d.ts +18 -0
  17. package/dist/Protocol.d.ts.map +1 -0
  18. package/dist/Protocol.js +11 -0
  19. package/dist/Protocol.js.map +1 -0
  20. package/dist/Source.d.ts +17 -6
  21. package/dist/Source.d.ts.map +1 -1
  22. package/dist/Source.js +23 -6
  23. package/dist/Source.js.map +1 -1
  24. package/dist/SourceConfig.d.ts +6 -8
  25. package/dist/SourceConfig.d.ts.map +1 -1
  26. package/dist/boot/App.d.ts +3 -2
  27. package/dist/boot/App.d.ts.map +1 -1
  28. package/dist/boot/CreateAppOptions.d.ts +3 -2
  29. package/dist/boot/CreateAppOptions.d.ts.map +1 -1
  30. package/dist/boot/bootstrap.d.ts.map +1 -1
  31. package/dist/boot/bootstrap.js +4 -3
  32. package/dist/boot/bootstrap.js.map +1 -1
  33. package/dist/boot/install.js +1 -1
  34. package/dist/boot/install.js.map +1 -1
  35. package/dist/boot/protocols.d.ts +4 -0
  36. package/dist/boot/protocols.d.ts.map +1 -0
  37. package/dist/boot/protocols.js +13 -0
  38. package/dist/boot/protocols.js.map +1 -0
  39. package/dist/boot/together.js +2 -2
  40. package/dist/boot/together.js.map +1 -1
  41. package/dist/index.d.ts +4 -2
  42. package/dist/index.d.ts.map +1 -1
  43. package/dist/index.js +1 -0
  44. package/dist/index.js.map +1 -1
  45. package/package.json +3 -3
  46. package/src/EffectiveOperationModel.ts +3 -6
  47. package/src/EffectiveOperationOptions.ts +1 -1
  48. package/src/FougereConfig.ts +10 -9
  49. package/src/FougereProtocols.ts +8 -0
  50. package/src/FougereSources.ts +8 -0
  51. package/src/Protocol.ts +24 -0
  52. package/src/Source.ts +34 -9
  53. package/src/SourceConfig.ts +6 -8
  54. package/src/boot/App.ts +3 -2
  55. package/src/boot/CreateAppOptions.ts +3 -2
  56. package/src/boot/bootstrap.ts +4 -3
  57. package/src/boot/install.ts +1 -1
  58. package/src/boot/protocols.ts +13 -0
  59. package/src/boot/together.ts +2 -2
  60. package/src/index.ts +4 -2
  61. package/dist/AdapterConfig.d.ts +0 -10
  62. package/dist/AdapterConfig.d.ts.map +0 -1
  63. package/dist/AdapterConfig.js +0 -3
  64. package/dist/AdapterConfig.js.map +0 -1
  65. package/src/AdapterConfig.ts +0 -11
@@ -1,10 +1,8 @@
1
+ import type { FougereSources } from './FougereSources.js';
1
2
  import type { NameOf } from './NameOf.js';
2
3
 
3
- /** What a config file can carry about a source — values, never a live driver. */
4
- export interface SourceConfig {
5
- /** The adapter that realizes it. Absent means the conventional one. */
6
- source?: NameOf<'source'>;
7
- /** The entities whose rows live here. Absent on the default source: it holds the rest. */
8
- entities?: string[];
9
- [key: string]: unknown;
10
- }
4
+ /** One entry of `sources:` — what its type admits, and the entities whose rows live there. */
5
+ export type SourceConfig = FougereSources[keyof FougereSources] & {
6
+ /** Absent on the default source: it holds the rest. */
7
+ entities?: NameOf<'entity'>[];
8
+ };
package/src/boot/App.ts CHANGED
@@ -7,6 +7,7 @@ import type { EffectiveOperationsMap } from '../EffectiveOperationsMap.js';
7
7
  import type { DispatchObserver } from '../dispatch/DispatchObserver.js';
8
8
  import type { DispatchPort } from '../dispatch/DispatchPort.js';
9
9
  import type { Storage } from '../storage/Storage.js';
10
+ import type { ProtocolConfig } from '../Protocol.js';
10
11
 
11
12
  /** The App object returned by createApp(). */
12
13
  export interface App extends DispatchPort {
@@ -14,8 +15,8 @@ export interface App extends DispatchPort {
14
15
  local: DispatchPort;
15
16
  /** Root container with builtins + frond scopes. */
16
17
  container: Container;
17
- /** Which protocol adapters this app declared, from `fougere.config.ts`. */
18
- adapters: Record<string, boolean | undefined>;
18
+ /** The protocols this app serves, from `fougere.config.ts`. */
19
+ protocols: ProtocolConfig;
19
20
  /** Where a call goes, as the config declared it — frond name to address. */
20
21
  remotes: Readonly<Record<string, string>>;
21
22
  /** Discovered fronds metadata. */
@@ -1,4 +1,5 @@
1
1
  import type { Container } from '@fougere/container';
2
+ import type { ProtocolConfig } from '../Protocol.js';
2
3
  import type { FrondDescriptor } from '../descriptor/FrondDescriptor.js';
3
4
  import type { FrondsStated } from '../FrondsStated.js';
4
5
  import type { ScanResult } from '../scan.js';
@@ -75,8 +76,8 @@ export interface CreateAppOptions {
75
76
  * here — a storage connection is the one case today.
76
77
  */
77
78
  onDispose?: () => Promise<void> | void;
78
- /** Which protocol adapters this app serves — see `FougereConfig.adapters`. */
79
- adapters?: Record<string, boolean | undefined>;
79
+ /** The protocols this app serves — see `FougereConfig.protocols`. */
80
+ protocols?: ProtocolConfig;
80
81
  /** Carries an announced fact out of this process — a broker, a queue, a log. */
81
82
  onEmit?: (fact: string, payload: unknown) => void | Promise<void>;
82
83
  }
@@ -1,4 +1,5 @@
1
1
  import { createContainer, type Container } from '@fougere/container';
2
+ import { servedProtocols } from './protocols.js';
2
3
  import { unregistered } from './unregistered.js';
3
4
  import { lowerFirst, type SchemaView } from '@fougere/schema';
4
5
 
@@ -151,7 +152,7 @@ async function readFronds(
151
152
  const operationModel = resolveEffectiveOperations(ordered, {
152
153
  diagnostics,
153
154
  remotes: options.remotes,
154
- adapters: options.adapters,
155
+ protocols: servedProtocols(options.protocols),
155
156
  });
156
157
  const scanMs = (performance.now() - scanStart).toFixed(0);
157
158
  log.info(`read ${ordered.length} frond(s) in ${scanMs}ms`
@@ -382,7 +383,7 @@ function hostingFor(
382
383
 
383
384
  const hosting: Hosting = {
384
385
  hostedHere: (entity) => !(options.remotes && (frondOf.get(entity) ?? '') in options.remotes),
385
- sourceOf: (name) => options.sourceOf?.(name) ?? 'db',
386
+ sourceOf: (name) => options.sourceOf?.(name) ?? 'default',
386
387
  enforces: (source, constraint) => options.enforces?.(source, constraint) ?? false,
387
388
  storageOf,
388
389
  entities: () => entityByName,
@@ -725,7 +726,7 @@ export async function createApp(options: CreateAppOptions): Promise<App> {
725
726
  const app: App = {
726
727
  container,
727
728
  fronds,
728
- adapters: options.adapters ?? {},
729
+ protocols: options.protocols ?? {},
729
730
  // As DECLARED, beside what the runtime observes — the two disagree exactly when something is misconfigured.
730
731
  remotes: Object.freeze({ ...options.remotes }),
731
732
  dispatch: (call) => dispatcher.dispatch(call),
@@ -212,7 +212,7 @@ function registerStorages(
212
212
  const release = releasing(assembly.hosting);
213
213
  for (const entity of frond.entities) {
214
214
  const key = storageKeyOf(entity.name);
215
- const source = options.sourceOf?.(entity.name) ?? 'db';
215
+ const source = options.sourceOf?.(entity.name) ?? 'default';
216
216
  if (declares(entity.entityClass, 'unique') && options.enforces?.(source, 'unique') === false) {
217
217
  unenforced.push(`${entity.name} in '${source}'`);
218
218
  }
@@ -0,0 +1,13 @@
1
+ import { JsonSchemaValidator, SchemaError, dotted, type JsonSchema } from '@fougere/schema';
2
+ import { Protocols, type ProtocolConfig } from '../Protocol.js';
3
+
4
+ /** Each protocol named in `protocols:` — served by an imported adapter, and judged by its format. */
5
+ export function servedProtocols(protocols: ProtocolConfig | undefined): ProtocolConfig {
6
+ for (const [name, options] of Object.entries(protocols ?? {})) {
7
+ const type = Protocols.resolve(name, `protocols.${name}`);
8
+ const refusal = JsonSchemaValidator.of(type.format.schema as JsonSchema).refusalOf(options, [`protocols.${name}`]);
9
+ if (refusal) throw new SchemaError(`${dotted(refusal.path)}: ${refusal.message}`);
10
+ }
11
+
12
+ return protocols ?? {};
13
+ }
@@ -225,7 +225,7 @@ export function registerFrames(
225
225
  * compensate a frame whose own engine holds transactions.
226
226
  */
227
227
  function frameOver(key: string, members: Members, scope: Container, world: FrameWorld): Frame {
228
- const sources = new Set(members.entities.map((member) => world.sourceOf?.(member.name) ?? 'db'));
228
+ const sources = new Set(members.entities.map((member) => world.sourceOf?.(member.name) ?? 'default'));
229
229
  const validator = (storage: Storage, name: string, schema: SchemaView) =>
230
230
  new StorageGuard(schema.getFields(), name, {}, heldBy(schema, name, world.hosting), releasing(world.hosting)).guard(storage);
231
231
 
@@ -244,7 +244,7 @@ function frameOver(key: string, members: Members, scope: Container, world: Frame
244
244
  // write and replays the inverses itself. `validator` stays OUTSIDE `recording`, so a write the
245
245
  // entity refuses never enters the journal.
246
246
  const why = sources.size > 1
247
- ? members.entities.map((one) => `${one.name} in '${world.sourceOf?.(one.name) ?? 'db'}'`).join(', ')
247
+ ? members.entities.map((one) => `${one.name} in '${world.sourceOf?.(one.name) ?? 'default'}'`).join(', ')
248
248
  : 'this storage hands out no transaction';
249
249
  world.log.info(`${key} — compensated: ${why} — no isolation`);
250
250
 
package/src/index.ts CHANGED
@@ -4,7 +4,8 @@ export { orderSeeds, runSeeds, seeding } from './boot/seed.js';
4
4
  export { AppLifecycle, checking, migrating } from './boot/AppLifecycle.js';
5
5
  export type { Extension } from './boot/Extension.js';
6
6
  export { defineFougere } from './define.js';
7
- export type { AdapterConfig } from './AdapterConfig.js';
7
+ export { Protocols, serves, type ProtocolConfig, type ProtocolType } from './Protocol.js';
8
+ export type { FougereProtocols } from './FougereProtocols.js';
8
9
  export type { FougereConfig } from './FougereConfig.js';
9
10
  export { statesModule, type FrondsStated, type FrondStated } from './FrondsStated.js';
10
11
  export { statedFronds, type StatedFrond } from './StatedFrond.js';
@@ -133,7 +134,8 @@ export type { Constraint } from './Constraint.js';
133
134
  export type { Source } from './Source.js';
134
135
  export type { SourceConfig } from './SourceConfig.js';
135
136
  export { sourceViewOf, type SourceView } from './SourceView.js';
136
- export { Sources } from './Source.js';
137
+ export { Sources, type SourceType } from './Source.js';
138
+ export type { FougereSources } from './FougereSources.js';
137
139
  export { storageOver } from './storage/Store.js';
138
140
  export type { Store } from './storage/Store.js';
139
141
  export type { Values } from './storage/Values.js';
@@ -1,10 +0,0 @@
1
- /** Protocol adapters, by the name of the package that provides them. */
2
- export interface AdapterConfig {
3
- /** `@fougere/adapter-rest` — REST under `/api/{frond}/{plural}`. */
4
- rest?: boolean;
5
- /** `@fougere/adapter-graphql` — a GraphQL schema over the same operations. */
6
- graphql?: boolean;
7
- /** A surface of your own; the framework only records that you declared it. */
8
- [adapter: string]: boolean | undefined;
9
- }
10
- //# sourceMappingURL=AdapterConfig.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AdapterConfig.d.ts","sourceRoot":"","sources":["../src/AdapterConfig.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,MAAM,WAAW,aAAa;IAC5B,oEAAoE;IACpE,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,8EAA8E;IAC9E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,8EAA8E;IAC9E,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;CACxC"}
@@ -1,3 +0,0 @@
1
- export {};
2
- // ── Loading ──────────────────────────────────────
3
- //# sourceMappingURL=AdapterConfig.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AdapterConfig.js","sourceRoot":"","sources":["../src/AdapterConfig.ts"],"names":[],"mappings":";AAUA,oDAAoD"}
@@ -1,11 +0,0 @@
1
- /** Protocol adapters, by the name of the package that provides them. */
2
- export interface AdapterConfig {
3
- /** `@fougere/adapter-rest` — REST under `/api/{frond}/{plural}`. */
4
- rest?: boolean;
5
- /** `@fougere/adapter-graphql` — a GraphQL schema over the same operations. */
6
- graphql?: boolean;
7
- /** A surface of your own; the framework only records that you declared it. */
8
- [adapter: string]: boolean | undefined;
9
- }
10
-
11
- // ── Loading ──────────────────────────────────────