@isaijs/core 0.1.6 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/dist/adapters/storage/r2/index.d.ts +3 -0
  2. package/dist/adapters/storage/r2/index.js +13 -2
  3. package/dist/auth/index.d.ts +2 -2
  4. package/dist/auth/index.js +2 -2
  5. package/dist/cli/index.js +79 -11
  6. package/dist/client/index.d.ts +4 -0
  7. package/dist/client/index.js +18 -13
  8. package/dist/{create-auth-BFKvQVOG.js → create-auth-BCvMwlVD.js} +3 -3
  9. package/dist/{data-layer-C5oJZ8V1.js → data-layer-BOVkYESH.js} +15 -10
  10. package/dist/{data-layer-43pme0Gy.d.ts → data-layer-nvm_ivGQ.d.ts} +6 -2
  11. package/dist/db/index.d.ts +2 -2
  12. package/dist/db/index.js +5 -5
  13. package/dist/{index-a7ElyL3B.d.ts → index-Bb9Px6SR.d.ts} +97 -18
  14. package/dist/{index-CYcklQ1l.d.ts → index-CaR3hb0i.d.ts} +5 -1
  15. package/dist/index.d.ts +2 -2
  16. package/dist/index.js +150 -78
  17. package/dist/{make-ByA-84h8.js → make-D6_caNkv.js} +21 -3
  18. package/dist/{makers-P9kg68C8.js → makers-DjkBP74P.js} +3 -3
  19. package/dist/{migrator-B25prc9n.js → migrator-vvvKa0Vk.js} +180 -36
  20. package/dist/{model-Dc3HunKb.js → model-6pJBqqGd.js} +31 -1
  21. package/dist/{policies-KsqmlX67.js → policies-C_oiSgmY.js} +1 -1
  22. package/dist/{resource-BQK7bkPQ.js → resource-DCg6LvMH.js} +8 -6
  23. package/dist/{tables-DgSwge7s.js → tables-DjW96Ubl.js} +1 -1
  24. package/dist/testing/index.d.ts +1 -1
  25. package/dist/testing/index.js +4 -4
  26. package/dist/{types-BgOkJy5d.d.ts → types-D5SIVeej.d.ts} +59 -2
  27. package/dist/validation/index.d.ts +2 -2
  28. package/dist/validation/index.js +1 -1
  29. package/dist/{validation-Cppmd0RV.js → validation-C3MCRBQO.js} +26 -3
  30. package/package.json +1 -1
@@ -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 Sensitivity, ft as StandardProps, g as KindDefinition, h as Definable, nt as AnyKind, ot as KindTypes, q as ImageType, st as Measure, w as Output, x as Input$2 } from "./index-CYcklQ1l.js";
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
- constructor(engine: Engine, target: M, query?: SelectQuery, paths?: readonly string[]);
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 images, 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 image, R as id, S as LIST_MAX, T as Shape, U as phone, V as quantity, W as phoneKind, X as file, Y as StoredFile, Z as files, _ as define, a as newToken, at as KindSpec, b as CarriesKind, c as slug, ct as Sensitivity, d as text, dt as StandardIssue, et as Fake, f as textKind, ft as StandardProps, g as KindDefinition, h as Definable, i as markdown, it as Kind, j as CalendarDate, k as toKind, l as slugify, lt as TypeText, m as url, mt as StandardSchemaV1, n as host, nt as AnyKind, o as personName, ot as KindTypes, p as token, pt as StandardResult, q as ImageType, r as line, rt as FileSpec, s as secret, st as Measure, t as email, tt as FakeContext, u as subdomain, ut as kind, v as json, w as Output, x as Input, y as urls, z as int } from "../index-CYcklQ1l.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, 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 };
@@ -1 +1 @@
1
- export { K as Fake, U as Kind, L as LIST_MAX, i as SIZES_MAX, G as ValidationError, D as choice, O as date, k as datetime, u as define, p as email, A as fakeUlid, a as file, s as files, j as flag, m as host, M as id, c as image, l as images, N as int, d as json, W as kind, h as line, R as list, g as markdown, P as money, _ as newToken, z as object, v as personName, t as phone, n as phoneKind, F as quantity, y as secret, I as sequence, B as serialize, b as slug, x as slugify, S as subdomain, C as text, w as textKind, V as toKind, T as token, E as url, f as urls, H as validate } from "../validation-Cppmd0RV.js";
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";
@@ -1105,6 +1105,10 @@ const IMAGE_TYPES = [
1105
1105
  const MB = 1048576;
1106
1106
  /** At most this many files in one field. */
1107
1107
  const FILES_MAX = 10;
1108
+ /** At most this many documents in one field: an order's files, all its lines'. */
1109
+ const DOCUMENTS_MAX = 100;
1110
+ /** A document's size: the Workers body limit, the most one request can carry. */
1111
+ const DOCUMENT_BYTES = 100 * MB;
1108
1112
  /** A file's id: `fil_` and a ULID. */
1109
1113
  const FILE_ID = /^fil_[0-9A-HJKMNP-TV-Z]{26}$/;
1110
1114
  /** A storage's name: a key of `storage` in `app.ts`. */
@@ -1244,10 +1248,27 @@ function image(options = {}) {
1244
1248
  many: false
1245
1249
  }));
1246
1250
  }
1251
+ const DOCUMENT_TYPES = [
1252
+ "pdf",
1253
+ "png",
1254
+ "jpeg",
1255
+ "webp"
1256
+ ];
1257
+ /** A PDF or an image to print or read whole (never resized), up to 100 MB. */
1258
+ function document(options = {}) {
1259
+ return fileKind("document", specOf({
1260
+ ...options,
1261
+ types: DOCUMENT_TYPES
1262
+ }, ALL_TYPES, {
1263
+ image: false,
1264
+ maxBytes: DOCUMENT_BYTES,
1265
+ many: false
1266
+ }));
1267
+ }
1247
1268
  /** A list kind of files, carrying its item's spec as a list. */
1248
- function many(name, item) {
1269
+ function many(name, item, max = FILES_MAX) {
1249
1270
  return new Kind({
1250
- ...named(name, list(item).max(FILES_MAX)).spec,
1271
+ ...named(name, list(item).max(max)).spec,
1251
1272
  file: {
1252
1273
  ...item.spec.file,
1253
1274
  many: true
@@ -1258,6 +1279,8 @@ function many(name, item) {
1258
1279
  const files = (options = {}) => many("files", file(options));
1259
1280
  /** Up to 10 images. */
1260
1281
  const images = (options = {}) => many("images", image(options));
1282
+ /** Up to 100 documents (PDFs and images, each up to 100 MB). */
1283
+ const documents = (options = {}) => many("documents", document(options), DOCUMENTS_MAX);
1261
1284
  //#endregion
1262
1285
  //#region src/internal/phone.ts
1263
1286
  /**
@@ -1313,4 +1336,4 @@ function phone(options = {}) {
1313
1336
  return phoneKind(() => region);
1314
1337
  }
1315
1338
  //#endregion
1316
- export { fakeUlid as A, serialize as B, text as C, choice as D, url as E, quantity as F, ValidationError as G, validate as H, sequence as I, Fake as K, LIST_MAX as L, id as M, int as N, date as O, money as P, list as R, subdomain as S, token as T, Kind as U, toKind as V, kind as W, newToken as _, file as a, slug as b, image as c, json as d, urls as f, markdown as g, line as h, SIZES_MAX as i, flag as j, datetime as k, images as l, host as m, phoneKind as n, fileTypeNames as o, email as p, fakeValue as q, isPhoneRegion as r, files as s, phone as t, define as u, personName as v, textKind as w, slugify as x, secret as y, object as z };
1339
+ export { date as A, list as B, slugify as C, token as D, textKind as E, int as F, Kind as G, serialize as H, money as I, Fake as J, kind as K, quantity as L, fakeUlid as M, flag as N, url as O, id as P, sequence as R, slug as S, text as T, toKind as U, object as V, validate as W, fakeValue as Y, line as _, document as a, personName as b, fileTypeNames as c, images as d, define as f, host as g, email as h, SIZES_MAX as i, datetime as j, choice as k, files as l, urls as m, phoneKind as n, documents as o, json as p, ValidationError as q, isPhoneRegion as r, file as s, phone as t, image as u, markdown as v, subdomain as w, secret as x, newToken as y, LIST_MAX as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@isaijs/core",
3
- "version": "0.1.6",
3
+ "version": "0.1.9",
4
4
  "description": "A batteries-included, type-safe TypeScript backend framework. Cloudflare first, no lock-in.",
5
5
  "type": "module",
6
6
  "license": "MIT",