@ultimat3/entity 25.2.0 → 26.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/package.json +5 -5
- package/src/aggregate.ts +1 -1
- package/src/array-element.ts +1 -1
- package/src/count-by.ts +2 -2
- package/src/entity-error.ts +3 -5
- package/src/entity.ts +1 -1
- package/src/record-key.ts +1 -1
- package/src/refuse.ts +2 -2
package/README.md
CHANGED
|
@@ -263,7 +263,7 @@ export const accounts = entity('account', {
|
|
|
263
263
|
|
|
264
264
|
| Override | What follows it |
|
|
265
265
|
|---|---|
|
|
266
|
-
| `entity(name, { table })` | every statement, index name and foreign key. The entity NAME stays the framework's key — the registry, the cache tag (`entity:account`), `x entities
|
|
266
|
+
| `entity(name, { table })` | every statement, index name and foreign key. The entity NAME stays the framework's key — the registry, the cache tag (`entity:account`), `x entities show` and every relation are keyed by it, so renaming a table never moves a cache tag or a policy |
|
|
267
267
|
| `.column(name)` | the DDL, the binding, the decoder, the predicate, the sort key, the cursor. Name it LAST in a chain — the link returns the general column, and only `uuid()` and `timestamp()` keep their own methods across it |
|
|
268
268
|
| `money({ columns })` | per part, merged over `<name>_minor` / `<name>_currency` / `<name>_scale`, so a table that renamed one does not restate the other two. `scale: null` says the table has no scale column: every amount is then at the currency's own minor unit, which is what an absent scale already means |
|
|
269
269
|
|
|
@@ -813,7 +813,7 @@ page.rows[0].author; // the member row, or null — always present
|
|
|
813
813
|
| Unknown name | `X_PRELOAD_UNKNOWN_RELATION` at `preload()` itself, not a page later |
|
|
814
814
|
| Shape | `belongsTo` attaches the row or `null`; `hasMany` an array — always present |
|
|
815
815
|
| Statements | one extra per relation, resolved concurrently; naming one twice is one statement |
|
|
816
|
-
| Ceiling | `preload('<relation>', { max })` — the most related rows one relation may attach to one page. Default `MAX_PRELOADED_ROWS` (10,000, the largest page a read may ask for). Past it the read is **refused** (`X_INVARIANT_VIOLATED`), never truncated, and it reads at most one row past the ceiling to know. Naming a relation twice is still one statement: a later call that states `max` replaces the earlier one, as a second `.limit()` does, and one that states none leaves it. The refusal's cause spells the call to write (`.preload('<relation>', { max: n })`); its fix is `x entities
|
|
816
|
+
| Ceiling | `preload('<relation>', { max })` — the most related rows one relation may attach to one page. Default `MAX_PRELOADED_ROWS` (10,000, the largest page a read may ask for). Past it the read is **refused** (`X_INVARIANT_VIOLATED`), never truncated, and it reads at most one row past the ceiling to know. Naming a relation twice is still one statement: a later call that states `max` replaces the earlier one, as a second `.limit()` does, and one that states none leaves it. The refusal's cause spells the call to write (`.preload('<relation>', { max: n })`); its fix is `x entities show <entity> --json` |
|
|
817
817
|
| Tenancy | carried onto the related read only when the other entity's tenant column shares the name; otherwise `X_TENANCY_UNSCOPED` refuses the related read rather than guess |
|
|
818
818
|
| Terminals | `page()`, `all()`, `one()` preload; `count()`, `countBy()` and `plan()` don't — none reads a row to attach one to |
|
|
819
819
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ultimat3/entity",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "26.0.0",
|
|
4
4
|
"description": "A table + its domain type + invariants the database also enforces",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -33,9 +33,9 @@
|
|
|
33
33
|
"test": "bun test"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@ultimat3/core": "
|
|
37
|
-
"@ultimat3/db": "
|
|
38
|
-
"@ultimat3/schema": "
|
|
39
|
-
"@ultimat3/time": "
|
|
36
|
+
"@ultimat3/core": "26.0.0",
|
|
37
|
+
"@ultimat3/db": "26.0.0",
|
|
38
|
+
"@ultimat3/schema": "26.0.0",
|
|
39
|
+
"@ultimat3/time": "26.0.0"
|
|
40
40
|
}
|
|
41
41
|
}
|
package/src/aggregate.ts
CHANGED
|
@@ -64,7 +64,7 @@ export const notAggregatable = (
|
|
|
64
64
|
fn === 'avg' && kind === 'money'
|
|
65
65
|
? `${entityName}.sum('${property}') and ${entityName}.count() — divide at the call site, where the rounding is a decision somebody made`
|
|
66
66
|
: candidates.length === 0
|
|
67
|
-
? `x entities
|
|
67
|
+
? `x entities show ${entityName} --json # this entity declares no column ${fn} can be applied to`
|
|
68
68
|
: `${entityName}.${fn}('${candidates[0]}') # ${fn} takes one of: ${candidates.join(', ')}`,
|
|
69
69
|
});
|
|
70
70
|
|
package/src/array-element.ts
CHANGED
|
@@ -52,7 +52,7 @@ const ARRAY_ELEMENT_FIXES = Object.freeze<Record<RefusedElement, string>>({
|
|
|
52
52
|
* and only a table could show.
|
|
53
53
|
*
|
|
54
54
|
* Not `reject()`: a declaration is repaired by an EDIT, and `reject`'s
|
|
55
|
-
* `x entities
|
|
55
|
+
* `x entities show column --json` is `X_DECLARATION_UNKNOWN` — no entity is named `column`, and
|
|
56
56
|
* there is no entity at all yet. So each fix is the edit that holds the list instead.
|
|
57
57
|
*/
|
|
58
58
|
export const arrayElementRefused = (kind: RefusedElement): EntityError => {
|
package/src/count-by.ts
CHANGED
|
@@ -42,7 +42,7 @@ const groupableColumns = <Row>(entity: EntityCore<Row>): readonly string[] =>
|
|
|
42
42
|
* Not `invariantViolated`: its fix opens `x entity explain`, which describes invariants nobody
|
|
43
43
|
* wrote here. What repairs this is one edit to the call — a different column, named in the message
|
|
44
44
|
* because the entity is the only place the answer lives. Only when this entity offers no such
|
|
45
|
-
* column does the fix become a command, and then it is `x entities
|
|
45
|
+
* column does the fix become a command, and then it is `x entities show`, which prints the
|
|
46
46
|
* kinds: there is no call to suggest, since every column it declares would be refused the same way.
|
|
47
47
|
*/
|
|
48
48
|
const notGroupable = <Row>(
|
|
@@ -57,7 +57,7 @@ const notGroupable = <Row>(
|
|
|
57
57
|
cause: `${entity.$name}.${operation}('${property}'): ${reason}`,
|
|
58
58
|
fix:
|
|
59
59
|
first === undefined
|
|
60
|
-
? `x entities
|
|
60
|
+
? `x entities show ${entity.$name} --json # this entity declares no column a count can be keyed by`
|
|
61
61
|
: `${entity.$name}.${operation}('${first}') # group by one of: ${groupableColumns(entity).join(', ')}`,
|
|
62
62
|
});
|
|
63
63
|
};
|
package/src/entity-error.ts
CHANGED
|
@@ -124,14 +124,12 @@ export class EntityError extends UltimateError {
|
|
|
124
124
|
* read is not spliced.
|
|
125
125
|
*/
|
|
126
126
|
export const describeCommand = (entityName: string): string =>
|
|
127
|
-
isFixShellSafe(entityName)
|
|
128
|
-
? `x entities describe ${entityName} --json`
|
|
129
|
-
: 'x entities list --json';
|
|
127
|
+
isFixShellSafe(entityName) ? `x entities show ${entityName} --json` : 'x entities list --json';
|
|
130
128
|
|
|
131
129
|
/**
|
|
132
130
|
* The entity name is a VALUE, never a literal — `entity.$name`, `table`, the `name` `entity()` was
|
|
133
131
|
* given. A literal is an entity that does not exist, and this fix then hands the reader
|
|
134
|
-
* `x entities
|
|
132
|
+
* `x entities show column --json`, which answers `X_DECLARATION_UNKNOWN` (issue #290). A
|
|
135
133
|
* refusal raised before any entity exists belongs in `refuse.ts`, where the caller supplies the
|
|
136
134
|
* edit; `refuse.test.ts` fails on a literal here.
|
|
137
135
|
*/
|
|
@@ -143,7 +141,7 @@ export const invariantViolated = (
|
|
|
143
141
|
new EntityError({
|
|
144
142
|
code: 'X_INVARIANT_VIOLATED',
|
|
145
143
|
cause: `${entityName}.${invariantName}: ${message}`,
|
|
146
|
-
fix: `x entities
|
|
144
|
+
fix: `x entities show ${entityName} --json # shows the invariant and its SQL CHECK`,
|
|
147
145
|
});
|
|
148
146
|
|
|
149
147
|
export const entityDuplicate = (name: string, existingTable: string): EntityError =>
|
package/src/entity.ts
CHANGED
|
@@ -41,7 +41,7 @@ export interface EntityInit<C extends ColumnMap> {
|
|
|
41
41
|
* cannot cover: `entity('user', { table: 'users', … })` reads and writes the table that is
|
|
42
42
|
* already there, and every statement, index name and foreign key follows it.
|
|
43
43
|
*
|
|
44
|
-
* The entity NAME stays the framework's key — the registry, the cache tag, `x entities
|
|
44
|
+
* The entity NAME stays the framework's key — the registry, the cache tag, `x entities show`
|
|
45
45
|
* and every relation are keyed by it — so renaming a table never moves a cache tag or a policy.
|
|
46
46
|
*/
|
|
47
47
|
readonly table?: string;
|
package/src/record-key.ts
CHANGED
|
@@ -23,7 +23,7 @@ export const recordKeyMissing = (type: string, column: string, value: unknown):
|
|
|
23
23
|
// `renderFixShellArg` inside the safe branch is verbatim there; it is the call
|
|
24
24
|
// `bun run fix-shell-arg` recognises as the screen.
|
|
25
25
|
fix: isFixShellSafe(type)
|
|
26
|
-
? `x entities
|
|
26
|
+
? `x entities show ${renderFixShellArg(type, 'ENTITY')} --json # lists the primary key; return the whole row (every primary-key column) from the handler that built this one`
|
|
27
27
|
: 'x entities list --json # find this entity, then return the whole row (every primary-key column) from the handler that built this one',
|
|
28
28
|
});
|
|
29
29
|
|
package/src/refuse.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// The two refusals raised while a SCHEMA is still being written — a column and an invariant — and
|
|
2
2
|
// why neither goes through `invariantViolated`: that builder's fix is
|
|
3
|
-
// `x entities
|
|
4
|
-
// literal `'column'` emitted `x entities
|
|
3
|
+
// `x entities show <entityName> --json`, which needs an entity that exists. Passing the
|
|
4
|
+
// literal `'column'` emitted `x entities show column --json`, which answers
|
|
5
5
|
// `X_DECLARATION_UNKNOWN` — a fix line that raises a second, unrelated error (issue #290).
|
|
6
6
|
//
|
|
7
7
|
// So the fix is a parameter: every caller supplies the EDIT that repairs its own refusal, the
|