@antelopejs/dms-database 0.0.13 → 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.
Files changed (173) hide show
  1. package/README.md +30 -5
  2. package/dist/db/models/query_history.model.d.ts +1 -0
  3. package/dist/db/models/query_history.model.js +6 -0
  4. package/dist/db/models/query_history.model.js.map +1 -1
  5. package/dist/db/tables/query_history.table.d.ts +3 -0
  6. package/dist/db/tables/query_history.table.js +12 -0
  7. package/dist/db/tables/query_history.table.js.map +1 -1
  8. package/dist/db/tables/saved_queries.table.d.ts +1 -0
  9. package/dist/db/tables/saved_queries.table.js +4 -0
  10. package/dist/db/tables/saved_queries.table.js.map +1 -1
  11. package/dist/i18n/messages.d.ts +39 -0
  12. package/dist/i18n/messages.js +64 -0
  13. package/dist/i18n/messages.js.map +1 -0
  14. package/dist/index.d.ts +1 -0
  15. package/dist/index.js +1 -7
  16. package/dist/index.js.map +1 -1
  17. package/dist/module.d.ts +11 -0
  18. package/dist/module.js +55 -0
  19. package/dist/module.js.map +1 -0
  20. package/dist/pages/data.d.ts +1 -1
  21. package/dist/pages/data.js +9 -6
  22. package/dist/pages/data.js.map +1 -1
  23. package/dist/pages/diagram.d.ts +9 -0
  24. package/dist/pages/diagram.js +45 -0
  25. package/dist/pages/diagram.js.map +1 -0
  26. package/dist/pages/index.d.ts +1 -0
  27. package/dist/pages/index.js +1 -0
  28. package/dist/pages/index.js.map +1 -1
  29. package/dist/pages/overview.d.ts +4 -1
  30. package/dist/pages/overview.js +113 -6
  31. package/dist/pages/overview.js.map +1 -1
  32. package/dist/pages/query.d.ts +1 -1
  33. package/dist/pages/query.js +22 -6
  34. package/dist/pages/query.js.map +1 -1
  35. package/dist/pages/schemas.d.ts +2 -1
  36. package/dist/pages/schemas.js +143 -6
  37. package/dist/pages/schemas.js.map +1 -1
  38. package/dist/routes/data.d.ts +8 -0
  39. package/dist/routes/data.js +84 -21
  40. package/dist/routes/data.js.map +1 -1
  41. package/dist/routes/index.d.ts +1 -0
  42. package/dist/routes/index.js +1 -0
  43. package/dist/routes/index.js.map +1 -1
  44. package/dist/routes/overview.d.ts +12 -0
  45. package/dist/routes/overview.js +55 -0
  46. package/dist/routes/overview.js.map +1 -0
  47. package/dist/routes/query.d.ts +5 -1
  48. package/dist/routes/query.js +162 -27
  49. package/dist/routes/query.js.map +1 -1
  50. package/dist/routes/tables.d.ts +15 -12
  51. package/dist/routes/tables.js +95 -55
  52. package/dist/routes/tables.js.map +1 -1
  53. package/dist/service/catalog.d.ts +3 -0
  54. package/dist/service/catalog.js +26 -0
  55. package/dist/service/catalog.js.map +1 -0
  56. package/dist/service/health.d.ts +3 -3
  57. package/dist/service/health.js +17 -14
  58. package/dist/service/health.js.map +1 -1
  59. package/dist/service/introspect.d.ts +3 -1
  60. package/dist/service/introspect.js +131 -43
  61. package/dist/service/introspect.js.map +1 -1
  62. package/dist/service/overview.d.ts +9 -0
  63. package/dist/service/overview.js +113 -0
  64. package/dist/service/overview.js.map +1 -0
  65. package/dist/service/queryInspection.d.ts +15 -0
  66. package/dist/service/queryInspection.js +107 -0
  67. package/dist/service/queryInspection.js.map +1 -0
  68. package/dist/service/references.d.ts +9 -0
  69. package/dist/service/references.js +52 -0
  70. package/dist/service/references.js.map +1 -0
  71. package/dist/service/schemaFilters.d.ts +26 -0
  72. package/dist/service/schemaFilters.js +42 -0
  73. package/dist/service/schemaFilters.js.map +1 -0
  74. package/dist/service/stagedSerialization.d.ts +2 -0
  75. package/dist/service/stagedSerialization.js +38 -10
  76. package/dist/service/stagedSerialization.js.map +1 -1
  77. package/dist/service/types.d.ts +11 -1
  78. package/dist/types/constants.d.ts +2 -0
  79. package/dist/types/constants.js +3 -1
  80. package/dist/types/constants.js.map +1 -1
  81. package/dist/utils/query.d.ts +0 -2
  82. package/dist/utils/query.js +0 -20
  83. package/dist/utils/query.js.map +1 -1
  84. package/frontend-vue/app/{composables → build/composables}/useDataBrowserGrid.ts +65 -50
  85. package/frontend-vue/app/build/composables/useDataBrowserTabs.ts +366 -0
  86. package/frontend-vue/app/build/composables/useDatabaseHealth.ts +50 -0
  87. package/frontend-vue/app/build/composables/useDatabaseSchemas.ts +140 -0
  88. package/frontend-vue/app/{composables → build/composables}/useDiagramPersistence.ts +47 -39
  89. package/frontend-vue/app/build/composables/useQueryRuntime.ts +217 -0
  90. package/frontend-vue/app/build/composables/useQueryStore.ts +162 -0
  91. package/frontend-vue/app/build/data/cellValues.ts +132 -0
  92. package/frontend-vue/app/build/data/instanceOptions.ts +36 -0
  93. package/frontend-vue/app/build/data/pickerMenus.ts +175 -0
  94. package/frontend-vue/app/build/data/recentTables.ts +48 -0
  95. package/frontend-vue/app/build/data/stagedEdits.ts +117 -0
  96. package/frontend-vue/app/build/data/stagedWrites.ts +64 -0
  97. package/frontend-vue/app/build/data/useStagedSave.ts +298 -0
  98. package/frontend-vue/app/build/diagram/autosave.ts +72 -0
  99. package/frontend-vue/app/build/diagram/graph.ts +585 -0
  100. package/frontend-vue/app/build/diagram/history.ts +178 -0
  101. package/frontend-vue/app/build/diagram/shortcuts.ts +62 -0
  102. package/frontend-vue/app/build/diagram/sync.ts +137 -0
  103. package/frontend-vue/app/build/query/completion.ts +100 -0
  104. package/frontend-vue/app/build/query/csv.ts +32 -0
  105. package/frontend-vue/app/build/query/examples.ts +38 -0
  106. package/frontend-vue/app/build/query/runs.ts +168 -0
  107. package/frontend-vue/app/build/query/tableColumns.ts +35 -0
  108. package/frontend-vue/app/build/query/target.ts +143 -0
  109. package/frontend-vue/app/build/schemas/filterState.ts +128 -0
  110. package/frontend-vue/app/build/schemas/useSchemasListing.ts +62 -0
  111. package/frontend-vue/app/build/utils/databaseLinks.ts +98 -0
  112. package/frontend-vue/app/build/utils/fieldTypes.ts +198 -0
  113. package/frontend-vue/app/build/utils/relativeTime.ts +19 -0
  114. package/frontend-vue/app/{utils → build/utils}/stagedSerialization.ts +7 -1
  115. package/frontend-vue/app/components/ConnectionStatus.vue +122 -0
  116. package/frontend-vue/app/components/DataBrowser.vue +126 -0
  117. package/frontend-vue/app/components/DataBrowserSidebar.vue +293 -210
  118. package/frontend-vue/app/components/DataBrowserTabBar.vue +185 -93
  119. package/frontend-vue/app/components/DataFilterBar.vue +163 -0
  120. package/frontend-vue/app/components/DataGrid.vue +737 -499
  121. package/frontend-vue/app/components/DataGridCell.vue +125 -77
  122. package/frontend-vue/app/components/DataGridHeaderCell.vue +119 -81
  123. package/frontend-vue/app/components/DiagramNoteNode.vue +81 -63
  124. package/frontend-vue/app/components/DiagramRelationEdge.vue +57 -27
  125. package/frontend-vue/app/components/DiagramStubNode.vue +16 -17
  126. package/frontend-vue/app/components/DiagramTableNode.vue +106 -68
  127. package/frontend-vue/app/components/InstancePicker.vue +195 -0
  128. package/frontend-vue/app/components/JsonCellPanel.vue +30 -29
  129. package/frontend-vue/app/components/QueryBuilderPanel.vue +290 -238
  130. package/frontend-vue/app/components/QueryConsole.vue +726 -0
  131. package/frontend-vue/app/components/QueryLibrary.vue +314 -0
  132. package/frontend-vue/app/components/QueryResultPanel.vue +556 -126
  133. package/frontend-vue/app/components/RowDrawer.vue +520 -0
  134. package/frontend-vue/app/components/SchemaDiagram.vue +1016 -1051
  135. package/frontend-vue/app/components/SchemaPicker.vue +86 -0
  136. package/frontend-vue/app/components/SchemasFilterBar.vue +201 -0
  137. package/frontend-vue/app/components/TableInspector.vue +741 -0
  138. package/frontend-vue/app/config/shortcuts-registry.ts +65 -0
  139. package/frontend-vue/dms.frontend.ts +5 -14
  140. package/frontend-vue/i18n/locales/database-en-GB.json +526 -193
  141. package/frontend-vue/i18n/locales/database-fr-FR.json +528 -195
  142. package/frontend-vue/package.json +2 -1
  143. package/frontend-vue/pnpm-lock.yaml +2601 -858
  144. package/frontend-vue/pnpm-workspace.yaml +1 -1
  145. package/frontend-vue/tests/dataBrowser.test.ts +206 -0
  146. package/frontend-vue/tests/diagram.test.ts +516 -0
  147. package/frontend-vue/tests/helpers.test.ts +205 -0
  148. package/frontend-vue/tests/instanceOptions.test.ts +53 -0
  149. package/frontend-vue/tests/locales.test.ts +56 -0
  150. package/frontend-vue/tests/persistence.test.ts +106 -5
  151. package/frontend-vue/tests/pickerMenus.test.ts +254 -0
  152. package/frontend-vue/tests/queryConsole.test.ts +282 -0
  153. package/frontend-vue/tests/queryRuntime.test.ts +2 -2
  154. package/frontend-vue/tests/registration.test.ts +36 -25
  155. package/frontend-vue/tests/schemasFilters.test.ts +115 -0
  156. package/package.json +9 -6
  157. package/frontend-vue/app/components/QueryFavoritesPanel.vue +0 -127
  158. package/frontend-vue/app/components/QueryHistoryPanel.vue +0 -134
  159. package/frontend-vue/app/components/SchemaTableInspector.vue +0 -278
  160. package/frontend-vue/app/composables/useDataBrowserTabs.ts +0 -255
  161. package/frontend-vue/app/composables/useDatabaseHealth.ts +0 -50
  162. package/frontend-vue/app/composables/useDatabaseSchemas.ts +0 -92
  163. package/frontend-vue/app/composables/useQueryRuntime.ts +0 -118
  164. package/frontend-vue/app/composables/useQueryStore.ts +0 -117
  165. package/frontend-vue/app/composables/useTableViewRowClick.ts +0 -22
  166. package/frontend-vue/app/custom-pages/database/data.vue +0 -41
  167. package/frontend-vue/app/custom-pages/database/overview.vue +0 -367
  168. package/frontend-vue/app/custom-pages/database/query.vue +0 -436
  169. package/frontend-vue/app/custom-pages/database/schemas.vue +0 -218
  170. package/frontend-vue/app/utils/databaseFieldModifiers.ts +0 -33
  171. package/frontend-vue/app/utils/databaseFieldTypeIcons.ts +0 -224
  172. package/frontend-vue/app/utils/dmsTableView.ts +0 -83
  173. package/frontend-vue/app/utils/relativeTime.ts +0 -18
@@ -14,80 +14,120 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.DatabaseTablesController = void 0;
16
16
  const interface_api_1 = require("@antelopejs/interface-api");
17
+ const interface_api_util_1 = require("@antelopejs/interface-api-util");
17
18
  const auth_1 = require("@antelopejs/interface-dms/auth");
19
+ const messages_1 = require("../i18n/messages");
18
20
  const introspect_1 = require("../service/introspect");
21
+ const schemaFilters_1 = require("../service/schemaFilters");
22
+ const schemaRegistry_1 = require("../service/schemaRegistry");
19
23
  const query_1 = require("../utils/query");
20
- const DEFAULT_LIMIT = 25;
21
- const MAX_LIMIT = 200;
22
- async function listAllTables(instance) {
24
+ const INSTANCE_LIMIT_DEFAULT = 100;
25
+ const INSTANCE_LIMIT_MAX = 500;
26
+ const instanceCollator = new Intl.Collator(undefined, { numeric: true });
27
+ function relationTargets(schemaId, table) {
28
+ const targets = table.relations.map((relation) => relation.toSchema === schemaId
29
+ ? relation.toTable
30
+ : `${relation.toSchema}.${relation.toTable}`);
31
+ return [...new Set(targets)];
32
+ }
33
+ function modifierNames(table, locale) {
34
+ const ids = new Set(Object.values(table.modifiers).flat());
35
+ return [...ids].map((id) => (0, messages_1.formatModifier)(locale, id));
36
+ }
37
+ function matchesSearch(table, needle) {
38
+ if (table.name.toLowerCase().includes(needle))
39
+ return true;
40
+ return Object.keys(table.fields).some((field) => field.toLowerCase().includes(needle));
41
+ }
42
+ function needleOf(text) {
43
+ const needle = text?.trim().toLowerCase();
44
+ return needle || undefined;
45
+ }
46
+ function matchesStructure({ schemaId, table }, filters, needle) {
47
+ if (filters.scope && schemaId !== filters.scope)
48
+ return false;
49
+ if (needle && !matchesSearch(table, needle))
50
+ return false;
51
+ if (filters.has.includes("relations") && table.relations.length === 0)
52
+ return false;
53
+ if (filters.has.includes("modifiers") &&
54
+ Object.values(table.modifiers).every((ids) => ids.length === 0))
55
+ return false;
56
+ return true;
57
+ }
58
+ function countRows(schemaId, tableName, instance) {
59
+ if (instance.kind === "all")
60
+ return (0, introspect_1.getTableTotalCount)(schemaId, tableName);
61
+ if (instance.kind === "default")
62
+ return (0, introspect_1.getTableElementCount)(schemaId, tableName);
63
+ return (0, introspect_1.getTableElementCount)(schemaId, tableName, instance.id);
64
+ }
65
+ async function listTableSourceRows(locale, filters) {
66
+ const needle = needleOf(filters.q);
23
67
  const summaries = await (0, introspect_1.listSchemaSummaries)();
24
- const rows = [];
25
- for (const summary of summaries) {
26
- const counts = await Promise.all(summary.tables.map((table) => (0, introspect_1.getTableElementCount)(summary.id, table.name, instance)));
27
- summary.tables.forEach((table, idx) => {
28
- rows.push({
29
- id: `${summary.id}::${table.name}`,
30
- schema: summary.id,
31
- name: table.name,
32
- columnCount: Object.keys(table.fields).length,
33
- indexCount: Object.keys(table.indexes).length,
34
- relationCount: (table.relations ?? []).length,
35
- elementCount: counts[idx] ?? 0,
36
- });
37
- });
38
- }
39
- return rows;
68
+ const registered = summaries.flatMap((summary) => summary.tables.map((table) => ({ schemaId: summary.id, table })));
69
+ const tables = registered.filter((listed) => matchesStructure(listed, filters, needle));
70
+ const counts = await Promise.all(tables.map(({ schemaId, table }) => countRows(schemaId, table.name, filters.instance)));
71
+ const rows = tables.map(({ schemaId, table }, index) => ({
72
+ id: `${schemaId}::${table.name}`,
73
+ schema: schemaId,
74
+ name: table.name,
75
+ elementCount: counts[index] ?? 0,
76
+ columnCount: Object.keys(table.fields).length,
77
+ indexCount: Object.keys(table.indexes ?? {}).length,
78
+ relations: relationTargets(schemaId, table),
79
+ modifiers: modifierNames(table, locale),
80
+ }));
81
+ return {
82
+ rows: filters.has.includes("empty")
83
+ ? rows.filter((row) => row.elementCount === 0)
84
+ : rows,
85
+ all: registered.length,
86
+ };
40
87
  }
41
- async function selectMatchingTables(schemaFilter, instanceFilter, search) {
42
- const all = await listAllTables((0, query_1.decodeInstanceFilter)(instanceFilter));
43
- const bySchema = (0, query_1.applyFilterToList)(all, "schema", schemaFilter);
44
- return (0, query_1.applySearchToList)(bySchema, "name", search);
88
+ function matchNamedInstances(instances, search, limit) {
89
+ const needle = needleOf(search);
90
+ const matches = instances
91
+ .filter((id) => !needle || id.toLowerCase().includes(needle))
92
+ .sort((left, right) => instanceCollator.compare(left, right));
93
+ return { instances: matches.slice(0, limit), total: matches.length };
45
94
  }
46
95
  let DatabaseTablesController = class DatabaseTablesController extends (0, interface_api_1.Controller)("/api/database/tables") {
47
- async list(_user, schemaFilter, instanceFilter, search, offsetRaw, limitRaw, sortKey, sortDirection) {
48
- const matching = await selectMatchingTables(schemaFilter, instanceFilter, search);
49
- const sorted = (0, query_1.applySortToList)(matching, sortKey, sortDirection);
50
- const offset = Math.max(0, (0, query_1.parseInteger)(offsetRaw, 0));
51
- const limit = (0, query_1.clamp)((0, query_1.parseInteger)(limitRaw, DEFAULT_LIMIT), 1, MAX_LIMIT);
52
- return {
53
- results: sorted.slice(offset, offset + limit),
54
- total: sorted.length,
55
- offset,
56
- limit,
57
- };
96
+ async source(user, scope, instance, q, has) {
97
+ const { rows, all } = await listTableSourceRows((0, messages_1.localeOf)(user), (0, schemaFilters_1.readSchemaFilters)({ scope, instance, q, has }));
98
+ return { results: rows, total: rows.length, all };
58
99
  }
59
- async count(_user, schemaFilter, instanceFilter, search) {
60
- return {
61
- total: (await selectMatchingTables(schemaFilter, instanceFilter, search))
62
- .length,
63
- };
100
+ async instances(schemaRaw, search, limitRaw) {
101
+ const schema = (0, query_1.asNonEmptyString)(schemaRaw);
102
+ (0, interface_api_util_1.assert)(schema, 400, "Missing 'schema'");
103
+ const registered = (0, schemaRegistry_1.getRegistry)().get(schema);
104
+ (0, interface_api_util_1.assert)(registered, 404, `Unknown schema ${schema}`);
105
+ const named = await (0, introspect_1.listSchemaInstances)(registered);
106
+ const limit = (0, query_1.clamp)((0, query_1.parseInteger)(limitRaw, INSTANCE_LIMIT_DEFAULT), 1, INSTANCE_LIMIT_MAX);
107
+ return matchNamedInstances(named, (0, query_1.asNonEmptyString)(search), limit);
64
108
  }
65
109
  };
66
110
  exports.DatabaseTablesController = DatabaseTablesController;
67
111
  __decorate([
68
- (0, interface_api_1.Get)("/list"),
112
+ (0, interface_api_1.Get)("/source"),
69
113
  __param(0, (0, auth_1.AuthRawUser)()),
70
- __param(1, (0, interface_api_1.Parameter)("filter_schema", "query")),
114
+ __param(1, (0, interface_api_1.Parameter)("filter_scope", "query")),
71
115
  __param(2, (0, interface_api_1.Parameter)("filter_instance", "query")),
72
- __param(3, (0, interface_api_1.Parameter)("search", "query")),
73
- __param(4, (0, interface_api_1.Parameter)("offset", "query")),
74
- __param(5, (0, interface_api_1.Parameter)("limit", "query")),
75
- __param(6, (0, interface_api_1.Parameter)("sortKey", "query")),
76
- __param(7, (0, interface_api_1.Parameter)("sortDirection", "query")),
116
+ __param(3, (0, interface_api_1.Parameter)("filter_q", "query")),
117
+ __param(4, (0, interface_api_1.Parameter)("filter_has", "query")),
77
118
  __metadata("design:type", Function),
78
- __metadata("design:paramtypes", [Function, Object, Object, Object, Object, Object, Object, Object]),
119
+ __metadata("design:paramtypes", [Function, Object, Object, Object, Object]),
79
120
  __metadata("design:returntype", Promise)
80
- ], DatabaseTablesController.prototype, "list", null);
121
+ ], DatabaseTablesController.prototype, "source", null);
81
122
  __decorate([
82
- (0, interface_api_1.Get)("/count"),
83
- __param(0, (0, auth_1.AuthRawUser)()),
84
- __param(1, (0, interface_api_1.Parameter)("filter_schema", "query")),
85
- __param(2, (0, interface_api_1.Parameter)("filter_instance", "query")),
86
- __param(3, (0, interface_api_1.Parameter)("search", "query")),
123
+ (0, interface_api_1.Get)("/instances"),
124
+ __param(0, (0, interface_api_1.Parameter)("schema", "query")),
125
+ __param(1, (0, interface_api_1.Parameter)("search", "query")),
126
+ __param(2, (0, interface_api_1.Parameter)("limit", "query")),
87
127
  __metadata("design:type", Function),
88
- __metadata("design:paramtypes", [Function, Object, Object, Object]),
128
+ __metadata("design:paramtypes", [Object, Object, Object]),
89
129
  __metadata("design:returntype", Promise)
90
- ], DatabaseTablesController.prototype, "count", null);
130
+ ], DatabaseTablesController.prototype, "instances", null);
91
131
  exports.DatabaseTablesController = DatabaseTablesController = __decorate([
92
132
  (0, auth_1.AuthOwnerOnly)()
93
133
  ], DatabaseTablesController);
@@ -1 +1 @@
1
- {"version":3,"file":"tables.js","sourceRoot":"","sources":["../../src/routes/tables.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tables.js","sourceRoot":"","sources":["../../src/routes/tables.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { ModuleReadoutLine } from "@antelopejs/interface-dms/page";
2
+ import { type LocaleCarrier } from "../i18n/messages";
3
+ export declare function readCatalogReadout(user: LocaleCarrier | undefined): Promise<ModuleReadoutLine[]>;
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.readCatalogReadout = readCatalogReadout;
4
+ const messages_1 = require("../i18n/messages");
5
+ const health_1 = require("./health");
6
+ const SEPARATOR = " · ";
7
+ async function readCatalogReadout(user) {
8
+ const locale = (0, messages_1.localeOf)(user);
9
+ const health = await (0, health_1.getOverviewHealth)();
10
+ if (health.status === "down") {
11
+ return [{ text: (0, messages_1.formatMessage)(locale, "connectionDown"), tone: "error" }];
12
+ }
13
+ const contents = [
14
+ (0, messages_1.formatCount)(locale, "tables", health.tableCount),
15
+ (0, messages_1.formatCount)(locale, "rows", health.totalRows),
16
+ ].join(SEPARATOR);
17
+ const connection = [(0, messages_1.formatCount)(locale, "schemas", health.schemaCount)];
18
+ if (health.latencyMs !== null) {
19
+ connection.push((0, messages_1.formatMessage)(locale, "latency", { value: String(health.latencyMs) }));
20
+ }
21
+ return [
22
+ { text: contents, tone: "success" },
23
+ { text: connection.join(SEPARATOR), tone: "info" },
24
+ ];
25
+ }
26
+ //# sourceMappingURL=catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../src/service/catalog.ts"],"names":[],"mappings":";;AAeA,gDAsBC;AApCD,+CAK0B;AAC1B,qCAA6C;AAE7C,MAAM,SAAS,GAAG,KAAK,CAAC;AAMjB,KAAK,UAAU,kBAAkB,CACtC,IAA+B;IAE/B,MAAM,MAAM,GAAG,IAAA,mBAAQ,EAAC,IAAI,CAAC,CAAC;IAC9B,MAAM,MAAM,GAAG,MAAM,IAAA,0BAAiB,GAAE,CAAC;IACzC,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;QAC7B,OAAO,CAAC,EAAE,IAAI,EAAE,IAAA,wBAAa,EAAC,MAAM,EAAE,gBAAgB,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;IAC5E,CAAC;IACD,MAAM,QAAQ,GAAG;QACf,IAAA,sBAAW,EAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,UAAU,CAAC;QAChD,IAAA,sBAAW,EAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,SAAS,CAAC;KAC9C,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAClB,MAAM,UAAU,GAAG,CAAC,IAAA,sBAAW,EAAC,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC;IACxE,IAAI,MAAM,CAAC,SAAS,KAAK,IAAI,EAAE,CAAC;QAC9B,UAAU,CAAC,IAAI,CACb,IAAA,wBAAa,EAAC,MAAM,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CACtE,CAAC;IACJ,CAAC;IACD,OAAO;QACL,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE;QACnC,EAAE,IAAI,EAAE,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE;KACnD,CAAC;AACJ,CAAC"}
@@ -8,13 +8,13 @@ export interface OverviewHealth {
8
8
  status: ConnectionStatus;
9
9
  latencyMs: number | null;
10
10
  driver: string | null;
11
- pool: string | null;
12
- collections: number;
11
+ checkedAt: string;
12
+ error: string | null;
13
13
  schemaCount: number;
14
14
  tableCount: number;
15
+ relationCount: number;
15
16
  indexCount: number;
16
17
  totalRows: number;
17
- sizeBytes: number | null;
18
18
  storage: StorageEntry[];
19
19
  }
20
20
  export declare function getOverviewHealth(): Promise<OverviewHealth>;
@@ -9,19 +9,24 @@ async function probeConnection() {
9
9
  const schemaIds = Array.from(registry.keys());
10
10
  const probeSchema = schemaIds[0] ? registry.get(schemaIds[0]) : undefined;
11
11
  if (!probeSchema)
12
- return { status: "ok", latencyMs: null };
12
+ return { status: "ok", latencyMs: null, error: null };
13
13
  const startedAt = Date.now();
14
14
  try {
15
15
  await probeSchema.listInstances().run();
16
- return { status: "ok", latencyMs: Date.now() - startedAt };
16
+ return { status: "ok", latencyMs: Date.now() - startedAt, error: null };
17
17
  }
18
- catch {
19
- return { status: "down", latencyMs: null };
18
+ catch (error) {
19
+ return {
20
+ status: "down",
21
+ latencyMs: null,
22
+ error: error instanceof Error ? error.message : String(error),
23
+ };
20
24
  }
21
25
  }
22
26
  async function aggregateStorage(summaries) {
23
27
  let tableCount = 0;
24
28
  let indexCount = 0;
29
+ let relationCount = 0;
25
30
  let totalRows = 0;
26
31
  const storage = [];
27
32
  for (const summary of summaries) {
@@ -31,28 +36,26 @@ async function aggregateStorage(summaries) {
31
36
  const rows = counts[idx] ?? 0;
32
37
  totalRows += rows;
33
38
  indexCount += Object.keys(table.indexes ?? {}).length;
39
+ relationCount += table.relations.length;
34
40
  storage.push({ schema: summary.id, table: table.name, rows });
35
41
  });
36
42
  }
37
43
  storage.sort((a, b) => b.rows - a.rows);
38
- return { tableCount, indexCount, totalRows, storage };
44
+ return { tableCount, relationCount, indexCount, totalRows, storage };
39
45
  }
40
46
  async function getOverviewHealth() {
41
- const { status, latencyMs } = await probeConnection();
47
+ const checkedAt = new Date().toISOString();
48
+ const { status, latencyMs, error } = await probeConnection();
42
49
  const summaries = await (0, introspect_1.listSchemaSummaries)();
43
- const { tableCount, indexCount, totalRows, storage } = await aggregateStorage(summaries);
50
+ const aggregate = await aggregateStorage(summaries);
44
51
  return {
45
52
  status,
46
53
  latencyMs,
47
54
  driver: (0, config_1.getModuleConfig)().driverLabel ?? null,
48
- pool: null,
49
- collections: tableCount,
55
+ checkedAt,
56
+ error,
50
57
  schemaCount: summaries.length,
51
- tableCount,
52
- indexCount,
53
- totalRows,
54
- sizeBytes: null,
55
- storage,
58
+ ...aggregate,
56
59
  };
57
60
  }
58
61
  //# sourceMappingURL=health.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/service/health.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/service/health.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,8 @@
1
- import type { InstanceId } from "@antelopejs/interface-database";
1
+ import { type InstanceId, type Schema } from "@antelopejs/interface-database";
2
2
  import type { SchemaSummary, SchemaSummaryWithStats } from "./types";
3
3
  export declare function listSchemaSummaries(): Promise<SchemaSummary[]>;
4
+ export declare function listSchemaInstances(schema: Schema): Promise<string[]>;
4
5
  export declare function getTableElementCount(schemaId: string, tableName: string, instance?: InstanceId): Promise<number>;
6
+ export declare function getTableTotalCount(schemaId: string, tableName: string): Promise<number>;
5
7
  export declare function listSchemaSummariesWithStats(): Promise<SchemaSummaryWithStats[]>;
6
8
  export declare function getTablePrimaryKey(schemaId: string, tableName: string): string | undefined;
@@ -1,10 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.listSchemaSummaries = listSchemaSummaries;
4
+ exports.listSchemaInstances = listSchemaInstances;
4
5
  exports.getTableElementCount = getTableElementCount;
6
+ exports.getTableTotalCount = getTableTotalCount;
5
7
  exports.listSchemaSummariesWithStats = listSchemaSummariesWithStats;
6
8
  exports.getTablePrimaryKey = getTablePrimaryKey;
7
9
  const logging_1 = require("@antelopejs/interface-core/logging");
10
+ const interface_database_1 = require("@antelopejs/interface-database");
8
11
  const interface_database_decorators_1 = require("@antelopejs/interface-database-decorators");
9
12
  const config_1 = require("../config");
10
13
  const fieldDescriptor_1 = require("./fieldDescriptor");
@@ -14,6 +17,7 @@ const STATS_TTL_MS = 30_000;
14
17
  const FIELDS_TTL_MS = 30_000;
15
18
  const FIELD_INFERENCE_SAMPLE_SIZE = 5;
16
19
  const UNKNOWN_DESCRIPTOR = { kind: "unknown" };
20
+ const NULL_DESCRIPTOR = { kind: "null" };
17
21
  const warnedRelations = new Set();
18
22
  function warnOnce(key, message) {
19
23
  if (warnedRelations.has(key))
@@ -66,13 +70,39 @@ function resolveModifiers(TableClass) {
66
70
  return out;
67
71
  }
68
72
  const fieldsCache = new Map();
73
+ function inferArrayType(items) {
74
+ const members = [];
75
+ for (const item of items) {
76
+ const type = inferFieldType(item);
77
+ if (!type)
78
+ continue;
79
+ const key = JSON.stringify(type);
80
+ if (!members.some((member) => JSON.stringify(member) === key))
81
+ members.push(type);
82
+ }
83
+ if (members.length === 0)
84
+ return { kind: "array" };
85
+ const [only] = members;
86
+ return {
87
+ kind: "array",
88
+ element: members.length === 1 && only ? only : { kind: "union", members },
89
+ };
90
+ }
91
+ function arrayOf(descriptor) {
92
+ const members = descriptor?.kind === "union" ? descriptor.members : [descriptor];
93
+ return members.find((member) => member?.kind === "array");
94
+ }
95
+ function refineSampled(seen, next) {
96
+ const untyped = seen?.kind === "array" && !seen.element;
97
+ return untyped && arrayOf(next)?.element ? next : (seen ?? next);
98
+ }
69
99
  function inferFieldType(value) {
70
100
  if (value === null || value === undefined)
71
101
  return undefined;
72
102
  if (value instanceof Date)
73
103
  return { kind: "date" };
74
104
  if (Array.isArray(value))
75
- return { kind: "array" };
105
+ return inferArrayType(value);
76
106
  if (typeof value === "object")
77
107
  return { kind: "object", fields: {} };
78
108
  if (typeof value === "string")
@@ -83,32 +113,80 @@ function inferFieldType(value) {
83
113
  return { kind: "boolean" };
84
114
  return undefined;
85
115
  }
86
- async function inferTableFields(schemaId, schema, tableName) {
87
- const cacheKey = `${schemaId}::${tableName}`;
88
- const cached = fieldsCache.get(cacheKey);
89
- const now = Date.now();
90
- if (cached && cached.expiresAt > now)
91
- return cached.value;
92
- const inferred = {};
116
+ async function sampleRows(schema, tableName, instance) {
93
117
  try {
94
- const sample = await schema
95
- .instance()
118
+ return (await schema
119
+ .instance(instance)
96
120
  .table(tableName)
97
- .slice(0, FIELD_INFERENCE_SAMPLE_SIZE);
98
- for (const row of sample) {
99
- if (!row || typeof row !== "object")
121
+ .slice(0, FIELD_INFERENCE_SAMPLE_SIZE));
122
+ }
123
+ catch {
124
+ return [];
125
+ }
126
+ }
127
+ async function sampleAnyInstance(schema, tableName) {
128
+ const rows = await sampleRows(schema, tableName);
129
+ if (rows.length > 0)
130
+ return rows;
131
+ for (const instance of await listSchemaInstances(schema)) {
132
+ const named = await sampleRows(schema, tableName, instance);
133
+ if (named.length > 0)
134
+ return named;
135
+ }
136
+ return [];
137
+ }
138
+ const INSTANCE_TAG_FIELD = "_instance";
139
+ const NULLISH_KINDS = new Set([
140
+ "null",
141
+ "undefined",
142
+ "any",
143
+ "unknown",
144
+ ]);
145
+ function admitsNull(descriptor) {
146
+ if (NULLISH_KINDS.has(descriptor.kind))
147
+ return true;
148
+ return (descriptor.kind === "union" &&
149
+ descriptor.members.some((member) => NULLISH_KINDS.has(member.kind)));
150
+ }
151
+ function withNull(descriptor) {
152
+ if (admitsNull(descriptor))
153
+ return descriptor;
154
+ if (descriptor.kind === "union")
155
+ return { kind: "union", members: [...descriptor.members, NULL_DESCRIPTOR] };
156
+ return { kind: "union", members: [descriptor, NULL_DESCRIPTOR] };
157
+ }
158
+ function inferFromRows(rows) {
159
+ const observed = new Map();
160
+ for (const row of rows) {
161
+ if (!row || typeof row !== "object")
162
+ continue;
163
+ for (const [key, value] of Object.entries(row)) {
164
+ if (key === INSTANCE_TAG_FIELD)
100
165
  continue;
101
- for (const [key, value] of Object.entries(row)) {
102
- if (key in inferred)
103
- continue;
104
- const type = inferFieldType(value);
105
- if (type !== undefined)
106
- inferred[key] = type;
107
- }
166
+ const field = observed.get(key) ?? { nullable: false };
167
+ if (value === null)
168
+ field.nullable = true;
169
+ else
170
+ field.type = refineSampled(field.type, inferFieldType(value));
171
+ observed.set(key, field);
108
172
  }
109
173
  }
110
- catch {
174
+ const inferred = {};
175
+ for (const [key, { type, nullable }] of observed) {
176
+ if (type)
177
+ inferred[key] = nullable ? withNull(type) : type;
178
+ else if (nullable)
179
+ inferred[key] = NULL_DESCRIPTOR;
111
180
  }
181
+ return inferred;
182
+ }
183
+ async function inferTableFields(schemaId, schema, tableName) {
184
+ const cacheKey = `${schemaId}::${tableName}`;
185
+ const cached = fieldsCache.get(cacheKey);
186
+ const now = Date.now();
187
+ if (cached && cached.expiresAt > now)
188
+ return cached.value;
189
+ const inferred = inferFromRows(await sampleAnyInstance(schema, tableName));
112
190
  fieldsCache.set(cacheKey, {
113
191
  value: inferred,
114
192
  expiresAt: now + FIELDS_TTL_MS,
@@ -183,17 +261,24 @@ async function summarizeTable(id, schema, tableName, def, tableClasses) {
183
261
  for (const [name, value] of Object.entries(definitionFields)) {
184
262
  fromDefinition[name] = (0, fieldDescriptor_1.toFieldDescriptor)(value);
185
263
  }
264
+ const withSampled = (name, descriptor) => {
265
+ const seen = sampled[name];
266
+ const element = arrayOf(seen)?.element;
267
+ const typed = descriptor.kind === "array" && !descriptor.element && element
268
+ ? { kind: "array", element }
269
+ : descriptor;
270
+ return seen && admitsNull(seen) ? withNull(typed) : typed;
271
+ };
186
272
  const fields = {};
187
273
  for (const name of declared.ordered) {
188
- fields[name] =
189
- fromDefinition[name] ??
190
- declared.types[name] ??
191
- sampled[name] ??
192
- UNKNOWN_DESCRIPTOR;
274
+ fields[name] = withSampled(name, fromDefinition[name] ??
275
+ declared.types[name] ??
276
+ sampled[name] ??
277
+ UNKNOWN_DESCRIPTOR);
193
278
  }
194
279
  for (const [name, descriptor] of Object.entries(fromDefinition)) {
195
280
  if (!(name in fields))
196
- fields[name] = descriptor;
281
+ fields[name] = withSampled(name, descriptor);
197
282
  }
198
283
  for (const [name, descriptor] of Object.entries(sampled)) {
199
284
  if (!(name in fields))
@@ -225,14 +310,18 @@ function tableCountKey(schemaId, tableName, instance) {
225
310
  return `${schemaId}::${String(instance ?? "")}::${tableName}`;
226
311
  }
227
312
  async function countTableRows(schema, tableName, instance) {
228
- try {
229
- const table = schema.instance(instance).table(tableName);
230
- const total = await table.count();
231
- return typeof total === "number" && Number.isFinite(total) ? total : 0;
232
- }
233
- catch {
234
- return 0;
235
- }
313
+ const table = schema.instance(instance).table(tableName);
314
+ const total = await table.count();
315
+ return typeof total === "number" && Number.isFinite(total) ? total : 0;
316
+ }
317
+ async function cachedCount(key, count) {
318
+ const cached = tableCountCache.get(key);
319
+ const now = Date.now();
320
+ if (cached && cached.expiresAt > now)
321
+ return cached.value;
322
+ const value = await count();
323
+ tableCountCache.set(key, { value, expiresAt: now + STATS_TTL_MS });
324
+ return value;
236
325
  }
237
326
  async function listSchemaInstances(schema) {
238
327
  try {
@@ -246,17 +335,16 @@ async function listSchemaInstances(schema) {
246
335
  }
247
336
  }
248
337
  async function getTableElementCount(schemaId, tableName, instance) {
249
- const key = tableCountKey(schemaId, tableName, instance);
250
- const cached = tableCountCache.get(key);
251
- const now = Date.now();
252
- if (cached && cached.expiresAt > now)
253
- return cached.value;
254
338
  const schema = (0, schemaRegistry_1.getRegistry)().get(schemaId);
255
339
  if (!schema)
256
340
  return 0;
257
- const value = await countTableRows(schema, tableName, instance);
258
- tableCountCache.set(key, { value, expiresAt: now + STATS_TTL_MS });
259
- return value;
341
+ return cachedCount(tableCountKey(schemaId, tableName, instance), () => countTableRows(schema, tableName, instance).catch(() => 0));
342
+ }
343
+ async function getTableTotalCount(schemaId, tableName) {
344
+ const schema = (0, schemaRegistry_1.getRegistry)().get(schemaId);
345
+ if (!schema)
346
+ return 0;
347
+ return cachedCount(tableCountKey(schemaId, tableName, interface_database_1.CROSS_INSTANCE), () => countTableRows(schema, tableName, interface_database_1.CROSS_INSTANCE).catch(() => 0));
260
348
  }
261
349
  async function computeInsights(id, schema) {
262
350
  const tableNames = Object.keys(schema.definition);