@isaijs/core 0.1.5 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/storage/r2/index.d.ts +3 -0
- package/dist/adapters/storage/r2/index.js +13 -2
- package/dist/auth/index.d.ts +2 -2
- package/dist/auth/index.js +2 -2
- package/dist/cli/index.js +79 -11
- package/dist/client/index.d.ts +4 -0
- package/dist/client/index.js +18 -13
- package/dist/{create-auth-BHdX68Ng.js → create-auth-BCvMwlVD.js} +18 -10
- package/dist/{data-layer-C5oJZ8V1.js → data-layer-CVCFjPyv.js} +15 -10
- package/dist/{data-layer-43pme0Gy.d.ts → data-layer-nvm_ivGQ.d.ts} +6 -2
- package/dist/db/index.d.ts +2 -2
- package/dist/db/index.js +5 -5
- package/dist/{index-D0FEnMhn.d.ts → index-Bb9Px6SR.d.ts} +116 -22
- package/dist/{index-CYcklQ1l.d.ts → index-CaR3hb0i.d.ts} +5 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +169 -79
- package/dist/{make-ByA-84h8.js → make-jMJABOWI.js} +21 -3
- package/dist/{makers-P9kg68C8.js → makers-A0Pj6Tda.js} +3 -3
- package/dist/{migrator-B25prc9n.js → migrator-DxTpns_-.js} +174 -30
- package/dist/{model-Dc3HunKb.js → model-6pJBqqGd.js} +31 -1
- package/dist/{policies-KsqmlX67.js → policies-C_oiSgmY.js} +1 -1
- package/dist/{resource-BQK7bkPQ.js → resource-BIMAiOre.js} +8 -6
- package/dist/{tables-DgSwge7s.js → tables-DjW96Ubl.js} +1 -1
- package/dist/testing/index.d.ts +1 -1
- package/dist/testing/index.js +4 -4
- package/dist/{types-BgOkJy5d.d.ts → types-D5SIVeej.d.ts} +59 -2
- package/dist/validation/index.d.ts +2 -2
- package/dist/validation/index.js +1 -1
- package/dist/{validation-Cppmd0RV.js → validation-C3MCRBQO.js} +26 -3
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { A as mapOperands, B as aroundDelete, F as unbound, H as aroundUpsert, I as fromBase64url$1, K as wrap, L as toBase64url, M as readsNow, N as readsOtherRows, O as storageOf, P as tableTotals, R as actionEntry, V as aroundUpdate, W as assertNotLog, _ as Expr, c as rowOf$1, h as Condition, i as columnNode, k as fieldsOf, l as IMPLICIT_FIELDS, n as assertNotEncrypted, o as fieldOf, r as columnName, v as Now, w as conditionNode, z as aroundCreate } from "./model-
|
|
1
|
+
import { P as id, q as ValidationError } from "./validation-C3MCRBQO.js";
|
|
2
|
+
import { A as mapOperands, B as aroundDelete, F as unbound, H as aroundUpsert, I as fromBase64url$1, K as wrap, L as toBase64url, M as readsNow, N as readsOtherRows, O as storageOf, P as tableTotals, R as actionEntry, V as aroundUpdate, W as assertNotLog, _ as Expr, c as rowOf$1, h as Condition, i as columnNode, k as fieldsOf, l as IMPLICIT_FIELDS, n as assertNotEncrypted, o as fieldOf, r as columnName, v as Now, w as conditionNode, z as aroundCreate } from "./model-6pJBqqGd.js";
|
|
3
3
|
import { r as ulid } from "./case-DpXlJCL9.js";
|
|
4
4
|
import { t as NotImplementedError } from "./errors-mCNLlXg9.js";
|
|
5
5
|
//#region src/db/errors.ts
|
|
@@ -814,13 +814,28 @@ function onConflict(model, conflict, writer) {
|
|
|
814
814
|
if ("fromInsert" in action) return `${target} DO UPDATE SET ${action.fromInsert.map((field) => `${column(model, field)} = excluded.${column(model, field)}`).join(", ")}`;
|
|
815
815
|
return `${target} DO UPDATE SET ${writer.set(action.set)}`;
|
|
816
816
|
}
|
|
817
|
+
/**
|
|
818
|
+
* A select. With a limit, computed fields are worked out for the rows it returns only: an inner
|
|
819
|
+
* query picks them (filtered, sorted, limited), and the outer one adds the computed values. SQLite
|
|
820
|
+
* otherwise works out every select-list subquery for every matching row before it sorts (a page of
|
|
821
|
+
* 24 products would price all 800 in their category), and each of those reads is billed. Not when
|
|
822
|
+
* the order is by a computed value: the inner query couldn't sort by it.
|
|
823
|
+
*/
|
|
817
824
|
function select(model, query, context) {
|
|
818
825
|
return withinLimit(context, (mode) => {
|
|
819
826
|
const writer = new Writer(model, mode, context);
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
827
|
+
const table = quote(model.table);
|
|
828
|
+
const order = query.order.length > 0 ? ` ORDER BY ${query.order.map(({ field, direction }) => `${column(model, field)} ${direction.toUpperCase()}`).join(", ")}` : "";
|
|
829
|
+
const limited = query.limit !== void 0 || query.offset !== void 0;
|
|
830
|
+
const computed = Object.values(model.fields).some((spec) => spec.computed);
|
|
831
|
+
const sortsByComputed = query.order.some(({ field }) => model.fields[field]?.computed);
|
|
832
|
+
const selection = writer.selection();
|
|
833
|
+
const inner = limited && computed && !sortsByComputed;
|
|
834
|
+
let text = inner ? `SELECT * FROM ${table}` : `SELECT ${selection} FROM ${table}`;
|
|
835
|
+
text += writer.where(query.where) + order;
|
|
836
|
+
if (limited) text += ` LIMIT ${writer.value(query.limit ?? -1)}`;
|
|
823
837
|
if (query.offset !== void 0) text += ` OFFSET ${writer.value(query.offset)}`;
|
|
838
|
+
if (inner) text = `SELECT ${selection} FROM (${text}) AS ${table}${order}`;
|
|
824
839
|
return writer.sql(text);
|
|
825
840
|
});
|
|
826
841
|
}
|
|
@@ -1037,7 +1052,23 @@ function columnDefinition(column) {
|
|
|
1037
1052
|
return definition;
|
|
1038
1053
|
}
|
|
1039
1054
|
function createTable(table) {
|
|
1040
|
-
|
|
1055
|
+
const columns = table.columns.map(columnDefinition).join(", ");
|
|
1056
|
+
return `CREATE TABLE ${quote(table.name)} (${columns})${table.withoutRowid ? " WITHOUT ROWID" : ""}`;
|
|
1057
|
+
}
|
|
1058
|
+
/** Where a rebuilt table's old rows wait while the new table is filled. */
|
|
1059
|
+
const aside = (table) => quote(`_isai_rebuild_${table}`);
|
|
1060
|
+
/** `operations.ts` → rebuild, in SQLite: one atomic step, its foreign keys checked at the end. */
|
|
1061
|
+
function rebuild(operation) {
|
|
1062
|
+
const { tables, copy, triggers } = operation;
|
|
1063
|
+
const columns = (table) => (copy[table] ?? []).map(quote).join(", ");
|
|
1064
|
+
return [
|
|
1065
|
+
"PRAGMA defer_foreign_keys = ON",
|
|
1066
|
+
...triggers.map((name) => `DROP TRIGGER IF EXISTS ${quote(name)}`),
|
|
1067
|
+
...tables.map((table) => `ALTER TABLE ${quote(table.name)} RENAME TO ${aside(table.name)}`),
|
|
1068
|
+
...tables.map(createTable),
|
|
1069
|
+
...tables.filter((table) => (copy[table.name] ?? []).length > 0).map((table) => `INSERT INTO ${quote(table.name)} (${columns(table.name)}) SELECT ${columns(table.name)} FROM ${aside(table.name)}`),
|
|
1070
|
+
...[...tables].reverse().map((table) => `DROP TABLE ${aside(table.name)}`)
|
|
1071
|
+
];
|
|
1041
1072
|
}
|
|
1042
1073
|
function createIndex(table, index) {
|
|
1043
1074
|
const columns = index.columns.map(quote).join(", ");
|
|
@@ -1229,6 +1260,7 @@ function render(operation) {
|
|
|
1229
1260
|
case "dropRule": return [`DROP ${operation.rule.kind.toUpperCase()} IF EXISTS ${quote(operation.rule.name)}`];
|
|
1230
1261
|
case "dropColumn": return [`ALTER TABLE ${quote(operation.table)} DROP COLUMN ${quote(operation.column.name)}`, ...dropCounter(operation.table, operation.column)];
|
|
1231
1262
|
case "dropTable": return [`DROP TABLE ${quote(operation.table.name)}`, ...operation.table.columns.flatMap((column) => dropCounter(operation.table.name, column))];
|
|
1263
|
+
case "rebuild": return rebuild(operation);
|
|
1232
1264
|
}
|
|
1233
1265
|
}
|
|
1234
1266
|
//#endregion
|
|
@@ -1500,10 +1532,15 @@ var Engine = class Engine {
|
|
|
1500
1532
|
};
|
|
1501
1533
|
//#endregion
|
|
1502
1534
|
//#region src/db/orm/include.ts
|
|
1535
|
+
/** How the boundary gives a query its `IncludeRule`: internal, so the app's API never shows it. */
|
|
1536
|
+
const withIncludeRule = Symbol("isai.withIncludeRule");
|
|
1503
1537
|
/** The rows of `model` whose `field` is one of `values`. */
|
|
1504
|
-
async function rowsWhereIn(engine, model, field, values) {
|
|
1538
|
+
async function rowsWhereIn(engine, model, field, values, rule) {
|
|
1505
1539
|
const spec = fieldOf(model, field);
|
|
1506
1540
|
if (!spec) throw new TypeError(`isai: ${model.name} has no field "${field}"`);
|
|
1541
|
+
if (values.length === 0) return [];
|
|
1542
|
+
const allowed = rule ? await rule(model) : void 0;
|
|
1543
|
+
if (allowed === false) return [];
|
|
1507
1544
|
const chunk = engine.driver.capabilities.maxBoundParams;
|
|
1508
1545
|
const found = [];
|
|
1509
1546
|
for (let start = 0; start < values.length; start += chunk) {
|
|
@@ -1513,7 +1550,7 @@ async function rowsWhereIn(engine, model, field, values) {
|
|
|
1513
1550
|
values: values.slice(start, start + chunk)
|
|
1514
1551
|
};
|
|
1515
1552
|
found.push(...await engine.read(model, {
|
|
1516
|
-
where: [where],
|
|
1553
|
+
where: allowed ? [where, allowed] : [where],
|
|
1517
1554
|
order: [{
|
|
1518
1555
|
field: "id",
|
|
1519
1556
|
direction: "asc"
|
|
@@ -1535,27 +1572,27 @@ function byHead(paths) {
|
|
|
1535
1572
|
}
|
|
1536
1573
|
return groups;
|
|
1537
1574
|
}
|
|
1538
|
-
async function loadIncludes(engine, model, registry, rows, paths) {
|
|
1575
|
+
async function loadIncludes(engine, model, registry, rows, paths, rule) {
|
|
1539
1576
|
if (rows.length === 0 || paths.length === 0) return;
|
|
1540
1577
|
for (const [head, tails] of byHead(paths)) {
|
|
1541
1578
|
const ref = fieldOf(model, head)?.ref;
|
|
1542
1579
|
if (ref) {
|
|
1543
1580
|
const target = registry.get(ref.model);
|
|
1544
|
-
const found = await rowsWhereIn(engine, target, "id", [...new Set(rows.map((row) => row[head]).filter((id) => id !== null && id !== void 0))]);
|
|
1545
|
-
await loadIncludes(engine, target, registry, found, tails);
|
|
1581
|
+
const found = await rowsWhereIn(engine, target, "id", [...new Set(rows.map((row) => row[head]).filter((id) => id !== null && id !== void 0))], rule);
|
|
1582
|
+
await loadIncludes(engine, target, registry, found, tails, rule);
|
|
1546
1583
|
const byId = new Map(found.map((row) => [row.id, row]));
|
|
1547
1584
|
for (const row of rows) row[head] = row[head] === null ? null : byId.get(row[head]) ?? null;
|
|
1548
1585
|
continue;
|
|
1549
1586
|
}
|
|
1550
1587
|
const relation = registry.relation(model.name, head);
|
|
1551
1588
|
if (!relation) throw new TypeError(`isai: ${model.name} has no ref or relation named "${head}"`);
|
|
1552
|
-
const found = await rowsWhereIn(engine, relation.model, relation.field, rows.map((row) => row.id));
|
|
1589
|
+
const found = await rowsWhereIn(engine, relation.model, relation.field, rows.map((row) => row.id), rule);
|
|
1553
1590
|
const groups = /* @__PURE__ */ new Map();
|
|
1554
1591
|
for (const row of found) {
|
|
1555
1592
|
const owner = row[relation.field];
|
|
1556
1593
|
groups.set(owner, [...groups.get(owner) ?? [], row]);
|
|
1557
1594
|
}
|
|
1558
|
-
await loadIncludes(engine, relation.model, registry, found, tails);
|
|
1595
|
+
await loadIncludes(engine, relation.model, registry, found, tails, rule);
|
|
1559
1596
|
for (const row of rows) row[head] = groups.get(row.id) ?? [];
|
|
1560
1597
|
}
|
|
1561
1598
|
}
|
|
@@ -1707,15 +1744,21 @@ var Query = class Query {
|
|
|
1707
1744
|
target;
|
|
1708
1745
|
query;
|
|
1709
1746
|
paths;
|
|
1747
|
+
rule;
|
|
1710
1748
|
constructor(engine, target, query = {
|
|
1711
1749
|
where: [],
|
|
1712
1750
|
order: [],
|
|
1713
1751
|
limit: void 0
|
|
1714
|
-
}, paths = []) {
|
|
1752
|
+
}, paths = [], rule) {
|
|
1715
1753
|
this.engine = engine;
|
|
1716
1754
|
this.target = target;
|
|
1717
1755
|
this.query = query;
|
|
1718
1756
|
this.paths = paths;
|
|
1757
|
+
this.rule = rule;
|
|
1758
|
+
}
|
|
1759
|
+
/** The same query, its includes held to `rule` (the boundary's; `./include`). */
|
|
1760
|
+
[withIncludeRule](rule) {
|
|
1761
|
+
return new Query(this.engine, this.target, this.query, this.paths, rule);
|
|
1719
1762
|
}
|
|
1720
1763
|
/** Repeated calls are ANDed. */
|
|
1721
1764
|
where(build) {
|
|
@@ -1739,7 +1782,7 @@ var Query = class Query {
|
|
|
1739
1782
|
}
|
|
1740
1783
|
/** Loads related rows: refs in place of their ids, relations as lists (`"fest"`, `"registrations.members"`). */
|
|
1741
1784
|
include(...paths) {
|
|
1742
|
-
return new Query(this.engine, this.target, this.query, [...this.paths, ...paths]);
|
|
1785
|
+
return new Query(this.engine, this.target, this.query, [...this.paths, ...paths], this.rule);
|
|
1743
1786
|
}
|
|
1744
1787
|
async all() {
|
|
1745
1788
|
return this.fetch({
|
|
@@ -1843,7 +1886,7 @@ var Query = class Query {
|
|
|
1843
1886
|
return this.withIncludes(await this.engine.read(this.target.spec, query));
|
|
1844
1887
|
}
|
|
1845
1888
|
async withIncludes(rows) {
|
|
1846
|
-
await loadIncludes(this.engine, this.target.spec, this.target.registry, rows, this.paths);
|
|
1889
|
+
await loadIncludes(this.engine, this.target.spec, this.target.registry, rows, this.paths, this.rule);
|
|
1847
1890
|
return rows;
|
|
1848
1891
|
}
|
|
1849
1892
|
/** The first row (by the query's order), or `undefined`. */
|
|
@@ -1870,7 +1913,7 @@ var Query = class Query {
|
|
|
1870
1913
|
return new Query(this.engine, this.target, {
|
|
1871
1914
|
...this.query,
|
|
1872
1915
|
...change
|
|
1873
|
-
}, this.paths);
|
|
1916
|
+
}, this.paths, this.rule);
|
|
1874
1917
|
}
|
|
1875
1918
|
};
|
|
1876
1919
|
/** Kinds a group key may be: never free text. */
|
|
@@ -2885,7 +2928,6 @@ var UnsafeMigration = class extends Error {
|
|
|
2885
2928
|
const COPY = "add a new field, copy the values in a data step, then remove the old one";
|
|
2886
2929
|
const KEPT = "add a new field; the database fills it, then remove the old one";
|
|
2887
2930
|
const PLAIN = "add a plain field, copy the values in a data step, then remove the old one";
|
|
2888
|
-
const REBUILD = "it needs a table rebuild, which isn't supported yet; add a new field instead";
|
|
2889
2931
|
const CLEANUP = "pick another name, or drop the retired one first with `isai cleanup`";
|
|
2890
2932
|
const same = (a, b) => JSON.stringify(a) === JSON.stringify(b);
|
|
2891
2933
|
/** Why a column can't stay as it is when its field changes, and what to do instead; undefined when it can. */
|
|
@@ -2905,9 +2947,88 @@ function columnChange(before, after) {
|
|
|
2905
2947
|
change: `it's no longer kept by the database (${before.maintained})`,
|
|
2906
2948
|
advice: PLAIN
|
|
2907
2949
|
};
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2950
|
+
}
|
|
2951
|
+
/** Every table in the database under a schema: live ones with their retired columns, and retired tables. */
|
|
2952
|
+
function physicalTables(schema, alsoRetired = []) {
|
|
2953
|
+
const retired = [...schema.retired, ...alsoRetired];
|
|
2954
|
+
const tables = /* @__PURE__ */ new Map();
|
|
2955
|
+
for (const table of Object.values(schema.tables)) {
|
|
2956
|
+
const gone = retired.flatMap((r) => r.kind === "column" && r.table === table.name ? [r.column] : []);
|
|
2957
|
+
tables.set(table.name, {
|
|
2958
|
+
table,
|
|
2959
|
+
columns: [...table.columns, ...gone]
|
|
2960
|
+
});
|
|
2961
|
+
}
|
|
2962
|
+
for (const r of retired) if (r.kind === "table" && !tables.has(r.table.name)) tables.set(r.table.name, {
|
|
2963
|
+
table: r.table,
|
|
2964
|
+
columns: r.table.columns
|
|
2965
|
+
});
|
|
2966
|
+
return tables;
|
|
2967
|
+
}
|
|
2968
|
+
const referenced = (columns) => new Set(columns.flatMap((c) => c.references ? [c.references.table] : []));
|
|
2969
|
+
/**
|
|
2970
|
+
* The rebuild these schemas need, if any: the tables whose storage or a reference changed, with
|
|
2971
|
+
* every table that references one of them (live or retired, before or after), so no foreign key is
|
|
2972
|
+
* left pointing at a table that was dropped (`operations.ts` → rebuild).
|
|
2973
|
+
*/
|
|
2974
|
+
function rebuildOf(previous, next, retiredNow, unsafe) {
|
|
2975
|
+
const before = physicalTables(previous);
|
|
2976
|
+
const after = physicalTables({
|
|
2977
|
+
...next,
|
|
2978
|
+
retired: previous.retired
|
|
2979
|
+
}, retiredNow);
|
|
2980
|
+
const roots = Object.values(next.tables).filter((table) => {
|
|
2981
|
+
const was = previous.tables[table.name];
|
|
2982
|
+
if (!was) return false;
|
|
2983
|
+
if (Boolean(was.withoutRowid) !== Boolean(table.withoutRowid)) return true;
|
|
2984
|
+
const references = new Map(was.columns.map((c) => [c.name, c.references]));
|
|
2985
|
+
return table.columns.some((c) => references.has(c.name) && !same(references.get(c.name), c.references));
|
|
2986
|
+
});
|
|
2987
|
+
if (roots.length === 0) return void 0;
|
|
2988
|
+
const members = new Set(roots.map((table) => table.name));
|
|
2989
|
+
for (let grew = true; grew;) {
|
|
2990
|
+
grew = false;
|
|
2991
|
+
for (const [name, table] of after) {
|
|
2992
|
+
if (members.has(name) || !before.has(name)) continue;
|
|
2993
|
+
if ([.../* @__PURE__ */ new Set([...referenced(table.columns), ...referenced(before.get(name)?.columns ?? [])])].some((ref) => members.has(ref))) {
|
|
2994
|
+
members.add(name);
|
|
2995
|
+
grew = true;
|
|
2996
|
+
}
|
|
2997
|
+
}
|
|
2998
|
+
}
|
|
2999
|
+
const ordered = [];
|
|
3000
|
+
const pending = new Set(members);
|
|
3001
|
+
while (pending.size > 0) {
|
|
3002
|
+
const ready = [...pending].filter((name) => [...referenced(after.get(name)?.columns ?? [])].every((ref) => ref === name || !pending.has(ref)));
|
|
3003
|
+
if (ready.length === 0) {
|
|
3004
|
+
const tables = [...pending].sort();
|
|
3005
|
+
unsafe.push({
|
|
3006
|
+
model: after.get(tables[0] ?? "")?.table.model ?? "",
|
|
3007
|
+
change: `its table is rebuilt, and ${tables.join(", ")} reference each other`,
|
|
3008
|
+
advice: "break the cycle (make one of the refs a plain field) before the change that rebuilds them"
|
|
3009
|
+
});
|
|
3010
|
+
return;
|
|
3011
|
+
}
|
|
3012
|
+
for (const name of ready.sort()) {
|
|
3013
|
+
ordered.push(name);
|
|
3014
|
+
pending.delete(name);
|
|
3015
|
+
}
|
|
3016
|
+
}
|
|
3017
|
+
const tables = ordered.map((name) => {
|
|
3018
|
+
const { table, columns } = after.get(name);
|
|
3019
|
+
return {
|
|
3020
|
+
...table,
|
|
3021
|
+
columns
|
|
3022
|
+
};
|
|
3023
|
+
});
|
|
3024
|
+
return {
|
|
3025
|
+
op: "rebuild",
|
|
3026
|
+
tables,
|
|
3027
|
+
copy: Object.fromEntries(tables.map((table) => {
|
|
3028
|
+
const had = new Set(before.get(table.name)?.columns.map((c) => c.name));
|
|
3029
|
+
return [table.name, table.columns.flatMap((c) => had.has(c.name) ? [c.name] : [])];
|
|
3030
|
+
})),
|
|
3031
|
+
triggers: []
|
|
2911
3032
|
};
|
|
2912
3033
|
}
|
|
2913
3034
|
/** A dropped column and an added one of the same kind, in one model: probably a rename. */
|
|
@@ -2998,12 +3119,18 @@ function diff(previous, next, since) {
|
|
|
2998
3119
|
index
|
|
2999
3120
|
});
|
|
3000
3121
|
}
|
|
3122
|
+
const rebuild = rebuildOf(previous, next, retired, unsafe);
|
|
3001
3123
|
if (unsafe.length > 0) throw new UnsafeMigration(unsafe);
|
|
3124
|
+
const rebuilt = new Set(rebuild?.tables.map((table) => table.name));
|
|
3002
3125
|
return {
|
|
3003
|
-
operations: [
|
|
3004
|
-
|
|
3005
|
-
table
|
|
3006
|
-
|
|
3126
|
+
operations: [
|
|
3127
|
+
...rebuild ? [rebuild] : [],
|
|
3128
|
+
...created.map((table) => ({
|
|
3129
|
+
op: "createTable",
|
|
3130
|
+
table
|
|
3131
|
+
})),
|
|
3132
|
+
...addColumns.filter((operation) => operation.op !== "addColumn" || !rebuilt.has(operation.table))
|
|
3133
|
+
],
|
|
3007
3134
|
retired,
|
|
3008
3135
|
renames
|
|
3009
3136
|
};
|
|
@@ -3154,7 +3281,15 @@ function tableOf(spec, registry, tables) {
|
|
|
3154
3281
|
unique: true
|
|
3155
3282
|
};
|
|
3156
3283
|
});
|
|
3157
|
-
const
|
|
3284
|
+
const declared = spec.indexes.map((index) => {
|
|
3285
|
+
const columns = index.fields.map(column);
|
|
3286
|
+
return {
|
|
3287
|
+
name: `${spec.table}_${columns.join("_")}_index`,
|
|
3288
|
+
columns,
|
|
3289
|
+
unique: false
|
|
3290
|
+
};
|
|
3291
|
+
});
|
|
3292
|
+
const refIndexes = columns.filter((c) => c.references && ![...uniques, ...declared].some((index) => index.columns[0] === c.name)).map((c) => ({
|
|
3158
3293
|
name: `${spec.table}_${c.name}_index`,
|
|
3159
3294
|
columns: [c.name],
|
|
3160
3295
|
unique: false
|
|
@@ -3169,7 +3304,11 @@ function tableOf(spec, registry, tables) {
|
|
|
3169
3304
|
name: spec.table,
|
|
3170
3305
|
model: spec.name,
|
|
3171
3306
|
columns,
|
|
3172
|
-
indexes: [
|
|
3307
|
+
indexes: [
|
|
3308
|
+
...uniques,
|
|
3309
|
+
...declared,
|
|
3310
|
+
...refIndexes
|
|
3311
|
+
],
|
|
3173
3312
|
guards: [...checks, ...limitGuards(spec)],
|
|
3174
3313
|
counts: countsOf(spec, registry),
|
|
3175
3314
|
copies: copiesOf(spec, registry),
|
|
@@ -3177,7 +3316,8 @@ function tableOf(spec, registry, tables) {
|
|
|
3177
3316
|
field,
|
|
3178
3317
|
column: columnName(field, fieldSpec),
|
|
3179
3318
|
transitions: fieldSpec.flow
|
|
3180
|
-
}] : [])
|
|
3319
|
+
}] : []),
|
|
3320
|
+
withoutRowid: true
|
|
3181
3321
|
};
|
|
3182
3322
|
}
|
|
3183
3323
|
function snapshotOf(models) {
|
|
@@ -3209,7 +3349,11 @@ function generateMigration(options) {
|
|
|
3209
3349
|
const { previous, dialect, name, clock = systemClock } = options;
|
|
3210
3350
|
const live = snapshotOf(options.models);
|
|
3211
3351
|
const { operations, retired, renames } = diff(previous, live, dayOf(clock.now()));
|
|
3212
|
-
const
|
|
3352
|
+
const triggers = dialect.migrations.rules(previous).flatMap((rule) => rule.kind === "trigger" ? [rule.name] : []);
|
|
3353
|
+
const statements = operations.map((operation) => operation.op === "rebuild" ? {
|
|
3354
|
+
...operation,
|
|
3355
|
+
triggers
|
|
3356
|
+
} : operation).flatMap((operation) => dialect.render(operation));
|
|
3213
3357
|
const last = statements.length > 0 ? name : previous.last;
|
|
3214
3358
|
const stillRetired = previous.retired.filter((r) => r.kind !== "index" || !live.tables[r.table]?.indexes.some((index) => index.name === r.index.name));
|
|
3215
3359
|
const snapshot = {
|
|
@@ -3605,4 +3749,4 @@ async function migrateFresh(driver, models, options = {}) {
|
|
|
3605
3749
|
await sync(driver, manifest, options);
|
|
3606
3750
|
}
|
|
3607
3751
|
//#endregion
|
|
3608
|
-
export { planUpdate as A,
|
|
3752
|
+
export { planUpdate as A, checkTenancy as B, database as C, recordAction as D, forUpkeep as E, modelOfRow as F, utc as G, evaluate as H, dialectFor as I, DatabaseError as J, newSecretKey as K, sqlite as L, Query as M, conditionOf as N, withTableTotals as O, withIncludeRule as P, PLATFORM as R, clockOf as S, driverOf as T, fixedClock as U, NeedsDatabase as V, systemClock as W, ReferenceFailed as X, NotFound as Y, UniqueFailed as Z, TODO as _, currentRelease as a, Database as b, rollback as c, applyRules as d, dayOf as f, UnsafeMigration as g, snapshotOf as h, acquireLock as i, keyCondition as j, planInsert as k, setReleaseStatus as l, emptySnapshot as m, migrateFresh as n, holdOf as o, generateMigration as p, CheckFailed as q, sync as r, releaseLock as s, migrate as t, startRelease as u, dataStep as v, decodeStored as w, Transaction as x, MigrationError as y, TENANT as z };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as
|
|
1
|
+
import { A as date, B as list, C as slugify, D as token, E as textKind, F as int, I as money, K as kind, L as quantity, M as fakeUlid, N as flag, O as url, P as id, R as sequence, S as slug, T as text, _ as line, a as document, b as personName, d as images, f as define, h as email, j as datetime, k as choice, l as files, m as urls, n as phoneKind, o as documents, p as json, s as file, u as image, v as markdown, w as subdomain, x as secret, y as newToken } from "./validation-C3MCRBQO.js";
|
|
2
2
|
import { n as snakeCase, r as ulid } from "./case-DpXlJCL9.js";
|
|
3
3
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
4
4
|
//#region src/internal/scope.ts
|
|
@@ -920,6 +920,10 @@ function fieldKinds(defaults) {
|
|
|
920
920
|
image: (options = {}) => field(image(options), "json"),
|
|
921
921
|
files: (options = {}) => field(files(options), "json"),
|
|
922
922
|
images: (options = {}) => field(images(options), "json"),
|
|
923
|
+
/** A PDF or image to print or read whole (never resized), up to 100 MB; `{ storage }` as for `file`. */
|
|
924
|
+
document: (options = {}) => field(document(options), "json"),
|
|
925
|
+
/** Up to 100 documents: an order's files. */
|
|
926
|
+
documents: (options = {}) => field(documents(options), "json"),
|
|
923
927
|
/** A row of another model, by its id. Restricts deletes of that row unless `.cascade()` / `.setNull()`. */
|
|
924
928
|
ref: (model, options = {}) => new Field(fieldSpec(id(`a ${model} id`), "text", { ref: {
|
|
925
929
|
model,
|
|
@@ -1091,6 +1095,31 @@ var Model = class Model {
|
|
|
1091
1095
|
});
|
|
1092
1096
|
}
|
|
1093
1097
|
/**
|
|
1098
|
+
* An index on these fields, in this order, for the lists the app runs: a list sorted by a field
|
|
1099
|
+
* (`.index("createdAt")`), or filtered by one field then sorted by another
|
|
1100
|
+
* (`.index("status", "createdAt")`). Refs index themselves, and traits bring the indexes their
|
|
1101
|
+
* behaviour needs (`publishable`: `publishedAt`; `ordered`: its group, then `position`), so most
|
|
1102
|
+
* models never call it. `isai check` warns when a resource sorts by a field no index leads with.
|
|
1103
|
+
* Each index costs a row written on every insert, and on each update of its fields.
|
|
1104
|
+
*/
|
|
1105
|
+
index(...fields) {
|
|
1106
|
+
const name = this.spec.name;
|
|
1107
|
+
if (fields.length === 0) throw new TypeError(`isai: ${name}.index() takes one or more fields`);
|
|
1108
|
+
if (new Set(fields).size !== fields.length) throw new TypeError(`isai: ${name}.index() lists a field twice`);
|
|
1109
|
+
for (const field of fields) {
|
|
1110
|
+
const spec = this.spec.fields[field];
|
|
1111
|
+
if (!spec || spec.computed) throw new TypeError(`isai: ${name}.index() lists "${field}", which isn't one of ${name}'s stored fields`);
|
|
1112
|
+
assertNotEncrypted(this.spec, field, "indexed");
|
|
1113
|
+
}
|
|
1114
|
+
const key = fields.join(",");
|
|
1115
|
+
if (this.spec.indexes.some((index) => index.fields.join(",") === key)) throw new TypeError(`isai: ${name} already has an index on ${fields.join(", ")}`);
|
|
1116
|
+
if (this.spec.uniques.some((unique) => unique.fields.join(",") === key)) throw new TypeError(`isai: ${name} already has a unique on ${fields.join(", ")}, which is an index too`);
|
|
1117
|
+
return this.derive({
|
|
1118
|
+
...this.spec,
|
|
1119
|
+
indexes: [...this.spec.indexes, { fields }]
|
|
1120
|
+
});
|
|
1121
|
+
}
|
|
1122
|
+
/**
|
|
1094
1123
|
* The table it's stored in, when that isn't its name in snake_case: after the model was renamed,
|
|
1095
1124
|
* so the data stays where it is (`model("Squad", {…}).table("team")`). Physical renames never happen.
|
|
1096
1125
|
*/
|
|
@@ -1302,6 +1331,7 @@ function defineModel(registry, name, declared, traits = [], origin = {}) {
|
|
|
1302
1331
|
table: snakeCase(name),
|
|
1303
1332
|
fields: withCopyPaths(name, specs, registry, () => spec),
|
|
1304
1333
|
uniques,
|
|
1334
|
+
indexes: traits.flatMap((trait) => (trait.spec.indexes ?? []).map((fields) => ({ fields }))),
|
|
1305
1335
|
checks: [],
|
|
1306
1336
|
traits: names,
|
|
1307
1337
|
...origin.database === void 0 ? {} : { database: origin.database },
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { G as isRecorded, _ as Expr, c as rowOf, h as Condition, j as nodesOf, r as columnName, w as conditionNode } from "./model-
|
|
1
|
+
import { G as isRecorded, _ as Expr, c as rowOf, h as Condition, j as nodesOf, r as columnName, w as conditionNode } from "./model-6pJBqqGd.js";
|
|
2
2
|
//#region src/auth/enforce.ts
|
|
3
3
|
/**
|
|
4
4
|
* Checking a policy: its action's condition, with the
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { C as asCondition, _ as Expr, g as Embed, l as IMPLICIT_FIELDS, r as columnName, s as computedFieldOf } from "./model-
|
|
4
|
-
import { r as actionsOf } from "./policies-
|
|
1
|
+
import { U as toKind, V as object, W as validate, q as ValidationError } from "./validation-C3MCRBQO.js";
|
|
2
|
+
import { X as ReferenceFailed, Y as NotFound, Z as UniqueFailed, q as CheckFailed } from "./migrator-DxTpns_-.js";
|
|
3
|
+
import { C as asCondition, _ as Expr, g as Embed, l as IMPLICIT_FIELDS, r as columnName, s as computedFieldOf } from "./model-6pJBqqGd.js";
|
|
4
|
+
import { r as actionsOf } from "./policies-C_oiSgmY.js";
|
|
5
5
|
import { n as RESERVED, t as LOOKUPS } from "./syntax-CrUZFrS7.js";
|
|
6
6
|
//#region src/api/fail.ts
|
|
7
7
|
/**
|
|
@@ -199,13 +199,15 @@ var Route = class {
|
|
|
199
199
|
anonymous;
|
|
200
200
|
handler;
|
|
201
201
|
platform;
|
|
202
|
-
|
|
202
|
+
upload;
|
|
203
|
+
constructor(method, path, input, anonymous, handler, platform = false, upload) {
|
|
203
204
|
this.method = method;
|
|
204
205
|
this.path = path;
|
|
205
206
|
this.input = input;
|
|
206
207
|
this.anonymous = anonymous;
|
|
207
208
|
this.handler = handler;
|
|
208
209
|
this.platform = platform;
|
|
210
|
+
this.upload = upload;
|
|
209
211
|
}
|
|
210
212
|
};
|
|
211
213
|
function declare(method) {
|
|
@@ -214,7 +216,7 @@ function declare(method) {
|
|
|
214
216
|
const handler = typeof second === "function" ? second : third;
|
|
215
217
|
if (!handler) throw new TypeError(`isai: ${method} ${path} has no handler`);
|
|
216
218
|
if (!path.startsWith("/")) throw new TypeError(`isai: a route's path starts with "/" (${method} ${path})`);
|
|
217
|
-
return new Route(method, path, options.input ?? {}, options.anonymous ?? false, handler, options.platform ?? false);
|
|
219
|
+
return new Route(method, path, options.input ?? {}, options.anonymous ?? false, handler, options.platform ?? false, options.upload);
|
|
218
220
|
}
|
|
219
221
|
return define;
|
|
220
222
|
}
|
package/dist/testing/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as DatabaseDriver, g as Storage } from "../index-Ce5p2-EB.js";
|
|
2
|
-
import { I as Clock, L as FixedClock, R as fixedClock, V as AnyModel, i as Row, l as Overrides, p as Database, s as Makers, u as Seed } from "../types-
|
|
2
|
+
import { I as Clock, L as FixedClock, R as fixedClock, V as AnyModel, i as Row, l as Overrides, p as Database, s as Makers, u as Seed } from "../types-D5SIVeej.js";
|
|
3
3
|
//#region src/testing/conformance/database.d.ts
|
|
4
4
|
/**
|
|
5
5
|
* Makes the driver under test. Every call must return a driver on an **empty** database:
|
package/dist/testing/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { t as __exportAll } from "../rolldown-runtime-D7D4PA-g.js";
|
|
2
|
-
import {
|
|
3
|
-
import { L as toBase64url, t as Model } from "../model-
|
|
4
|
-
import { t as createDataLayer } from "../data-layer-
|
|
5
|
-
import { d as forgetGoogleKeys, r as authOf, s as GOOGLE, t as makers, y as seedAs } from "../makers-
|
|
2
|
+
import { G as utc, I as dialectFor, R as PLATFORM, U as fixedClock, a as currentRelease, b as Database, c as rollback, i as acquireLock, j as keyCondition, l as setReleaseStatus, m as emptySnapshot, n as migrateFresh, o as holdOf, p as generateMigration, r as sync, s as releaseLock, t as migrate, u as startRelease, v as dataStep, y as MigrationError, z as TENANT } from "../migrator-DxTpns_-.js";
|
|
3
|
+
import { L as toBase64url, t as Model } from "../model-6pJBqqGd.js";
|
|
4
|
+
import { t as createDataLayer } from "../data-layer-CVCFjPyv.js";
|
|
5
|
+
import { d as forgetGoogleKeys, r as authOf, s as GOOGLE, t as makers, y as seedAs } from "../makers-A0Pj6Tda.js";
|
|
6
6
|
import { describe, expect, it } from "vitest";
|
|
7
7
|
//#region src/testing/conformance/database.ts
|
|
8
8
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as DatabaseDriver, f as Row$1, h as Sql, o as DialectName } from "./index-Ce5p2-EB.js";
|
|
2
|
-
import { E as list, G as FileType, M as IdInput, T as Shape, Y as StoredFile, ct as
|
|
2
|
+
import { E as list, G as FileType, M as IdInput, T as Shape, Y as StoredFile, ct as KindTypes, g as KindDefinition, h as Definable, it as AnyKind, lt as Measure, mt as StandardProps, q as ImageType, ut as Sensitivity, w as Output, x as Input$2 } from "./index-CaR3hb0i.js";
|
|
3
3
|
//#region src/db/fields/slot.d.ts
|
|
4
4
|
interface SlotSpec {
|
|
5
5
|
/** Namespaced by module: `auth.owner`. */
|
|
@@ -296,6 +296,14 @@ declare function fieldKinds(defaults: () => SchemaDefaults): {
|
|
|
296
296
|
readonly types?: readonly ImageType[];
|
|
297
297
|
readonly storage?: string;
|
|
298
298
|
}) => Field<StoredFile[], StoredFile[], false, false, {}>;
|
|
299
|
+
/** A PDF or image to print or read whole (never resized), up to 100 MB; `{ storage }` as for `file`. */
|
|
300
|
+
document: (options?: {
|
|
301
|
+
readonly storage?: string;
|
|
302
|
+
}) => Field<StoredFile, StoredFile, false, false, {}>;
|
|
303
|
+
/** Up to 100 documents: an order's files. */
|
|
304
|
+
documents: (options?: {
|
|
305
|
+
readonly storage?: string;
|
|
306
|
+
}) => Field<StoredFile[], StoredFile[], false, false, {}>;
|
|
299
307
|
/** A row of another model, by its id. Restricts deletes of that row unless `.cascade()` / `.setNull()`. */
|
|
300
308
|
ref: <const Model extends string, const Related extends string | undefined = undefined>(model: Model, options?: {
|
|
301
309
|
readonly related?: Related;
|
|
@@ -673,6 +681,10 @@ declare class ModelRegistry {
|
|
|
673
681
|
interface UniqueSpec {
|
|
674
682
|
readonly fields: readonly string[];
|
|
675
683
|
}
|
|
684
|
+
/** An index the model asks for (`.index(...)`, or a trait's), by field names, in order. */
|
|
685
|
+
interface IndexSpec {
|
|
686
|
+
readonly fields: readonly string[];
|
|
687
|
+
}
|
|
676
688
|
interface CheckSpec {
|
|
677
689
|
readonly name: string;
|
|
678
690
|
readonly condition: ConditionNode;
|
|
@@ -685,6 +697,8 @@ interface ModelSpec {
|
|
|
685
697
|
/** Every field, implicit ones first, in declaration order. */
|
|
686
698
|
readonly fields: Readonly<Record<string, FieldSpec>>;
|
|
687
699
|
readonly uniques: readonly UniqueSpec[];
|
|
700
|
+
/** Its plain indexes: its traits' first, then `.index(...)`. Refs' indexes are added by the schema. */
|
|
701
|
+
readonly indexes: readonly IndexSpec[];
|
|
688
702
|
readonly checks: readonly CheckSpec[];
|
|
689
703
|
/** The traits it took (`ordered`, `singleton`…), by name. */
|
|
690
704
|
readonly traits: readonly string[];
|
|
@@ -773,6 +787,15 @@ declare class Model<Name extends string = string, F extends Fields = Fields, Uni
|
|
|
773
787
|
get name(): Name;
|
|
774
788
|
/** A unique combination of two or more fields (one field: `.unique()` on the field). */
|
|
775
789
|
unique<const K extends readonly [keyof F & string, keyof F & string, ...(keyof F & string)[]]>(...fields: K): Model<Name, F, Uniques | K>;
|
|
790
|
+
/**
|
|
791
|
+
* An index on these fields, in this order, for the lists the app runs: a list sorted by a field
|
|
792
|
+
* (`.index("createdAt")`), or filtered by one field then sorted by another
|
|
793
|
+
* (`.index("status", "createdAt")`). Refs index themselves, and traits bring the indexes their
|
|
794
|
+
* behaviour needs (`publishable`: `publishedAt`; `ordered`: its group, then `position`), so most
|
|
795
|
+
* models never call it. `isai check` warns when a resource sorts by a field no index leads with.
|
|
796
|
+
* Each index costs a row written on every insert, and on each update of its fields.
|
|
797
|
+
*/
|
|
798
|
+
index<const K extends readonly [keyof (ImplicitFields & F) & string, ...(keyof (ImplicitFields & F) & string)[]]>(...fields: K): Model<Name, F, Uniques>;
|
|
776
799
|
/**
|
|
777
800
|
* The table it's stored in, when that isn't its name in snake_case: after the model was renamed,
|
|
778
801
|
* so the data stays where it is (`model("Squad", {…}).table("team")`). Physical renames never happen.
|
|
@@ -941,6 +964,12 @@ interface TableSnapshot {
|
|
|
941
964
|
readonly counts: readonly CountSnapshot[];
|
|
942
965
|
readonly copies: readonly CopySnapshot[];
|
|
943
966
|
readonly flows: readonly FlowSnapshot[];
|
|
967
|
+
/**
|
|
968
|
+
* Its rows live in its primary key's index (`WITHOUT ROWID`): every model's table, since the id is
|
|
969
|
+
* text, so a plain table would also keep a hidden rowid and a second index on the id, one more row
|
|
970
|
+
* written per insert and read per lookup. Absent in snapshots from before, whose tables are rebuilt.
|
|
971
|
+
*/
|
|
972
|
+
readonly withoutRowid?: true;
|
|
944
973
|
}
|
|
945
974
|
/**
|
|
946
975
|
* Something the models no longer have, kept in the database until `isai cleanup` so that an
|
|
@@ -1013,6 +1042,25 @@ type Operation = {
|
|
|
1013
1042
|
{
|
|
1014
1043
|
readonly op: "dropTable";
|
|
1015
1044
|
readonly table: TableSnapshot;
|
|
1045
|
+
} |
|
|
1046
|
+
/**
|
|
1047
|
+
* Tables made again (a new storage, a reference's `onDelete`), with every table that references
|
|
1048
|
+
* one of them, so no foreign key ever points at a dropped table. Cloudflare's SQLite can't turn
|
|
1049
|
+
* foreign keys off (`PRAGMA foreign_keys = OFF` is ignored), and dropping a referenced table
|
|
1050
|
+
* deletes its rows first, which would cascade into the rows that reference them. So: the old
|
|
1051
|
+
* tables are renamed aside, the new ones created and filled, and the old ones dropped children
|
|
1052
|
+
* first, when nothing references them any more. Rules (indexes, triggers) are dropped with them,
|
|
1053
|
+
* every trigger first (one naming a renamed table would stop the rename), and come back from the
|
|
1054
|
+
* schema after the step.
|
|
1055
|
+
*/
|
|
1056
|
+
{
|
|
1057
|
+
readonly op: "rebuild";
|
|
1058
|
+
/** The tables as they become, retired columns included, in dependency order (parents first). */
|
|
1059
|
+
readonly tables: readonly TableSnapshot[];
|
|
1060
|
+
/** Each table's columns that hold data now, copied across. */
|
|
1061
|
+
readonly copy: Readonly<Record<string, readonly string[]>>;
|
|
1062
|
+
/** Every trigger the database has now, by name. */
|
|
1063
|
+
readonly triggers: readonly string[];
|
|
1016
1064
|
};
|
|
1017
1065
|
//#endregion
|
|
1018
1066
|
//#region src/db/dialects/dialect.d.ts
|
|
@@ -1227,6 +1275,12 @@ declare class Engine {
|
|
|
1227
1275
|
private secrets;
|
|
1228
1276
|
}
|
|
1229
1277
|
//#endregion
|
|
1278
|
+
//#region src/db/orm/include.d.ts
|
|
1279
|
+
/** The condition a model's related rows must meet, or `false` when none may be read. */
|
|
1280
|
+
type IncludeRule = (model: ModelSpec) => Promise<ConditionNode | false>;
|
|
1281
|
+
/** How the boundary gives a query its `IncludeRule`: internal, so the app's API never shows it. */
|
|
1282
|
+
declare const withIncludeRule: unique symbol;
|
|
1283
|
+
//#endregion
|
|
1230
1284
|
//#region src/db/orm/page.d.ts
|
|
1231
1285
|
interface PageOptions {
|
|
1232
1286
|
/** Rows per page. */
|
|
@@ -1312,7 +1366,10 @@ declare class Query<M extends AnyModel, R> implements PromiseLike<R[]> {
|
|
|
1312
1366
|
private readonly target;
|
|
1313
1367
|
private readonly query;
|
|
1314
1368
|
private readonly paths;
|
|
1315
|
-
|
|
1369
|
+
private readonly rule?;
|
|
1370
|
+
constructor(engine: Engine, target: M, query?: SelectQuery, paths?: readonly string[], rule?: IncludeRule | undefined);
|
|
1371
|
+
/** The same query, its includes held to `rule` (the boundary's; `./include`). */
|
|
1372
|
+
[withIncludeRule](rule: IncludeRule): Query<M, R>;
|
|
1316
1373
|
/** Repeated calls are ANDed. */
|
|
1317
1374
|
where(build: (row: RowOf<M>) => Condition): Query<M, R>;
|
|
1318
1375
|
order(...keys: readonly OrderKey<M>[]): Query<M, R>;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { a as ValidationError, i as Result, n as IssueCode, r as Path, t as Issue } from "../issues-CKto95IW.js";
|
|
2
|
-
import { $ as
|
|
3
|
-
export { type AnyKind, type CalendarDate, type CarriesKind, type Definable, Fake, type FakeContext, type FileSpec, type FileType, type IdInput, type ImageSize, type ImageType, type Input, type Issue, type IssueCode, Kind, type KindDefinition, type KindSpec, type KindTypes, LIST_MAX, type Measure, type ObjectShape, type Output, type Path, type Result, SIZES_MAX, type Sensitivity, type Shape, type StandardIssue, type StandardProps, type StandardResult, type StandardSchemaV1, type StoredFile, type TypeText, ValidationError, choice, date, datetime, define, email, fakeUlid, file, files, flag, host, id, image, images, int, json, kind, line, list, markdown, money, newToken, object, personName, phone, phoneKind, quantity, secret, sequence, serialize, slug, slugify, subdomain, text, textKind, toKind, token, url, urls, validate };
|
|
2
|
+
import { $ as files, A as validate, B as money, C as ObjectShape, D as object, E as list, F as datetime, G as FileType, H as sequence, I as fakeUlid, J as SIZES_MAX, K as ImageSize, L as flag, M as IdInput, N as choice, O as serialize, P as date, Q as file, R as id, S as LIST_MAX, T as Shape, U as phone, V as quantity, W as phoneKind, X as document, Y as StoredFile, Z as documents, _ as define, a as newToken, at as FileSpec, b as CarriesKind, c as slug, ct as KindTypes, d as text, dt as TypeText, et as image, f as textKind, ft as kind, g as KindDefinition, gt as StandardSchemaV1, h as Definable, ht as StandardResult, i as markdown, it as AnyKind, j as CalendarDate, k as toKind, l as slugify, lt as Measure, m as url, mt as StandardProps, n as host, nt as Fake, o as personName, ot as Kind, p as token, pt as StandardIssue, q as ImageType, r as line, rt as FakeContext, s as secret, st as KindSpec, t as email, tt as images, u as subdomain, ut as Sensitivity, v as json, w as Output, x as Input, y as urls, z as int } from "../index-CaR3hb0i.js";
|
|
3
|
+
export { type AnyKind, type CalendarDate, type CarriesKind, type Definable, Fake, type FakeContext, type FileSpec, type FileType, type IdInput, type ImageSize, type ImageType, type Input, type Issue, type IssueCode, Kind, type KindDefinition, type KindSpec, type KindTypes, LIST_MAX, type Measure, type ObjectShape, type Output, type Path, type Result, SIZES_MAX, type Sensitivity, type Shape, type StandardIssue, type StandardProps, type StandardResult, type StandardSchemaV1, type StoredFile, type TypeText, ValidationError, choice, date, datetime, define, document, documents, email, fakeUlid, file, files, flag, host, id, image, images, int, json, kind, line, list, markdown, money, newToken, object, personName, phone, phoneKind, quantity, secret, sequence, serialize, slug, slugify, subdomain, text, textKind, toKind, token, url, urls, validate };
|
package/dist/validation/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { J as Fake, G as Kind, z as LIST_MAX, i as SIZES_MAX, q as ValidationError, k as choice, A as date, j as datetime, f as define, a as document, o as documents, h as email, M as fakeUlid, s as file, l as files, N as flag, g as host, P as id, u as image, d as images, F as int, p as json, K as kind, _ as line, B as list, v as markdown, I as money, y as newToken, V as object, b as personName, t as phone, n as phoneKind, L as quantity, x as secret, R as sequence, H as serialize, S as slug, C as slugify, w as subdomain, T as text, E as textKind, U as toKind, D as token, O as url, m as urls, W as validate } from "../validation-C3MCRBQO.js";
|