@fougere/defaults 0.19.1-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.
package/README.md CHANGED
@@ -1,7 +1,8 @@
1
1
  # @fougere/defaults
2
2
  > The conventional boot
3
- `bootApp()` and `resolveStorage()` — **the single** place that names a storage
4
- package. Changing engine is a change here, and nowhere else.
3
+ `bootApp()` and `resolveStorage()` — **the single** place that reads `sources:`. It names no
4
+ engine: the config imports the adapters it uses, and memory, the fallback for an app that
5
+ declares no source, is the only one it brings.
5
6
 
6
7
  ## Installation
7
8
  ```bash
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@ import { type App, type CreateAppOptions } from '@fougere/core';
3
3
  export { remoteTransport } from './transport/RemoteTransport.js';
4
4
  export { declaresStorage } from './storage/DeclaredStorage.js';
5
5
  export { layerOf, resolveStorage, storageFrom } from './storage/ResolvedStorage.js';
6
- export type { DbConfig } from './storage/DbConfig.js';
6
+ export type { SourceEntities } from './storage/SourceEntities.js';
7
7
  export type { ResolvedStorage } from './storage/ResolvedStorage.js';
8
8
  export interface BootAppOptions {
9
9
  /** Boot only these fronds, by name. Absent = every discovered frond. */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,gEAAgE;AAChE,OAAO,EAAa,KAAK,GAAG,EAAE,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAO3E,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AACpF,YAAY,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACtD,YAAY,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAEpE,MAAM,WAAW,cAAc;IAC7B,wEAAwE;IACxE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,gDAAgD;IAChD,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB;;;OAGG;IACH,UAAU,CAAC,EAAE,gBAAgB,CAAC,YAAY,CAAC,CAAC;IAC5C;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,cAAmB,GAAG,OAAO,CAAC,GAAG,CAAC,CAmBnF"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,gEAAgE;AAChE,OAAO,EAAa,KAAK,GAAG,EAAE,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAM3E,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AACpF,YAAY,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAClE,YAAY,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAEpE,MAAM,WAAW,cAAc;IAC7B,wEAAwE;IACxE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,gDAAgD;IAChD,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB;;;OAGG;IACH,UAAU,CAAC,EAAE,gBAAgB,CAAC,YAAY,CAAC,CAAC;IAC5C;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,cAAmB,GAAG,OAAO,CAAC,GAAG,CAAC,CAmBnF"}
package/dist/index.js CHANGED
@@ -25,8 +25,8 @@ export async function bootApp(root, opts = {}) {
25
25
  // `{}` and never undefined: `boot` reads the config's own `fronds:` when handed nothing.
26
26
  remotes: useRemotes ? elsewhere : {},
27
27
  remoteTransport: useRemotes ? await remoteTransport() : undefined,
28
- // One resolver, one place that knows a storage package.
29
- db: (cfg) => (storage = resolveStorage(cfg.db, cfg.sources, root)),
28
+ // One resolver, one place that reads `sources:`.
29
+ storage: (cfg) => (storage = resolveStorage(cfg.sources, root)),
30
30
  extensions: [...(opts.migrates ? [migrating((app) => storage?.migrate?.(app))] : []), ...(opts.extensions ?? [])],
31
31
  });
32
32
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,gEAAgE;AAChE,OAAO,EAAE,SAAS,EAAmC,MAAM,eAAe,CAAC;AAC3E,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE3D,OAAO,EAAE,cAAc,EAAwB,MAAM,8BAA8B,CAAC;AACpF,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAEjE,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAsBpF;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAY,EAAE,IAAI,GAAmB,EAAE;IACnE,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,CAAC;IACtC,2FAA2F;IAC3F,sFAAsF;IACtF,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;IACvD,MAAM,SAAS,GAAG,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAChH,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;IACrD,IAAI,OAAoC,CAAC;IAEzC,OAAO,IAAI,CAAC;QACV,IAAI;QACJ,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM;QAC9B,yFAAyF;QACzF,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE;QACpC,eAAe,EAAE,UAAU,CAAC,CAAC,CAAC,MAAM,eAAe,EAAE,CAAC,CAAC,CAAC,SAAS;QACjE,wDAAwD;QACxD,EAAE,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,OAAO,GAAG,cAAc,CAAC,GAAG,CAAC,EAAc,EAAG,GAA6B,CAAC,OAAgB,EAAE,IAAI,CAAC,CAAC;QAClH,UAAU,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC;KAClH,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,gEAAgE;AAChE,OAAO,EAAE,SAAS,EAAmC,MAAM,eAAe,CAAC;AAC3E,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAwB,MAAM,8BAA8B,CAAC;AACpF,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAEjE,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAsBpF;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAY,EAAE,IAAI,GAAmB,EAAE;IACnE,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,CAAC;IACtC,2FAA2F;IAC3F,sFAAsF;IACtF,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;IACvD,MAAM,SAAS,GAAG,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAChH,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;IACrD,IAAI,OAAoC,CAAC;IAEzC,OAAO,IAAI,CAAC;QACV,IAAI;QACJ,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM;QAC9B,yFAAyF;QACzF,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE;QACpC,eAAe,EAAE,UAAU,CAAC,CAAC,CAAC,MAAM,eAAe,EAAE,CAAC,CAAC,CAAC,SAAS;QACjE,iDAAiD;QACjD,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,OAAO,GAAG,cAAc,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QAC/D,UAAU,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC;KAClH,CAAC,CAAC;AACL,CAAC"}
@@ -1,12 +1,4 @@
1
- import { type Source } from '@fougere/core';
2
- import type { DbConfig } from './DbConfig.js';
3
- import type { SourceEntities } from './SourceEntities.js';
1
+ import type { SourceConfig } from '@fougere/core';
4
2
  /** Does this config ask for persistence at all? */
5
- export declare function declaresStorage(dbConf: DbConfig): boolean;
6
- export interface DeclaredStorage {
7
- /** The default source — where an entity no placement names lands. */
8
- db: Source;
9
- /** The other places. Absent means one source, the way it always was. */
10
- sources?: Record<string, SourceEntities>;
11
- }
3
+ export declare function declaresStorage(sources: Record<string, SourceConfig> | undefined): boolean;
12
4
  //# sourceMappingURL=DeclaredStorage.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"DeclaredStorage.d.ts","sourceRoot":"","sources":["../../src/storage/DeclaredStorage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,mDAAmD;AACnD,wBAAgB,eAAe,CAAC,MAAM,EAAE,QAAQ,GAAG,OAAO,CAIzD;AAED,MAAM,WAAW,eAAe;IAC9B,qEAAqE;IACrE,EAAE,EAAE,MAAM,CAAC;IACX,wEAAwE;IACxE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;CAC1C"}
1
+ {"version":3,"file":"DeclaredStorage.d.ts","sourceRoot":"","sources":["../../src/storage/DeclaredStorage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,mDAAmD;AACnD,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,GAAG,SAAS,GAAG,OAAO,CAE1F"}
@@ -1,7 +1,5 @@
1
1
  /** Does this config ask for persistence at all? */
2
- export function declaresStorage(dbConf) {
3
- if (dbConf === false || dbConf === undefined)
4
- return false;
5
- return true;
2
+ export function declaresStorage(sources) {
3
+ return Object.keys(sources ?? {}).length > 0;
6
4
  }
7
5
  //# sourceMappingURL=DeclaredStorage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DeclaredStorage.js","sourceRoot":"","sources":["../../src/storage/DeclaredStorage.ts"],"names":[],"mappings":"AAIA,mDAAmD;AACnD,MAAM,UAAU,eAAe,CAAC,MAAgB;IAC9C,IAAI,MAAM,KAAK,KAAK,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IAE3D,OAAO,IAAI,CAAC;AACd,CAAC"}
1
+ {"version":3,"file":"DeclaredStorage.js","sourceRoot":"","sources":["../../src/storage/DeclaredStorage.ts"],"names":[],"mappings":"AAEA,mDAAmD;AACnD,MAAM,UAAU,eAAe,CAAC,OAAiD;IAC/E,OAAO,MAAM,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;AAC/C,CAAC"}
@@ -1,12 +1,7 @@
1
- import '@fougere/adapter-sql/sqlite';
2
1
  import type { App } from '@fougere/core';
3
- import { type Constraint } from '@fougere/core';
4
- import type { DbConfig } from './DbConfig.js';
5
- import type { SourcesConfig } from './SourcesConfig.js';
6
- import type { DeclaredStorage } from './DeclaredStorage.js';
2
+ import { type Constraint, type SourceConfig } from '@fougere/core';
3
+ import type { SourceEntities } from './SourceEntities.js';
7
4
  export interface ResolvedStorage {
8
- /** The default source's engine handle — what `fougere migrate` reads the live tables through. */
9
- db?: unknown;
10
5
  storageFactory: ((entity: any, name: string) => any) | undefined;
11
6
  /**
12
7
  * The source an entity's rows live in — what decides whether a frame gets a real transaction or
@@ -36,8 +31,11 @@ export interface ResolvedStorage {
36
31
  /** Close every engine this opened — the dual of opening them, declared by whoever did. */
37
32
  close?: () => Promise<void>;
38
33
  }
39
- /** Resolve the data layer. */
40
- export declare function resolveStorage(dbConf: DbConfig, sources?: SourcesConfig,
34
+ /**
35
+ * Resolve the data layer from `sources:`. The one entry listing no entities holds the rest; none
36
+ * at all keeps the rows in memory, and saying so is the whole fallback.
37
+ */
38
+ export declare function resolveStorage(sources: Record<string, SourceConfig> | undefined,
41
39
  /**
42
40
  * Where a relative `path:` is counted from — the directory of the config that named it.
43
41
  *
@@ -49,7 +47,7 @@ export declare function resolveStorage(dbConf: DbConfig, sources?: SourcesConfig
49
47
  */
50
48
  root?: string): ResolvedStorage;
51
49
  /** The same routing `resolveStorage` performs, over engines the CALLER built. */
52
- export declare function storageFrom(declared: DeclaredStorage): ResolvedStorage;
50
+ export declare function storageFrom(sources: Record<string, SourceEntities>): ResolvedStorage;
53
51
  /**
54
52
  * The data layer as `createApp` takes it — one gesture, not eight named by hand.
55
53
  *
@@ -1 +1 @@
1
- {"version":3,"file":"ResolvedStorage.d.ts","sourceRoot":"","sources":["../../src/storage/ResolvedStorage.ts"],"names":[],"mappings":"AAAA,OAAO,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AAIzC,OAAO,EAAiC,KAAK,UAAU,EAAe,MAAM,eAAe,CAAC;AAG5F,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE5D,MAAM,WAAW,eAAe;IAC9B,iGAAiG;IACjG,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,GAAG,CAAC,GAAG,SAAS,CAAC;IACjE;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,MAAM,CAAC;IAC1C;;;OAGG;IACH,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;IACnC,8DAA8D;IAC9D,OAAO,CAAC,EAAE,MAAM,MAAM,EAAE,CAAC;IACzB,mFAAmF;IACnF,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;IACxC,kGAAkG;IAClG,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,KAAK,OAAO,CAAC;IAC/D,0FAA0F;IAC1F,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,cAAc,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,GAAG,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IACvH;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC/C,0FAA0F;IAC1F,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC1C,0FAA0F;IAC1F,KAAK,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAE7B;AAED,8BAA8B;AAC9B,wBAAgB,cAAc,CAC5B,MAAM,EAAE,QAAQ,EAChB,OAAO,CAAC,EAAE,aAAa;AACvB;;;;;;;;GAQG;AACH,IAAI,CAAC,EAAE,MAAM,GACZ,eAAe,CAgBjB;AAoCD,iFAAiF;AACjF,wBAAgB,WAAW,CAAC,QAAQ,EAAE,eAAe,GAAG,eAAe,CAqFtE;AAED;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,OAAO,EAAE,eAAe;IAE5C,cAAc,YAlMU,GAAG,QAAQ,MAAM,KAAK,GAAG;IAmMjD,QAAQ,gBA9Lc,MAAM,KAAK,MAAM;IA+LvC,SAAS,YAtLU,MAAM,KAAK,OAAO;IAuLrC,QAAQ,YArLU,MAAM,cAAc,UAAU,KAAK,OAAO;IAsL5D,UAAU,EAAwB,KAAK;IACvC,OAAO,SA9KO,GAAG,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC;EAgL1C"}
1
+ {"version":3,"file":"ResolvedStorage.d.ts","sourceRoot":"","sources":["../../src/storage/ResolvedStorage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AAIzC,OAAO,EAAiC,KAAK,UAAU,EAAe,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAE/G,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,MAAM,WAAW,eAAe;IAC9B,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,GAAG,CAAC,GAAG,SAAS,CAAC;IACjE;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,MAAM,CAAC;IAC1C;;;OAGG;IACH,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;IACnC,8DAA8D;IAC9D,OAAO,CAAC,EAAE,MAAM,MAAM,EAAE,CAAC;IACzB,mFAAmF;IACnF,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;IACxC,kGAAkG;IAClG,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,KAAK,OAAO,CAAC;IAC/D,0FAA0F;IAC1F,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,cAAc,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,GAAG,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IACvH;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC/C,0FAA0F;IAC1F,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC1C,0FAA0F;IAC1F,KAAK,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAE7B;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,GAAG,SAAS;AACjD;;;;;;;;GAQG;AACH,IAAI,CAAC,EAAE,MAAM,GACZ,eAAe,CAQjB;AA8CD,iFAAiF;AACjF,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,GAAG,eAAe,CAmFpF;AAED;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,OAAO,EAAE,eAAe;IAE5C,cAAc,YApMU,GAAG,QAAQ,MAAM,KAAK,GAAG;IAqMjD,QAAQ,gBAhMc,MAAM,KAAK,MAAM;IAiMvC,SAAS,YAxLU,MAAM,KAAK,OAAO;IAyLrC,QAAQ,YAvLU,MAAM,cAAc,UAAU,KAAK,OAAO;IAwL5D,UAAU,EAAwB,KAAK;IACvC,OAAO,SAhLO,GAAG,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC;EAkL1C"}
@@ -1,12 +1,13 @@
1
- import '@fougere/adapter-sql/sqlite';
2
1
  import { lowerFirst } from '@fougere/core/contract';
3
2
  import { existsSync } from 'node:fs';
4
3
  import { isAbsolute, resolve } from 'node:path';
5
4
  import { Logger, Sources, sourceViewOf } from '@fougere/core';
6
5
  import { createMemorySource } from '@fougere/adapter-memory';
7
- import { declaresStorage } from './DeclaredStorage.js';
8
- /** Resolve the data layer. */
9
- export function resolveStorage(dbConf, sources,
6
+ /**
7
+ * Resolve the data layer from `sources:`. The one entry listing no entities holds the rest; none
8
+ * at all keeps the rows in memory, and saying so is the whole fallback.
9
+ */
10
+ export function resolveStorage(sources,
10
11
  /**
11
12
  * Where a relative `path:` is counted from — the directory of the config that named it.
12
13
  *
@@ -17,33 +18,21 @@ export function resolveStorage(dbConf, sources,
17
18
  * seeds ran, and the app served an empty domain with a green boot.
18
19
  */
19
20
  root) {
20
- if (!declaresStorage(dbConf)) {
21
- new Logger('storage').warn('no `db:` declared — rows live in memory and are gone when the process exits');
22
- return storageFrom({ db: createMemorySource() });
23
- }
24
- const named = {};
25
- for (const [name, conf] of Object.entries(sources ?? {})) {
26
- named[name] = { source: built(conf, `sources.${name}`, root), entities: conf.entities };
27
- }
28
- return storageFrom({
29
- db: built(typeof dbConf === 'object' ? dbConf : {}, 'db', root),
30
- sources: named,
31
- });
32
- }
33
- /** One config entry, resolved to the adapter it names. */
34
- function built(conf, field, root) {
35
- const name = conf.source ?? DEFAULT_ADAPTER;
36
- return Sources.open(name, anchored(conf, root), `${field}.source`);
21
+ const opened = Object.fromEntries(Object.entries(sources ?? {}).map(([name, entry]) => {
22
+ const { entities, ...rest } = entry;
23
+ return [name, { source: Sources.open(anchored(rest, root), `sources.${name}`), entities }];
24
+ }));
25
+ return storageFrom(opened);
37
26
  }
38
27
  /**
39
28
  * A relative path, counted from the config that named it. `:memory:` names no file and an
40
29
  * absolute path already says where it is — both pass through untouched, which is what
41
30
  * keeps this from being a second reader of what a path means.
42
31
  */
43
- function anchored(conf, root) {
44
- const path = conf.path;
32
+ function anchored(entry, root) {
33
+ const path = entry.path;
45
34
  if (!root || typeof path !== 'string' || path === ':memory:' || isAbsolute(path))
46
- return conf;
35
+ return entry;
47
36
  const anchoredPath = resolve(root, path);
48
37
  // Anchoring MOVES a database that a deployment has been running against, and the driver
49
38
  // would create the new one without a word: additive migration, seeds, an empty domain
@@ -53,19 +42,33 @@ function anchored(conf, root) {
53
42
  process.emitWarning(`${path} resolves to ${anchoredPath} beside the config that named it, and a database `
54
43
  + `already sits at ${beside}. Fougere opens the first; move the file, or write the path you mean.`);
55
44
  }
56
- return { ...conf, path: anchoredPath };
45
+ return { ...entry, path: anchoredPath };
46
+ }
47
+ /** Where an entity no source names lives, and what it is called — the one entry listing none. */
48
+ function defaultOf(sources) {
49
+ const unlisted = Object.entries(sources).filter(([, placement]) => placement.entities === undefined);
50
+ if (unlisted.length > 1) {
51
+ throw new Error(`sources: ${unlisted.map(([name]) => `'${name}'`).join(' and ')} list no entities, and nothing says which `
52
+ + 'one holds the rest. Give all but one of them their entities.');
53
+ }
54
+ if (unlisted.length === 1)
55
+ return [unlisted[0][0], unlisted[0][1].source];
56
+ new Logger('storage').warn(Object.keys(sources).length === 0
57
+ ? 'no `sources:` declared — rows live in memory and are gone when the process exits'
58
+ : 'no source lists no entities — the rows of every entity no source names live in memory and are gone when the process exits');
59
+ return ['memory', createMemorySource()];
57
60
  }
58
- /** What a config naming no adapter means. */
59
- const DEFAULT_ADAPTER = 'sql';
60
61
  /** The same routing `resolveStorage` performs, over engines the CALLER built. */
61
- export function storageFrom(declared) {
62
- const { db: base, sources } = declared;
62
+ export function storageFrom(sources) {
63
+ const [DEFAULT, base] = defaultOf(sources);
63
64
  // Where each named entity lives. An entity claimed by two sources is refused naming
64
65
  // both: the rows would be read from one and written to the other, by whichever
65
66
  // registration ran last — the same silent duplicate `remotes:` refuses one level up.
66
67
  const home = new Map();
67
68
  const engines = new Map();
68
- for (const [name, placement] of Object.entries(sources ?? {})) {
69
+ for (const [name, placement] of Object.entries(sources)) {
70
+ if (placement.entities === undefined)
71
+ continue;
69
72
  engines.set(name, placement.source);
70
73
  for (const entity of placement.entities) {
71
74
  const key = lowerFirst(entity);
@@ -78,7 +81,6 @@ export function storageFrom(declared) {
78
81
  }
79
82
  // The default source answers to the name the config gave it, so a refusal naming two
80
83
  // sources names things the author can find in their own file.
81
- const DEFAULT = 'db';
82
84
  const sourceOf = (entityName) => home.get(lowerFirst(entityName)) ?? DEFAULT;
83
85
  const engineOf = (source) => (source === DEFAULT ? base : engines.get(source));
84
86
  const engineFor = (entityName) => {
@@ -86,15 +88,13 @@ export function storageFrom(declared) {
86
88
  return (source && engines.get(source)) || base;
87
89
  };
88
90
  return {
89
- // Opaque, and narrowed by whoever needs it — auth wants a handle, the CLI wants Kysely.
90
- db: base.db,
91
91
  storageFactory: (entity, name) => engineFor(name).storageFactory(entity, name),
92
92
  sourceOf,
93
93
  dbOf: (source) => engineOf(source)?.db,
94
94
  sources: () => [DEFAULT, ...engines.keys()],
95
95
  // Asked of the source that will run the work, never of the default one: a frame whose
96
- // members all live in a transactional source gets its transaction even when `db:` has
97
- // none. A source that hands out none leaves the answer `false`, and a frame reads it:
96
+ // members all live in a transactional source gets its transaction even when the default
97
+ // source has none. A source that hands out none leaves the answer `false`, and a frame reads it:
98
98
  // `boot/together.ts` compensates instead, and says which of the two it built.
99
99
  transacts: (source) => engineOf(source)?.transacted !== undefined,
100
100
  // Absent means the judge is alone with it: a source that keeps no constraint of its own
@@ -1 +1 @@
1
- {"version":3,"file":"ResolvedStorage.js","sourceRoot":"","sources":["../../src/storage/ResolvedStorage.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ResolvedStorage.js","sourceRoot":"","sources":["../../src/storage/ResolvedStorage.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { type Source } from '@fougere/core';
2
- /** One source: what realizes it, and the entities that live there. */
2
+ /** One source: what realizes it, and the entities that live there — none listed on the default one. */
3
3
  export interface SourceEntities {
4
4
  source: Source;
5
- entities: string[];
5
+ entities?: string[];
6
6
  }
7
7
  //# sourceMappingURL=SourceEntities.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SourceEntities.d.ts","sourceRoot":"","sources":["../../src/storage/SourceEntities.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,eAAe,CAAC;AAE5C,sEAAsE;AACtE,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB"}
1
+ {"version":3,"file":"SourceEntities.d.ts","sourceRoot":"","sources":["../../src/storage/SourceEntities.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,eAAe,CAAC;AAE5C,uGAAuG;AACvG,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fougere/defaults",
3
- "version": "0.19.1-alpha.0",
3
+ "version": "0.20.0-alpha.0",
4
4
  "description": "The conventional boot of a Fougere app — the one place storage is wired.",
5
5
  "keywords": [
6
6
  "fougere",
@@ -29,21 +29,21 @@
29
29
  "src"
30
30
  ],
31
31
  "dependencies": {
32
- "@fougere/core": "0.19.1-alpha.0",
33
- "@fougere/adapter-sql": "0.19.1-alpha.0",
34
- "@fougere/transport-http": "0.19.1-alpha.0",
35
- "@fougere/container": "0.19.1-alpha.0",
36
- "@fougere/compiler": "0.19.1-alpha.0",
37
- "@fougere/adapter-memory": "0.19.1-alpha.0"
32
+ "@fougere/core": "0.20.0-alpha.0",
33
+ "@fougere/transport-http": "0.20.0-alpha.0",
34
+ "@fougere/container": "0.20.0-alpha.0",
35
+ "@fougere/compiler": "0.20.0-alpha.0",
36
+ "@fougere/adapter-memory": "0.20.0-alpha.0"
38
37
  },
39
38
  "publishConfig": {
40
39
  "access": "public"
41
40
  },
42
41
  "devDependencies": {
43
- "@fougere/schema": "0.19.1-alpha.0",
42
+ "@fougere/schema": "0.20.0-alpha.0",
44
43
  "kysely": "^0.28.17",
45
44
  "better-sqlite3": "^13.0.3",
46
- "@types/better-sqlite3": "^7.6.13"
45
+ "@types/better-sqlite3": "^7.6.13",
46
+ "@fougere/adapter-sql": "0.20.0-alpha.0"
47
47
  },
48
48
  "scripts": {
49
49
  "build": "rm -rf dist && tsc",
package/src/index.ts CHANGED
@@ -2,14 +2,13 @@
2
2
  import { migrating, type App, type CreateAppOptions } from '@fougere/core';
3
3
  import { boot } from '@fougere/compiler';
4
4
  import { loadConfig, remotesOf } from '@fougere/core/node';
5
- import { type DbConfig } from './storage/DbConfig.js';
6
5
  import { resolveStorage, type ResolvedStorage } from './storage/ResolvedStorage.js';
7
6
  import { remoteTransport } from './transport/RemoteTransport.js';
8
7
 
9
8
  export { remoteTransport } from './transport/RemoteTransport.js';
10
9
  export { declaresStorage } from './storage/DeclaredStorage.js';
11
10
  export { layerOf, resolveStorage, storageFrom } from './storage/ResolvedStorage.js';
12
- export type { DbConfig } from './storage/DbConfig.js';
11
+ export type { SourceEntities } from './storage/SourceEntities.js';
13
12
  export type { ResolvedStorage } from './storage/ResolvedStorage.js';
14
13
 
15
14
  export interface BootAppOptions {
@@ -49,8 +48,8 @@ export async function bootApp(root: string, opts: BootAppOptions = {}): Promise<
49
48
  // `{}` and never undefined: `boot` reads the config's own `fronds:` when handed nothing.
50
49
  remotes: useRemotes ? elsewhere : {},
51
50
  remoteTransport: useRemotes ? await remoteTransport() : undefined,
52
- // One resolver, one place that knows a storage package.
53
- db: (cfg) => (storage = resolveStorage(cfg.db as DbConfig, (cfg as { sources?: unknown }).sources as never, root)),
51
+ // One resolver, one place that reads `sources:`.
52
+ storage: (cfg) => (storage = resolveStorage(cfg.sources, root)),
54
53
  extensions: [...(opts.migrates ? [migrating((app) => storage?.migrate?.(app))] : []), ...(opts.extensions ?? [])],
55
54
  });
56
55
  }
@@ -1,17 +1,6 @@
1
- import { type Source } from '@fougere/core';
2
- import type { DbConfig } from './DbConfig.js';
3
- import type { SourceEntities } from './SourceEntities.js';
1
+ import type { SourceConfig } from '@fougere/core';
4
2
 
5
3
  /** Does this config ask for persistence at all? */
6
- export function declaresStorage(dbConf: DbConfig): boolean {
7
- if (dbConf === false || dbConf === undefined) return false;
8
-
9
- return true;
10
- }
11
-
12
- export interface DeclaredStorage {
13
- /** The default source — where an entity no placement names lands. */
14
- db: Source;
15
- /** The other places. Absent means one source, the way it always was. */
16
- sources?: Record<string, SourceEntities>;
4
+ export function declaresStorage(sources: Record<string, SourceConfig> | undefined): boolean {
5
+ return Object.keys(sources ?? {}).length > 0;
17
6
  }
@@ -1,19 +1,12 @@
1
- import '@fougere/adapter-sql/sqlite';
2
1
  import type { App } from '@fougere/core';
3
2
  import { lowerFirst } from '@fougere/core/contract';
4
3
  import { existsSync } from 'node:fs';
5
4
  import { isAbsolute, resolve } from 'node:path';
6
- import { Logger, Sources, sourceViewOf, type Constraint, type Source } from '@fougere/core';
5
+ import { Logger, Sources, sourceViewOf, type Constraint, type Source, type SourceConfig } from '@fougere/core';
7
6
  import { createMemorySource } from '@fougere/adapter-memory';
8
- import { declaresStorage } from './DeclaredStorage.js';
9
- import type { DbConfig } from './DbConfig.js';
10
- import type { SourcesConfig } from './SourcesConfig.js';
11
7
  import type { SourceEntities } from './SourceEntities.js';
12
- import type { DeclaredStorage } from './DeclaredStorage.js';
13
8
 
14
9
  export interface ResolvedStorage {
15
- /** The default source's engine handle — what `fougere migrate` reads the live tables through. */
16
- db?: unknown;
17
10
  storageFactory: ((entity: any, name: string) => any) | undefined;
18
11
  /**
19
12
  * The source an entity's rows live in — what decides whether a frame gets a real transaction or
@@ -45,10 +38,12 @@ export interface ResolvedStorage {
45
38
  /** Raw synchronous handle, when the engine exposes one. */
46
39
  }
47
40
 
48
- /** Resolve the data layer. */
41
+ /**
42
+ * Resolve the data layer from `sources:`. The one entry listing no entities holds the rest; none
43
+ * at all keeps the rows in memory, and saying so is the whole fallback.
44
+ */
49
45
  export function resolveStorage(
50
- dbConf: DbConfig,
51
- sources?: SourcesConfig,
46
+ sources: Record<string, SourceConfig> | undefined,
52
47
  /**
53
48
  * Where a relative `path:` is counted from — the directory of the config that named it.
54
49
  *
@@ -60,28 +55,13 @@ export function resolveStorage(
60
55
  */
61
56
  root?: string,
62
57
  ): ResolvedStorage {
63
- if (!declaresStorage(dbConf)) {
64
- new Logger('storage').warn('no `db:` declared — rows live in memory and are gone when the process exits');
58
+ const opened = Object.fromEntries(Object.entries(sources ?? {}).map(([name, entry]) => {
59
+ const { entities, ...rest } = entry as { entities?: string[] } & Record<string, unknown>;
65
60
 
66
- return storageFrom({ db: createMemorySource() });
67
- }
61
+ return [name, { source: Sources.open(anchored(rest, root), `sources.${name}`), entities }];
62
+ }));
68
63
 
69
- const named: Record<string, SourceEntities> = {};
70
- for (const [name, conf] of Object.entries(sources ?? {})) {
71
- named[name] = { source: built(conf, `sources.${name}`, root), entities: conf.entities };
72
- }
73
-
74
- return storageFrom({
75
- db: built(typeof dbConf === 'object' ? dbConf : {}, 'db', root),
76
- sources: named,
77
- });
78
- }
79
-
80
- /** One config entry, resolved to the adapter it names. */
81
- function built(conf: Record<string, unknown>, field: string, root?: string): Source {
82
- const name = (conf.source as string | undefined) ?? DEFAULT_ADAPTER;
83
-
84
- return Sources.open(name, anchored(conf, root) as never, `${field}.source`);
64
+ return storageFrom(opened);
85
65
  }
86
66
 
87
67
  /**
@@ -89,9 +69,9 @@ function built(conf: Record<string, unknown>, field: string, root?: string): Sou
89
69
  * absolute path already says where it is — both pass through untouched, which is what
90
70
  * keeps this from being a second reader of what a path means.
91
71
  */
92
- function anchored(conf: Record<string, unknown>, root?: string): Record<string, unknown> {
93
- const path = conf.path;
94
- if (!root || typeof path !== 'string' || path === ':memory:' || isAbsolute(path)) return conf;
72
+ function anchored(entry: Record<string, unknown>, root?: string): Record<string, unknown> {
73
+ const path = entry.path;
74
+ if (!root || typeof path !== 'string' || path === ':memory:' || isAbsolute(path)) return entry;
95
75
 
96
76
  const anchoredPath = resolve(root, path);
97
77
  // Anchoring MOVES a database that a deployment has been running against, and the driver
@@ -105,22 +85,40 @@ function anchored(conf: Record<string, unknown>, root?: string): Record<string,
105
85
  );
106
86
  }
107
87
 
108
- return { ...conf, path: anchoredPath };
88
+ return { ...entry, path: anchoredPath };
109
89
  }
110
90
 
111
- /** What a config naming no adapter means. */
112
- const DEFAULT_ADAPTER = 'sql';
91
+ /** Where an entity no source names lives, and what it is called — the one entry listing none. */
92
+ function defaultOf(sources: Record<string, SourceEntities>): [string, Source] {
93
+ const unlisted = Object.entries(sources).filter(([, placement]) => placement.entities === undefined);
94
+ if (unlisted.length > 1) {
95
+ throw new Error(
96
+ `sources: ${unlisted.map(([name]) => `'${name}'`).join(' and ')} list no entities, and nothing says which `
97
+ + 'one holds the rest. Give all but one of them their entities.',
98
+ );
99
+ }
100
+ if (unlisted.length === 1) return [unlisted[0]![0], unlisted[0]![1].source];
101
+
102
+ new Logger('storage').warn(
103
+ Object.keys(sources).length === 0
104
+ ? 'no `sources:` declared — rows live in memory and are gone when the process exits'
105
+ : 'no source lists no entities — the rows of every entity no source names live in memory and are gone when the process exits',
106
+ );
107
+
108
+ return ['memory', createMemorySource()];
109
+ }
113
110
 
114
111
  /** The same routing `resolveStorage` performs, over engines the CALLER built. */
115
- export function storageFrom(declared: DeclaredStorage): ResolvedStorage {
116
- const { db: base, sources } = declared;
112
+ export function storageFrom(sources: Record<string, SourceEntities>): ResolvedStorage {
113
+ const [DEFAULT, base] = defaultOf(sources);
117
114
 
118
115
  // Where each named entity lives. An entity claimed by two sources is refused naming
119
116
  // both: the rows would be read from one and written to the other, by whichever
120
117
  // registration ran last — the same silent duplicate `remotes:` refuses one level up.
121
118
  const home = new Map<string, string>();
122
119
  const engines = new Map<string, Source>();
123
- for (const [name, placement] of Object.entries(sources ?? {})) {
120
+ for (const [name, placement] of Object.entries(sources)) {
121
+ if (placement.entities === undefined) continue;
124
122
  engines.set(name, placement.source);
125
123
  for (const entity of placement.entities) {
126
124
  const key = lowerFirst(entity);
@@ -136,7 +134,6 @@ export function storageFrom(declared: DeclaredStorage): ResolvedStorage {
136
134
 
137
135
  // The default source answers to the name the config gave it, so a refusal naming two
138
136
  // sources names things the author can find in their own file.
139
- const DEFAULT = 'db';
140
137
  const sourceOf = (entityName: string) => home.get(lowerFirst(entityName)) ?? DEFAULT;
141
138
  const engineOf = (source: string) => (source === DEFAULT ? base : engines.get(source));
142
139
  const engineFor = (entityName: string) => {
@@ -146,15 +143,13 @@ export function storageFrom(declared: DeclaredStorage): ResolvedStorage {
146
143
  };
147
144
 
148
145
  return {
149
- // Opaque, and narrowed by whoever needs it — auth wants a handle, the CLI wants Kysely.
150
- db: (base as { db?: unknown }).db,
151
146
  storageFactory: (entity: any, name: string) => engineFor(name).storageFactory(entity, name),
152
147
  sourceOf,
153
148
  dbOf: (source) => (engineOf(source) as { db?: unknown } | undefined)?.db,
154
149
  sources: () => [DEFAULT, ...engines.keys()],
155
150
  // Asked of the source that will run the work, never of the default one: a frame whose
156
- // members all live in a transactional source gets its transaction even when `db:` has
157
- // none. A source that hands out none leaves the answer `false`, and a frame reads it:
151
+ // members all live in a transactional source gets its transaction even when the default
152
+ // source has none. A source that hands out none leaves the answer `false`, and a frame reads it:
158
153
  // `boot/together.ts` compensates instead, and says which of the two it built.
159
154
  transacts: (source) => engineOf(source)?.transacted !== undefined,
160
155
  // Absent means the judge is alone with it: a source that keeps no constraint of its own
@@ -1,7 +1,7 @@
1
1
  import { type Source } from '@fougere/core';
2
2
 
3
- /** One source: what realizes it, and the entities that live there. */
3
+ /** One source: what realizes it, and the entities that live there — none listed on the default one. */
4
4
  export interface SourceEntities {
5
5
  source: Source;
6
- entities: string[];
6
+ entities?: string[];
7
7
  }
@@ -1,7 +0,0 @@
1
- /** The `db` field of fougere.config.ts, read structurally. */
2
- export type DbConfig = false | 'sqlite' | {
3
- source?: string;
4
- dialect?: string;
5
- path?: string;
6
- } | undefined;
7
- //# sourceMappingURL=DbConfig.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"DbConfig.d.ts","sourceRoot":"","sources":["../../src/storage/DbConfig.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,MAAM,MAAM,QAAQ,GAChB,KAAK,GACL,QAAQ,GACR;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GACpD,SAAS,CAAC"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=DbConfig.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"DbConfig.js","sourceRoot":"","sources":["../../src/storage/DbConfig.ts"],"names":[],"mappings":""}
@@ -1,8 +0,0 @@
1
- /** A named source and the entities it holds — the `sources` field, read structurally. */
2
- export type SourcesConfig = Record<string, {
3
- source?: string;
4
- dialect?: string;
5
- path?: string;
6
- entities: string[];
7
- }> | undefined;
8
- //# sourceMappingURL=SourcesConfig.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"SourcesConfig.d.ts","sourceRoot":"","sources":["../../src/storage/SourcesConfig.ts"],"names":[],"mappings":"AAAA,yFAAyF;AACzF,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,GAAG,SAAS,CAAC"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=SourcesConfig.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"SourcesConfig.js","sourceRoot":"","sources":["../../src/storage/SourcesConfig.ts"],"names":[],"mappings":""}
@@ -1,6 +0,0 @@
1
- /** The `db` field of fougere.config.ts, read structurally. */
2
- export type DbConfig =
3
- | false
4
- | 'sqlite'
5
- | { source?: string; dialect?: string; path?: string }
6
- | undefined;
@@ -1,2 +0,0 @@
1
- /** A named source and the entities it holds — the `sources` field, read structurally. */
2
- export type SourcesConfig = Record<string, { source?: string; dialect?: string; path?: string; entities: string[] }> | undefined;