@solidev/data 1.0.1 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +46 -0
- package/README.md +40 -44
- package/fesm2022/solidev-data-mdedit.mjs +583 -0
- package/fesm2022/solidev-data-mdedit.mjs.map +1 -0
- package/fesm2022/solidev-data-richedit.mjs +1132 -157
- package/fesm2022/solidev-data-richedit.mjs.map +1 -1
- package/fesm2022/solidev-data.mjs +1092 -719
- package/fesm2022/solidev-data.mjs.map +1 -1
- package/package.json +19 -2
- package/types/solidev-data-mdedit.d.ts +226 -0
- package/types/solidev-data-richedit.d.ts +286 -69
- package/types/solidev-data.d.ts +1261 -1038
package/AGENTS.md
CHANGED
|
@@ -371,6 +371,52 @@ Notes worth knowing:
|
|
|
371
371
|
**Do not try to bind `[save]`.** It is declared as a plain class property, not an
|
|
372
372
|
`input()`, so it is not template-bindable. Control saving via `mode`.
|
|
373
373
|
|
|
374
|
+
### 7.1 Long text — `<data-richedit>` and `<data-mdedit>`
|
|
375
|
+
|
|
376
|
+
**They are not dispedit editors.** `dispedit` lives in the primary entry point and
|
|
377
|
+
cannot import a secondary one, so use these components directly. For the
|
|
378
|
+
read-only half, point a dispedit at the rendered `…_html` column with
|
|
379
|
+
`[viewer]="'html'"` — that renders trusted HTML and covers markdown too, since a
|
|
380
|
+
markdown field is stored with an `…_html` twin. It does **not** sanitize: use it
|
|
381
|
+
only on HTML your own editor produced.
|
|
382
|
+
|
|
383
|
+
Two editors live in their own entry points, so they are only pulled in if imported:
|
|
384
|
+
|
|
385
|
+
```html
|
|
386
|
+
<!-- HTML, @solidev/data/richedit -->
|
|
387
|
+
<data-richedit [model]="thing" field="description">Description</data-richedit>
|
|
388
|
+
|
|
389
|
+
<!-- markdown source, @solidev/data/mdedit -->
|
|
390
|
+
<data-mdedit [model]="thing" field="notes" toolbar="light">Notes</data-mdedit>
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
Same inputs on both (`model`, `field`, `htmlField`, `mode`, `edit`, `editable`,
|
|
394
|
+
`hideLabel`, `hideButton`, `fc`, `form`, `toolbar`), one output (`changed`).
|
|
395
|
+
|
|
396
|
+
- **They show the value first.** In `dd` mode a click on the value or the label
|
|
397
|
+
reveals the editor, exactly like dispedit; `[editable]="false"` forbids it.
|
|
398
|
+
`inline` and `form` show the editor straight away.
|
|
399
|
+
- **`field` names a pair.** Given `field="description"` they edit
|
|
400
|
+
`description_src` and display `description_html` when the model declares them,
|
|
401
|
+
and fall back to `description` for both when it does not. `[htmlField]`
|
|
402
|
+
overrides the display half.
|
|
403
|
+
|
|
404
|
+
- **They do not auto-save.** Unlike dispedit, the value reaches the API only when
|
|
405
|
+
the built-in save button runs `save()`, and only in `mode="dd"`. In `inline` and
|
|
406
|
+
`form` the model is updated in memory and nothing is sent.
|
|
407
|
+
- **`[fc]` short-circuits everything.** Supply your own control and there is no
|
|
408
|
+
field manager lookup, no seeding from the model, and **no `changed` emissions**.
|
|
409
|
+
- **No extra install.** `prosemirror-*` and `@codemirror/*` are ordinary peer
|
|
410
|
+
dependencies, so npm brings them in with the library. Neither reaches the
|
|
411
|
+
application bundle unless its entry point is imported.
|
|
412
|
+
- **Rendering a `…_html` column elsewhere** needs `SafeHtmlPipe` from
|
|
413
|
+
`@solidev/data`: `<div [innerHTML]="thing.notes_html | safeHtml"></div>`.
|
|
414
|
+
Angular's sanitizer drops the inline styles the editor writes, so a plain
|
|
415
|
+
`[innerHTML]` renders alignment and colours away. Server-produced HTML only.
|
|
416
|
+
- **Testing needs `installEditorDomShims()`** from `@solidev/data`, called in
|
|
417
|
+
`beforeEach` — jsdom has no layout engine and both editors measure the document.
|
|
418
|
+
Then `await fixture.whenStable()`, since both mount in `afterNextRender`.
|
|
419
|
+
|
|
374
420
|
---
|
|
375
421
|
|
|
376
422
|
## 8. Bootstrap wiring
|
package/README.md
CHANGED
|
@@ -1,36 +1,37 @@
|
|
|
1
1
|
# @solidev/data
|
|
2
2
|
|
|
3
|
-
A **Django-REST-Framework-style data layer for Angular**. Declare a model once and get
|
|
4
|
-
|
|
5
|
-
display/edit widgets — all driven by that single declaration.
|
|
3
|
+
A **Django-REST-Framework-style data layer for Angular**. Declare a model once and get HTTP access, querysets,
|
|
4
|
+
filtering, sorting, pagination, forms, validation and display/edit widgets — all driven by that single declaration.
|
|
6
5
|
|
|
7
6
|
```ts
|
|
8
7
|
export class ProductBase extends DataModel {
|
|
9
|
-
static override readonly __name: string =
|
|
8
|
+
static override readonly __name: string = "ProductBase";
|
|
10
9
|
|
|
11
|
-
@charField({ description:
|
|
10
|
+
@charField({ description: "Name", maxLength: 200 })
|
|
12
11
|
public name!: string;
|
|
13
12
|
|
|
14
|
-
@charField({
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
@charField({
|
|
14
|
+
description: "Status",
|
|
15
|
+
choices: [
|
|
16
|
+
{ value: "draft", desc: "Draft" },
|
|
17
|
+
{ value: "published", desc: "Published" },
|
|
18
|
+
],
|
|
19
|
+
})
|
|
18
20
|
public status!: string;
|
|
19
21
|
|
|
20
|
-
@foreignKeyField({ description:
|
|
22
|
+
@foreignKeyField({ description: "Category", related: "Category", priority: -1 })
|
|
21
23
|
public category!: number;
|
|
22
24
|
}
|
|
23
25
|
```
|
|
24
26
|
|
|
25
27
|
```html
|
|
26
|
-
<data-dispedit [model]="product" field="name"
|
|
28
|
+
<data-dispedit [model]="product" field="name" mode="dd" [editable]="true" />
|
|
27
29
|
<data-dispedit [model]="product" field="status" mode="dd" [editable]="true" />
|
|
28
|
-
<data-dispedit [model]="product" field="category" mode="dd" [editable]="true"
|
|
29
|
-
[collection]="categories" />
|
|
30
|
+
<data-dispedit [model]="product" field="category" mode="dd" [editable]="true" [collection]="categories" />
|
|
30
31
|
```
|
|
31
32
|
|
|
32
|
-
That is the whole idea: `status` renders as a `<select>` and `category` as an FK
|
|
33
|
-
|
|
33
|
+
That is the whole idea: `status` renders as a `<select>` and `category` as an FK dropdown **because the field metadata
|
|
34
|
+
says so**. You declare the model; the UI follows.
|
|
34
35
|
|
|
35
36
|
## Install
|
|
36
37
|
|
|
@@ -40,57 +41,52 @@ npm install @solidev/data
|
|
|
40
41
|
|
|
41
42
|
```ts
|
|
42
43
|
bootstrapApplication(AppComponent, {
|
|
43
|
-
providers: [
|
|
44
|
-
{ provide: DATA_API_URL, useValue: 'https://api.example.com/v1' },
|
|
45
|
-
provideHttpClient(),
|
|
46
|
-
],
|
|
44
|
+
providers: [{ provide: DATA_API_URL, useValue: "https://api.example.com/v1" }, provideHttpClient()],
|
|
47
45
|
});
|
|
48
46
|
```
|
|
49
47
|
|
|
50
48
|
## What's in the box
|
|
51
49
|
|
|
52
|
-
| Module
|
|
53
|
-
|
|
54
|
-
| **data**
|
|
55
|
-
| **modellist**
|
|
56
|
-
| **dispedit**
|
|
57
|
-
| **auth**
|
|
58
|
-
| **messages, routing, updates, uploader, richedit** | supporting pieces
|
|
50
|
+
| Module | What it gives you |
|
|
51
|
+
| -------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
|
|
52
|
+
| **data** | `DataModel` + field decorators, `Collection<T>`, `Queryset<T>`, `DataBackend` (with SSR `TransferState` support) |
|
|
53
|
+
| **modellist** | `ModelListService` — field selection, filters, sorter, paginator, and the components to render them |
|
|
54
|
+
| **dispedit** | `<data-dispedit>` and friends — metadata-driven display/edit, FK/M2M pickers, flags, safe-delete |
|
|
55
|
+
| **auth** | JWT service + interceptor with automatic refresh and replay |
|
|
56
|
+
| **messages, routing, updates, uploader, richedit** | supporting pieces |
|
|
59
57
|
|
|
60
58
|
## Documentation
|
|
61
59
|
|
|
62
|
-
- **Guides** — see the `docs/` directory in the repository, also published in the
|
|
63
|
-
|
|
64
|
-
- **API reference** — generated with [compodoc](https://compodoc.app):
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
(tree categories, m2m tags, geolocated stores, flags) that is **test-covered**, so it
|
|
68
|
-
cannot drift from the library.
|
|
60
|
+
- **Guides** — see the `docs/` directory in the repository, also published in the generated documentation under
|
|
61
|
+
**Guides**.
|
|
62
|
+
- **API reference** — generated with [compodoc](https://compodoc.app): `npm run mkdocs:serve`.
|
|
63
|
+
- **Worked example** — `projects/data/src/examples/catalog/`, a small catalog domain (tree categories, m2m tags,
|
|
64
|
+
geolocated stores, flags) that is **test-covered**, so it cannot drift from the library.
|
|
69
65
|
|
|
70
66
|
### Using this library with an AI agent
|
|
71
67
|
|
|
72
|
-
This package ships **[`AGENTS.md`](./AGENTS.md)** — a rules file covering the model
|
|
73
|
-
|
|
74
|
-
|
|
68
|
+
This package ships **[`AGENTS.md`](./AGENTS.md)** — a rules file covering the model conventions and the runtime
|
|
69
|
+
contracts that fail silently when broken. It is available in consuming projects at
|
|
70
|
+
`node_modules/@solidev/data/AGENTS.md`.
|
|
75
71
|
|
|
76
72
|
Point your agent at it from your own `AGENTS.md` / `CLAUDE.md`:
|
|
77
73
|
|
|
78
74
|
```markdown
|
|
79
|
-
This project uses `@solidev/data`. Before writing or changing any model, collection,
|
|
80
|
-
|
|
81
|
-
and follow it.
|
|
75
|
+
This project uses `@solidev/data`. Before writing or changing any model, collection, list component, or `dispedit`
|
|
76
|
+
usage, read `node_modules/@solidev/data/AGENTS.md` and follow it.
|
|
82
77
|
```
|
|
83
78
|
|
|
84
79
|
## Start here
|
|
85
80
|
|
|
86
|
-
Whatever else you skip, read the **Relations** guide and the **Traps** guide. The
|
|
87
|
-
|
|
88
|
-
of the ways to misuse this library fail **silently**.
|
|
81
|
+
Whatever else you skip, read the **Relations** guide and the **Traps** guide. The FK ⇄ details pairing is a runtime
|
|
82
|
+
contract enforced by string concatenation, and most of the ways to misuse this library fail **silently**.
|
|
89
83
|
|
|
90
84
|
## Requirements
|
|
91
85
|
|
|
92
|
-
Angular 22+. Peer dependencies: `@angular/common`, `@angular/core`, and
|
|
93
|
-
|
|
86
|
+
Angular 22+. Peer dependencies: `@angular/common`, `@angular/core`, `@ng-bootstrap/ng-bootstrap` and `jwt-decode`, plus
|
|
87
|
+
the engines behind the two editor entry points — `prosemirror-*` for `@solidev/data/richedit` and `@codemirror/*` for
|
|
88
|
+
`@solidev/data/mdedit`. npm 7+ installs all of them with the package; the editors only reach your bundle if you import
|
|
89
|
+
their entry point.
|
|
94
90
|
|
|
95
91
|
## Licence
|
|
96
92
|
|