@cogenta/schema 0.2.0 → 0.4.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/dist/define-collection.d.ts.map +1 -1
- package/dist/define-collection.js +53 -3
- package/dist/define-collection.js.map +1 -1
- package/dist/generate-types.d.ts.map +1 -1
- package/dist/generate-types.js +6 -1
- package/dist/generate-types.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/media-usage.d.ts +56 -0
- package/dist/media-usage.d.ts.map +1 -0
- package/dist/media-usage.js +89 -0
- package/dist/media-usage.js.map +1 -0
- package/dist/rich-text.d.ts +28 -2
- package/dist/rich-text.d.ts.map +1 -1
- package/dist/rich-text.js +26 -3
- package/dist/rich-text.js.map +1 -1
- package/dist/routing/index.d.ts +5 -1
- package/dist/routing/index.d.ts.map +1 -1
- package/dist/routing/index.js +2 -0
- package/dist/routing/index.js.map +1 -1
- package/dist/routing/not-found-log.d.ts +78 -0
- package/dist/routing/not-found-log.d.ts.map +1 -0
- package/dist/routing/not-found-log.js +153 -0
- package/dist/routing/not-found-log.js.map +1 -0
- package/dist/routing/redirect-patterns.d.ts +61 -0
- package/dist/routing/redirect-patterns.d.ts.map +1 -0
- package/dist/routing/redirect-patterns.js +173 -0
- package/dist/routing/redirect-patterns.js.map +1 -0
- package/dist/routing/redirects.d.ts +27 -4
- package/dist/routing/redirects.d.ts.map +1 -1
- package/dist/routing/redirects.js +160 -48
- package/dist/routing/redirects.js.map +1 -1
- package/dist/scheduling/index.d.ts +2 -0
- package/dist/scheduling/index.d.ts.map +1 -1
- package/dist/scheduling/index.js +1 -0
- package/dist/scheduling/index.js.map +1 -1
- package/dist/scheduling/registry.d.ts +147 -0
- package/dist/scheduling/registry.d.ts.map +1 -0
- package/dist/scheduling/registry.js +318 -0
- package/dist/scheduling/registry.js.map +1 -0
- package/dist/search/extract.d.ts +24 -0
- package/dist/search/extract.d.ts.map +1 -1
- package/dist/search/extract.js +63 -8
- package/dist/search/extract.js.map +1 -1
- package/dist/search/index.d.ts +2 -1
- package/dist/search/index.d.ts.map +1 -1
- package/dist/search/index.js +1 -9
- package/dist/search/index.js.map +1 -1
- package/dist/store/admin-theme-store.d.ts +26 -0
- package/dist/store/admin-theme-store.d.ts.map +1 -0
- package/dist/store/admin-theme-store.js +81 -0
- package/dist/store/admin-theme-store.js.map +1 -0
- package/dist/store/admin-theme-tables.d.ts +24 -0
- package/dist/store/admin-theme-tables.d.ts.map +1 -0
- package/dist/store/admin-theme-tables.js +41 -0
- package/dist/store/admin-theme-tables.js.map +1 -0
- package/dist/store/admin-theme-templates.d.ts +135 -0
- package/dist/store/admin-theme-templates.d.ts.map +1 -0
- package/dist/store/admin-theme-templates.js +217 -0
- package/dist/store/admin-theme-templates.js.map +1 -0
- package/dist/store/columns.d.ts.map +1 -1
- package/dist/store/columns.js +8 -2
- package/dist/store/columns.js.map +1 -1
- package/dist/store/diff.d.ts +40 -0
- package/dist/store/diff.d.ts.map +1 -1
- package/dist/store/diff.js +148 -0
- package/dist/store/diff.js.map +1 -1
- package/dist/store/index.d.ts +47 -4
- package/dist/store/index.d.ts.map +1 -1
- package/dist/store/index.js +26 -2
- package/dist/store/index.js.map +1 -1
- package/dist/store/maintenance-store.d.ts +34 -0
- package/dist/store/maintenance-store.d.ts.map +1 -0
- package/dist/store/maintenance-store.js +92 -0
- package/dist/store/maintenance-store.js.map +1 -0
- package/dist/store/menu-store.d.ts +146 -0
- package/dist/store/menu-store.d.ts.map +1 -0
- package/dist/store/menu-store.js +565 -0
- package/dist/store/menu-store.js.map +1 -0
- package/dist/store/menu-tables.d.ts +38 -0
- package/dist/store/menu-tables.d.ts.map +1 -0
- package/dist/store/menu-tables.js +117 -0
- package/dist/store/menu-tables.js.map +1 -0
- package/dist/store/naming.d.ts +1 -1
- package/dist/store/naming.d.ts.map +1 -1
- package/dist/store/naming.js +2 -0
- package/dist/store/naming.js.map +1 -1
- package/dist/store/pattern-store.d.ts +75 -0
- package/dist/store/pattern-store.d.ts.map +1 -0
- package/dist/store/pattern-store.js +118 -0
- package/dist/store/pattern-store.js.map +1 -0
- package/dist/store/pattern-tables.d.ts +29 -0
- package/dist/store/pattern-tables.d.ts.map +1 -0
- package/dist/store/pattern-tables.js +53 -0
- package/dist/store/pattern-tables.js.map +1 -0
- package/dist/store/read-only.d.ts +3 -3
- package/dist/store/read-only.d.ts.map +1 -1
- package/dist/store/read-only.js +4 -3
- package/dist/store/read-only.js.map +1 -1
- package/dist/store/redirect-tracking.d.ts +50 -0
- package/dist/store/redirect-tracking.d.ts.map +1 -0
- package/dist/store/redirect-tracking.js +91 -0
- package/dist/store/redirect-tracking.js.map +1 -0
- package/dist/store/review-transitions.d.ts +34 -0
- package/dist/store/review-transitions.d.ts.map +1 -0
- package/dist/store/review-transitions.js +51 -0
- package/dist/store/review-transitions.js.map +1 -0
- package/dist/store/role-permission-export.d.ts +22 -0
- package/dist/store/role-permission-export.d.ts.map +1 -0
- package/dist/store/role-permission-export.js +0 -0
- package/dist/store/role-permission-export.js.map +1 -0
- package/dist/store/role-permission-overlay.d.ts +27 -0
- package/dist/store/role-permission-overlay.d.ts.map +1 -0
- package/dist/store/role-permission-overlay.js +0 -0
- package/dist/store/role-permission-overlay.js.map +1 -0
- package/dist/store/role-permission-store.d.ts +72 -0
- package/dist/store/role-permission-store.d.ts.map +1 -0
- package/dist/store/role-permission-store.js +148 -0
- package/dist/store/role-permission-store.js.map +1 -0
- package/dist/store/role-permission-tables.d.ts +27 -0
- package/dist/store/role-permission-tables.d.ts.map +1 -0
- package/dist/store/role-permission-tables.js +52 -0
- package/dist/store/role-permission-tables.js.map +1 -0
- package/dist/store/scheduled-publish-enqueue.d.ts +37 -0
- package/dist/store/scheduled-publish-enqueue.d.ts.map +1 -0
- package/dist/store/scheduled-publish-enqueue.js +51 -0
- package/dist/store/scheduled-publish-enqueue.js.map +1 -0
- package/dist/store/scheduled-publish-failures.d.ts +36 -0
- package/dist/store/scheduled-publish-failures.d.ts.map +1 -0
- package/dist/store/scheduled-publish-failures.js +67 -0
- package/dist/store/scheduled-publish-failures.js.map +1 -0
- package/dist/store/schema-2-1-migration.d.ts +29 -0
- package/dist/store/schema-2-1-migration.d.ts.map +1 -0
- package/dist/store/schema-2-1-migration.js +71 -0
- package/dist/store/schema-2-1-migration.js.map +1 -0
- package/dist/store/search-console-store.d.ts +44 -0
- package/dist/store/search-console-store.d.ts.map +1 -0
- package/dist/store/search-console-store.js +90 -0
- package/dist/store/search-console-store.js.map +1 -0
- package/dist/store/search-console-tables.d.ts +14 -0
- package/dist/store/search-console-tables.d.ts.map +1 -0
- package/dist/store/search-console-tables.js +29 -0
- package/dist/store/search-console-tables.js.map +1 -0
- package/dist/store/search-indexing.d.ts +36 -0
- package/dist/store/search-indexing.d.ts.map +1 -1
- package/dist/store/search-indexing.js +33 -0
- package/dist/store/search-indexing.js.map +1 -1
- package/dist/store/site-settings-registry.d.ts +164 -0
- package/dist/store/site-settings-registry.d.ts.map +1 -0
- package/dist/store/site-settings-registry.js +1160 -0
- package/dist/store/site-settings-registry.js.map +1 -0
- package/dist/store/site-settings-store.d.ts +42 -0
- package/dist/store/site-settings-store.d.ts.map +1 -0
- package/dist/store/site-settings-store.js +97 -0
- package/dist/store/site-settings-store.js.map +1 -0
- package/dist/store/site-settings-tables.d.ts +29 -0
- package/dist/store/site-settings-tables.d.ts.map +1 -0
- package/dist/store/site-settings-tables.js +48 -0
- package/dist/store/site-settings-tables.js.map +1 -0
- package/dist/store/store.d.ts +57 -2
- package/dist/store/store.d.ts.map +1 -1
- package/dist/store/store.js +278 -37
- package/dist/store/store.js.map +1 -1
- package/dist/store/tables.d.ts.map +1 -1
- package/dist/store/tables.js +11 -0
- package/dist/store/tables.js.map +1 -1
- package/dist/store/taxonomy-store.d.ts.map +1 -1
- package/dist/store/taxonomy-store.js +90 -39
- package/dist/store/taxonomy-store.js.map +1 -1
- package/dist/store/taxonomy-usage.d.ts +47 -0
- package/dist/store/taxonomy-usage.d.ts.map +1 -0
- package/dist/store/taxonomy-usage.js +101 -0
- package/dist/store/taxonomy-usage.js.map +1 -0
- package/dist/store/theme-store.d.ts +73 -0
- package/dist/store/theme-store.d.ts.map +1 -0
- package/dist/store/theme-store.js +193 -0
- package/dist/store/theme-store.js.map +1 -0
- package/dist/store/types.d.ts +36 -1
- package/dist/store/types.d.ts.map +1 -1
- package/dist/store/values.d.ts.map +1 -1
- package/dist/store/values.js +28 -1
- package/dist/store/values.js.map +1 -1
- package/dist/system-fields.d.ts +8 -1
- package/dist/system-fields.d.ts.map +1 -1
- package/dist/system-fields.js +14 -1
- package/dist/system-fields.js.map +1 -1
- package/dist/types.d.ts +54 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +21 -0
- package/dist/types.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"menu-tables.d.ts","sourceRoot":"","sources":["../../src/store/menu-tables.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAqC,MAAM,eAAe,CAAA;AAItF;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,eAAO,MAAM,WAAW;aACtB,KAAK,EAAE,eAAe;aACtB,KAAK,EAAE,oBAAoB;CACnB,CAAA;AAEV,sFAAsF;AACtF,eAAO,MAAM,qBAAqB,QAAa,CAAA;AAE/C,iEAAiE;AACjE,eAAO,MAAM,oBAAoB,KAAK,CAAA;AAEtC,wBAAsB,gBAAgB,CAAC,EAAE,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAkFxE"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { identifier, sql } from '@cogenta/core';
|
|
2
|
+
import { integerColumn, jsonColumn, textColumn, timestampColumn, uuidColumn } from './columns.js';
|
|
3
|
+
import { indexName } from './naming.js';
|
|
4
|
+
/**
|
|
5
|
+
* Navigation menus.
|
|
6
|
+
*
|
|
7
|
+
* Unlike a taxonomy, a menu is not declared in the site's schema — it is
|
|
8
|
+
* created and edited entirely at runtime, from the admin or the API. So it
|
|
9
|
+
* gets one fixed pair of tables (`ensureMarketplaceTables`'s pattern), not one
|
|
10
|
+
* table per name the way `taxonomyTable()` mints one per declared taxonomy.
|
|
11
|
+
*
|
|
12
|
+
* A menu belongs to a locale, the way a localised collection does (ADR-0014):
|
|
13
|
+
* a site with French and English navigation has two rows in `cogenta_menus`
|
|
14
|
+
* sharing a `name`, not one row carrying two labels.
|
|
15
|
+
*
|
|
16
|
+
* An item's tree is a materialised path exactly like `taxonomy-path.ts`'s,
|
|
17
|
+
* reusing its helpers rather than a second implementation: a menu is
|
|
18
|
+
* structurally the same shape (a named tree), just editable without a schema
|
|
19
|
+
* declaration.
|
|
20
|
+
*
|
|
21
|
+
* `location` (fiche 09, task 3): where a menu renders on the public site
|
|
22
|
+
* (`primary`, `footer`, …), carried by the menu row itself rather than by a
|
|
23
|
+
* contract D extension. A theme is not the one true source of navigation
|
|
24
|
+
* vocabulary — a future second theme must be able to declare its own
|
|
25
|
+
* locations without a data migration — so the column stores an arbitrary
|
|
26
|
+
* string, unique per locale when set, and nothing here or in the router
|
|
27
|
+
* hardcodes what values it may hold. `null` (the default) means "not slotted
|
|
28
|
+
* anywhere yet", exactly the state every menu created before this column
|
|
29
|
+
* existed is already in.
|
|
30
|
+
*/
|
|
31
|
+
export const MENU_TABLES = {
|
|
32
|
+
menus: 'cogenta_menus',
|
|
33
|
+
items: 'cogenta_menu_items',
|
|
34
|
+
};
|
|
35
|
+
/** Ids plus the deepest realistic nesting: `/`, then a UUID and a slash per level. */
|
|
36
|
+
export const MENU_ITEM_PATH_LENGTH = 37 * 8 + 1;
|
|
37
|
+
/** How long a `location` key (`primary`, `footer`, …) may be. */
|
|
38
|
+
export const MENU_LOCATION_LENGTH = 64;
|
|
39
|
+
export async function ensureMenuTables(db) {
|
|
40
|
+
const dialect = db.dialect;
|
|
41
|
+
const menus = identifier(MENU_TABLES.menus, dialect);
|
|
42
|
+
const items = identifier(MENU_TABLES.items, dialect);
|
|
43
|
+
const menuStatements = [
|
|
44
|
+
sql `create table if not exists ${menus} (
|
|
45
|
+
${identifier('id', dialect)} ${uuidColumn(dialect)} not null primary key,
|
|
46
|
+
${identifier('name', dialect)} ${textColumn(dialect, 128)} not null,
|
|
47
|
+
${identifier('locale', dialect)} ${textColumn(dialect, 16)} not null,
|
|
48
|
+
${identifier('label', dialect)} ${textColumn(dialect, 255)} not null,
|
|
49
|
+
${identifier('location', dialect)} ${textColumn(dialect, MENU_LOCATION_LENGTH)},
|
|
50
|
+
${identifier('created_at', dialect)} ${timestampColumn(dialect)} not null,
|
|
51
|
+
${identifier('updated_at', dialect)} ${timestampColumn(dialect)} not null
|
|
52
|
+
)`,
|
|
53
|
+
sql `create table if not exists ${items} (
|
|
54
|
+
${identifier('id', dialect)} ${uuidColumn(dialect)} not null primary key,
|
|
55
|
+
${identifier('menu_id', dialect)} ${uuidColumn(dialect)} not null,
|
|
56
|
+
${identifier('parent_id', dialect)} ${uuidColumn(dialect)},
|
|
57
|
+
${identifier('label', dialect)} ${textColumn(dialect, 255)} not null,
|
|
58
|
+
${identifier('kind', dialect)} ${textColumn(dialect, 32)} not null,
|
|
59
|
+
${identifier('target_collection', dialect)} ${textColumn(dialect, 128)},
|
|
60
|
+
${identifier('target_entry_id', dialect)} ${uuidColumn(dialect)},
|
|
61
|
+
${identifier('target_taxonomy', dialect)} ${textColumn(dialect, 128)},
|
|
62
|
+
${identifier('target_term_id', dialect)} ${uuidColumn(dialect)},
|
|
63
|
+
${identifier('url', dialect)} ${textColumn(dialect, 2048)},
|
|
64
|
+
${identifier('title', dialect)} ${textColumn(dialect, 255)},
|
|
65
|
+
${identifier('position', dialect)} ${integerColumn()} not null,
|
|
66
|
+
${identifier('path', dialect)} ${textColumn(dialect, MENU_ITEM_PATH_LENGTH)} not null,
|
|
67
|
+
${identifier('open_in_new_tab', dialect)} ${jsonColumn()} not null,
|
|
68
|
+
${identifier('created_at', dialect)} ${timestampColumn(dialect)} not null,
|
|
69
|
+
${identifier('updated_at', dialect)} ${timestampColumn(dialect)} not null,
|
|
70
|
+
constraint ${identifier(indexName(MENU_TABLES.items, 'menu_fk'), dialect)}
|
|
71
|
+
foreign key (${identifier('menu_id', dialect)})
|
|
72
|
+
references ${menus} (${identifier('id', dialect)}) on delete cascade,
|
|
73
|
+
constraint ${identifier(indexName(MENU_TABLES.items, 'parent_fk'), dialect)}
|
|
74
|
+
foreign key (${identifier('parent_id', dialect)})
|
|
75
|
+
references ${items} (${identifier('id', dialect)}) on delete cascade
|
|
76
|
+
)`,
|
|
77
|
+
];
|
|
78
|
+
for (const statement of menuStatements) {
|
|
79
|
+
await db.query(statement);
|
|
80
|
+
}
|
|
81
|
+
// A database whose tables predate this column: `create table if not
|
|
82
|
+
// exists` above is a no-op for it, so the column is added the same way
|
|
83
|
+
// every other in-place table growth in this codebase is (schema-2-migration
|
|
84
|
+
// does the same for `deleted_at`). Failure here means the column already
|
|
85
|
+
// exists — the only realistic cause on a table this function has already
|
|
86
|
+
// run against — so it is swallowed exactly like the index statements below.
|
|
87
|
+
const columnStatements = [
|
|
88
|
+
sql `alter table ${menus} add column ${identifier('location', dialect)} ${textColumn(dialect, MENU_LOCATION_LENGTH)}`,
|
|
89
|
+
sql `alter table ${items} add column ${identifier('target_taxonomy', dialect)} ${textColumn(dialect, 128)}`,
|
|
90
|
+
sql `alter table ${items} add column ${identifier('target_term_id', dialect)} ${uuidColumn(dialect)}`,
|
|
91
|
+
sql `alter table ${items} add column ${identifier('title', dialect)} ${textColumn(dialect, 255)}`,
|
|
92
|
+
];
|
|
93
|
+
for (const statement of columnStatements) {
|
|
94
|
+
await db.query(statement).catch(() => undefined);
|
|
95
|
+
}
|
|
96
|
+
const indexStatements = [
|
|
97
|
+
// A menu name is unique per locale: French and English navigation can
|
|
98
|
+
// both be called "main" without colliding.
|
|
99
|
+
sql `create unique index ${identifier(indexName(MENU_TABLES.menus, 'name_locale_unique'), dialect)}
|
|
100
|
+
on ${menus} (${identifier('name', dialect)}, ${identifier('locale', dialect)})`,
|
|
101
|
+
// Same shape for `location`: at most one menu may claim a given slot in a
|
|
102
|
+
// given locale. `null` never collides with `null` on any of the three
|
|
103
|
+
// dialects (Postgres, MySQL/MariaDB and SQLite all treat a null as
|
|
104
|
+
// distinct from every other null in a unique index), which is exactly
|
|
105
|
+
// what lets every unslotted menu coexist.
|
|
106
|
+
sql `create unique index ${identifier(indexName(MENU_TABLES.menus, 'location_locale_unique'), dialect)}
|
|
107
|
+
on ${menus} (${identifier('location', dialect)}, ${identifier('locale', dialect)})`,
|
|
108
|
+
sql `create index ${identifier(indexName(MENU_TABLES.items, 'menu_path'), dialect)}
|
|
109
|
+
on ${items} (${identifier('menu_id', dialect)}, ${identifier('path', dialect)})`,
|
|
110
|
+
sql `create index ${identifier(indexName(MENU_TABLES.items, 'parent'), dialect)}
|
|
111
|
+
on ${items} (${identifier('parent_id', dialect)}, ${identifier('position', dialect)})`,
|
|
112
|
+
];
|
|
113
|
+
for (const statement of indexStatements) {
|
|
114
|
+
await db.query(statement).catch(() => undefined);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=menu-tables.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"menu-tables.js","sourceRoot":"","sources":["../../src/store/menu-tables.ts"],"names":[],"mappings":"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"}
|
package/dist/store/naming.d.ts
CHANGED
|
@@ -28,7 +28,7 @@ export declare function columnFor(field: string): string;
|
|
|
28
28
|
* rather than silently shadowed — `updated_at` written by an editor would break
|
|
29
29
|
* every ordering and every cache decision in the product.
|
|
30
30
|
*/
|
|
31
|
-
export declare const SYSTEM_COLUMNS: readonly ['id', 'created_at', 'updated_at', 'created_by', 'updated_by', 'status', 'deleted_at', 'locale', 'translation_of', 'version', 'provenance', 'provenance_detail'];
|
|
31
|
+
export declare const SYSTEM_COLUMNS: readonly ['id', 'created_at', 'updated_at', 'created_by', 'updated_by', 'status', 'deleted_at', 'review_state', 'assigned_reviewer', 'locale', 'translation_of', 'version', 'provenance', 'provenance_detail'];
|
|
32
32
|
export type SystemColumn = (typeof SYSTEM_COLUMNS)[number];
|
|
33
33
|
export declare function isSystemColumn(column: string): column is SystemColumn;
|
|
34
34
|
//# sourceMappingURL=naming.d.ts.map
|
|
@@ -1 +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,2EAA2E;AAC3E,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAEvE;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEtD;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,YAAY,EACZ,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"}
|
|
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,2EAA2E;AAC3E,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAEvE;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEtD;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,YAAY,EACZ,cAAc,EACd,mBAAmB,EACnB,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"}
|
package/dist/store/naming.js
CHANGED
package/dist/store/naming.js.map
CHANGED
|
@@ -1 +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,2EAA2E;AAC3E,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;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAAC,QAAgB;IAC5C,OAAO,OAAO,CAAC,GAAG,MAAM,OAAO,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAA;AACzD,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,YAAY;IACZ,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"}
|
|
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,2EAA2E;AAC3E,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;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAAC,QAAgB;IAC5C,OAAO,OAAO,CAAC,GAAG,MAAM,OAAO,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAA;AACzD,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,YAAY;IACZ,cAAc;IACd,mBAAmB;IACnB,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,75 @@
|
|
|
1
|
+
import { type DatabaseHandle } from '@cogenta/core';
|
|
2
|
+
import type { Provenance } from '../types.js';
|
|
3
|
+
import type { PatternKind } from './pattern-tables.js';
|
|
4
|
+
/**
|
|
5
|
+
* The persistence layer of the page builder's pattern/template library
|
|
6
|
+
* (fiche 43 sub-chantier A; fiche 05 task 1).
|
|
7
|
+
*
|
|
8
|
+
* Deliberately **not** content (contract A): a pattern carries no `status`,
|
|
9
|
+
* no `version`, no trash, no `translationOf` — it is a shape an editor
|
|
10
|
+
* composes from existing blocks, not a published thing of its own. It does
|
|
11
|
+
* carry `provenance`/`provenanceDetail`, in the same two-value/detail shape
|
|
12
|
+
* contract A uses for an entry, because the same question applies just as
|
|
13
|
+
* much here: a pattern an agent generated must never read back
|
|
14
|
+
* indistinguishable from one a person built by hand (the EU AI Act
|
|
15
|
+
* disclosure obligation `docs/03-decisions.md` already tracks for content).
|
|
16
|
+
*/
|
|
17
|
+
export type { PatternKind } from './pattern-tables.js';
|
|
18
|
+
/** Same shape contract A's `provenanceDetail` carries, kept local rather than imported: a pattern is not an entry, and this table has no dependency on `store/types.ts`. */
|
|
19
|
+
export interface PatternProvenanceDetail {
|
|
20
|
+
readonly agent?: string;
|
|
21
|
+
readonly model?: string;
|
|
22
|
+
readonly at?: string;
|
|
23
|
+
readonly prompt?: string;
|
|
24
|
+
}
|
|
25
|
+
/** The wire shape of one block — identical to contract A's `ContentBlock`, kept local for the same reason as `PatternProvenanceDetail`. */
|
|
26
|
+
export interface PatternBlock {
|
|
27
|
+
readonly key: string;
|
|
28
|
+
readonly type: string;
|
|
29
|
+
readonly data: Readonly<Record<string, unknown>>;
|
|
30
|
+
}
|
|
31
|
+
export interface Pattern {
|
|
32
|
+
readonly id: string;
|
|
33
|
+
readonly name: string;
|
|
34
|
+
/** An admin-only, free-form grouping label — never validated against a fixed set (unlike contract B's own vocabulary). */
|
|
35
|
+
readonly category: string | null;
|
|
36
|
+
readonly kind: PatternKind;
|
|
37
|
+
readonly blocks: readonly PatternBlock[];
|
|
38
|
+
readonly provenance: Provenance;
|
|
39
|
+
readonly provenanceDetail: PatternProvenanceDetail | null;
|
|
40
|
+
readonly createdAt: string;
|
|
41
|
+
readonly updatedAt: string;
|
|
42
|
+
}
|
|
43
|
+
export interface CreatePatternInput {
|
|
44
|
+
readonly id?: string;
|
|
45
|
+
readonly name: string;
|
|
46
|
+
readonly category?: string | null;
|
|
47
|
+
readonly kind: PatternKind;
|
|
48
|
+
readonly blocks: readonly PatternBlock[];
|
|
49
|
+
/** Defaults to `'human'` — the same default contract A's own store uses. */
|
|
50
|
+
readonly provenance?: Provenance;
|
|
51
|
+
readonly provenanceDetail?: PatternProvenanceDetail | null;
|
|
52
|
+
}
|
|
53
|
+
export interface UpdatePatternInput {
|
|
54
|
+
readonly name?: string;
|
|
55
|
+
/** Absent leaves it untouched; `null` clears it; a string reassigns it. */
|
|
56
|
+
readonly category?: string | null;
|
|
57
|
+
}
|
|
58
|
+
export interface ListPatternsOptions {
|
|
59
|
+
readonly kind?: PatternKind;
|
|
60
|
+
}
|
|
61
|
+
export interface PatternStoreOptions {
|
|
62
|
+
readonly db: DatabaseHandle;
|
|
63
|
+
/** Injectable so tests can pin time; nothing else should pass it. */
|
|
64
|
+
readonly now?: () => Date;
|
|
65
|
+
readonly newId?: () => string;
|
|
66
|
+
}
|
|
67
|
+
export interface PatternStore {
|
|
68
|
+
create(input: CreatePatternInput): Promise<Pattern>;
|
|
69
|
+
read(id: string): Promise<Pattern | null>;
|
|
70
|
+
update(id: string, input: UpdatePatternInput): Promise<Pattern>;
|
|
71
|
+
delete(id: string): Promise<boolean>;
|
|
72
|
+
list(options?: ListPatternsOptions): Promise<readonly Pattern[]>;
|
|
73
|
+
}
|
|
74
|
+
export declare function createPatternStore(options: PatternStoreOptions): PatternStore;
|
|
75
|
+
//# sourceMappingURL=pattern-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pattern-store.d.ts","sourceRoot":"","sources":["../../src/store/pattern-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { CogentaError, identifier, sql, } from '@cogenta/core';
|
|
2
|
+
import { newId as uuidv7 } from '../id.js';
|
|
3
|
+
import { joinFragments } from './fragments.js';
|
|
4
|
+
import { PATTERN_TABLE } from './pattern-tables.js';
|
|
5
|
+
function text(value) {
|
|
6
|
+
return typeof value === 'string' ? value : String(value);
|
|
7
|
+
}
|
|
8
|
+
function nullableText(value) {
|
|
9
|
+
return value === null || value === undefined ? null : text(value);
|
|
10
|
+
}
|
|
11
|
+
function parseBlocks(raw) {
|
|
12
|
+
const parsed = typeof raw === 'string' ? JSON.parse(raw) : raw;
|
|
13
|
+
if (!Array.isArray(parsed))
|
|
14
|
+
return [];
|
|
15
|
+
return parsed;
|
|
16
|
+
}
|
|
17
|
+
function parseProvenanceDetail(raw) {
|
|
18
|
+
if (raw === null || raw === undefined)
|
|
19
|
+
return null;
|
|
20
|
+
const parsed = typeof raw === 'string' ? JSON.parse(raw) : raw;
|
|
21
|
+
return (parsed ?? null);
|
|
22
|
+
}
|
|
23
|
+
function patternNotFound(id) {
|
|
24
|
+
return new CogentaError({
|
|
25
|
+
code: 'PATTERN_UNKNOWN',
|
|
26
|
+
message: `No pattern "${id}".`,
|
|
27
|
+
hint: 'Check the identifier — list the patterns of this site to find the right one.',
|
|
28
|
+
details: { id },
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
export function createPatternStore(options) {
|
|
32
|
+
const { db } = options;
|
|
33
|
+
const dialect = db.dialect;
|
|
34
|
+
const now = options.now ?? (() => new Date());
|
|
35
|
+
const newId = options.newId ?? uuidv7;
|
|
36
|
+
const patterns = identifier(PATTERN_TABLE, dialect);
|
|
37
|
+
const idColumn = identifier('id', dialect);
|
|
38
|
+
const kindColumn = identifier('kind', dialect);
|
|
39
|
+
const createdAtColumn = identifier('created_at', dialect);
|
|
40
|
+
const updatedAtColumn = identifier('updated_at', dialect);
|
|
41
|
+
const stamp = () => now().toISOString();
|
|
42
|
+
function toPattern(row) {
|
|
43
|
+
return {
|
|
44
|
+
id: text(row.id),
|
|
45
|
+
name: text(row.name),
|
|
46
|
+
category: nullableText(row.category),
|
|
47
|
+
kind: text(row.kind),
|
|
48
|
+
blocks: parseBlocks(row.blocks),
|
|
49
|
+
provenance: text(row.provenance),
|
|
50
|
+
provenanceDetail: parseProvenanceDetail(row.provenance_detail),
|
|
51
|
+
createdAt: text(row.created_at),
|
|
52
|
+
updatedAt: text(row.updated_at),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
async function rowOf(tx, id) {
|
|
56
|
+
const found = await tx.query(sql `select * from ${patterns} where ${idColumn} = ${id}`);
|
|
57
|
+
return found.rows[0] ?? null;
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
create: async (input) => {
|
|
61
|
+
const id = input.id ?? newId();
|
|
62
|
+
const at = stamp();
|
|
63
|
+
await db.query(sql `insert into ${patterns} (${joinFragments([
|
|
64
|
+
idColumn,
|
|
65
|
+
identifier('name', dialect),
|
|
66
|
+
identifier('category', dialect),
|
|
67
|
+
kindColumn,
|
|
68
|
+
identifier('blocks', dialect),
|
|
69
|
+
identifier('provenance', dialect),
|
|
70
|
+
identifier('provenance_detail', dialect),
|
|
71
|
+
createdAtColumn,
|
|
72
|
+
updatedAtColumn,
|
|
73
|
+
], ', ')}) values (
|
|
74
|
+
${id}, ${input.name}, ${input.category ?? null}, ${input.kind},
|
|
75
|
+
${JSON.stringify(input.blocks)},
|
|
76
|
+
${input.provenance ?? 'human'},
|
|
77
|
+
${input.provenanceDetail === undefined || input.provenanceDetail === null ? null : JSON.stringify(input.provenanceDetail)},
|
|
78
|
+
${at}, ${at}
|
|
79
|
+
)`);
|
|
80
|
+
const row = await rowOf(db, id);
|
|
81
|
+
if (row === null)
|
|
82
|
+
throw patternNotFound(id);
|
|
83
|
+
return toPattern(row);
|
|
84
|
+
},
|
|
85
|
+
read: async (id) => {
|
|
86
|
+
const row = await rowOf(db, id);
|
|
87
|
+
return row === null ? null : toPattern(row);
|
|
88
|
+
},
|
|
89
|
+
update: async (id, input) => db.transaction(async (tx) => {
|
|
90
|
+
const row = await rowOf(tx, id);
|
|
91
|
+
if (row === null)
|
|
92
|
+
throw patternNotFound(id);
|
|
93
|
+
const assignments = [sql `${updatedAtColumn} = ${stamp()}`];
|
|
94
|
+
if (input.name !== undefined) {
|
|
95
|
+
assignments.push(sql `${identifier('name', dialect)} = ${input.name}`);
|
|
96
|
+
}
|
|
97
|
+
if (input.category !== undefined) {
|
|
98
|
+
assignments.push(sql `${identifier('category', dialect)} = ${input.category}`);
|
|
99
|
+
}
|
|
100
|
+
await tx.query(sql `update ${patterns} set ${joinFragments(assignments, ', ')} where ${idColumn} = ${id}`);
|
|
101
|
+
const after = await rowOf(tx, id);
|
|
102
|
+
if (after === null)
|
|
103
|
+
throw patternNotFound(id);
|
|
104
|
+
return toPattern(after);
|
|
105
|
+
}, { immediate: true }),
|
|
106
|
+
delete: async (id) => {
|
|
107
|
+
const removed = await db.query(sql `delete from ${patterns} where ${idColumn} = ${id}`);
|
|
108
|
+
return removed.rowsAffected > 0;
|
|
109
|
+
},
|
|
110
|
+
list: async (listOptions = {}) => {
|
|
111
|
+
const found = await db.query(listOptions.kind === undefined
|
|
112
|
+
? sql `select * from ${patterns} order by ${createdAtColumn} desc`
|
|
113
|
+
: sql `select * from ${patterns} where ${kindColumn} = ${listOptions.kind} order by ${createdAtColumn} desc`);
|
|
114
|
+
return found.rows.map(toPattern);
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=pattern-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pattern-store.js","sourceRoot":"","sources":["../../src/store/pattern-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type DatabaseHandle } from '@cogenta/core';
|
|
2
|
+
/**
|
|
3
|
+
* The page builder's motif/model library (fiche 43, sub-chantier A; fiche 05
|
|
4
|
+
* task 1).
|
|
5
|
+
*
|
|
6
|
+
* A pattern is not schema-declared content — it is a reusable *shape*, an
|
|
7
|
+
* editor's own composition saved from the builder — so it gets the same
|
|
8
|
+
* one-fixed-table treatment as a menu (`menu-tables.ts`) rather than a table
|
|
9
|
+
* per collection. `blocks` stores exactly the contract-B block list the
|
|
10
|
+
* builder already sends to `POST /api/builder/render` (`key`/`type`/`data`),
|
|
11
|
+
* never HTML or CSS (R3): inserting a pattern is indistinguishable from
|
|
12
|
+
* placing the same blocks by hand.
|
|
13
|
+
*
|
|
14
|
+
* `kind` distinguishes a **motif** (a handful of blocks dropped into an
|
|
15
|
+
* existing page, added to whatever is already there) from a **modèle de page
|
|
16
|
+
* complet** (fiche 43 sub-chantier A's "second niveau" — replaces the whole
|
|
17
|
+
* block zone, and only after the admin asks for explicit confirmation; that
|
|
18
|
+
* confirmation is a UI concern, not something this table enforces). Both
|
|
19
|
+
* shapes are "a list of blocks"; nothing about the stored row differs.
|
|
20
|
+
*/
|
|
21
|
+
export declare const PATTERN_TABLE = "cogenta_patterns";
|
|
22
|
+
export declare const PATTERN_KINDS: readonly ['pattern', 'template'];
|
|
23
|
+
export type PatternKind = (typeof PATTERN_KINDS)[number];
|
|
24
|
+
/** How long a pattern's `name` may be. */
|
|
25
|
+
export declare const PATTERN_NAME_LENGTH = 255;
|
|
26
|
+
/** How long a pattern's `category` (an admin-only, free-form grouping label) may be. */
|
|
27
|
+
export declare const PATTERN_CATEGORY_LENGTH = 64;
|
|
28
|
+
export declare function ensurePatternTables(db: DatabaseHandle): Promise<void>;
|
|
29
|
+
//# sourceMappingURL=pattern-tables.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pattern-tables.d.ts","sourceRoot":"","sources":["../../src/store/pattern-tables.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAqC,MAAM,eAAe,CAAA;AAItF;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,aAAa,qBAAqB,CAAA;AAE/C,eAAO,MAAM,aAAa,YAAI,SAAS,EAAE,UAAU,CAAU,CAAA;AAC7D,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAA;AAExD,0CAA0C;AAC1C,eAAO,MAAM,mBAAmB,MAAM,CAAA;AACtC,wFAAwF;AACxF,eAAO,MAAM,uBAAuB,KAAK,CAAA;AAEzC,wBAAsB,mBAAmB,CAAC,EAAE,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAyB3E"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { identifier, sql } from '@cogenta/core';
|
|
2
|
+
import { jsonColumn, textColumn, timestampColumn, uuidColumn } from './columns.js';
|
|
3
|
+
import { indexName } from './naming.js';
|
|
4
|
+
/**
|
|
5
|
+
* The page builder's motif/model library (fiche 43, sub-chantier A; fiche 05
|
|
6
|
+
* task 1).
|
|
7
|
+
*
|
|
8
|
+
* A pattern is not schema-declared content — it is a reusable *shape*, an
|
|
9
|
+
* editor's own composition saved from the builder — so it gets the same
|
|
10
|
+
* one-fixed-table treatment as a menu (`menu-tables.ts`) rather than a table
|
|
11
|
+
* per collection. `blocks` stores exactly the contract-B block list the
|
|
12
|
+
* builder already sends to `POST /api/builder/render` (`key`/`type`/`data`),
|
|
13
|
+
* never HTML or CSS (R3): inserting a pattern is indistinguishable from
|
|
14
|
+
* placing the same blocks by hand.
|
|
15
|
+
*
|
|
16
|
+
* `kind` distinguishes a **motif** (a handful of blocks dropped into an
|
|
17
|
+
* existing page, added to whatever is already there) from a **modèle de page
|
|
18
|
+
* complet** (fiche 43 sub-chantier A's "second niveau" — replaces the whole
|
|
19
|
+
* block zone, and only after the admin asks for explicit confirmation; that
|
|
20
|
+
* confirmation is a UI concern, not something this table enforces). Both
|
|
21
|
+
* shapes are "a list of blocks"; nothing about the stored row differs.
|
|
22
|
+
*/
|
|
23
|
+
export const PATTERN_TABLE = 'cogenta_patterns';
|
|
24
|
+
export const PATTERN_KINDS = ['pattern', 'template'];
|
|
25
|
+
/** How long a pattern's `name` may be. */
|
|
26
|
+
export const PATTERN_NAME_LENGTH = 255;
|
|
27
|
+
/** How long a pattern's `category` (an admin-only, free-form grouping label) may be. */
|
|
28
|
+
export const PATTERN_CATEGORY_LENGTH = 64;
|
|
29
|
+
export async function ensurePatternTables(db) {
|
|
30
|
+
const dialect = db.dialect;
|
|
31
|
+
const patterns = identifier(PATTERN_TABLE, dialect);
|
|
32
|
+
await db.query(sql `create table if not exists ${patterns} (
|
|
33
|
+
${identifier('id', dialect)} ${uuidColumn(dialect)} not null primary key,
|
|
34
|
+
${identifier('name', dialect)} ${textColumn(dialect, PATTERN_NAME_LENGTH)} not null,
|
|
35
|
+
${identifier('category', dialect)} ${textColumn(dialect, PATTERN_CATEGORY_LENGTH)},
|
|
36
|
+
${identifier('kind', dialect)} ${textColumn(dialect, 16)} not null,
|
|
37
|
+
${identifier('blocks', dialect)} ${jsonColumn()} not null,
|
|
38
|
+
${identifier('provenance', dialect)} ${textColumn(dialect, 16)} not null,
|
|
39
|
+
${identifier('provenance_detail', dialect)} ${jsonColumn()},
|
|
40
|
+
${identifier('created_at', dialect)} ${timestampColumn(dialect)} not null,
|
|
41
|
+
${identifier('updated_at', dialect)} ${timestampColumn(dialect)} not null
|
|
42
|
+
)`);
|
|
43
|
+
const indexStatements = [
|
|
44
|
+
// Listing is always "every pattern of this kind, most recent first" — the
|
|
45
|
+
// only query the picker and the library screen ever make.
|
|
46
|
+
sql `create index ${identifier(indexName(PATTERN_TABLE, 'kind_created'), dialect)}
|
|
47
|
+
on ${patterns} (${identifier('kind', dialect)}, ${identifier('created_at', dialect)})`,
|
|
48
|
+
];
|
|
49
|
+
for (const statement of indexStatements) {
|
|
50
|
+
await db.query(statement).catch(() => undefined);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=pattern-tables.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pattern-tables.js","sourceRoot":"","sources":["../../src/store/pattern-tables.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,UAAU,EAAoB,GAAG,EAAE,MAAM,eAAe,CAAA;AACtF,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAClF,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAEvC;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,kBAAkB,CAAA;AAE/C,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,SAAS,EAAE,UAAU,CAAU,CAAA;AAG7D,0CAA0C;AAC1C,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,CAAA;AACtC,wFAAwF;AACxF,MAAM,CAAC,MAAM,uBAAuB,GAAG,EAAE,CAAA;AAEzC,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,EAAkB;IAC1D,MAAM,OAAO,GAAG,EAAE,CAAC,OAAO,CAAA;IAC1B,MAAM,QAAQ,GAAG,UAAU,CAAC,aAAa,EAAE,OAAO,CAAC,CAAA;IAEnD,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,CAAA,8BAA8B,QAAQ;MACpD,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,UAAU,CAAC,OAAO,CAAC;MAChD,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,UAAU,CAAC,OAAO,EAAE,mBAAmB,CAAC;MACvE,UAAU,CAAC,UAAU,EAAE,OAAO,CAAC,IAAI,UAAU,CAAC,OAAO,EAAE,uBAAuB,CAAC;MAC/E,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC;MACtD,UAAU,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,UAAU,EAAE;MAC7C,UAAU,CAAC,YAAY,EAAE,OAAO,CAAC,IAAI,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC;MAC5D,UAAU,CAAC,mBAAmB,EAAE,OAAO,CAAC,IAAI,UAAU,EAAE;MACxD,UAAU,CAAC,YAAY,EAAE,OAAO,CAAC,IAAI,eAAe,CAAC,OAAO,CAAC;MAC7D,UAAU,CAAC,YAAY,EAAE,OAAO,CAAC,IAAI,eAAe,CAAC,OAAO,CAAC;IAC/D,CAAC,CAAA;IAEH,MAAM,eAAe,GAAkB;QACrC,0EAA0E;QAC1E,0DAA0D;QAC1D,GAAG,CAAA,gBAAgB,UAAU,CAAC,SAAS,CAAC,aAAa,EAAE,cAAc,CAAC,EAAE,OAAO,CAAC;aACvE,QAAQ,KAAK,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,UAAU,CAAC,YAAY,EAAE,OAAO,CAAC,GAAG;KAC3F,CAAA;IACD,KAAK,MAAM,SAAS,IAAI,eAAe,EAAE,CAAC;QACxC,MAAM,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAA;IAClD,CAAC;AACH,CAAC"}
|
|
@@ -4,9 +4,9 @@ import type { ContentValues } from './types.js';
|
|
|
4
4
|
* "Commencer par une démo en lecture seule" (L9 tâche 12, playground). Wraps
|
|
5
5
|
* any `ContentStore` so every mutating method refuses instead of writing —
|
|
6
6
|
* `create`/`duplicate`/`update`/`delete`/`untrash`/`purge`/`purgeExpired`/
|
|
7
|
-
* `publish`/`unpublish`/`restore` — while every
|
|
8
|
-
* `readVersion`/`diff`/`translations
|
|
9
|
-
* through, unchanged.
|
|
7
|
+
* `publish`/`unpublish`/`restore`/`claimForScheduledPublish` — while every
|
|
8
|
+
* read (`read`/`list`/`history`/`readVersion`/`diff`/`translations`/
|
|
9
|
+
* `resolveLocale`) passes straight through, unchanged.
|
|
10
10
|
*
|
|
11
11
|
* The three trash methods are refused for the reason `delete` always was, and
|
|
12
12
|
* `purge` most of all: a read-only demo that let a visitor empty the trash
|
|
@@ -1 +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;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,SAAS,aAAa,GAAG,aAAa,EAC7E,KAAK,EAAE,YAAY,CAAC,OAAO,CAAC,GAC3B,YAAY,CAAC,OAAO,CAAC,
|
|
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;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,SAAS,aAAa,GAAG,aAAa,EAC7E,KAAK,EAAE,YAAY,CAAC,OAAO,CAAC,GAC3B,YAAY,CAAC,OAAO,CAAC,CA2BvB"}
|
package/dist/store/read-only.js
CHANGED
|
@@ -3,9 +3,9 @@ import { CogentaError } from '@cogenta/core';
|
|
|
3
3
|
* "Commencer par une démo en lecture seule" (L9 tâche 12, playground). Wraps
|
|
4
4
|
* any `ContentStore` so every mutating method refuses instead of writing —
|
|
5
5
|
* `create`/`duplicate`/`update`/`delete`/`untrash`/`purge`/`purgeExpired`/
|
|
6
|
-
* `publish`/`unpublish`/`restore` — while every
|
|
7
|
-
* `readVersion`/`diff`/`translations
|
|
8
|
-
* through, unchanged.
|
|
6
|
+
* `publish`/`unpublish`/`restore`/`claimForScheduledPublish` — while every
|
|
7
|
+
* read (`read`/`list`/`history`/`readVersion`/`diff`/`translations`/
|
|
8
|
+
* `resolveLocale`) passes straight through, unchanged.
|
|
9
9
|
*
|
|
10
10
|
* The three trash methods are refused for the reason `delete` always was, and
|
|
11
11
|
* `purge` most of all: a read-only demo that let a visitor empty the trash
|
|
@@ -41,6 +41,7 @@ export function withReadOnlyStore(store) {
|
|
|
41
41
|
publish: () => refuse(),
|
|
42
42
|
unpublish: () => refuse(),
|
|
43
43
|
restore: () => refuse(),
|
|
44
|
+
claimForScheduledPublish: () => refuse(),
|
|
44
45
|
};
|
|
45
46
|
}
|
|
46
47
|
//# sourceMappingURL=read-only.js.map
|
|
@@ -1 +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;;;;;;;;;;;;;;;;;GAiBG;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,SAAS,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE;QACzB,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE;QACtB,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE;QACtB,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE;QACvB,KAAK,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE;QACrB,YAAY,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE;QAC5B,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE;QACvB,SAAS,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE;QACzB,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE;
|
|
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;;;;;;;;;;;;;;;;;GAiBG;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,SAAS,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE;QACzB,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE;QACtB,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE;QACtB,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE;QACvB,KAAK,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE;QACrB,YAAY,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE;QAC5B,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE;QACvB,SAAS,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE;QACzB,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE;QACvB,wBAAwB,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE;KACzC,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { type RedirectStore } from '../routing/index.js';
|
|
2
|
+
import type { CollectionDefinition } from '../types.js';
|
|
3
|
+
import type { ContentStore } from './store.js';
|
|
4
|
+
import type { ContentValues } from './types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Writes the redirect a slug rename owes, by wrapping the store.
|
|
7
|
+
*
|
|
8
|
+
* `recordSlugChange` (`../routing/slug-change.ts`) has existed since before
|
|
9
|
+
* this file and is fully tested on its own — chain flattening, loop refusal,
|
|
10
|
+
* reversibility — but nothing in `store/` ever called it (fiche 12, task 3
|
|
11
|
+
* audit: "rien dans `packages/schema/src/store/` ne touche la table de
|
|
12
|
+
* redirections"). This is that missing call, made the same way
|
|
13
|
+
* `withSearchIndexing` wires the search index: by wrapping the store rather
|
|
14
|
+
* than hooking a transport, so REST, GraphQL and the theme renderer — all
|
|
15
|
+
* handed the same store instance by `serve.ts` — get it for free.
|
|
16
|
+
*
|
|
17
|
+
* **Why the published face is re-read, not the value `update`/`publish`
|
|
18
|
+
* return.** With drafts enabled, `update()` on an already-published entry only
|
|
19
|
+
* *stages* a change — contract A's own rule, reused rather than
|
|
20
|
+
* reimplemented: the live row does not move until `publish()`. The value
|
|
21
|
+
* `update()` returns is always the *working* face (`state: 'working'`), which
|
|
22
|
+
* would carry the new slug immediately and fire a redirect for a URL that is
|
|
23
|
+
* not public yet. Reading `state: 'published'` before and after the call,
|
|
24
|
+
* exactly as `search-indexing.ts`'s `reindex` already does for the same
|
|
25
|
+
* reason, makes "was this ever actually served" a fact the store answers
|
|
26
|
+
* rather than something this wrapper has to guess at.
|
|
27
|
+
*/
|
|
28
|
+
export interface RedirectTrackingOptions {
|
|
29
|
+
readonly collection: CollectionDefinition;
|
|
30
|
+
readonly redirects: RedirectStore;
|
|
31
|
+
/**
|
|
32
|
+
* Called when recording the redirect fails. Defaults to swallowing it.
|
|
33
|
+
*
|
|
34
|
+
* A failed redirect write must never fail the content save that triggered
|
|
35
|
+
* it — a slow or locked redirects table is not a reason to lose an editor's
|
|
36
|
+
* rename. Callers with a logger pass one so the failure stays visible.
|
|
37
|
+
*/
|
|
38
|
+
readonly onError?: (error: unknown) => void;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Wraps a `ContentStore` so that renaming the slug of a **published** entry
|
|
42
|
+
* writes a 301 from the old path to the new one, with no caller having to
|
|
43
|
+
* remember to.
|
|
44
|
+
*
|
|
45
|
+
* A collection with no `f.slug(...)` field is returned unwrapped — there is
|
|
46
|
+
* nothing this decorator could ever do for it, and wrapping it anyway would
|
|
47
|
+
* only cost two extra reads per write for nothing.
|
|
48
|
+
*/
|
|
49
|
+
export declare function withRedirectTracking<TValues extends ContentValues = ContentValues>(store: ContentStore<TValues>, options: RedirectTrackingOptions): ContentStore<TValues>;
|
|
50
|
+
//# sourceMappingURL=redirect-tracking.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redirect-tracking.d.ts","sourceRoot":"","sources":["../../src/store/redirect-tracking.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAoB,MAAM,qBAAqB,CAAA;AAC1E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,UAAU,EAAE,oBAAoB,CAAA;IACzC,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAA;IACjC;;;;;;OAMG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAA;CAC5C;AA2DD;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,SAAS,aAAa,GAAG,aAAa,EAChF,KAAK,EAAE,YAAY,CAAC,OAAO,CAAC,EAC5B,OAAO,EAAE,uBAAuB,GAC/B,YAAY,CAAC,OAAO,CAAC,CA+BvB"}
|