@coffer-org/server 1.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.
Files changed (61) hide show
  1. package/dist/collection-io.d.ts +20 -0
  2. package/dist/collection-io.d.ts.map +1 -0
  3. package/dist/collection-io.js +111 -0
  4. package/dist/collection-io.js.map +1 -0
  5. package/dist/db.d.ts +6 -0
  6. package/dist/db.d.ts.map +1 -0
  7. package/dist/db.js +45 -0
  8. package/dist/db.js.map +1 -0
  9. package/dist/entity-schema.d.ts +32 -0
  10. package/dist/entity-schema.d.ts.map +1 -0
  11. package/dist/entity-schema.js +147 -0
  12. package/dist/entity-schema.js.map +1 -0
  13. package/dist/extend-io.d.ts +8 -0
  14. package/dist/extend-io.d.ts.map +1 -0
  15. package/dist/extend-io.js +34 -0
  16. package/dist/extend-io.js.map +1 -0
  17. package/dist/extend-table.d.ts +6 -0
  18. package/dist/extend-table.d.ts.map +1 -0
  19. package/dist/extend-table.js +28 -0
  20. package/dist/extend-table.js.map +1 -0
  21. package/dist/index.d.ts +2 -0
  22. package/dist/index.d.ts.map +1 -0
  23. package/dist/index.js +420 -0
  24. package/dist/index.js.map +1 -0
  25. package/dist/local-api.d.ts +6 -0
  26. package/dist/local-api.d.ts.map +1 -0
  27. package/dist/local-api.js +46 -0
  28. package/dist/local-api.js.map +1 -0
  29. package/dist/mutate.d.ts +22 -0
  30. package/dist/mutate.d.ts.map +1 -0
  31. package/dist/mutate.js +128 -0
  32. package/dist/mutate.js.map +1 -0
  33. package/dist/plugin-discovery.d.ts +36 -0
  34. package/dist/plugin-discovery.d.ts.map +1 -0
  35. package/dist/plugin-discovery.js +137 -0
  36. package/dist/plugin-discovery.js.map +1 -0
  37. package/dist/plugin-hooks.d.ts +35 -0
  38. package/dist/plugin-hooks.d.ts.map +1 -0
  39. package/dist/plugin-hooks.js +3 -0
  40. package/dist/plugin-hooks.js.map +1 -0
  41. package/dist/plugin-runtime.d.ts +36 -0
  42. package/dist/plugin-runtime.d.ts.map +1 -0
  43. package/dist/plugin-runtime.js +195 -0
  44. package/dist/plugin-runtime.js.map +1 -0
  45. package/dist/plugins-api.d.ts +3 -0
  46. package/dist/plugins-api.d.ts.map +1 -0
  47. package/dist/plugins-api.js +53 -0
  48. package/dist/plugins-api.js.map +1 -0
  49. package/dist/registry-context.d.ts +11 -0
  50. package/dist/registry-context.d.ts.map +1 -0
  51. package/dist/registry-context.js +13 -0
  52. package/dist/registry-context.js.map +1 -0
  53. package/dist/schema-sync.d.ts +2 -0
  54. package/dist/schema-sync.d.ts.map +1 -0
  55. package/dist/schema-sync.js +13 -0
  56. package/dist/schema-sync.js.map +1 -0
  57. package/dist/temporal.d.ts +21 -0
  58. package/dist/temporal.d.ts.map +1 -0
  59. package/dist/temporal.js +39 -0
  60. package/dist/temporal.js.map +1 -0
  61. package/package.json +34 -0
@@ -0,0 +1,20 @@
1
+ import type { EntityManager } from '@mikro-orm/core';
2
+ import type { ModuleDef } from '@coffer-org/sdk/module';
3
+ type Row = Record<string, unknown>;
4
+ /** Розділити вхід на base-колонки і collection-масиви (по ключах collection-груп). */
5
+ export declare function splitCollections(m: ModuleDef, input: Row): {
6
+ base: Row;
7
+ collections: Record<string, Row[]>;
8
+ };
9
+ /** Записати collection-рядки: повна заміна (delete-all + insert) у межах транзакції tx. */
10
+ export declare function writeCollections(tx: EntityManager, m: ModuleDef, parentId: string, collections: Record<string, Row[]>): Promise<void>;
11
+ /** Прочитати всі collection-рядки запису, nest під ключ групи. ORDER BY position. */
12
+ export declare function readCollections(em: EntityManager, m: ModuleDef, parentId: string): Promise<Record<string, Row[]>>;
13
+ /** nested {addr:{city}} → плоско {addr__city}. */
14
+ export declare function flattenEmbedded(m: ModuleDef, input: Row): Row;
15
+ /** плоско {addr__city} → nested {addr:{city}}. */
16
+ export declare function nestEmbedded(m: ModuleDef, row: Row): Row;
17
+ /** Видалити всі collection-рядки запису (каскад при delete батька). */
18
+ export declare function deleteCollections(tx: EntityManager, m: ModuleDef, parentId: string): Promise<void>;
19
+ export {};
20
+ //# sourceMappingURL=collection-io.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collection-io.d.ts","sourceRoot":"","sources":["../src/collection-io.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAMxD,KAAK,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEnC,sFAAsF;AACtF,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,GAAG;IAAE,IAAI,EAAE,GAAG,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;CAAE,CAU5G;AAED,2FAA2F;AAC3F,wBAAsB,gBAAgB,CACpC,EAAE,EAAE,aAAa,EACjB,CAAC,EAAE,SAAS,EACZ,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,GACjC,OAAO,CAAC,IAAI,CAAC,CAef;AAED,qFAAqF;AACrF,wBAAsB,eAAe,CACnC,EAAE,EAAE,aAAa,EACjB,CAAC,EAAE,SAAS,EACZ,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,CAUhC;AAYD,kDAAkD;AAClD,wBAAgB,eAAe,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,GAAG,GAAG,CAY7D;AAED,kDAAkD;AAClD,wBAAgB,YAAY,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,GAAG,GAAG,GAAG,CAiBxD;AAED,uEAAuE;AACvE,wBAAsB,iBAAiB,CAAC,EAAE,EAAE,aAAa,EAAE,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAKxG"}
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Read/Write 1↔M collection-груп. Кожна collection-група → child-таблиця
3
+ * vault__module__key з parent_id+position. Дзеркало extend-table.ts, але N рядків.
4
+ */
5
+ import { randomUUID } from 'node:crypto';
6
+ import { serialize } from '@mikro-orm/core';
7
+ import { collectionGroups } from '@coffer-org/sdk/module';
8
+ import { isGroup, isEmbeddedGroup } from '@coffer-org/sdk/fields';
9
+ import { childTableName } from './entity-schema.js';
10
+ /** Розділити вхід на base-колонки і collection-масиви (по ключах collection-груп). */
11
+ export function splitCollections(m, input) {
12
+ const keys = new Set(collectionGroups(m.fields).map((c) => c.key));
13
+ const base = {};
14
+ const collections = {};
15
+ for (const [k, v] of Object.entries(input)) {
16
+ if (keys.has(k)) {
17
+ if (Array.isArray(v))
18
+ collections[k] = v;
19
+ }
20
+ else
21
+ base[k] = v;
22
+ }
23
+ return { base, collections };
24
+ }
25
+ /** Записати collection-рядки: повна заміна (delete-all + insert) у межах транзакції tx. */
26
+ export async function writeCollections(tx, m, parentId, collections) {
27
+ for (const c of collectionGroups(m.fields)) {
28
+ const rows = collections[c.key];
29
+ if (rows === undefined)
30
+ continue;
31
+ const table = childTableName(m.vault, m.module, c.key);
32
+ await tx.nativeDelete(table, { parent_id: parentId });
33
+ let position = 0;
34
+ for (const r of rows) {
35
+ const childKeys = c.group.fields.filter((f) => 'key' in f).map((f) => f.key);
36
+ const picked = {};
37
+ for (const ck of childKeys)
38
+ if (r[ck] !== undefined)
39
+ picked[ck] = r[ck];
40
+ await tx.upsert(table, { id: randomUUID(), parent_id: parentId, position, ...picked });
41
+ position += 1;
42
+ }
43
+ }
44
+ }
45
+ /** Прочитати всі collection-рядки запису, nest під ключ групи. ORDER BY position. */
46
+ export async function readCollections(em, m, parentId) {
47
+ const out = {};
48
+ for (const c of collectionGroups(m.fields)) {
49
+ const table = childTableName(m.vault, m.module, c.key);
50
+ const rows = await em.find(table, { parent_id: parentId }, {
51
+ orderBy: { position: 'asc' },
52
+ });
53
+ out[c.key] = serialize(rows).map(({ id: _id, parent_id: _pid, position: _pos, ...rest }) => rest);
54
+ }
55
+ return out;
56
+ }
57
+ /** Зібрати embedded-групи [key, GroupEl] (рекурсивно крізь layout). */
58
+ function embeddedGroups(fields) {
59
+ const out = [];
60
+ for (const it of fields) {
61
+ if (isGroup(it) && isEmbeddedGroup(it))
62
+ out.push([it.key, it]);
63
+ else if (isGroup(it) && !it.key)
64
+ out.push(...embeddedGroups(it.fields));
65
+ }
66
+ return out;
67
+ }
68
+ /** nested {addr:{city}} → плоско {addr__city}. */
69
+ export function flattenEmbedded(m, input) {
70
+ const out = { ...input };
71
+ for (const [key, g] of embeddedGroups(m.fields)) {
72
+ const nested = out[key];
73
+ delete out[key];
74
+ if (nested && typeof nested === 'object') {
75
+ for (const f of g.fields) {
76
+ if ('key' in f)
77
+ out[`${key}__${f.key}`] = nested[f.key];
78
+ }
79
+ }
80
+ }
81
+ return out;
82
+ }
83
+ /** плоско {addr__city} → nested {addr:{city}}. */
84
+ export function nestEmbedded(m, row) {
85
+ const out = { ...row };
86
+ for (const [key, g] of embeddedGroups(m.fields)) {
87
+ const nested = {};
88
+ let any = false;
89
+ for (const f of g.fields) {
90
+ if (!('key' in f))
91
+ continue;
92
+ const col = `${key}__${f.key}`;
93
+ if (col in out) {
94
+ nested[f.key] = out[col];
95
+ delete out[col];
96
+ any = true;
97
+ }
98
+ }
99
+ if (any)
100
+ out[key] = nested;
101
+ }
102
+ return out;
103
+ }
104
+ /** Видалити всі collection-рядки запису (каскад при delete батька). */
105
+ export async function deleteCollections(tx, m, parentId) {
106
+ for (const c of collectionGroups(m.fields)) {
107
+ const table = childTableName(m.vault, m.module, c.key);
108
+ await tx.nativeDelete(table, { parent_id: parentId });
109
+ }
110
+ }
111
+ //# sourceMappingURL=collection-io.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collection-io.js","sourceRoot":"","sources":["../src/collection-io.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAG5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAElE,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAIpD,sFAAsF;AACtF,MAAM,UAAU,gBAAgB,CAAC,CAAY,EAAE,KAAU;IACvD,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACnE,MAAM,IAAI,GAAQ,EAAE,CAAC;IACrB,MAAM,WAAW,GAA0B,EAAE,CAAC;IAC9C,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3C,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAChB,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;gBAAE,WAAW,CAAC,CAAC,CAAC,GAAG,CAAU,CAAC;QACpD,CAAC;;YAAM,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACrB,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;AAC/B,CAAC;AAED,2FAA2F;AAC3F,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,EAAiB,EACjB,CAAY,EACZ,QAAgB,EAChB,WAAkC;IAElC,KAAK,MAAM,CAAC,IAAI,gBAAgB,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3C,MAAM,IAAI,GAAG,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAChC,IAAI,IAAI,KAAK,SAAS;YAAE,SAAS;QACjC,MAAM,KAAK,GAAG,cAAc,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC;QACvD,MAAM,EAAE,CAAC,YAAY,CAAC,KAAc,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAW,CAAC,CAAC;QACxE,IAAI,QAAQ,GAAG,CAAC,CAAC;QACjB,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;YACrB,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAE,CAAqB,CAAC,GAAG,CAAC,CAAC;YAClG,MAAM,MAAM,GAAQ,EAAE,CAAC;YACvB,KAAK,MAAM,EAAE,IAAI,SAAS;gBAAE,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,SAAS;oBAAE,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;YACxE,MAAM,EAAE,CAAC,MAAM,CAAC,KAAc,EAAE,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,MAAM,EAAW,CAAC,CAAC;YACzG,QAAQ,IAAI,CAAC,CAAC;QAChB,CAAC;IACH,CAAC;AACH,CAAC;AAED,qFAAqF;AACrF,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,EAAiB,EACjB,CAAY,EACZ,QAAgB;IAEhB,MAAM,GAAG,GAA0B,EAAE,CAAC;IACtC,KAAK,MAAM,CAAC,IAAI,gBAAgB,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3C,MAAM,KAAK,GAAG,cAAc,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC;QACvD,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,KAAc,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAW,EAAE;YAC3E,OAAO,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAW;SACtC,CAAC,CAAC;QACH,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAI,SAAS,CAAC,IAAI,CAAW,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;IAC/G,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,uEAAuE;AACvE,SAAS,cAAc,CAAC,MAAkB;IACxC,MAAM,GAAG,GAAwB,EAAE,CAAC;IACpC,KAAK,MAAM,EAAE,IAAI,MAAM,EAAE,CAAC;QACxB,IAAI,OAAO,CAAC,EAAE,CAAC,IAAI,eAAe,CAAC,EAAE,CAAC;YAAE,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,GAAI,EAAE,EAAE,CAAC,CAAC,CAAC;aAC3D,IAAI,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG;YAAE,GAAG,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC,EAAE,CAAC,MAAoB,CAAC,CAAC,CAAC;IACxF,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,kDAAkD;AAClD,MAAM,UAAU,eAAe,CAAC,CAAY,EAAE,KAAU;IACtD,MAAM,GAAG,GAAQ,EAAE,GAAG,KAAK,EAAE,CAAC;IAC9B,KAAK,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,cAAc,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;QAChD,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,CAAoB,CAAC;QAC3C,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC;QAChB,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;YACzC,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC;gBACzB,IAAI,KAAK,IAAI,CAAC;oBAAE,GAAG,CAAC,GAAG,GAAG,KAAM,CAAqB,CAAC,GAAG,EAAE,CAAC,GAAI,MAAc,CAAE,CAAqB,CAAC,GAAG,CAAC,CAAC;YAC7G,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,kDAAkD;AAClD,MAAM,UAAU,YAAY,CAAC,CAAY,EAAE,GAAQ;IACjD,MAAM,GAAG,GAAQ,EAAE,GAAG,GAAG,EAAE,CAAC;IAC5B,KAAK,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,cAAc,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;QAChD,MAAM,MAAM,GAAQ,EAAE,CAAC;QACvB,IAAI,GAAG,GAAG,KAAK,CAAC;QAChB,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC;YACzB,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;gBAAE,SAAS;YAC5B,MAAM,GAAG,GAAG,GAAG,GAAG,KAAM,CAAqB,CAAC,GAAG,EAAE,CAAC;YACpD,IAAI,GAAG,IAAI,GAAG,EAAE,CAAC;gBACf,MAAM,CAAE,CAAqB,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;gBAC9C,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC;gBAChB,GAAG,GAAG,IAAI,CAAC;YACb,CAAC;QACH,CAAC;QACD,IAAI,GAAG;YAAE,GAAG,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC;IAC7B,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,uEAAuE;AACvE,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,EAAiB,EAAE,CAAY,EAAE,QAAgB;IACvF,KAAK,MAAM,CAAC,IAAI,gBAAgB,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3C,MAAM,KAAK,GAAG,cAAc,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC;QACvD,MAAM,EAAE,CAAC,YAAY,CAAC,KAAc,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAW,CAAC,CAAC;IAC1E,CAAC;AACH,CAAC"}
package/dist/db.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ import { MikroORM } from '@mikro-orm/core';
2
+ import type { EntitySchema, EntityManager } from '@mikro-orm/core';
3
+ export declare function getOrm(): MikroORM;
4
+ export declare function getEm(): EntityManager;
5
+ export declare function initDb(entities: EntitySchema[]): Promise<MikroORM>;
6
+ //# sourceMappingURL=db.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,QAAQ,EAA4B,MAAM,iBAAiB,CAAC;AAErE,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAQnE,wBAAgB,MAAM,IAAI,QAAQ,CAGjC;AACD,wBAAgB,KAAK,IAAI,aAAa,CAGrC;AAED,wBAAsB,MAAM,CAAC,QAAQ,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,CAaxE"}
package/dist/db.js ADDED
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Підключення до БД через MikroORM (SQLite).
3
+ * ORM-шар навмисно тонкий: щоб перейти на Postgres —
4
+ * 1. `npm install @mikro-orm/postgresql`,
5
+ * 2. змінити SqliteDriver на PostgreSqlDriver,
6
+ * 3. dbName на рядок підключення.
7
+ *
8
+ * WAL-режим: у MikroORM v7 @mikro-orm/sqlite працює на better-sqlite3
9
+ * (синхронний драйвер, без knex-пулу), тому WAL ставимо через PRAGMA одразу
10
+ * після MikroORM.init(). WAL персистентний (зберігається в заголовку файлу БД),
11
+ * тож одного виклику достатньо. foreign_keys=ON MikroORM вмикає сам.
12
+ */
13
+ import { mkdirSync } from 'node:fs';
14
+ import { dirname } from 'node:path';
15
+ import { MikroORM, EntityCaseNamingStrategy } from '@mikro-orm/core';
16
+ import { SqliteDriver } from '@mikro-orm/sqlite';
17
+ const DB_PATH = process.env['DB_PATH'] ?? 'data/app.db';
18
+ mkdirSync(dirname(DB_PATH), { recursive: true });
19
+ // Синглтони — заповнюються в initDb().
20
+ let _orm;
21
+ export function getOrm() {
22
+ if (!_orm)
23
+ throw new Error('initDb() ще не викликано');
24
+ return _orm;
25
+ }
26
+ export function getEm() {
27
+ if (!_orm)
28
+ throw new Error('initDb() ще не викликано');
29
+ return _orm.em;
30
+ }
31
+ export async function initDb(entities) {
32
+ _orm = await MikroORM.init({
33
+ driver: SqliteDriver,
34
+ dbName: DB_PATH,
35
+ entities,
36
+ // Властивості → колонки дослівно (camelCase поля плагінів зберігаються як є):
37
+ // camelCase-поля плагінів лишаються camelCase у БД, snake_case системні — як є.
38
+ namingStrategy: EntityCaseNamingStrategy,
39
+ discovery: { warnWhenNoEntities: false },
40
+ });
41
+ // WAL через PRAGMA (better-sqlite3, без knex-пулу — див. коментар угорі файлу).
42
+ await _orm.em.getConnection().execute('PRAGMA journal_mode = WAL');
43
+ return _orm;
44
+ }
45
+ //# sourceMappingURL=db.js.map
package/dist/db.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.js","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGjD,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,aAAa,CAAC;AACxD,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAEjD,uCAAuC;AACvC,IAAI,IAA0B,CAAC;AAE/B,MAAM,UAAU,MAAM;IACpB,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;IACvD,OAAO,IAAI,CAAC;AACd,CAAC;AACD,MAAM,UAAU,KAAK;IACnB,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;IACvD,OAAO,IAAI,CAAC,EAAE,CAAC;AACjB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,QAAwB;IACnD,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC;QACzB,MAAM,EAAE,YAAY;QACpB,MAAM,EAAE,OAAO;QACf,QAAQ;QACR,8EAA8E;QAC9E,gFAAgF;QAChF,cAAc,EAAE,wBAAwB;QACxC,SAAS,EAAE,EAAE,kBAAkB,EAAE,KAAK,EAAE;KACzC,CAAC,CAAC;IACH,gFAAgF;IAChF,MAAM,IAAI,CAAC,EAAE,CAAC,aAAa,EAAE,CAAC,OAAO,CAAC,2BAA2B,CAAC,CAAC;IACnE,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * MikroORM EntitySchema — похідна від ModuleDef/ExtendDef (джерело істини: f.*).
3
+ * DB-agnostic: імпортує лише @mikro-orm/core + типи ядра.
4
+ * Колонки: text→text, integer→integer, real→float, boolean→boolean.
5
+ *
6
+ * Фізичну схему створює runtime-синк (schema-sync.ts) з цих описів.
7
+ * Тут — лише in-memory опис для типобезпечних запитів.
8
+ */
9
+ import { EntitySchema } from '@mikro-orm/core';
10
+ import type { ModuleDef } from '@coffer-org/sdk/module';
11
+ import type { ExtendDef } from '@coffer-org/sdk/extend';
12
+ import type { SettingsDef } from '@coffer-org/sdk/settings';
13
+ import type { PluginManifest } from '@coffer-org/sdk/plugin';
14
+ /** Ім'я сутності (= ім'я таблиці) для модуля: vault__module. */
15
+ export declare function moduleTableName(vault: string, module: string): string;
16
+ /** EntitySchema для одного модуля плагіна. */
17
+ export declare function buildEntitySchema(m: ModuleDef): EntitySchema;
18
+ /** EntitySchema для extend-таблиці (PK = base_id). */
19
+ export declare function buildExtendEntitySchema(e: ExtendDef): EntitySchema;
20
+ /** EntitySchema для singleton-таблиці налаштувань плагіна. PK = plugin_id. */
21
+ export declare function buildSettingsEntitySchema(pluginId: string, settings: SettingsDef): EntitySchema;
22
+ /** Ім'я child-таблиці collection-групи. */
23
+ export declare function childTableName(vault: string, module: string, key: string): string;
24
+ /** Усі child-схеми модуля (рекурсивно: collection усередині collection). */
25
+ export declare function buildCollectionEntities(m: ModuleDef): EntitySchema[];
26
+ export declare const EventSchema: EntitySchema<any, never, import("@mikro-orm/core").EntityCtor<any>>;
27
+ export declare const PluginRowSchema: EntitySchema<any, never, import("@mikro-orm/core").EntityCtor<any>>;
28
+ /** Схеми сутностей плагінів (модулі власних vault'ів + vaultModules + extends + settings). */
29
+ export declare function buildPluginEntities(plugins: PluginManifest[]): EntitySchema[];
30
+ /** Системні схеми — реєструються в initDb() ДО читання _plugins. */
31
+ export declare const systemEntities: EntitySchema[];
32
+ //# sourceMappingURL=entity-schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entity-schema.d.ts","sourceRoot":"","sources":["../src/entity-schema.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,KAAK,EAAE,SAAS,EAAmB,MAAM,wBAAwB,CAAC;AAEzE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAExD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAY7D,gEAAgE;AAChE,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAErE;AAED,8CAA8C;AAE9C,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,SAAS,GAAG,YAAY,CAkB5D;AAED,sDAAsD;AACtD,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,SAAS,GAAG,YAAY,CAUlE;AAED,8EAA8E;AAC9E,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,GAAG,YAAY,CAa/F;AAID,2CAA2C;AAC3C,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAEjF;AAiBD,4EAA4E;AAC5E,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,SAAS,GAAG,YAAY,EAAE,CAUpE;AAKD,eAAO,MAAM,WAAW,qEAatB,CAAC;AAEH,eAAO,MAAM,eAAe,qEAQ1B,CAAC;AAEH,8FAA8F;AAC9F,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,cAAc,EAAE,GAAG,YAAY,EAAE,CAO7E;AAED,oEAAoE;AACpE,eAAO,MAAM,cAAc,EAAE,YAAY,EAAmC,CAAC"}
@@ -0,0 +1,147 @@
1
+ /**
2
+ * MikroORM EntitySchema — похідна від ModuleDef/ExtendDef (джерело істини: f.*).
3
+ * DB-agnostic: імпортує лише @mikro-orm/core + типи ядра.
4
+ * Колонки: text→text, integer→integer, real→float, boolean→boolean.
5
+ *
6
+ * Фізичну схему створює runtime-синк (schema-sync.ts) з цих описів.
7
+ * Тут — лише in-memory опис для типобезпечних запитів.
8
+ */
9
+ import { EntitySchema } from '@mikro-orm/core';
10
+ import { fieldEntries, collectionGroups } from '@coffer-org/sdk/module';
11
+ function mikroType(col) {
12
+ if (col === 'integer')
13
+ return 'integer';
14
+ if (col === 'real')
15
+ return 'float';
16
+ if (col === 'boolean')
17
+ return 'boolean';
18
+ if (col === 'date')
19
+ return 'date';
20
+ if (col === 'time')
21
+ return 'time';
22
+ if (col === 'datetime')
23
+ return 'datetime';
24
+ return 'text';
25
+ }
26
+ /** Ім'я сутності (= ім'я таблиці) для модуля: vault__module. */
27
+ export function moduleTableName(vault, module) {
28
+ return `${vault}__${module}`;
29
+ }
30
+ /** EntitySchema для одного модуля плагіна. */
31
+ export function buildEntitySchema(m) {
32
+ // Використовуємо Record<string, any> — EntitySchemaProperty — складний умовний тип,
33
+ // тому будуємо properties динамічно і передаємо через as any.
34
+ const properties = {
35
+ id: { type: 'text', primary: true }, // ЄДИНЕ обов'язкове системне поле
36
+ created_at: { type: 'text' }, // інфраструктура (авто-керована, поза fields)
37
+ updated_at: { type: 'text' },
38
+ };
39
+ for (const [key, field] of fieldEntries(m.fields)) {
40
+ if (field.virtual)
41
+ continue;
42
+ properties[key] = {
43
+ type: mikroType(field.column),
44
+ nullable: !field.required,
45
+ };
46
+ }
47
+ const name = moduleTableName(m.vault, m.module);
48
+ return new EntitySchema({ name, tableName: name, properties });
49
+ }
50
+ /** EntitySchema для extend-таблиці (PK = base_id). */
51
+ export function buildExtendEntitySchema(e) {
52
+ const properties = {
53
+ base_id: { type: 'text', primary: true },
54
+ };
55
+ for (const [key, field] of fieldEntries(e.fields)) {
56
+ if (field.virtual)
57
+ continue;
58
+ properties[key] = { type: mikroType(field.column), nullable: true };
59
+ }
60
+ const name = `extend__${e.id}`;
61
+ return new EntitySchema({ name, tableName: name, properties });
62
+ }
63
+ /** EntitySchema для singleton-таблиці налаштувань плагіна. PK = plugin_id. */
64
+ export function buildSettingsEntitySchema(pluginId, settings) {
65
+ const properties = {
66
+ plugin_id: { type: 'text', primary: true },
67
+ };
68
+ for (const [key, field] of fieldEntries(settings.fields)) {
69
+ if (field.virtual)
70
+ continue;
71
+ properties[key] = {
72
+ type: mikroType(field.column),
73
+ nullable: !field.required,
74
+ };
75
+ }
76
+ const name = `_settings__${pluginId}`;
77
+ return new EntitySchema({ name, tableName: name, properties });
78
+ }
79
+ // ─── Collection-групи → child-таблиці ──────────────────────────────────────
80
+ /** Ім'я child-таблиці collection-групи. */
81
+ export function childTableName(vault, module, key) {
82
+ return `${vault}__${module}__${key}`;
83
+ }
84
+ /** Child EntitySchema для однієї collection-групи. */
85
+ function buildChildSchema(vault, module, c) {
86
+ const properties = {
87
+ id: { type: 'text', primary: true },
88
+ parent_id: { type: 'text', index: true },
89
+ position: { type: 'integer' },
90
+ };
91
+ for (const [key, fm] of fieldEntries(c.group.fields)) {
92
+ if (fm.virtual)
93
+ continue;
94
+ properties[key] = { type: mikroType(fm.column), nullable: !fm.required };
95
+ }
96
+ const name = childTableName(vault, module, c.key);
97
+ return new EntitySchema({ name, tableName: name, properties });
98
+ }
99
+ /** Усі child-схеми модуля (рекурсивно: collection усередині collection). */
100
+ export function buildCollectionEntities(m) {
101
+ const out = [];
102
+ for (const c of collectionGroups(m.fields)) {
103
+ out.push(buildChildSchema(m.vault, m.module, c));
104
+ const nested = collectionGroups(c.group.fields);
105
+ for (const g of nested) {
106
+ out.push(buildChildSchema(m.vault, `${m.module}__${c.key}`, g));
107
+ }
108
+ }
109
+ return out;
110
+ }
111
+ // ─── Системні схеми (плагін core) ──────────────────────────────────────────
112
+ // Авторитетне джерело колонок: ці схеми (фізичну схему створює schema-sync.ts).
113
+ export const EventSchema = new EntitySchema({
114
+ name: '_Event',
115
+ tableName: '_events',
116
+ properties: {
117
+ id: { type: 'text', primary: true },
118
+ ts: { type: 'text' },
119
+ actor: { type: 'text' },
120
+ op: { type: 'text' },
121
+ type: { type: 'text' },
122
+ record_id: { type: 'text' },
123
+ before: { type: 'text', nullable: true },
124
+ after: { type: 'text', nullable: true },
125
+ },
126
+ });
127
+ export const PluginRowSchema = new EntitySchema({
128
+ name: '_Plugin',
129
+ tableName: '_plugins',
130
+ properties: {
131
+ id: { type: 'text', primary: true },
132
+ enabled: { type: 'integer', nullable: false },
133
+ updated_at: { type: 'text' },
134
+ },
135
+ });
136
+ /** Схеми сутностей плагінів (модулі власних vault'ів + vaultModules + extends + settings). */
137
+ export function buildPluginEntities(plugins) {
138
+ return plugins.flatMap((p) => [
139
+ ...(p.vaults ?? []).flatMap((v) => v.modules.flatMap((m) => [buildEntitySchema(m), ...buildCollectionEntities(m)])),
140
+ ...(p.vaultModules ?? []).flatMap((m) => [buildEntitySchema(m), ...buildCollectionEntities(m)]),
141
+ ...(p.extends_ ?? []).map(buildExtendEntitySchema),
142
+ ...(p.settings && p.settings.fields.length > 0 ? [buildSettingsEntitySchema(p.id, p.settings)] : []),
143
+ ]);
144
+ }
145
+ /** Системні схеми — реєструються в initDb() ДО читання _plugins. */
146
+ export const systemEntities = [EventSchema, PluginRowSchema];
147
+ //# sourceMappingURL=entity-schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entity-schema.js","sourceRoot":"","sources":["../src/entity-schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /** Розділити тіло запиту: базові поля + extend-дані (_extend_<id>). */
2
+ export declare function splitBody(body: unknown): {
3
+ base: Record<string, unknown>;
4
+ extData: Record<string, Record<string, unknown>>;
5
+ };
6
+ /** Зберегти extend-дані після успішного save базового запису. */
7
+ export declare function saveExtends(vault: string, module: string, baseId: string, extData: Record<string, Record<string, unknown>>): Promise<void>;
8
+ //# sourceMappingURL=extend-io.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extend-io.d.ts","sourceRoot":"","sources":["../src/extend-io.ts"],"names":[],"mappings":"AAQA,uEAAuE;AACvE,wBAAgB,SAAS,CAAC,IAAI,EAAE,OAAO,GAAG;IACxC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAClD,CASA;AAED,iEAAiE;AACjE,wBAAsB,WAAW,CAC/B,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAC/C,OAAO,CAAC,IAAI,CAAC,CAUf"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Спільна логіка вводу/виводу extend-даних для HTTP-роутів (index.ts) та
3
+ * in-process API (local-api.ts). Уникає дублювання splitBody/saveExtends.
4
+ */
5
+ import { getExtendsFor } from './registry-context.js';
6
+ import { buildExtendZodPartial } from '@coffer-org/sdk/extend';
7
+ import { extendEntityName, upsertExtendRecord } from './extend-table.js';
8
+ /** Розділити тіло запиту: базові поля + extend-дані (_extend_<id>). */
9
+ export function splitBody(body) {
10
+ const raw = (body ?? {});
11
+ const base = {};
12
+ const extData = {};
13
+ for (const [k, v] of Object.entries(raw)) {
14
+ if (k.startsWith('_extend_'))
15
+ extData[k.slice(8)] = (v ?? {});
16
+ else
17
+ base[k] = v;
18
+ }
19
+ return { base, extData };
20
+ }
21
+ /** Зберегти extend-дані після успішного save базового запису. */
22
+ export async function saveExtends(vault, module, baseId, extData) {
23
+ for (const e of getExtendsFor(vault, module)) {
24
+ const data = extData[e.id];
25
+ if (data === undefined)
26
+ continue;
27
+ // Валідуємо extend-дані
28
+ const parsed = buildExtendZodPartial(e).safeParse(data);
29
+ if (parsed.success && Object.keys(parsed.data).length > 0) {
30
+ await upsertExtendRecord(extendEntityName(e), baseId, parsed.data);
31
+ }
32
+ }
33
+ }
34
+ //# sourceMappingURL=extend-io.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extend-io.js","sourceRoot":"","sources":["../src/extend-io.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEzE,uEAAuE;AACvE,MAAM,UAAU,SAAS,CAAC,IAAa;IAIrC,MAAM,GAAG,GAAG,CAAC,IAAI,IAAI,EAAE,CAA4B,CAAC;IACpD,MAAM,IAAI,GAA4B,EAAE,CAAC;IACzC,MAAM,OAAO,GAA4C,EAAE,CAAC;IAC5D,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACzC,IAAI,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC;YAAE,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAA4B,CAAC;;YACpF,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AAC3B,CAAC;AAED,iEAAiE;AACjE,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,KAAa,EACb,MAAc,EACd,MAAc,EACd,OAAgD;IAEhD,KAAK,MAAM,CAAC,IAAI,aAAa,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,CAAC;QAC7C,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC3B,IAAI,IAAI,KAAK,SAAS;YAAE,SAAS;QACjC,wBAAwB;QACxB,MAAM,MAAM,GAAG,qBAAqB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QACxD,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1D,MAAM,kBAAkB,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,IAA+B,CAAC,CAAC;QAChG,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { ExtendDef } from '@coffer-org/sdk/extend';
2
+ export declare function extendEntityName(e: ExtendDef): string;
3
+ export declare function getExtendRecord(name: string, baseId: string): Promise<Record<string, unknown> | undefined>;
4
+ export declare function upsertExtendRecord(name: string, baseId: string, data: Record<string, unknown>): Promise<void>;
5
+ export declare function deleteExtendRecord(name: string, baseId: string): Promise<void>;
6
+ //# sourceMappingURL=extend-table.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extend-table.d.ts","sourceRoot":"","sources":["../src/extend-table.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAGxD,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,SAAS,GAAG,MAAM,CAErD;AAID,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC,CAKhH;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAGnH;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAKpF"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Підтримка extend-таблиць на рівні сервера.
3
+ * Кожен ExtendDef → сутність `extend__<id>` з base_id PK.
4
+ */
5
+ import { serialize } from '@mikro-orm/core';
6
+ import { getEm } from './db.js';
7
+ export function extendEntityName(e) {
8
+ return `extend__${e.id}`;
9
+ }
10
+ // ─── CRUD ─────────────────────────────────────────────────────────────────────
11
+ export async function getExtendRecord(name, baseId) {
12
+ const fork = getEm().fork();
13
+ const row = await fork.findOne(name, { base_id: baseId });
14
+ if (!row)
15
+ return undefined;
16
+ return serialize(row);
17
+ }
18
+ export async function upsertExtendRecord(name, baseId, data) {
19
+ const fork = getEm().fork();
20
+ await fork.upsert(name, { base_id: baseId, ...data });
21
+ }
22
+ export async function deleteExtendRecord(name, baseId) {
23
+ const fork = getEm().fork();
24
+ const ref = fork.getReference(name, baseId);
25
+ fork.remove(ref);
26
+ await fork.flush();
27
+ }
28
+ //# sourceMappingURL=extend-table.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extend-table.js","sourceRoot":"","sources":["../src/extend-table.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAEhC,MAAM,UAAU,gBAAgB,CAAC,CAAY;IAC3C,OAAO,WAAW,CAAC,CAAC,EAAE,EAAE,CAAC;AAC3B,CAAC;AAED,iFAAiF;AAEjF,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAY,EAAE,MAAc;IAChE,MAAM,IAAI,GAAG,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC;IAC5B,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAa,EAAE,EAAE,OAAO,EAAE,MAAM,EAAW,CAAC,CAAC;IAC5E,IAAI,CAAC,GAAG;QAAE,OAAO,SAAS,CAAC;IAC3B,OAAO,SAAS,CAAC,GAAG,CAA4B,CAAC;AACnD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,IAAY,EAAE,MAAc,EAAE,IAA6B;IAClG,MAAM,IAAI,GAAG,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC;IAC5B,MAAM,IAAI,CAAC,MAAM,CAAC,IAAa,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAW,CAAC,CAAC;AAC1E,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,IAAY,EAAE,MAAc;IACnE,MAAM,IAAI,GAAG,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC;IAC5B,MAAM,GAAG,GAAG,IAAI,CAAC,YAAY,CAAC,IAAa,EAAE,MAAe,CAAC,CAAC;IAC9D,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACjB,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;AACrB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}