@softure-ai/core 0.1.5 → 0.1.7
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/CHANGELOG.md +18 -0
- package/README.md +53 -9
- package/dist/calendar-day.d.ts +6 -0
- package/dist/calendar-day.d.ts.map +1 -0
- package/dist/calendar-day.js +32 -0
- package/dist/calendar-day.js.map +1 -0
- package/dist/config.d.ts +30 -7
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +8 -1
- package/dist/config.js.map +1 -1
- package/dist/i18n.d.ts.map +1 -1
- package/dist/i18n.js +7 -2
- package/dist/i18n.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/module.d.ts +3 -0
- package/dist/module.d.ts.map +1 -1
- package/dist/module.js +7 -0
- package/dist/module.js.map +1 -1
- package/dist/safe-error.d.ts +18 -0
- package/dist/safe-error.d.ts.map +1 -1
- package/dist/safe-error.js +29 -4
- package/dist/safe-error.js.map +1 -1
- package/package.json +2 -1
- package/src/calendar-day.ts +38 -0
- package/src/config.ts +39 -4
- package/src/i18n.ts +8 -2
- package/src/index.ts +5 -1
- package/src/module.ts +9 -0
- package/src/safe-error.ts +34 -4
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Newest first. Each version lists what changed for an app that uses `@softure-ai/core`. When an app has run a version in
|
|
4
|
+
production, the version gets a line `verified in: <app>@<commit>` ([docs/05](../../docs/05-adoption-playbook.md),
|
|
5
|
+
"Definition of done"). Versions before the first one below are described in their GitHub Releases (`core@x.y.z`).
|
|
6
|
+
|
|
7
|
+
## 0.1.7
|
|
8
|
+
|
|
9
|
+
- `toCalendarDay(instant, timeZone)` and `getCalendarDay(clock, timeZone)`: the calendar day (`YYYY-MM-DD`) of an
|
|
10
|
+
instant, or today from a `Clock`, in an IANA time zone rather than the process zone (#251).
|
|
11
|
+
|
|
12
|
+
## 0.1.6
|
|
13
|
+
|
|
14
|
+
- `PublicError`, `isPublicError` and `getPublicMessage`: a message written for the user passes through, every other error's text stays out (`safeError` is unchanged).
|
|
15
|
+
- `selectPlural` builds one `Intl.PluralRules` per locale and reuses it.
|
|
16
|
+
- `database: { url, handle }`: the config can carry the app's own database handle, shared with the modules.
|
|
17
|
+
- An empty `database.url` is accepted when the config is defined and refused only by a command that connects (build stages need no `DATABASE_URL`).
|
|
18
|
+
- A guard against loading the package as CommonJS (ESM only).
|
package/README.md
CHANGED
|
@@ -1,16 +1,13 @@
|
|
|
1
1
|
# @softure-ai/core
|
|
2
2
|
|
|
3
|
-
**Status:** wave 0 · implemented in FD-3 (`core-contract`), 0.1.5, prepared for its first release (the owner's tag, `scripts/release/README.md`).
|
|
4
|
-
|
|
5
3
|
The contract every SOFTURE module stands on. Standard:
|
|
6
|
-
[docs/02-module-standard.md](../../docs/02-module-standard.md).
|
|
7
|
-
`{ ok, error }` action results, `src/lib/safe-error.ts` and `src/lib/plural.ts`.
|
|
4
|
+
[docs/02-module-standard.md](../../docs/02-module-standard.md).
|
|
8
5
|
|
|
9
6
|
## 1. What it provides
|
|
10
7
|
|
|
11
8
|
The app configuration (`defineSoftureConfig`), the module contract (`defineModule`), `Result`
|
|
12
9
|
with namespaced error codes, an injectable `Clock`, `pl`/`en` messages with partial overrides,
|
|
13
|
-
and `safeError`. `@softure-ai/core/cli` loads the app's config for the modules' command-line tools.
|
|
10
|
+
and `safeError` with `PublicError`. `@softure-ai/core/cli` loads the app's config for the modules' command-line tools.
|
|
14
11
|
|
|
15
12
|
## 2. Installation
|
|
16
13
|
|
|
@@ -24,7 +21,10 @@ Node ≥ 22, ESM only. The only runtime dependency is `zod`.
|
|
|
24
21
|
|
|
25
22
|
```ts
|
|
26
23
|
interface SoftureConfigInput {
|
|
27
|
-
database?: {
|
|
24
|
+
database?: { // required once any module has a dbSchema
|
|
25
|
+
url: string;
|
|
26
|
+
handle?: () => DatabaseHandle | Promise<DatabaseHandle>; // the app's own handle, see below
|
|
27
|
+
} | null;
|
|
28
28
|
locale: "en" | "pl";
|
|
29
29
|
timezone: string; // IANA zone, e.g. "Europe/Warsaw"
|
|
30
30
|
appOrigin: string; // http(s) origin without a path
|
|
@@ -55,6 +55,20 @@ unknown locale or zone, an origin with a path, a module listed twice, two module
|
|
|
55
55
|
schema, a required dependency missing, a dependency outside its version range (also an optional
|
|
56
56
|
one, when listed), a dependency cycle, or a module with a `dbSchema` and no `database`.
|
|
57
57
|
|
|
58
|
+
An empty `database.url` is not one of those problems. `next build`, a Docker builder stage running
|
|
59
|
+
`--export-migrations` and other build steps import the config without `DATABASE_URL`, so
|
|
60
|
+
`DATABASE_URL ?? ""` defines a valid config there; the first connection (`createDatabase` and
|
|
61
|
+
`getSharedDatabase` in `@softure-ai/db`, `softure migrate`, the module CLIs and the health route)
|
|
62
|
+
refuses the empty URL and names the setting. No placeholder URL is needed for a build.
|
|
63
|
+
|
|
64
|
+
`database.handle` is for an app that already has its own database client: every module, the
|
|
65
|
+
health route and the package commands then use that one handle instead of opening a second one on
|
|
66
|
+
`url` (with `pglite://`, a second instance on the same directory corrupts it). It is a function,
|
|
67
|
+
called on first use and never by `defineSoftureConfig`, and it must return the app's process-wide
|
|
68
|
+
handle; wrap a client with `createPostgresHandle(pool)` or `createPgliteHandle(client)`. Details and
|
|
69
|
+
the alternative (the app builds on the shared handle): `@softure-ai/db` README §3, "One handle per
|
|
70
|
+
process".
|
|
71
|
+
|
|
58
72
|
A command that never connects loads the config inside `withDatabaseOptional(() => import(...))`:
|
|
59
73
|
there a missing, `null` or empty `database.url` gives `database: null` instead of a refusal, also when
|
|
60
74
|
a module has a `dbSchema`; a real URL is kept and every other check still runs. The flag is scoped to
|
|
@@ -199,7 +213,8 @@ None. Tokens, slots and styles live in `@softure-ai/ui`.
|
|
|
199
213
|
string in place of a group are ignored.
|
|
200
214
|
- `formatMessage("{count} of {total}", { count, total })` fills placeholders; a missing value
|
|
201
215
|
stays visible as `{name}`.
|
|
202
|
-
- `selectPlural(locale, count, { one, few, many, other })` uses `Intl.PluralRules
|
|
216
|
+
- `selectPlural(locale, count, { one, few, many, other })` uses `Intl.PluralRules`, built once per
|
|
217
|
+
locale and reused.
|
|
203
218
|
- `getMessage(dictionary, "errors.unexpected")` reads a dotted path.
|
|
204
219
|
- Core's own keys (`coreMessages`): `errors.database_failed`, `errors.unexpected`, the copy for
|
|
205
220
|
the `core.database_failed` and `core.unexpected` codes.
|
|
@@ -211,11 +226,40 @@ None. Tokens, slots and styles live in `@softure-ai/ui`.
|
|
|
211
226
|
bare SQL statement) or `core.unexpected`, so no SQL or parameter reaches a caller.
|
|
212
227
|
`errorLogLabel(error)` gives a log line with the error class and SQLSTATE only, never the text.
|
|
213
228
|
|
|
229
|
+
A message written for the user on purpose ("This plan has ended; pick another one.") travels as a
|
|
230
|
+
`PublicError`: `getPublicMessage(error)` returns its message, and `null` for every other error, so the
|
|
231
|
+
pass-through is one line and nothing else slips out:
|
|
232
|
+
|
|
233
|
+
```ts
|
|
234
|
+
import { getPublicMessage, PublicError, safeError } from "@softure-ai/core";
|
|
235
|
+
|
|
236
|
+
// domain code
|
|
237
|
+
if (plan.endedAt !== null) throw new PublicError("This plan has ended; pick another one.");
|
|
238
|
+
|
|
239
|
+
// where the error is caught (an MCP tool, an action)
|
|
240
|
+
} catch (error) {
|
|
241
|
+
return { text: getPublicMessage(error) ?? t(safeError(error).error) };
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
`isPublicError` recognises one from another copy of core too (a registry symbol, not `instanceof`).
|
|
246
|
+
`safeError` itself still answers `core.unexpected` for it, since callers switch on its two codes.
|
|
247
|
+
|
|
214
248
|
**Time.** Server code receives a `Clock` (`ModuleContext.clock`) instead of calling `new Date()`.
|
|
215
249
|
`systemClock` is the real one; `createTestClock(start)` has `advance(ms)` and `set(date)`.
|
|
216
250
|
A whole test run can also move to another day without code changes: `TEST_TODAY=YYYY-MM-DD` with the
|
|
217
251
|
`@softure-ai/testing/vitest-setup` setup file shifts the global `Date` (and so `systemClock`) to that
|
|
218
|
-
day while time keeps running ([`@softure-ai/testing`](../testing/README.md)).
|
|
252
|
+
day while time keeps running ([`@softure-ai/testing`](../testing/README.md)). The same setup file pins
|
|
253
|
+
the tests to a zone with a negative offset, so a date computed without an explicit zone fails there.
|
|
254
|
+
|
|
255
|
+
**Calendar days.** "Today" is a day in a zone, never in the process zone: on a server in UTC an evening
|
|
256
|
+
in New York is already tomorrow. `toCalendarDay(instant, timeZone)` returns the `YYYY-MM-DD` day of an
|
|
257
|
+
instant in an IANA zone, and `getCalendarDay(clock, timeZone)` today's day from a `Clock`; pass the
|
|
258
|
+
app's `timezone` from the config. Both throw a `RangeError` for an invalid date or an unknown zone.
|
|
259
|
+
|
|
260
|
+
```ts
|
|
261
|
+
getCalendarDay(context.clock, config.timezone); // "2026-10-08"
|
|
262
|
+
```
|
|
219
263
|
|
|
220
264
|
## 10. Hooks
|
|
221
265
|
|
|
@@ -241,4 +285,4 @@ manifest's `privacy.exports` / `privacy.deletes` flag is true. The `privacy` mod
|
|
|
241
285
|
are rejected.
|
|
242
286
|
- Route maps mix mounted paths and redirect targets, so two modules may share a path; mount
|
|
243
287
|
collisions are left to `softure doctor`.
|
|
244
|
-
- No date or number formatting helpers
|
|
288
|
+
- No date or number formatting helpers beyond the calendar day; apps use `Intl` with `config.locale` and `config.timezone`.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Clock } from "./clock.js";
|
|
2
|
+
/** The calendar day (`YYYY-MM-DD`) of `instant` in `timeZone`. Throws a `RangeError` for an invalid date or zone. */
|
|
3
|
+
export declare function toCalendarDay(instant: Date, timeZone: string): string;
|
|
4
|
+
/** Today's calendar day (`YYYY-MM-DD`) in `timeZone`, read from `clock`. */
|
|
5
|
+
export declare function getCalendarDay(clock: Clock, timeZone: string): string;
|
|
6
|
+
//# sourceMappingURL=calendar-day.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"calendar-day.d.ts","sourceRoot":"","sources":["../src/calendar-day.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAIxC,qHAAqH;AACrH,wBAAgB,aAAa,CAAC,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQrE;AAED,4EAA4E;AAC5E,wBAAgB,cAAc,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAErE"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
const formatters = new Map();
|
|
2
|
+
/** The calendar day (`YYYY-MM-DD`) of `instant` in `timeZone`. Throws a `RangeError` for an invalid date or zone. */
|
|
3
|
+
export function toCalendarDay(instant, timeZone) {
|
|
4
|
+
if (Number.isNaN(instant.getTime())) {
|
|
5
|
+
throw new RangeError("toCalendarDay: invalid date");
|
|
6
|
+
}
|
|
7
|
+
// Parts, not the formatted string: a locale's date pattern (`en-CA`) has changed between ICU versions.
|
|
8
|
+
const parts = getFormatter(timeZone).formatToParts(instant);
|
|
9
|
+
const readPart = (type) => parts.find((part) => part.type === type)?.value ?? "";
|
|
10
|
+
return `${readPart("year").padStart(4, "0")}-${readPart("month")}-${readPart("day")}`;
|
|
11
|
+
}
|
|
12
|
+
/** Today's calendar day (`YYYY-MM-DD`) in `timeZone`, read from `clock`. */
|
|
13
|
+
export function getCalendarDay(clock, timeZone) {
|
|
14
|
+
return toCalendarDay(clock.now(), timeZone);
|
|
15
|
+
}
|
|
16
|
+
function getFormatter(timeZone) {
|
|
17
|
+
let format = formatters.get(timeZone);
|
|
18
|
+
if (format === undefined) {
|
|
19
|
+
format = createFormatter(timeZone);
|
|
20
|
+
formatters.set(timeZone, format);
|
|
21
|
+
}
|
|
22
|
+
return format;
|
|
23
|
+
}
|
|
24
|
+
function createFormatter(timeZone) {
|
|
25
|
+
try {
|
|
26
|
+
return new Intl.DateTimeFormat("en-US", { timeZone, year: "numeric", month: "2-digit", day: "2-digit" });
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
throw new RangeError(`toCalendarDay: "${timeZone}" is not an IANA time zone`, { cause: error });
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=calendar-day.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"calendar-day.js","sourceRoot":"","sources":["../src/calendar-day.ts"],"names":[],"mappings":"AAIA,MAAM,UAAU,GAAG,IAAI,GAAG,EAA+B,CAAC;AAE1D,qHAAqH;AACrH,MAAM,UAAU,aAAa,CAAC,OAAa,EAAE,QAAgB;IAC3D,IAAI,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,UAAU,CAAC,6BAA6B,CAAC,CAAC;IACtD,CAAC;IACD,uGAAuG;IACvG,MAAM,KAAK,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IAC5D,MAAM,QAAQ,GAAG,CAAC,IAAkC,EAAU,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,KAAK,IAAI,EAAE,CAAC;IACvH,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,QAAQ,CAAC,OAAO,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;AACxF,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,cAAc,CAAC,KAAY,EAAE,QAAgB;IAC3D,OAAO,aAAa,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,QAAQ,CAAC,CAAC;AAC9C,CAAC;AAED,SAAS,YAAY,CAAC,QAAgB;IACpC,IAAI,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACtC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,MAAM,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;QACnC,UAAU,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACnC,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,eAAe,CAAC,QAAgB;IACvC,IAAI,CAAC;QACH,OAAO,IAAI,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;IAC3G,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,UAAU,CAAC,mBAAmB,QAAQ,4BAA4B,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IAClG,CAAC;AACH,CAAC"}
|
package/dist/config.d.ts
CHANGED
|
@@ -1,11 +1,35 @@
|
|
|
1
1
|
import { type Locale } from "./i18n.js";
|
|
2
2
|
import type { AnySoftureModule } from "./module.js";
|
|
3
3
|
import { type Result } from "./result.js";
|
|
4
|
+
/**
|
|
5
|
+
* Filled by `@softure-ai/db` through declaration merging with `{ handle: DatabaseHandle }`, so `database.handle`
|
|
6
|
+
* is typed wherever db's types are loaded. Core cannot import db (db depends on core).
|
|
7
|
+
*/
|
|
8
|
+
export interface SoftureDatabaseHandleTypes {
|
|
9
|
+
}
|
|
10
|
+
/** The handle `database.handle` returns: db's `DatabaseHandle`, or `unknown` where db's types are not loaded. */
|
|
11
|
+
export type SoftureDatabaseHandle = SoftureDatabaseHandleTypes extends {
|
|
12
|
+
readonly handle: infer Handle;
|
|
13
|
+
} ? Handle : unknown;
|
|
14
|
+
type MaybePromise<T> = T | Promise<T>;
|
|
15
|
+
export interface SoftureDatabaseConfig {
|
|
16
|
+
readonly url: string;
|
|
17
|
+
/**
|
|
18
|
+
* The app's own database handle, for an app that already has a client: every module, the health route and
|
|
19
|
+
* every package command then query through it instead of opening a second handle on `url` (with `pglite://`,
|
|
20
|
+
* a second PGlite instance on one directory corrupts it). Called on first use, not when the config is defined,
|
|
21
|
+
* so a build never connects. It must return the app's process-wide handle (memoized, e.g. on `globalThis`):
|
|
22
|
+
* `next dev` re-evaluates the config and calls a new function after each reload. Wrap a client with
|
|
23
|
+
* `createPostgresHandle(pool)` or `createPgliteHandle(client)` from `@softure-ai/db`.
|
|
24
|
+
*/
|
|
25
|
+
readonly handle?: () => MaybePromise<SoftureDatabaseHandle>;
|
|
26
|
+
}
|
|
4
27
|
export interface SoftureConfig {
|
|
5
|
-
/**
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
28
|
+
/**
|
|
29
|
+
* `null` when the app has no database; required as soon as a module has a `dbSchema`. An empty `url`
|
|
30
|
+
* (`DATABASE_URL` unset, as in a build step) is accepted here and refused by the first connection.
|
|
31
|
+
*/
|
|
32
|
+
readonly database: SoftureDatabaseConfig | null;
|
|
9
33
|
readonly locale: Locale;
|
|
10
34
|
/** IANA time zone used for every date shown or computed per calendar day. */
|
|
11
35
|
readonly timezone: string;
|
|
@@ -16,9 +40,7 @@ export interface SoftureConfig {
|
|
|
16
40
|
}
|
|
17
41
|
/** What the app writes in `softure.config.ts`. */
|
|
18
42
|
export interface SoftureConfigInput {
|
|
19
|
-
readonly database?:
|
|
20
|
-
readonly url: string;
|
|
21
|
-
} | null;
|
|
43
|
+
readonly database?: SoftureDatabaseConfig | null;
|
|
22
44
|
readonly locale: Locale;
|
|
23
45
|
readonly timezone: string;
|
|
24
46
|
readonly appOrigin: string;
|
|
@@ -36,4 +58,5 @@ export declare function getModule(config: SoftureConfig, id: string): AnySofture
|
|
|
36
58
|
* keep the listed order. Dependencies that are not listed are ignored here.
|
|
37
59
|
*/
|
|
38
60
|
export declare function sortModulesByDependencies(modules: readonly AnySoftureModule[]): Result<AnySoftureModule[], "core.dependency_cycle">;
|
|
61
|
+
export {};
|
|
39
62
|
//# sourceMappingURL=config.d.ts.map
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAKA,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AAGnD,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAKA,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AAGnD;;;GAGG;AAEH,MAAM,WAAW,0BAA0B;CAAG;AAE9C,iHAAiH;AACjH,MAAM,MAAM,qBAAqB,GAAG,0BAA0B,SAAS;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,MAAM,CAAA;CAAE,GAAG,MAAM,GAAG,OAAO,CAAC;AAE5H,KAAK,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;AAEtC,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB;;;;;;;OAOG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,YAAY,CAAC,qBAAqB,CAAC,CAAC;CAC7D;AAED,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,qBAAqB,GAAG,IAAI,CAAC;IAChD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,6EAA6E;IAC7E,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,mFAAmF;IACnF,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,yDAAyD;IACzD,QAAQ,CAAC,OAAO,EAAE,SAAS,gBAAgB,EAAE,CAAC;CAC/C;AAED,kDAAkD;AAClD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,QAAQ,CAAC,EAAE,qBAAqB,GAAG,IAAI,CAAC;IACjD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,SAAS,gBAAgB,EAAE,CAAC;CAC/C;AAsBD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,kBAAkB,GAAG,aAAa,CAkB5E;AAED,oFAAoF;AACpF,wBAAgB,SAAS,CAAC,MAAM,EAAE,aAAa,EAAE,EAAE,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAEzF;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,SAAS,gBAAgB,EAAE,GACnC,MAAM,CAAC,gBAAgB,EAAE,EAAE,uBAAuB,CAAC,CAGrD"}
|
package/dist/config.js
CHANGED
|
@@ -8,8 +8,15 @@ import { err, ok } from "./result.js";
|
|
|
8
8
|
import { parseVersionRange, satisfiesRange } from "./version-range.js";
|
|
9
9
|
const CONFIG_SUBJECT = "softure.config (defineSoftureConfig)";
|
|
10
10
|
const configSchema = z.object({
|
|
11
|
+
// The URL is not checked for emptiness here: builds import the config without DATABASE_URL, so an empty URL is
|
|
12
|
+
// refused when something connects (`createDatabase` in @softure-ai/db), not when the config is defined.
|
|
11
13
|
database: z
|
|
12
|
-
.object({
|
|
14
|
+
.object({
|
|
15
|
+
url: z.string(),
|
|
16
|
+
handle: z
|
|
17
|
+
.custom((value) => typeof value === "function", "must be a function returning the app's database handle")
|
|
18
|
+
.optional(),
|
|
19
|
+
})
|
|
13
20
|
.nullable()
|
|
14
21
|
.default(null),
|
|
15
22
|
locale: z.enum(LOCALES),
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,oGAAoG;AACpG,gEAAgE;AAChE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAe,MAAM,WAAW,CAAC;AAEjD,OAAO,EAAE,GAAG,EAAE,EAAE,EAAe,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/i18n.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../src/i18n.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,OAAO,uBAAwB,CAAC;AAE7C,MAAM,MAAM,MAAM,GAAG,CAAC,OAAO,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC;AAE9C,sDAAsD;AACtD,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,WAAW,CAAC;CAC9C;AAED,8DAA8D;AAC9D,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI;KAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAAE,CAAC;AAEnG,0CAA0C;AAC1C,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,WAAW,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;AAE9E,wDAAwD;AACxD,MAAM,MAAM,gBAAgB,CAAC,CAAC,SAAS,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAE9F,2FAA2F;AAC3F,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAExD;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,WAAW,EACjD,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC,EACzB,SAAS,GAAE,gBAAgB,CAAC,CAAC,CAAM,GAClC,YAAY,CAAC,CAAC,CAAC,CAMjB;AAED,mFAAmF;AACnF,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAM,GAAG,MAAM,CAK9G;
|
|
1
|
+
{"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../src/i18n.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,OAAO,uBAAwB,CAAC;AAE7C,MAAM,MAAM,MAAM,GAAG,CAAC,OAAO,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC;AAE9C,sDAAsD;AACtD,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,WAAW,CAAC;CAC9C;AAED,8DAA8D;AAC9D,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI;KAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAAE,CAAC;AAEnG,0CAA0C;AAC1C,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,WAAW,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;AAE9E,wDAAwD;AACxD,MAAM,MAAM,gBAAgB,CAAC,CAAC,SAAS,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAE9F,2FAA2F;AAC3F,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAExD;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,WAAW,EACjD,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC,EACzB,SAAS,GAAE,gBAAgB,CAAC,CAAC,CAAM,GAClC,YAAY,CAAC,CAAC,CAAC,CAMjB;AAED,mFAAmF;AACnF,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAM,GAAG,MAAM,CAK9G;AAID,qFAAqF;AACrF,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,MAAM,CAOtF;AAED,kGAAkG;AAClG,wBAAgB,UAAU,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAS9E"}
|
package/dist/i18n.js
CHANGED
|
@@ -23,10 +23,15 @@ export function formatMessage(template, params = {}) {
|
|
|
23
23
|
return value === undefined ? placeholder : String(value);
|
|
24
24
|
});
|
|
25
25
|
}
|
|
26
|
+
const pluralRulesByLocale = new Map();
|
|
26
27
|
/** The form for `count` under the plural rules of `locale` ("1 file", "2 files"). */
|
|
27
28
|
export function selectPlural(locale, count, forms) {
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
let rules = pluralRulesByLocale.get(locale);
|
|
30
|
+
if (rules === undefined) {
|
|
31
|
+
rules = new Intl.PluralRules(locale);
|
|
32
|
+
pluralRulesByLocale.set(locale, rules);
|
|
33
|
+
}
|
|
34
|
+
return forms[rules.select(count)] ?? forms.other;
|
|
30
35
|
}
|
|
31
36
|
/** The message at a dotted path (`login.title`), or `undefined` when there is no string there. */
|
|
32
37
|
export function getMessage(tree, path) {
|
package/dist/i18n.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"i18n.js","sourceRoot":"","sources":["../src/i18n.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,sEAAsE;AAEtE,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,IAAI,EAAE,IAAI,CAAU,CAAC;AA4B7C,MAAM,UAAU,QAAQ,CAAC,KAAc;IACrC,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,KAAK,KAAK,CAAC,CAAC;AACpD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAC3B,QAAyB,EACzB,YAAiC,EAAE;IAEnC,MAAM,MAAM,GAAG,EAAuB,CAAC;IACvC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC,MAAM,CAAC,CAAM,CAAC;IACvE,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,aAAa,CAAC,QAAgB,EAAE,SAAoD,EAAE;IACpG,OAAO,QAAQ,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,WAAW,EAAE,IAAY,EAAE,EAAE;QAClE,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;QAC3B,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;AACL,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,YAAY,CAAC,MAAc,EAAE,KAAa,EAAE,KAAkB;IAC5E,MAAM,
|
|
1
|
+
{"version":3,"file":"i18n.js","sourceRoot":"","sources":["../src/i18n.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
export { getCalendarDay, toCalendarDay } from "./calendar-day.js";
|
|
1
2
|
export { createTestClock, systemClock, type Clock, type TestClock } from "./clock.js";
|
|
2
3
|
export { formatMessage, getMessage, isLocale, LOCALES, mergeMessages, selectPlural, type DeepPartial, type Dictionaries, type Locale, type MessageOverrides, type MessageTree, type PluralForms, } from "./i18n.js";
|
|
3
4
|
export { coreMessages, type CoreMessages } from "./messages/index.js";
|
|
4
5
|
export { err, ok, type Err, type ErrorCode, type Ok, type Result } from "./result.js";
|
|
5
|
-
export { errorLogLabel, safeError, type CoreErrorCode } from "./safe-error.js";
|
|
6
|
-
export { defineSoftureConfig, getModule, sortModulesByDependencies, type SoftureConfig, type SoftureConfigInput, } from "./config.js";
|
|
6
|
+
export { errorLogLabel, getPublicMessage, isPublicError, PublicError, safeError, type CoreErrorCode } from "./safe-error.js";
|
|
7
|
+
export { defineSoftureConfig, getModule, sortModulesByDependencies, type SoftureConfig, type SoftureConfigInput, type SoftureDatabaseConfig, type SoftureDatabaseHandle, type SoftureDatabaseHandleTypes, } from "./config.js";
|
|
7
8
|
export { SoftureConfigError } from "./config-error.js";
|
|
8
9
|
export { withDatabaseOptional } from "./database-requirement.js";
|
|
9
10
|
export { moduleManifestSchema, type ModuleManifest } from "./manifest.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,KAAK,KAAK,EAAE,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AACtF,OAAO,EACL,aAAa,EACb,UAAU,EACV,QAAQ,EACR,OAAO,EACP,aAAa,EACb,YAAY,EACZ,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,MAAM,EACX,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,KAAK,WAAW,GACjB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,YAAY,EAAE,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACtE,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,KAAK,GAAG,EAAE,KAAK,SAAS,EAAE,KAAK,EAAE,EAAE,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AACtF,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,KAAK,aAAa,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,KAAK,KAAK,EAAE,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AACtF,OAAO,EACL,aAAa,EACb,UAAU,EACV,QAAQ,EACR,OAAO,EACP,aAAa,EACb,YAAY,EACZ,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,MAAM,EACX,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,KAAK,WAAW,GACjB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,YAAY,EAAE,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACtE,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,KAAK,GAAG,EAAE,KAAK,SAAS,EAAE,KAAK,EAAE,EAAE,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AACtF,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,aAAa,EAAE,WAAW,EAAE,SAAS,EAAE,KAAK,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC7H,OAAO,EACL,mBAAmB,EACnB,SAAS,EACT,yBAAyB,EACzB,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,0BAA0B,GAChC,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAAE,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AAC1E,OAAO,EACL,YAAY,EACZ,oBAAoB,EACpB,YAAY,EACZ,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACrB,KAAK,UAAU,EACf,KAAK,kBAAkB,EACvB,KAAK,aAAa,GACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,KAAK,eAAe,EAAE,KAAK,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AACvG,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,KAAK,YAAY,EAAE,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC;AACpG,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,cAAc,EAAE,KAAK,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
// Public API of @softure-ai/core: the contract every SOFTURE module stands on
|
|
2
2
|
// (docs/02-module-standard.md). The Next.js registry is a separate entry: `@softure-ai/core/next`.
|
|
3
|
+
export { getCalendarDay, toCalendarDay } from "./calendar-day.js";
|
|
3
4
|
export { createTestClock, systemClock } from "./clock.js";
|
|
4
5
|
export { formatMessage, getMessage, isLocale, LOCALES, mergeMessages, selectPlural, } from "./i18n.js";
|
|
5
6
|
export { coreMessages } from "./messages/index.js";
|
|
6
7
|
export { err, ok } from "./result.js";
|
|
7
|
-
export { errorLogLabel, safeError } from "./safe-error.js";
|
|
8
|
+
export { errorLogLabel, getPublicMessage, isPublicError, PublicError, safeError } from "./safe-error.js";
|
|
8
9
|
export { defineSoftureConfig, getModule, sortModulesByDependencies, } from "./config.js";
|
|
9
10
|
export { SoftureConfigError } from "./config-error.js";
|
|
10
11
|
export { withDatabaseOptional } from "./database-requirement.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,mGAAmG;AACnG,OAAO,EAAE,eAAe,EAAE,WAAW,EAA8B,MAAM,YAAY,CAAC;AACtF,OAAO,EACL,aAAa,EACb,UAAU,EACV,QAAQ,EACR,OAAO,EACP,aAAa,EACb,YAAY,GAOb,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,YAAY,EAAqB,MAAM,qBAAqB,CAAC;AACtE,OAAO,EAAE,GAAG,EAAE,EAAE,EAAkD,MAAM,aAAa,CAAC;AACtF,OAAO,EAAE,aAAa,EAAE,SAAS,EAAsB,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,mGAAmG;AACnG,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,WAAW,EAA8B,MAAM,YAAY,CAAC;AACtF,OAAO,EACL,aAAa,EACb,UAAU,EACV,QAAQ,EACR,OAAO,EACP,aAAa,EACb,YAAY,GAOb,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,YAAY,EAAqB,MAAM,qBAAqB,CAAC;AACtE,OAAO,EAAE,GAAG,EAAE,EAAE,EAAkD,MAAM,aAAa,CAAC;AACtF,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,aAAa,EAAE,WAAW,EAAE,SAAS,EAAsB,MAAM,iBAAiB,CAAC;AAC7H,OAAO,EACL,mBAAmB,EACnB,SAAS,EACT,yBAAyB,GAM1B,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAAuB,MAAM,eAAe,CAAC;AAC1E,OAAO,EACL,YAAY,EACZ,oBAAoB,EACpB,YAAY,GAUb,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAuC,MAAM,gBAAgB,CAAC;AACvG,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAyC,MAAM,eAAe,CAAC;AACpG,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,cAAc,EAAmC,MAAM,oBAAoB,CAAC"}
|
package/dist/module.d.ts
CHANGED
|
@@ -38,6 +38,9 @@ export interface ModuleMigrations {
|
|
|
38
38
|
* Write this instead of `new URL("../migrations/", import.meta.url)`: bundlers (Next.js Turbopack)
|
|
39
39
|
* treat that literal form as an asset import and fail the app's build on a folder. Only
|
|
40
40
|
* `softure migrate` reads the folder, under plain Node, where both forms give the same URL.
|
|
41
|
+
*
|
|
42
|
+
* ESM only: a CJS bundle (esbuild `--format=cjs`) empties `import.meta`, so the URL is undefined and
|
|
43
|
+
* this throws naming the bundle format instead of a bare "Invalid URL".
|
|
41
44
|
*/
|
|
42
45
|
export declare function resolveMigrationsDir(moduleUrl: string | URL, relativePath: string): URL;
|
|
43
46
|
type RouteMap = Readonly<Record<string, string>>;
|
package/dist/module.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,OAAO,EAAiB,KAAK,YAAY,EAAE,KAAK,gBAAgB,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AACtG,OAAO,EAAwB,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AAC1E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,qFAAqF;AACrF,MAAM,WAAW,aAAa,CAAC,SAAS,GAAG,OAAO;IAChD,iCAAiC;IACjC,QAAQ,CAAC,EAAE,EAAE,SAAS,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;CAChC;AAED;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;IAC/F,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;CAClG;AAED;;;;GAIG;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,EAAE,aAAa,KAAK,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;AAEjF,MAAM,WAAW,gBAAgB;IAC/B,yGAAyG;IACzG,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;CACnB;AAED
|
|
1
|
+
{"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"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"}
|
package/dist/module.js
CHANGED
|
@@ -8,8 +8,15 @@ import { moduleManifestSchema } from "./manifest.js";
|
|
|
8
8
|
* Write this instead of `new URL("../migrations/", import.meta.url)`: bundlers (Next.js Turbopack)
|
|
9
9
|
* treat that literal form as an asset import and fail the app's build on a folder. Only
|
|
10
10
|
* `softure migrate` reads the folder, under plain Node, where both forms give the same URL.
|
|
11
|
+
*
|
|
12
|
+
* ESM only: a CJS bundle (esbuild `--format=cjs`) empties `import.meta`, so the URL is undefined and
|
|
13
|
+
* this throws naming the bundle format instead of a bare "Invalid URL".
|
|
11
14
|
*/
|
|
12
15
|
export function resolveMigrationsDir(moduleUrl, relativePath) {
|
|
16
|
+
// The type says string | URL; a CJS bundle still passes undefined at runtime.
|
|
17
|
+
if (moduleUrl === undefined || moduleUrl === "") {
|
|
18
|
+
throw new Error("resolveMigrationsDir: no module URL (import.meta.url is undefined), so this code runs from a CJS bundle; SOFTURE packages are ESM only, bundle with --format=esm");
|
|
19
|
+
}
|
|
13
20
|
return new URL(relativePath, moduleUrl);
|
|
14
21
|
}
|
|
15
22
|
/**
|
package/dist/module.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module.js","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACrE,OAAO,EAAE,aAAa,EAA8D,MAAM,WAAW,CAAC;AACtG,OAAO,EAAE,oBAAoB,EAAuB,MAAM,eAAe,CAAC;AAkC1E
|
|
1
|
+
{"version":3,"file":"module.js","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"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"}
|
package/dist/safe-error.d.ts
CHANGED
|
@@ -5,10 +5,28 @@ export type CoreErrorCode = "core.database_failed" | "core.unexpected";
|
|
|
5
5
|
* The caller logs `errorLogLabel(error)` when it needs a trace.
|
|
6
6
|
*/
|
|
7
7
|
export declare function safeError(error: unknown): Err<CoreErrorCode>;
|
|
8
|
+
declare const PUBLIC_ERROR_BRAND: unique symbol;
|
|
9
|
+
/**
|
|
10
|
+
* An error whose message is written for the user ("This plan has ended; pick another one."), thrown
|
|
11
|
+
* deliberately by domain code. Its message is safe to show; every other error's is not. Branded with
|
|
12
|
+
* a registry symbol, so it is still recognised when an app ends up with two copies of core.
|
|
13
|
+
*/
|
|
14
|
+
export declare class PublicError extends Error {
|
|
15
|
+
readonly [PUBLIC_ERROR_BRAND] = true;
|
|
16
|
+
constructor(message: string, options?: ErrorOptions);
|
|
17
|
+
}
|
|
18
|
+
/** Whether `error` is a `PublicError`, from this copy of core or another. */
|
|
19
|
+
export declare function isPublicError(error: unknown): error is PublicError;
|
|
20
|
+
/**
|
|
21
|
+
* The message of a `PublicError`, or `null` for anything else: the pass-through for deliberate
|
|
22
|
+
* domain messages, next to `safeError` for the rest (`getPublicMessage(error) ?? t(safeError(error).error)`).
|
|
23
|
+
*/
|
|
24
|
+
export declare function getPublicMessage(error: unknown): string | null;
|
|
8
25
|
/**
|
|
9
26
|
* A log label for an error on a path that handles personal data: the kind of error, never its
|
|
10
27
|
* text. Returns the class name and, when present, the Postgres SQLSTATE (also looked up on
|
|
11
28
|
* `cause`, where Drizzle keeps the driver error).
|
|
12
29
|
*/
|
|
13
30
|
export declare function errorLogLabel(error: unknown): string;
|
|
31
|
+
export {};
|
|
14
32
|
//# sourceMappingURL=safe-error.d.ts.map
|
package/dist/safe-error.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"safe-error.d.ts","sourceRoot":"","sources":["../src/safe-error.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"safe-error.d.ts","sourceRoot":"","sources":["../src/safe-error.ts"],"names":[],"mappings":"AAKA,OAAO,EAAO,KAAK,GAAG,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,MAAM,aAAa,GAAG,sBAAsB,GAAG,iBAAiB,CAAC;AAEvE;;;GAGG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,GAAG,CAAC,aAAa,CAAC,CAE5D;AAED,QAAA,MAAM,kBAAkB,eAAqC,CAAC;AAE9D;;;;GAIG;AACH,qBAAa,WAAY,SAAQ,KAAK;IACpC,QAAQ,CAAC,CAAC,kBAAkB,CAAC,QAAQ;gBAEzB,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAIpD;AAED,6EAA6E;AAC7E,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,WAAW,CAElE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAE9D;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAOpD"}
|
package/dist/safe-error.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
// Turning a caught error into something safe to hand outside the process
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
1
|
+
// Turning a caught error into something safe to hand outside the process: a Drizzle
|
|
2
|
+
// `Failed query: … params: …` once reached a chat transcript through a success payload. The
|
|
3
|
+
// scrubbing happens where the error is caught, so a value that never carried the SQL cannot leak
|
|
4
|
+
// it later. Copy for the codes lives in `messages`. The one exception is a `PublicError`, whose
|
|
5
|
+
// message the code wrote for the user on purpose; `getPublicMessage` hands that text out.
|
|
5
6
|
import { err } from "./result.js";
|
|
6
7
|
/**
|
|
7
8
|
* A failure result for an unexpected error, with nothing of the error's text in it.
|
|
@@ -10,6 +11,30 @@ import { err } from "./result.js";
|
|
|
10
11
|
export function safeError(error) {
|
|
11
12
|
return err(isDatabaseError(error) ? "core.database_failed" : "core.unexpected");
|
|
12
13
|
}
|
|
14
|
+
const PUBLIC_ERROR_BRAND = Symbol.for("softure.public-error");
|
|
15
|
+
/**
|
|
16
|
+
* An error whose message is written for the user ("This plan has ended; pick another one."), thrown
|
|
17
|
+
* deliberately by domain code. Its message is safe to show; every other error's is not. Branded with
|
|
18
|
+
* a registry symbol, so it is still recognised when an app ends up with two copies of core.
|
|
19
|
+
*/
|
|
20
|
+
export class PublicError extends Error {
|
|
21
|
+
[PUBLIC_ERROR_BRAND] = true;
|
|
22
|
+
constructor(message, options) {
|
|
23
|
+
super(message, options);
|
|
24
|
+
this.name = "PublicError";
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/** Whether `error` is a `PublicError`, from this copy of core or another. */
|
|
28
|
+
export function isPublicError(error) {
|
|
29
|
+
return error instanceof Error && error[PUBLIC_ERROR_BRAND] === true;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The message of a `PublicError`, or `null` for anything else: the pass-through for deliberate
|
|
33
|
+
* domain messages, next to `safeError` for the rest (`getPublicMessage(error) ?? t(safeError(error).error)`).
|
|
34
|
+
*/
|
|
35
|
+
export function getPublicMessage(error) {
|
|
36
|
+
return isPublicError(error) ? error.message : null;
|
|
37
|
+
}
|
|
13
38
|
/**
|
|
14
39
|
* A log label for an error on a path that handles personal data: the kind of error, never its
|
|
15
40
|
* text. Returns the class name and, when present, the Postgres SQLSTATE (also looked up on
|
package/dist/safe-error.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"safe-error.js","sourceRoot":"","sources":["../src/safe-error.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"safe-error.js","sourceRoot":"","sources":["../src/safe-error.ts"],"names":[],"mappings":"AAAA,oFAAoF;AACpF,4FAA4F;AAC5F,iGAAiG;AACjG,gGAAgG;AAChG,0FAA0F;AAC1F,OAAO,EAAE,GAAG,EAAY,MAAM,aAAa,CAAC;AAI5C;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,KAAc;IACtC,OAAO,GAAG,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC;AAClF,CAAC;AAED,MAAM,kBAAkB,GAAG,MAAM,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;AAE9D;;;;GAIG;AACH,MAAM,OAAO,WAAY,SAAQ,KAAK;IAC3B,CAAC,kBAAkB,CAAC,GAAG,IAAI,CAAC;IAErC,YAAY,OAAe,EAAE,OAAsB;QACjD,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC5B,CAAC;CACF;AAED,6EAA6E;AAC7E,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,OAAO,KAAK,YAAY,KAAK,IAAK,KAAoD,CAAC,kBAAkB,CAAC,KAAK,IAAI,CAAC;AACtH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAc;IAC7C,OAAO,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;AACrD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,IAAI,CAAC,CAAC,KAAK,YAAY,KAAK,CAAC,EAAE,CAAC;QAC9B,OAAO,OAAO,KAAK,CAAC;IACtB,CAAC;IAED,MAAM,IAAI,GAAG,YAAY,CAAC,KAAK,CAAC,IAAI,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC9D,OAAO,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,IAAI,SAAS,IAAI,EAAE,CAAC;AACnE,CAAC;AAED,SAAS,eAAe,CAAC,KAAc;IACrC,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5D,4DAA4D;IAC5D,IAAI,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACnC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,8FAA8F;IAC9F,8DAA8D;IAC9D,OAAO,gCAAgC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AACxD,CAAC;AAED,8EAA8E;AAC9E,SAAS,YAAY,CAAC,KAAc;IAClC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC,EAAE,CAAC;QACtE,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;IACxB,OAAO,OAAO,IAAI,KAAK,QAAQ,IAAI,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AAC9E,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@softure-ai/core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"description": "The SOFTURE AI module contract: app config, module definitions, Result, Clock and messages.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
},
|
|
16
16
|
"files": [
|
|
17
17
|
"dist",
|
|
18
|
+
"CHANGELOG.md",
|
|
18
19
|
"src",
|
|
19
20
|
"!src/**/*.test.ts",
|
|
20
21
|
"!src/**/*.test.tsx"
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// The calendar day of an instant in a given IANA time zone, as `YYYY-MM-DD`. "Today" computed in the
|
|
2
|
+
// process zone is a classic date bug: on a server in UTC, an evening in New York is already tomorrow.
|
|
3
|
+
import type { Clock } from "./clock.js";
|
|
4
|
+
|
|
5
|
+
const formatters = new Map<string, Intl.DateTimeFormat>();
|
|
6
|
+
|
|
7
|
+
/** The calendar day (`YYYY-MM-DD`) of `instant` in `timeZone`. Throws a `RangeError` for an invalid date or zone. */
|
|
8
|
+
export function toCalendarDay(instant: Date, timeZone: string): string {
|
|
9
|
+
if (Number.isNaN(instant.getTime())) {
|
|
10
|
+
throw new RangeError("toCalendarDay: invalid date");
|
|
11
|
+
}
|
|
12
|
+
// Parts, not the formatted string: a locale's date pattern (`en-CA`) has changed between ICU versions.
|
|
13
|
+
const parts = getFormatter(timeZone).formatToParts(instant);
|
|
14
|
+
const readPart = (type: Intl.DateTimeFormatPartTypes): string => parts.find((part) => part.type === type)?.value ?? "";
|
|
15
|
+
return `${readPart("year").padStart(4, "0")}-${readPart("month")}-${readPart("day")}`;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** Today's calendar day (`YYYY-MM-DD`) in `timeZone`, read from `clock`. */
|
|
19
|
+
export function getCalendarDay(clock: Clock, timeZone: string): string {
|
|
20
|
+
return toCalendarDay(clock.now(), timeZone);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function getFormatter(timeZone: string): Intl.DateTimeFormat {
|
|
24
|
+
let format = formatters.get(timeZone);
|
|
25
|
+
if (format === undefined) {
|
|
26
|
+
format = createFormatter(timeZone);
|
|
27
|
+
formatters.set(timeZone, format);
|
|
28
|
+
}
|
|
29
|
+
return format;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function createFormatter(timeZone: string): Intl.DateTimeFormat {
|
|
33
|
+
try {
|
|
34
|
+
return new Intl.DateTimeFormat("en-US", { timeZone, year: "numeric", month: "2-digit", day: "2-digit" });
|
|
35
|
+
} catch (error) {
|
|
36
|
+
throw new RangeError(`toCalendarDay: "${timeZone}" is not an IANA time zone`, { cause: error });
|
|
37
|
+
}
|
|
38
|
+
}
|
package/src/config.ts
CHANGED
|
@@ -8,9 +8,37 @@ import type { AnySoftureModule } from "./module.js";
|
|
|
8
8
|
import { err, ok, type Result } from "./result.js";
|
|
9
9
|
import { parseVersionRange, satisfiesRange } from "./version-range.js";
|
|
10
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Filled by `@softure-ai/db` through declaration merging with `{ handle: DatabaseHandle }`, so `database.handle`
|
|
13
|
+
* is typed wherever db's types are loaded. Core cannot import db (db depends on core).
|
|
14
|
+
*/
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-object-type -- an augmentation point, empty on purpose
|
|
16
|
+
export interface SoftureDatabaseHandleTypes {}
|
|
17
|
+
|
|
18
|
+
/** The handle `database.handle` returns: db's `DatabaseHandle`, or `unknown` where db's types are not loaded. */
|
|
19
|
+
export type SoftureDatabaseHandle = SoftureDatabaseHandleTypes extends { readonly handle: infer Handle } ? Handle : unknown;
|
|
20
|
+
|
|
21
|
+
type MaybePromise<T> = T | Promise<T>;
|
|
22
|
+
|
|
23
|
+
export interface SoftureDatabaseConfig {
|
|
24
|
+
readonly url: string;
|
|
25
|
+
/**
|
|
26
|
+
* The app's own database handle, for an app that already has a client: every module, the health route and
|
|
27
|
+
* every package command then query through it instead of opening a second handle on `url` (with `pglite://`,
|
|
28
|
+
* a second PGlite instance on one directory corrupts it). Called on first use, not when the config is defined,
|
|
29
|
+
* so a build never connects. It must return the app's process-wide handle (memoized, e.g. on `globalThis`):
|
|
30
|
+
* `next dev` re-evaluates the config and calls a new function after each reload. Wrap a client with
|
|
31
|
+
* `createPostgresHandle(pool)` or `createPgliteHandle(client)` from `@softure-ai/db`.
|
|
32
|
+
*/
|
|
33
|
+
readonly handle?: () => MaybePromise<SoftureDatabaseHandle>;
|
|
34
|
+
}
|
|
35
|
+
|
|
11
36
|
export interface SoftureConfig {
|
|
12
|
-
/**
|
|
13
|
-
|
|
37
|
+
/**
|
|
38
|
+
* `null` when the app has no database; required as soon as a module has a `dbSchema`. An empty `url`
|
|
39
|
+
* (`DATABASE_URL` unset, as in a build step) is accepted here and refused by the first connection.
|
|
40
|
+
*/
|
|
41
|
+
readonly database: SoftureDatabaseConfig | null;
|
|
14
42
|
readonly locale: Locale;
|
|
15
43
|
/** IANA time zone used for every date shown or computed per calendar day. */
|
|
16
44
|
readonly timezone: string;
|
|
@@ -22,7 +50,7 @@ export interface SoftureConfig {
|
|
|
22
50
|
|
|
23
51
|
/** What the app writes in `softure.config.ts`. */
|
|
24
52
|
export interface SoftureConfigInput {
|
|
25
|
-
readonly database?:
|
|
53
|
+
readonly database?: SoftureDatabaseConfig | null;
|
|
26
54
|
readonly locale: Locale;
|
|
27
55
|
readonly timezone: string;
|
|
28
56
|
readonly appOrigin: string;
|
|
@@ -32,8 +60,15 @@ export interface SoftureConfigInput {
|
|
|
32
60
|
const CONFIG_SUBJECT = "softure.config (defineSoftureConfig)";
|
|
33
61
|
|
|
34
62
|
const configSchema = z.object({
|
|
63
|
+
// The URL is not checked for emptiness here: builds import the config without DATABASE_URL, so an empty URL is
|
|
64
|
+
// refused when something connects (`createDatabase` in @softure-ai/db), not when the config is defined.
|
|
35
65
|
database: z
|
|
36
|
-
.object({
|
|
66
|
+
.object({
|
|
67
|
+
url: z.string(),
|
|
68
|
+
handle: z
|
|
69
|
+
.custom<NonNullable<SoftureDatabaseConfig["handle"]>>((value) => typeof value === "function", "must be a function returning the app's database handle")
|
|
70
|
+
.optional(),
|
|
71
|
+
})
|
|
37
72
|
.nullable()
|
|
38
73
|
.default(null),
|
|
39
74
|
locale: z.enum(LOCALES),
|
package/src/i18n.ts
CHANGED
|
@@ -57,10 +57,16 @@ export function formatMessage(template: string, params: Readonly<Record<string,
|
|
|
57
57
|
});
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
const pluralRulesByLocale = new Map<Locale, Intl.PluralRules>();
|
|
61
|
+
|
|
60
62
|
/** The form for `count` under the plural rules of `locale` ("1 file", "2 files"). */
|
|
61
63
|
export function selectPlural(locale: Locale, count: number, forms: PluralForms): string {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
+
let rules = pluralRulesByLocale.get(locale);
|
|
65
|
+
if (rules === undefined) {
|
|
66
|
+
rules = new Intl.PluralRules(locale);
|
|
67
|
+
pluralRulesByLocale.set(locale, rules);
|
|
68
|
+
}
|
|
69
|
+
return forms[rules.select(count)] ?? forms.other;
|
|
64
70
|
}
|
|
65
71
|
|
|
66
72
|
/** The message at a dotted path (`login.title`), or `undefined` when there is no string there. */
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// Public API of @softure-ai/core: the contract every SOFTURE module stands on
|
|
2
2
|
// (docs/02-module-standard.md). The Next.js registry is a separate entry: `@softure-ai/core/next`.
|
|
3
|
+
export { getCalendarDay, toCalendarDay } from "./calendar-day.js";
|
|
3
4
|
export { createTestClock, systemClock, type Clock, type TestClock } from "./clock.js";
|
|
4
5
|
export {
|
|
5
6
|
formatMessage,
|
|
@@ -17,13 +18,16 @@ export {
|
|
|
17
18
|
} from "./i18n.js";
|
|
18
19
|
export { coreMessages, type CoreMessages } from "./messages/index.js";
|
|
19
20
|
export { err, ok, type Err, type ErrorCode, type Ok, type Result } from "./result.js";
|
|
20
|
-
export { errorLogLabel, safeError, type CoreErrorCode } from "./safe-error.js";
|
|
21
|
+
export { errorLogLabel, getPublicMessage, isPublicError, PublicError, safeError, type CoreErrorCode } from "./safe-error.js";
|
|
21
22
|
export {
|
|
22
23
|
defineSoftureConfig,
|
|
23
24
|
getModule,
|
|
24
25
|
sortModulesByDependencies,
|
|
25
26
|
type SoftureConfig,
|
|
26
27
|
type SoftureConfigInput,
|
|
28
|
+
type SoftureDatabaseConfig,
|
|
29
|
+
type SoftureDatabaseHandle,
|
|
30
|
+
type SoftureDatabaseHandleTypes,
|
|
27
31
|
} from "./config.js";
|
|
28
32
|
export { SoftureConfigError } from "./config-error.js";
|
|
29
33
|
export { withDatabaseOptional } from "./database-requirement.js";
|
package/src/module.ts
CHANGED
|
@@ -47,8 +47,17 @@ export interface ModuleMigrations {
|
|
|
47
47
|
* Write this instead of `new URL("../migrations/", import.meta.url)`: bundlers (Next.js Turbopack)
|
|
48
48
|
* treat that literal form as an asset import and fail the app's build on a folder. Only
|
|
49
49
|
* `softure migrate` reads the folder, under plain Node, where both forms give the same URL.
|
|
50
|
+
*
|
|
51
|
+
* ESM only: a CJS bundle (esbuild `--format=cjs`) empties `import.meta`, so the URL is undefined and
|
|
52
|
+
* this throws naming the bundle format instead of a bare "Invalid URL".
|
|
50
53
|
*/
|
|
51
54
|
export function resolveMigrationsDir(moduleUrl: string | URL, relativePath: string): URL {
|
|
55
|
+
// The type says string | URL; a CJS bundle still passes undefined at runtime.
|
|
56
|
+
if ((moduleUrl as string | URL | undefined) === undefined || moduleUrl === "") {
|
|
57
|
+
throw new Error(
|
|
58
|
+
"resolveMigrationsDir: no module URL (import.meta.url is undefined), so this code runs from a CJS bundle; SOFTURE packages are ESM only, bundle with --format=esm",
|
|
59
|
+
);
|
|
60
|
+
}
|
|
52
61
|
return new URL(relativePath, moduleUrl);
|
|
53
62
|
}
|
|
54
63
|
|
package/src/safe-error.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
// Turning a caught error into something safe to hand outside the process
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
1
|
+
// Turning a caught error into something safe to hand outside the process: a Drizzle
|
|
2
|
+
// `Failed query: … params: …` once reached a chat transcript through a success payload. The
|
|
3
|
+
// scrubbing happens where the error is caught, so a value that never carried the SQL cannot leak
|
|
4
|
+
// it later. Copy for the codes lives in `messages`. The one exception is a `PublicError`, whose
|
|
5
|
+
// message the code wrote for the user on purpose; `getPublicMessage` hands that text out.
|
|
5
6
|
import { err, type Err } from "./result.js";
|
|
6
7
|
|
|
7
8
|
export type CoreErrorCode = "core.database_failed" | "core.unexpected";
|
|
@@ -14,6 +15,35 @@ export function safeError(error: unknown): Err<CoreErrorCode> {
|
|
|
14
15
|
return err(isDatabaseError(error) ? "core.database_failed" : "core.unexpected");
|
|
15
16
|
}
|
|
16
17
|
|
|
18
|
+
const PUBLIC_ERROR_BRAND = Symbol.for("softure.public-error");
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* An error whose message is written for the user ("This plan has ended; pick another one."), thrown
|
|
22
|
+
* deliberately by domain code. Its message is safe to show; every other error's is not. Branded with
|
|
23
|
+
* a registry symbol, so it is still recognised when an app ends up with two copies of core.
|
|
24
|
+
*/
|
|
25
|
+
export class PublicError extends Error {
|
|
26
|
+
readonly [PUBLIC_ERROR_BRAND] = true;
|
|
27
|
+
|
|
28
|
+
constructor(message: string, options?: ErrorOptions) {
|
|
29
|
+
super(message, options);
|
|
30
|
+
this.name = "PublicError";
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Whether `error` is a `PublicError`, from this copy of core or another. */
|
|
35
|
+
export function isPublicError(error: unknown): error is PublicError {
|
|
36
|
+
return error instanceof Error && (error as Error & { [PUBLIC_ERROR_BRAND]?: unknown })[PUBLIC_ERROR_BRAND] === true;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* The message of a `PublicError`, or `null` for anything else: the pass-through for deliberate
|
|
41
|
+
* domain messages, next to `safeError` for the rest (`getPublicMessage(error) ?? t(safeError(error).error)`).
|
|
42
|
+
*/
|
|
43
|
+
export function getPublicMessage(error: unknown): string | null {
|
|
44
|
+
return isPublicError(error) ? error.message : null;
|
|
45
|
+
}
|
|
46
|
+
|
|
17
47
|
/**
|
|
18
48
|
* A log label for an error on a path that handles personal data: the kind of error, never its
|
|
19
49
|
* text. Returns the class name and, when present, the Postgres SQLSTATE (also looked up on
|