@cogenta/schema 0.1.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/dist/define-collection.d.ts +8 -0
- package/dist/define-collection.d.ts.map +1 -0
- package/dist/define-collection.js +311 -0
- package/dist/define-collection.js.map +1 -0
- package/dist/errors.d.ts +16 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +18 -0
- package/dist/errors.js.map +1 -0
- package/dist/fields.d.ts +117 -0
- package/dist/fields.d.ts.map +1 -0
- package/dist/fields.js +107 -0
- package/dist/fields.js.map +1 -0
- package/dist/generate-schema-json.d.ts +61 -0
- package/dist/generate-schema-json.d.ts.map +1 -0
- package/dist/generate-schema-json.js +128 -0
- package/dist/generate-schema-json.js.map +1 -0
- package/dist/generate-types.d.ts +5 -0
- package/dist/generate-types.d.ts.map +1 -0
- package/dist/generate-types.js +220 -0
- package/dist/generate-types.js.map +1 -0
- package/dist/id.d.ts +8 -0
- package/dist/id.d.ts.map +1 -0
- package/dist/id.js +8 -0
- package/dist/id.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/rich-text.d.ts +164 -0
- package/dist/rich-text.d.ts.map +1 -0
- package/dist/rich-text.js +97 -0
- package/dist/rich-text.js.map +1 -0
- package/dist/routing/ids.d.ts +18 -0
- package/dist/routing/ids.d.ts.map +1 -0
- package/dist/routing/ids.js +41 -0
- package/dist/routing/ids.js.map +1 -0
- package/dist/routing/index.d.ts +13 -0
- package/dist/routing/index.d.ts.map +1 -0
- package/dist/routing/index.js +7 -0
- package/dist/routing/index.js.map +1 -0
- package/dist/routing/redirects.d.ts +76 -0
- package/dist/routing/redirects.d.ts.map +1 -0
- package/dist/routing/redirects.js +237 -0
- package/dist/routing/redirects.js.map +1 -0
- package/dist/routing/resolve.d.ts +38 -0
- package/dist/routing/resolve.d.ts.map +1 -0
- package/dist/routing/resolve.js +23 -0
- package/dist/routing/resolve.js.map +1 -0
- package/dist/routing/router.d.ts +51 -0
- package/dist/routing/router.d.ts.map +1 -0
- package/dist/routing/router.js +132 -0
- package/dist/routing/router.js.map +1 -0
- package/dist/routing/slug-change.d.ts +39 -0
- package/dist/routing/slug-change.d.ts.map +1 -0
- package/dist/routing/slug-change.js +44 -0
- package/dist/routing/slug-change.js.map +1 -0
- package/dist/routing/slug.d.ts +82 -0
- package/dist/routing/slug.d.ts.map +1 -0
- package/dist/routing/slug.js +124 -0
- package/dist/routing/slug.js.map +1 -0
- package/dist/routing/slugify.d.ts +29 -0
- package/dist/routing/slugify.d.ts.map +1 -0
- package/dist/routing/slugify.js +104 -0
- package/dist/routing/slugify.js.map +1 -0
- package/dist/scheduling/index.d.ts +3 -0
- package/dist/scheduling/index.d.ts.map +1 -0
- package/dist/scheduling/index.js +2 -0
- package/dist/scheduling/index.js.map +1 -0
- package/dist/scheduling/publish.d.ts +71 -0
- package/dist/scheduling/publish.d.ts.map +1 -0
- package/dist/scheduling/publish.js +122 -0
- package/dist/scheduling/publish.js.map +1 -0
- package/dist/search/extract.d.ts +25 -0
- package/dist/search/extract.d.ts.map +1 -0
- package/dist/search/extract.js +188 -0
- package/dist/search/extract.js.map +1 -0
- package/dist/search/index.d.ts +36 -0
- package/dist/search/index.d.ts.map +1 -0
- package/dist/search/index.js +44 -0
- package/dist/search/index.js.map +1 -0
- package/dist/search/mysql.d.ts +7 -0
- package/dist/search/mysql.d.ts.map +1 -0
- package/dist/search/mysql.js +121 -0
- package/dist/search/mysql.js.map +1 -0
- package/dist/search/postgres.d.ts +9 -0
- package/dist/search/postgres.d.ts.map +1 -0
- package/dist/search/postgres.js +167 -0
- package/dist/search/postgres.js.map +1 -0
- package/dist/search/query.d.ts +35 -0
- package/dist/search/query.d.ts.map +1 -0
- package/dist/search/query.js +116 -0
- package/dist/search/query.js.map +1 -0
- package/dist/search/sqlite.d.ts +16 -0
- package/dist/search/sqlite.d.ts.map +1 -0
- package/dist/search/sqlite.js +166 -0
- package/dist/search/sqlite.js.map +1 -0
- package/dist/search/table.d.ts +49 -0
- package/dist/search/table.d.ts.map +1 -0
- package/dist/search/table.js +86 -0
- package/dist/search/table.js.map +1 -0
- package/dist/search/text.d.ts +42 -0
- package/dist/search/text.d.ts.map +1 -0
- package/dist/search/text.js +56 -0
- package/dist/search/text.js.map +1 -0
- package/dist/search/types.d.ts +98 -0
- package/dist/search/types.d.ts.map +1 -0
- package/dist/search/types.js +2 -0
- package/dist/search/types.js.map +1 -0
- package/dist/store/columns.d.ts +33 -0
- package/dist/store/columns.d.ts.map +1 -0
- package/dist/store/columns.js +113 -0
- package/dist/store/columns.js.map +1 -0
- package/dist/store/cursor.d.ts +23 -0
- package/dist/store/cursor.d.ts.map +1 -0
- package/dist/store/cursor.js +36 -0
- package/dist/store/cursor.js.map +1 -0
- package/dist/store/diff.d.ts +59 -0
- package/dist/store/diff.d.ts.map +1 -0
- package/dist/store/diff.js +124 -0
- package/dist/store/diff.js.map +1 -0
- package/dist/store/fragments.d.ts +13 -0
- package/dist/store/fragments.d.ts.map +1 -0
- package/dist/store/fragments.js +25 -0
- package/dist/store/fragments.js.map +1 -0
- package/dist/store/index.d.ts +22 -0
- package/dist/store/index.d.ts.map +1 -0
- package/dist/store/index.js +16 -0
- package/dist/store/index.js.map +1 -0
- package/dist/store/naming.d.ts +25 -0
- package/dist/store/naming.d.ts.map +1 -0
- package/dist/store/naming.js +80 -0
- package/dist/store/naming.js.map +1 -0
- package/dist/store/read-only.d.ts +16 -0
- package/dist/store/read-only.d.ts.map +1 -0
- package/dist/store/read-only.js +36 -0
- package/dist/store/read-only.js.map +1 -0
- package/dist/store/store.d.ts +52 -0
- package/dist/store/store.d.ts.map +1 -0
- package/dist/store/store.js +706 -0
- package/dist/store/store.js.map +1 -0
- package/dist/store/tables.d.ts +40 -0
- package/dist/store/tables.d.ts.map +1 -0
- package/dist/store/tables.js +267 -0
- package/dist/store/tables.js.map +1 -0
- package/dist/store/types.d.ts +105 -0
- package/dist/store/types.d.ts.map +1 -0
- package/dist/store/types.js +2 -0
- package/dist/store/types.js.map +1 -0
- package/dist/store/uuid.d.ts +6 -0
- package/dist/store/uuid.d.ts.map +1 -0
- package/dist/store/uuid.js +64 -0
- package/dist/store/uuid.js.map +1 -0
- package/dist/store/values.d.ts +40 -0
- package/dist/store/values.d.ts.map +1 -0
- package/dist/store/values.js +160 -0
- package/dist/store/values.js.map +1 -0
- package/dist/system-fields.d.ts +60 -0
- package/dist/system-fields.d.ts.map +1 -0
- package/dist/system-fields.js +73 -0
- package/dist/system-fields.js.map +1 -0
- package/dist/types.d.ts +101 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +32 -0
- package/dist/types.js.map +1 -0
- package/dist/validation.d.ts +54 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +183 -0
- package/dist/validation.js.map +1 -0
- package/package.json +43 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** `publishedAt` becomes `published_at`. Digits stay attached to what precedes them. */
|
|
2
|
+
export declare function toSnakeCase(name: string): string;
|
|
3
|
+
export declare function entriesTable(collection: string): string;
|
|
4
|
+
/**
|
|
5
|
+
* One row per block, never a JSON array in the content row (contract A).
|
|
6
|
+
*
|
|
7
|
+
* Three features depend on blocks being rows: answering "which pages use this
|
|
8
|
+
* medium" for the media library, invalidating cache tags on publication, and
|
|
9
|
+
* chunking content per block for RAG. None of them survive a JSON column.
|
|
10
|
+
*/
|
|
11
|
+
export declare function blocksTable(collection: string): string;
|
|
12
|
+
export declare function versionsTable(collection: string): string;
|
|
13
|
+
/** The join table of a `many: true` relation. */
|
|
14
|
+
export declare function relationTable(collection: string, field: string): string;
|
|
15
|
+
export declare function indexName(table: string, suffix: string): string;
|
|
16
|
+
export declare function columnFor(field: string): string;
|
|
17
|
+
/**
|
|
18
|
+
* Columns the engine owns. A user field that lands on one of these is refused
|
|
19
|
+
* rather than silently shadowed — `updated_at` written by an editor would break
|
|
20
|
+
* every ordering and every cache decision in the product.
|
|
21
|
+
*/
|
|
22
|
+
export declare const SYSTEM_COLUMNS: readonly ['id', 'created_at', 'updated_at', 'created_by', 'updated_by', 'status', 'locale', 'translation_of', 'version', 'provenance', 'provenance_detail'];
|
|
23
|
+
export type SystemColumn = (typeof SYSTEM_COLUMNS)[number];
|
|
24
|
+
export declare function isSystemColumn(column: string): column is SystemColumn;
|
|
25
|
+
//# sourceMappingURL=naming.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"naming.d.ts","sourceRoot":"","sources":["../../src/store/naming.ts"],"names":[],"mappings":"AAiCA,wFAAwF;AACxF,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,iDAAiD;AACjD,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAEvE;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED;;;;GAIG;AACH,eAAO,MAAM,cAAc,YACzB,IAAI,EACJ,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,QAAQ,EACR,QAAQ,EACR,gBAAgB,EAChB,SAAS,EACT,YAAY,EACZ,mBAAmB,CACX,CAAA;AAEV,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAA;AAE1D,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,IAAI,YAAY,CAErE"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { CogentaError } from '@cogenta/core';
|
|
2
|
+
/**
|
|
3
|
+
* Physical names, derived from the schema in exactly one place.
|
|
4
|
+
*
|
|
5
|
+
* The rule is that nothing outside this file ever builds a table or column name
|
|
6
|
+
* by concatenation: the migration generator, the store and the tests must agree
|
|
7
|
+
* on the same string, and a second spelling of it is a silent data loss waiting
|
|
8
|
+
* for the day someone renames a collection.
|
|
9
|
+
*/
|
|
10
|
+
const PREFIX = 'cogenta_';
|
|
11
|
+
/**
|
|
12
|
+
* MySQL refuses an identifier longer than 64 characters, and truncating one
|
|
13
|
+
* would make two collections collide on the same table. Failing at schema load
|
|
14
|
+
* with a name in the message costs a rename; failing at migration time on the
|
|
15
|
+
* one dialect nobody develops against costs a day.
|
|
16
|
+
*/
|
|
17
|
+
const MAX_IDENTIFIER_LENGTH = 64;
|
|
18
|
+
function checked(name) {
|
|
19
|
+
if (name.length > MAX_IDENTIFIER_LENGTH) {
|
|
20
|
+
throw new CogentaError({
|
|
21
|
+
code: 'CONFIG_INVALID',
|
|
22
|
+
message: `The generated SQL identifier "${name}" is ${name.length} characters long.`,
|
|
23
|
+
hint: `MySQL allows at most ${MAX_IDENTIFIER_LENGTH}. Shorten the collection or field name.`,
|
|
24
|
+
details: { name },
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
return name;
|
|
28
|
+
}
|
|
29
|
+
/** `publishedAt` becomes `published_at`. Digits stay attached to what precedes them. */
|
|
30
|
+
export function toSnakeCase(name) {
|
|
31
|
+
return name.replace(/([a-z0-9])([A-Z])/g, '$1_$2').toLowerCase();
|
|
32
|
+
}
|
|
33
|
+
export function entriesTable(collection) {
|
|
34
|
+
return checked(`${PREFIX}${toSnakeCase(collection)}`);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* One row per block, never a JSON array in the content row (contract A).
|
|
38
|
+
*
|
|
39
|
+
* Three features depend on blocks being rows: answering "which pages use this
|
|
40
|
+
* medium" for the media library, invalidating cache tags on publication, and
|
|
41
|
+
* chunking content per block for RAG. None of them survive a JSON column.
|
|
42
|
+
*/
|
|
43
|
+
export function blocksTable(collection) {
|
|
44
|
+
return checked(`${entriesTable(collection)}_blocks`);
|
|
45
|
+
}
|
|
46
|
+
export function versionsTable(collection) {
|
|
47
|
+
return checked(`${entriesTable(collection)}_versions`);
|
|
48
|
+
}
|
|
49
|
+
/** The join table of a `many: true` relation. */
|
|
50
|
+
export function relationTable(collection, field) {
|
|
51
|
+
return checked(`${entriesTable(collection)}_${toSnakeCase(field)}`);
|
|
52
|
+
}
|
|
53
|
+
export function indexName(table, suffix) {
|
|
54
|
+
return checked(`${table}_${suffix}`);
|
|
55
|
+
}
|
|
56
|
+
export function columnFor(field) {
|
|
57
|
+
return checked(toSnakeCase(field));
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Columns the engine owns. A user field that lands on one of these is refused
|
|
61
|
+
* rather than silently shadowed — `updated_at` written by an editor would break
|
|
62
|
+
* every ordering and every cache decision in the product.
|
|
63
|
+
*/
|
|
64
|
+
export const SYSTEM_COLUMNS = [
|
|
65
|
+
'id',
|
|
66
|
+
'created_at',
|
|
67
|
+
'updated_at',
|
|
68
|
+
'created_by',
|
|
69
|
+
'updated_by',
|
|
70
|
+
'status',
|
|
71
|
+
'locale',
|
|
72
|
+
'translation_of',
|
|
73
|
+
'version',
|
|
74
|
+
'provenance',
|
|
75
|
+
'provenance_detail',
|
|
76
|
+
];
|
|
77
|
+
export function isSystemColumn(column) {
|
|
78
|
+
return SYSTEM_COLUMNS.includes(column);
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=naming.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"naming.js","sourceRoot":"","sources":["../../src/store/naming.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAE5C;;;;;;;GAOG;AAEH,MAAM,MAAM,GAAG,UAAU,CAAA;AAEzB;;;;;GAKG;AACH,MAAM,qBAAqB,GAAG,EAAE,CAAA;AAEhC,SAAS,OAAO,CAAC,IAAY;IAC3B,IAAI,IAAI,CAAC,MAAM,GAAG,qBAAqB,EAAE,CAAC;QACxC,MAAM,IAAI,YAAY,CAAC;YACrB,IAAI,EAAE,gBAAgB;YACtB,OAAO,EAAE,iCAAiC,IAAI,QAAQ,IAAI,CAAC,MAAM,mBAAmB;YACpF,IAAI,EAAE,wBAAwB,qBAAqB,yCAAyC;YAC5F,OAAO,EAAE,EAAE,IAAI,EAAE;SAClB,CAAC,CAAA;IACJ,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,OAAO,IAAI,CAAC,OAAO,CAAC,oBAAoB,EAAE,OAAO,CAAC,CAAC,WAAW,EAAE,CAAA;AAClE,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,UAAkB;IAC7C,OAAO,OAAO,CAAC,GAAG,MAAM,GAAG,WAAW,CAAC,UAAU,CAAC,EAAE,CAAC,CAAA;AACvD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,UAAkB;IAC5C,OAAO,OAAO,CAAC,GAAG,YAAY,CAAC,UAAU,CAAC,SAAS,CAAC,CAAA;AACtD,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,UAAkB;IAC9C,OAAO,OAAO,CAAC,GAAG,YAAY,CAAC,UAAU,CAAC,WAAW,CAAC,CAAA;AACxD,CAAC;AAED,iDAAiD;AACjD,MAAM,UAAU,aAAa,CAAC,UAAkB,EAAE,KAAa;IAC7D,OAAO,OAAO,CAAC,GAAG,YAAY,CAAC,UAAU,CAAC,IAAI,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;AACrE,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,KAAa,EAAE,MAAc;IACrD,OAAO,OAAO,CAAC,GAAG,KAAK,IAAI,MAAM,EAAE,CAAC,CAAA;AACtC,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,KAAa;IACrC,OAAO,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAA;AACpC,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,IAAI;IACJ,YAAY;IACZ,YAAY;IACZ,YAAY;IACZ,YAAY;IACZ,QAAQ;IACR,QAAQ;IACR,gBAAgB;IAChB,SAAS;IACT,YAAY;IACZ,mBAAmB;CACX,CAAA;AAIV,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,OAAQ,cAAoC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;AAC/D,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ContentStore } from './store.js';
|
|
2
|
+
import type { ContentValues } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* "Commencer par une démo en lecture seule" (L9 tâche 12, playground). Wraps
|
|
5
|
+
* any `ContentStore` so every mutating method refuses instead of writing —
|
|
6
|
+
* `create`/`update`/`delete`/`publish`/`unpublish`/`restore` — while every
|
|
7
|
+
* read (`read`/`list`/`history`/`readVersion`/`diff`/`translations`/
|
|
8
|
+
* `resolveLocale`) passes straight through, unchanged.
|
|
9
|
+
*
|
|
10
|
+
* A single wrap at the store level protects every consumer built on top of
|
|
11
|
+
* it — REST's `ContentService` and GraphQL's gateway both construct their
|
|
12
|
+
* stores from the same `storeFor` closure in `serve.ts`, so wrapping there
|
|
13
|
+
* covers both transports with one guard, not two.
|
|
14
|
+
*/
|
|
15
|
+
export declare function withReadOnlyStore<TValues extends ContentValues = ContentValues>(store: ContentStore<TValues>): ContentStore<TValues>;
|
|
16
|
+
//# sourceMappingURL=read-only.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-only.d.ts","sourceRoot":"","sources":["../../src/store/read-only.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,SAAS,aAAa,GAAG,aAAa,EAC7E,KAAK,EAAE,YAAY,CAAC,OAAO,CAAC,GAC3B,YAAY,CAAC,OAAO,CAAC,CAsBvB"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { CogentaError } from '@cogenta/core';
|
|
2
|
+
/**
|
|
3
|
+
* "Commencer par une démo en lecture seule" (L9 tâche 12, playground). Wraps
|
|
4
|
+
* any `ContentStore` so every mutating method refuses instead of writing —
|
|
5
|
+
* `create`/`update`/`delete`/`publish`/`unpublish`/`restore` — while every
|
|
6
|
+
* read (`read`/`list`/`history`/`readVersion`/`diff`/`translations`/
|
|
7
|
+
* `resolveLocale`) passes straight through, unchanged.
|
|
8
|
+
*
|
|
9
|
+
* A single wrap at the store level protects every consumer built on top of
|
|
10
|
+
* it — REST's `ContentService` and GraphQL's gateway both construct their
|
|
11
|
+
* stores from the same `storeFor` closure in `serve.ts`, so wrapping there
|
|
12
|
+
* covers both transports with one guard, not two.
|
|
13
|
+
*/
|
|
14
|
+
export function withReadOnlyStore(store) {
|
|
15
|
+
// `async` so a synchronous refusal still surfaces as a rejected promise —
|
|
16
|
+
// every `ContentStore` method is `Promise`-returning, and a caller that
|
|
17
|
+
// awaits it (every real caller does) must see a rejection, not a thrown
|
|
18
|
+
// exception at the call site.
|
|
19
|
+
async function refuse() {
|
|
20
|
+
throw new CogentaError({
|
|
21
|
+
code: 'CONTENT_READ_ONLY',
|
|
22
|
+
message: 'This instance is read-only; the requested change was not saved.',
|
|
23
|
+
hint: 'This is a read-only demo instance (e.g. a playground). Reads work normally; writes are refused, not silently dropped.',
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
...store,
|
|
28
|
+
create: () => refuse(),
|
|
29
|
+
update: () => refuse(),
|
|
30
|
+
delete: () => refuse(),
|
|
31
|
+
publish: () => refuse(),
|
|
32
|
+
unpublish: () => refuse(),
|
|
33
|
+
restore: () => refuse(),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=read-only.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-only.js","sourceRoot":"","sources":["../../src/store/read-only.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAI5C;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,iBAAiB,CAC/B,KAA4B;IAE5B,0EAA0E;IAC1E,wEAAwE;IACxE,wEAAwE;IACxE,8BAA8B;IAC9B,KAAK,UAAU,MAAM;QACnB,MAAM,IAAI,YAAY,CAAC;YACrB,IAAI,EAAE,mBAAmB;YACzB,OAAO,EAAE,iEAAiE;YAC1E,IAAI,EAAE,uHAAuH;SAC9H,CAAC,CAAA;IACJ,CAAC;IAED,OAAO;QACL,GAAG,KAAK;QACR,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE;QACtB,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE;QACtB,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE;QACtB,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE;QACvB,SAAS,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE;QACzB,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE;KACxB,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { type DatabaseHandle } from '@cogenta/core';
|
|
2
|
+
import type { CollectionDefinition } from '../types.js';
|
|
3
|
+
import { type ContentDiff } from './diff.js';
|
|
4
|
+
import type { ContentEntry, ContentValues, CreateInput, EntryState, ListOptions, LocaleResolution, Page, ResolveLocaleOptions, UpdateInput, VersionSummary } from './types.js';
|
|
5
|
+
/**
|
|
6
|
+
* The persistence layer of a collection.
|
|
7
|
+
*
|
|
8
|
+
* Three ideas hold it together, and everything else follows from them:
|
|
9
|
+
*
|
|
10
|
+
* 1. **The entry table holds the live state** — what the public renderer reads.
|
|
11
|
+
* A draft of an already-published entry is a row in the versions table, not a
|
|
12
|
+
* mutation of the live row. That is what makes "the public role can never
|
|
13
|
+
* reach a draft" a property of the storage rather than of a filter someone
|
|
14
|
+
* has to remember to write.
|
|
15
|
+
* 2. **Blocks are rows, keyed by `(entry, version, zone, key)`** (contract A).
|
|
16
|
+
* The live blocks are those at the entry's own version, so publishing a draft
|
|
17
|
+
* is a version number moving, not a block rewrite.
|
|
18
|
+
* 3. **One row per locale** (ADR-0014), so `status`, `version` and publication
|
|
19
|
+
* are per language by construction, not by convention.
|
|
20
|
+
*/
|
|
21
|
+
export interface ContentStoreOptions {
|
|
22
|
+
readonly db: DatabaseHandle;
|
|
23
|
+
readonly collection: CollectionDefinition;
|
|
24
|
+
/** The locale an entry gets when the caller does not say. */
|
|
25
|
+
readonly defaultLocale?: string;
|
|
26
|
+
/** Injectable so tests can pin time; nothing else should pass it. */
|
|
27
|
+
readonly now?: () => Date;
|
|
28
|
+
readonly newId?: () => string;
|
|
29
|
+
}
|
|
30
|
+
export interface ContentStore<TValues extends ContentValues = ContentValues> {
|
|
31
|
+
create(input: CreateInput<TValues>): Promise<ContentEntry<TValues>>;
|
|
32
|
+
read(id: string, options?: {
|
|
33
|
+
readonly state?: EntryState;
|
|
34
|
+
}): Promise<ContentEntry<TValues> | null>;
|
|
35
|
+
update(id: string, input: UpdateInput<TValues>): Promise<ContentEntry<TValues>>;
|
|
36
|
+
delete(id: string): Promise<boolean>;
|
|
37
|
+
list(options?: ListOptions): Promise<Page<ContentEntry<TValues>>>;
|
|
38
|
+
publish(id: string, input?: {
|
|
39
|
+
readonly publishedBy?: string | null;
|
|
40
|
+
}): Promise<ContentEntry<TValues>>;
|
|
41
|
+
unpublish(id: string, input?: {
|
|
42
|
+
readonly status?: 'draft' | 'archived';
|
|
43
|
+
}): Promise<ContentEntry<TValues>>;
|
|
44
|
+
history(id: string): Promise<readonly VersionSummary[]>;
|
|
45
|
+
readVersion(id: string, version: number): Promise<ContentEntry<TValues> | null>;
|
|
46
|
+
restore(id: string, version: number, input?: UpdateInput<TValues>): Promise<ContentEntry<TValues>>;
|
|
47
|
+
diff(id: string, from: number, to: number): Promise<ContentDiff>;
|
|
48
|
+
translations(id: string): Promise<readonly ContentEntry<TValues>[]>;
|
|
49
|
+
resolveLocale(id: string, locale: string, options: ResolveLocaleOptions): Promise<LocaleResolution<TValues>>;
|
|
50
|
+
}
|
|
51
|
+
export declare function createContentStore<TValues extends ContentValues = ContentValues>(options: ContentStoreOptions): ContentStore<TValues>;
|
|
52
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/store/store.ts"],"names":[],"mappings":"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"}
|