@dynamic-entity/server 2.4.1 → 3.0.0-rc.1

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
@@ -278,6 +278,13 @@ will name their zip `.csv`.
278
278
  comma-separated, so Excel in those locales opens them as one column — offer `xlsx` there.
279
279
  - **`.xlsx`** — through `exceljs`. Cells keep their types: a date cell arrives as a `Date` at
280
280
  UTC midnight and is read as the calendar date it is, in every timezone.
281
+ - **Dates written as text.** `2026-09-05` is always read as written. A date in digits such as
282
+ `05/09/2026` reads two ways, so it is an error unless you say which: pass
283
+ `dateOrder: 'DMY'` (day first) or `'MDY'` (month first) to `createImportRouter` or
284
+ `runImport`. It is never guessed. Releases before 2.5.0 read it month first without
285
+ saying so; see the changelog if your sheets are day first. A preview response carries the
286
+ router's `dateOrder`, so the wizard reads its review the same way and refuses to commit if
287
+ it was told a different order.
281
288
  - A pre-2007 `.xls` and a UTF-16 file are **named** rather than parsed into nonsense.
282
289
 
283
290
  ---
package/express.d.mts CHANGED
@@ -1,14 +1,17 @@
1
- import { EntityFormConfig, FormRule, ImportLookups } from '@dynamic-entity/core';
2
- import { Request, Router, Response } from 'express';
3
- import { B as BatchInfo, I as ImportLimits, T as TemplateFormat } from './write-template-CzKVVjgT.mjs';
4
- import 'node:stream';
1
+ import { EntityFormConfig, FormRule, ImportLookups, DateOrder } from '@dynamic-entity/core';
2
+ import { Request, Router } from 'express';
3
+ import { sendFailure as sendFailure$1, templateFilename as templateFilename$1 } from 'sheet-to-schema/node';
4
+ import { B as BatchInfo, I as ImportLimits } from './run-import-BUClq6BR.mjs';
5
5
 
6
6
  /**
7
- * express.ts — four routes over the framework-neutral core, and no privileges.
7
+ * express.ts — four routes, and no privileges.
8
8
  *
9
- * Everything this file does, a Fastify, Nest or Next route could do in the same few lines:
10
- * find the config, read the upload, call `previewSheet` / `runImport` / `writeTemplate`, and
11
- * answer. It is one caller of the package rather than the package's shape.
9
+ * Since 3.0 the routes are sheet-to-schema's (`createImportRouter` in `sheet-to-schema/node`),
10
+ * which resolves a schema adapter by the name in the path. This is that router with a config
11
+ * behind each name: it finds the config, checks its lookups were supplied, turns it into
12
+ * `entityFormConfigAdapter` with the entity's rules, and answers a preview with the same
13
+ * suggestion the browser makes. Reading the upload, the limits, the timeouts and the failure
14
+ * envelope are the router's own, and are the code this file had until 3.0.
12
15
  *
13
16
  * **Not this router's job, said out loud.** Concurrency limiting, authentication and
14
17
  * authorization are the consumer's. The router is mounted inside their app, behind their
@@ -41,6 +44,12 @@ interface ImportRouterOptions {
41
44
  rules?: Record<string, readonly FormRule[]>;
42
45
  /** Values for every `listName` any config mentions. A server has no `LOOKUP_REGISTRY`. */
43
46
  lookups?: ImportLookups;
47
+ /**
48
+ * The order of a date written in digits, for every import and validation this router runs:
49
+ * `DMY` for day first, `MDY` for month first. Without it, a date that reads two ways
50
+ * (`05/09/2026`) fails its row. See `RunImportOptions.dateOrder`.
51
+ */
52
+ dateOrder?: DateOrder;
44
53
  /**
45
54
  * Where records go.
46
55
  *
@@ -70,20 +79,17 @@ declare function listNamesOf(config: EntityFormConfig): string[];
70
79
  *
71
80
  * The caller passes `config.entity`, not the route segment. They are usually the same string,
72
81
  * and when they are not — a consumer mounting a plural route, `{ employees: employeeConfig }` —
73
- * the config is the one that names the data. Reading the route key instead made the map key
74
- * carry meaning it was never given, which is a footgun with no upside: the key is a route
75
- * segment and nothing else.
82
+ * the config is the one that names the data.
76
83
  */
77
- declare function templateFilename(entity: string, format: TemplateFormat): string;
84
+ declare const templateFilename: typeof templateFilename$1;
78
85
  /**
79
86
  * Send whatever went wrong as the envelope, unless the response has already started.
80
87
  *
81
- * Exported so it can be tested against a response that has already begun: a template that
82
- * failed part-way is already partly on the wire, and the only honest thing left is to end the
83
- * connection abruptly. A 200 with a truncated body is a corrupt file that looks like a good
84
- * one, which is the worst of the available outcomes.
88
+ * A template that failed part-way is already partly on the wire, and the only honest thing
89
+ * left is to end the connection abruptly. A 200 with a truncated body is a corrupt file that
90
+ * looks like a good one, which is the worst of the available outcomes.
85
91
  */
86
- declare function sendFailure(response: Response, error: unknown): void;
92
+ declare const sendFailure: typeof sendFailure$1;
87
93
  declare function createImportRouter(options: ImportRouterOptions): Router;
88
94
 
89
95
  export { type ConfigSource, type ImportRouterOptions, type OnImport, createImportRouter, listNamesOf, sendFailure, templateFilename };
package/express.d.ts CHANGED
@@ -1,14 +1,17 @@
1
- import { EntityFormConfig, FormRule, ImportLookups } from '@dynamic-entity/core';
2
- import { Request, Router, Response } from 'express';
3
- import { B as BatchInfo, I as ImportLimits, T as TemplateFormat } from './write-template-CzKVVjgT.js';
4
- import 'node:stream';
1
+ import { EntityFormConfig, FormRule, ImportLookups, DateOrder } from '@dynamic-entity/core';
2
+ import { Request, Router } from 'express';
3
+ import { sendFailure as sendFailure$1, templateFilename as templateFilename$1 } from 'sheet-to-schema/node';
4
+ import { B as BatchInfo, I as ImportLimits } from './run-import-BUClq6BR.js';
5
5
 
6
6
  /**
7
- * express.ts — four routes over the framework-neutral core, and no privileges.
7
+ * express.ts — four routes, and no privileges.
8
8
  *
9
- * Everything this file does, a Fastify, Nest or Next route could do in the same few lines:
10
- * find the config, read the upload, call `previewSheet` / `runImport` / `writeTemplate`, and
11
- * answer. It is one caller of the package rather than the package's shape.
9
+ * Since 3.0 the routes are sheet-to-schema's (`createImportRouter` in `sheet-to-schema/node`),
10
+ * which resolves a schema adapter by the name in the path. This is that router with a config
11
+ * behind each name: it finds the config, checks its lookups were supplied, turns it into
12
+ * `entityFormConfigAdapter` with the entity's rules, and answers a preview with the same
13
+ * suggestion the browser makes. Reading the upload, the limits, the timeouts and the failure
14
+ * envelope are the router's own, and are the code this file had until 3.0.
12
15
  *
13
16
  * **Not this router's job, said out loud.** Concurrency limiting, authentication and
14
17
  * authorization are the consumer's. The router is mounted inside their app, behind their
@@ -41,6 +44,12 @@ interface ImportRouterOptions {
41
44
  rules?: Record<string, readonly FormRule[]>;
42
45
  /** Values for every `listName` any config mentions. A server has no `LOOKUP_REGISTRY`. */
43
46
  lookups?: ImportLookups;
47
+ /**
48
+ * The order of a date written in digits, for every import and validation this router runs:
49
+ * `DMY` for day first, `MDY` for month first. Without it, a date that reads two ways
50
+ * (`05/09/2026`) fails its row. See `RunImportOptions.dateOrder`.
51
+ */
52
+ dateOrder?: DateOrder;
44
53
  /**
45
54
  * Where records go.
46
55
  *
@@ -70,20 +79,17 @@ declare function listNamesOf(config: EntityFormConfig): string[];
70
79
  *
71
80
  * The caller passes `config.entity`, not the route segment. They are usually the same string,
72
81
  * and when they are not — a consumer mounting a plural route, `{ employees: employeeConfig }` —
73
- * the config is the one that names the data. Reading the route key instead made the map key
74
- * carry meaning it was never given, which is a footgun with no upside: the key is a route
75
- * segment and nothing else.
82
+ * the config is the one that names the data.
76
83
  */
77
- declare function templateFilename(entity: string, format: TemplateFormat): string;
84
+ declare const templateFilename: typeof templateFilename$1;
78
85
  /**
79
86
  * Send whatever went wrong as the envelope, unless the response has already started.
80
87
  *
81
- * Exported so it can be tested against a response that has already begun: a template that
82
- * failed part-way is already partly on the wire, and the only honest thing left is to end the
83
- * connection abruptly. A 200 with a truncated body is a corrupt file that looks like a good
84
- * one, which is the worst of the available outcomes.
88
+ * A template that failed part-way is already partly on the wire, and the only honest thing
89
+ * left is to end the connection abruptly. A 200 with a truncated body is a corrupt file that
90
+ * looks like a good one, which is the worst of the available outcomes.
85
91
  */
86
- declare function sendFailure(response: Response, error: unknown): void;
92
+ declare const sendFailure: typeof sendFailure$1;
87
93
  declare function createImportRouter(options: ImportRouterOptions): Router;
88
94
 
89
95
  export { type ConfigSource, type ImportRouterOptions, type OnImport, createImportRouter, listNamesOf, sendFailure, templateFilename };