target-supabase-sdk 0.2.3 → 0.2.5

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 (163) hide show
  1. package/README.md +24 -18
  2. package/dist/browser.d.ts +11 -4
  3. package/dist/browser.d.ts.map +1 -1
  4. package/dist/browser.js +3 -3
  5. package/dist/chunks/{enable-log-persist-C7GJo_Nc.js → enable-log-persist-BL2FaGQp.js} +10 -8
  6. package/dist/chunks/enable-log-persist-BL2FaGQp.js.map +1 -0
  7. package/dist/chunks/{create-logger-DyH3mZ8p.js → list.api-Ab9v8yOg.js} +66 -57
  8. package/dist/chunks/list.api-Ab9v8yOg.js.map +1 -0
  9. package/dist/chunks/{word.interface-DLgRobKV.js → word.interface-Mw7bTSqs.js} +1191 -97
  10. package/dist/chunks/word.interface-Mw7bTSqs.js.map +1 -0
  11. package/dist/extraction/extraction.api.d.ts +117 -0
  12. package/dist/extraction/extraction.api.d.ts.map +1 -0
  13. package/dist/extraction/extraction.interface.d.ts +43 -0
  14. package/dist/extraction/extraction.interface.d.ts.map +1 -0
  15. package/dist/list/list.interface.d.ts +2 -2
  16. package/dist/list/list.interface.d.ts.map +1 -1
  17. package/dist/node/fs/json-state-store.d.ts.map +1 -1
  18. package/dist/node/fs/runtime-state-path.d.ts +17 -0
  19. package/dist/node/fs/runtime-state-path.d.ts.map +1 -0
  20. package/dist/node/fs/sharded-json-state-store.d.ts +19 -0
  21. package/dist/node/fs/sharded-json-state-store.d.ts.map +1 -0
  22. package/dist/node/node-runtime.base.d.ts +13 -1
  23. package/dist/node/node-runtime.base.d.ts.map +1 -1
  24. package/dist/node/process/create-managed-child-processes.d.ts +12 -0
  25. package/dist/node/process/create-managed-child-processes.d.ts.map +1 -0
  26. package/dist/node/process/index.d.ts +3 -1
  27. package/dist/node/process/index.d.ts.map +1 -1
  28. package/dist/node/process/managed-child-processes.d.ts +15 -2
  29. package/dist/node/process/managed-child-processes.d.ts.map +1 -1
  30. package/dist/node/runtime-state/create-service-runtime-state-store.d.ts +27 -0
  31. package/dist/node/runtime-state/create-service-runtime-state-store.d.ts.map +1 -0
  32. package/dist/node/runtime-state/index.d.ts +4 -0
  33. package/dist/node/runtime-state/index.d.ts.map +1 -0
  34. package/dist/node/runtime-state/service-runtime-state.types.d.ts +57 -0
  35. package/dist/node/runtime-state/service-runtime-state.types.d.ts.map +1 -0
  36. package/dist/node/service-guard/index.d.ts +9 -0
  37. package/dist/node/service-guard/index.d.ts.map +1 -0
  38. package/dist/node/service-guard/register-service-guard-runner.d.ts +9 -0
  39. package/dist/node/service-guard/register-service-guard-runner.d.ts.map +1 -0
  40. package/dist/node/service-guard/run-readiness-gate.d.ts +11 -0
  41. package/dist/node/service-guard/run-readiness-gate.d.ts.map +1 -0
  42. package/dist/node/service-guard/run-service-guard-tick.d.ts +7 -0
  43. package/dist/node/service-guard/run-service-guard-tick.d.ts.map +1 -0
  44. package/dist/node/service-guard/service-guard-node.d.ts +18 -0
  45. package/dist/node/service-guard/service-guard-node.d.ts.map +1 -0
  46. package/dist/node/service-guard/service-guard.interface.d.ts +58 -0
  47. package/dist/node/service-guard/service-guard.interface.d.ts.map +1 -0
  48. package/dist/node/service-guard/worker-spawn-cooldown.d.ts +4 -0
  49. package/dist/node/service-guard/worker-spawn-cooldown.d.ts.map +1 -0
  50. package/dist/node/service-host/index.d.ts +9 -0
  51. package/dist/node/service-host/index.d.ts.map +1 -0
  52. package/dist/node/service-host/registry-slot-guard-step.d.ts +21 -0
  53. package/dist/node/service-host/registry-slot-guard-step.d.ts.map +1 -0
  54. package/dist/node/service-host/service-host.d.ts +36 -0
  55. package/dist/node/service-host/service-host.d.ts.map +1 -0
  56. package/dist/node/service-host/single-process-service.d.ts +21 -0
  57. package/dist/node/service-host/single-process-service.d.ts.map +1 -0
  58. package/dist/node.d.ts +15 -2
  59. package/dist/node.d.ts.map +1 -1
  60. package/dist/node.js +2221 -1485
  61. package/dist/node.js.map +1 -1
  62. package/dist/preload.js +3 -3
  63. package/dist/service/config.api.d.ts +143 -0
  64. package/dist/service/config.api.d.ts.map +1 -0
  65. package/dist/service/config.interface.d.ts +22 -0
  66. package/dist/service/config.interface.d.ts.map +1 -0
  67. package/dist/service/index.d.ts +16 -17
  68. package/dist/service/index.d.ts.map +1 -1
  69. package/dist/service/registry-lifecycle.d.ts +43 -0
  70. package/dist/service/registry-lifecycle.d.ts.map +1 -0
  71. package/dist/service/registry.service.d.ts +117 -0
  72. package/dist/service/registry.service.d.ts.map +1 -0
  73. package/dist/service/service-bootstrap.d.ts +28 -0
  74. package/dist/service/service-bootstrap.d.ts.map +1 -0
  75. package/dist/service/service.api.d.ts +160 -0
  76. package/dist/service/service.api.d.ts.map +1 -1
  77. package/dist/service/service.interface.d.ts +32 -1
  78. package/dist/service/service.interface.d.ts.map +1 -1
  79. package/dist/shared/log/index.d.ts +4 -0
  80. package/dist/shared/log/index.d.ts.map +1 -1
  81. package/dist/shared/log/log-batch.d.ts +44 -0
  82. package/dist/shared/log/log-batch.d.ts.map +1 -0
  83. package/dist/shared/log/log-persist-coordinator.d.ts +37 -0
  84. package/dist/shared/log/log-persist-coordinator.d.ts.map +1 -0
  85. package/dist/shared/log/log-persist-flush.d.ts.map +1 -1
  86. package/dist/shared/log/log-persist.config.d.ts +0 -1
  87. package/dist/shared/log/log-persist.config.d.ts.map +1 -1
  88. package/dist/shared/log/log-persist.interface.d.ts +8 -0
  89. package/dist/shared/log/log-persist.interface.d.ts.map +1 -1
  90. package/dist/shared/utils/config-path.utils.d.ts +21 -0
  91. package/dist/shared/utils/config-path.utils.d.ts.map +1 -1
  92. package/dist/shared/utils/get-value-at-path.d.ts +3 -0
  93. package/dist/shared/utils/get-value-at-path.d.ts.map +1 -0
  94. package/dist/task/index.d.ts +2 -0
  95. package/dist/task/index.d.ts.map +1 -1
  96. package/dist/task/task-manager.d.ts +1 -1
  97. package/dist/task/task-manager.d.ts.map +1 -1
  98. package/dist/task/task-post-retry.api.d.ts +24 -0
  99. package/dist/task/task-post-retry.api.d.ts.map +1 -0
  100. package/dist/task/task-repo-context.d.ts +7 -1
  101. package/dist/task/task-repo-context.d.ts.map +1 -1
  102. package/dist/trigger/trigger-manager.d.ts +1 -1
  103. package/dist/trigger/trigger-manager.d.ts.map +1 -1
  104. package/dist/trigger/trigger-node.d.ts +1 -0
  105. package/dist/trigger/trigger-node.d.ts.map +1 -1
  106. package/dist/trigger/trigger.constant.d.ts +1 -1
  107. package/dist/trigger/trigger.constant.d.ts.map +1 -1
  108. package/dist/trigger/trigger.interface.d.ts +10 -0
  109. package/dist/trigger/trigger.interface.d.ts.map +1 -1
  110. package/package.json +4 -2
  111. package/src/browser.ts +102 -4
  112. package/src/extraction/extraction.api.ts +232 -0
  113. package/src/extraction/extraction.interface.ts +45 -0
  114. package/src/list/list.interface.ts +2 -2
  115. package/src/node/fs/json-state-store.ts +5 -2
  116. package/src/node/fs/runtime-state-path.ts +35 -0
  117. package/src/node/fs/sharded-json-state-store.ts +157 -0
  118. package/src/node/node-runtime.base.ts +37 -6
  119. package/src/node/process/create-managed-child-processes.ts +27 -0
  120. package/src/node/process/index.ts +4 -0
  121. package/src/node/process/managed-child-processes.ts +48 -15
  122. package/src/node/runtime-state/create-service-runtime-state-store.ts +125 -0
  123. package/src/node/runtime-state/index.ts +17 -0
  124. package/src/node/runtime-state/service-runtime-state.types.ts +64 -0
  125. package/src/node/service-guard/index.ts +17 -0
  126. package/src/node/service-guard/register-service-guard-runner.ts +64 -0
  127. package/src/node/service-guard/run-readiness-gate.ts +34 -0
  128. package/src/node/service-guard/run-service-guard-tick.ts +106 -0
  129. package/src/node/service-guard/service-guard-node.ts +52 -0
  130. package/src/node/service-guard/service-guard.interface.ts +64 -0
  131. package/src/node/service-guard/worker-spawn-cooldown.ts +13 -0
  132. package/src/node/service-host/index.ts +30 -0
  133. package/src/node/service-host/registry-slot-guard-step.ts +57 -0
  134. package/src/node/service-host/service-host.ts +168 -0
  135. package/src/node/service-host/single-process-service.ts +58 -0
  136. package/src/node.ts +69 -0
  137. package/src/service/config.api.ts +224 -0
  138. package/src/service/config.interface.ts +25 -0
  139. package/src/service/index.ts +78 -149
  140. package/src/service/registry-lifecycle.ts +144 -0
  141. package/src/service/registry.service.ts +726 -0
  142. package/src/service/service-bootstrap.ts +74 -0
  143. package/src/service/service.api.ts +13 -0
  144. package/src/service/service.interface.ts +36 -1
  145. package/src/shared/log/index.ts +13 -0
  146. package/src/shared/log/log-batch.ts +156 -0
  147. package/src/shared/log/log-persist-coordinator.ts +107 -0
  148. package/src/shared/log/log-persist-flush.ts +3 -3
  149. package/src/shared/log/log-persist.config.ts +0 -2
  150. package/src/shared/log/log-persist.interface.ts +10 -0
  151. package/src/shared/utils/config-path.utils.ts +35 -0
  152. package/src/shared/utils/get-value-at-path.ts +17 -0
  153. package/src/task/index.ts +2 -0
  154. package/src/task/task-manager.ts +10 -4
  155. package/src/task/task-post-retry.api.ts +61 -0
  156. package/src/task/task-repo-context.ts +8 -1
  157. package/src/trigger/trigger-manager.ts +4 -2
  158. package/src/trigger/trigger-node.ts +10 -4
  159. package/src/trigger/trigger.constant.ts +1 -1
  160. package/src/trigger/trigger.interface.ts +10 -0
  161. package/dist/chunks/create-logger-DyH3mZ8p.js.map +0 -1
  162. package/dist/chunks/enable-log-persist-C7GJo_Nc.js.map +0 -1
  163. package/dist/chunks/word.interface-DLgRobKV.js.map +0 -1
package/src/node.ts CHANGED
@@ -51,16 +51,21 @@ export {
51
51
  nodeBufferToArrayBuffer,
52
52
  readAndVerifySourceFile,
53
53
  } from "./node/fs/read-source-file";
54
+ export type { BaseNodeRuntimeOptions, NodeLoopContext } from "./node/node-runtime.base";
54
55
  export { BaseNodeRuntime } from "./node/node-runtime.base";
55
56
  export type {
56
57
  BuildNodeImportArgsInput,
58
+ CreateManagedChildProcessesOptions,
59
+ CriticalExitHandler,
57
60
  ManagedChildProcessesOptions,
61
+ SpawnChildOptions,
58
62
  SpawnChildResult,
59
63
  SpawnTsxChildOptions,
60
64
  StopAllChildrenOptions,
61
65
  } from "./node/process";
62
66
  export {
63
67
  buildNodeImportArgs,
68
+ createManagedChildProcesses,
64
69
  isChildProcessRunning,
65
70
  ManagedChildProcesses,
66
71
  spawnTsxChild,
@@ -85,6 +90,48 @@ export {
85
90
  runReadinessChecks,
86
91
  waitForServiceReady,
87
92
  } from "./node/readiness";
93
+ export type {
94
+ CreateServiceRuntimeStateStoreOptions,
95
+ FinishRunnerTickOptions,
96
+ GuardRuntimeSlice,
97
+ ReadinessRuntimeSlice,
98
+ ReadinessStatus,
99
+ SchedulerRuntimeSlice,
100
+ ServiceRuntimeCoreNestedKey,
101
+ ServiceRuntimeExtraSlicePatch,
102
+ ServiceRuntimeNestedKeys,
103
+ ServiceRuntimeState,
104
+ ServiceRuntimeStateStore,
105
+ WorkerRuntimeSlice,
106
+ } from "./node/runtime-state";
107
+ export { createServiceRuntimeStateStore } from "./node/runtime-state";
108
+ export type {
109
+ ApplyRegistrySlotGuardInput,
110
+ ApplyRegistrySlotGuardResult,
111
+ RegisterServiceGuardRunnerOptions,
112
+ RunReadinessGateInput,
113
+ ServiceGuardNodeOptions,
114
+ ServiceGuardTickInput,
115
+ ServiceGuardTickResult,
116
+ ServiceHost,
117
+ ServiceHostClosable,
118
+ ServiceHostContext,
119
+ ServiceHostOptions,
120
+ SingleProcessServiceContext,
121
+ SingleProcessServiceOptions,
122
+ } from "./node/service-host";
123
+ export {
124
+ applyRegistrySlotGuardStep,
125
+ createServiceHost,
126
+ getWorkerSpawnCooldownLastAt,
127
+ markWorkerSpawned,
128
+ registerServiceGuardRunner,
129
+ runReadinessGate,
130
+ runServiceGuardTick,
131
+ runSingleProcessService,
132
+ SERVICE_GUARD_RUNNER_KEY,
133
+ ServiceGuardNode,
134
+ } from "./node/service-host";
88
135
  export { RepoManager } from "./repo/repo-manager";
89
136
  export {
90
137
  disableLogPersist,
@@ -105,6 +152,25 @@ export type {
105
152
  LogPersistStats,
106
153
  WaitForLogPersistReadyOptions,
107
154
  } from "./shared/log/log-persist.interface";
155
+ export type { LogPersistCoordinator, LogPersistCoordinatorOptions } from "./shared/log/log-persist-coordinator";
156
+ export { createLogPersistCoordinator } from "./shared/log/log-persist-coordinator";
157
+ export type {
158
+ ConfigSchema,
159
+ LoadCachedJsConfigOptions,
160
+ ResolveFirstExistingPathOptions,
161
+ } from "./shared/utils/config-path.utils";
162
+ export {
163
+ getConfigFileDir,
164
+ importJsConfigModule,
165
+ loadCachedJsConfigModule,
166
+ pathExists,
167
+ resolveFirstExistingPath,
168
+ resolvePathFromBaseDir,
169
+ resolvePathFromConfigFile,
170
+ resolvePathFromCwd,
171
+ toFileImportHref,
172
+ } from "./shared/utils/config-path.utils";
173
+ export { getValueAtPath } from "./shared/utils/get-value-at-path";
108
174
  export type {
109
175
  BootstrapLocalTasksResult,
110
176
  BootstrapLocalTasksStatus,
@@ -132,6 +198,9 @@ export {
132
198
  } from "./task/task-manager";
133
199
  export { TaskNode } from "./task/task-node";
134
200
  export type { PostTaskPayload } from "./task/task-post.api";
201
+ export { postTask, postTaskSchema } from "./task/task-post.api";
202
+ export type { PostTaskWithRetryOptions, PostTaskWithRetryResult } from "./task/task-post-retry.api";
203
+ export { POST_TASK_DEFAULT_MAX_ATTEMPTS, postTaskWithRetry } from "./task/task-post-retry.api";
135
204
  export { postTaskWithValidation } from "./task/task-post-validated.api";
136
205
  export type {
137
206
  TaskRepoValidationFailureReason,
@@ -0,0 +1,224 @@
1
+ import { z } from "zod";
2
+ import {
3
+ createTarget,
4
+ getPossibleTarget,
5
+ getTarget,
6
+ isOptimisticLockError,
7
+ type QueryFilter,
8
+ updateTargetDetails,
9
+ validateWithSchema,
10
+ } from "../core.api";
11
+ import { generateResponse } from "../core.interface";
12
+ import { CategoryConfig, type Config, type ConfigDetails, TARGET_SYSTEM_REGISTRY_KEY } from "./config.interface";
13
+ import { type ServiceSlot, ServiceSlotStatus } from "./service.interface";
14
+
15
+ const targetIdSchema = z.string().trim().min(1);
16
+
17
+ export const getConfigSchema = z
18
+ .object({
19
+ id: targetIdSchema.optional(),
20
+ value: z.string().trim().min(1).optional(),
21
+ })
22
+ .refine(
23
+ (payload) => {
24
+ const hasId = payload.id != null && payload.id !== "";
25
+ const hasValue = payload.value != null && payload.value !== "";
26
+ return hasId !== hasValue;
27
+ },
28
+ { message: "Provide exactly one of id or value" },
29
+ );
30
+
31
+ export type GetConfigPayload = z.infer<typeof getConfigSchema>;
32
+
33
+ /** One declarative EMPTY slot entry for seeding the system registry. */
34
+ export const systemRegistrySeedSlotSchema = z.object({
35
+ serviceValue: z.string().trim().min(1),
36
+ });
37
+
38
+ export type SystemRegistrySeedSlot = z.infer<typeof systemRegistrySeedSlotSchema>;
39
+
40
+ export const postSystemRegistryConfigSchema = z.object({
41
+ /** When omitted, {@link DEFAULT_SYSTEM_REGISTRY_SEED_SLOTS} is used. */
42
+ slots: z.array(systemRegistrySeedSlotSchema).min(1).optional(),
43
+ tagList: z.array(z.string()).optional().default([]),
44
+ });
45
+
46
+ export type PostSystemRegistryConfigPayload = z.infer<typeof postSystemRegistryConfigSchema>;
47
+
48
+ /** Same payload shape as {@link postSystemRegistryConfig} — replaces slots with fresh EMPTY rows. */
49
+ export const resetSystemRegistryConfigSchema = postSystemRegistryConfigSchema;
50
+
51
+ export type ResetSystemRegistryConfigPayload = PostSystemRegistryConfigPayload;
52
+
53
+ const DEFAULT_RESET_RETRY_ATTEMPTS = 5;
54
+ const RESET_RETRY_DELAY_MS = 50;
55
+
56
+ /** Default one EMPTY slot per known L3 service (override via payload or seed file). */
57
+ export const DEFAULT_SYSTEM_REGISTRY_SEED_SLOTS: readonly SystemRegistrySeedSlot[] = [
58
+ { serviceValue: "log-service" },
59
+ { serviceValue: "watch-service" },
60
+ { serviceValue: "download-service" },
61
+ { serviceValue: "storage-service" },
62
+ ] as const;
63
+
64
+ const configCategoryFilter: QueryFilter = {
65
+ field: "category",
66
+ operator: "eq",
67
+ value: CategoryConfig.CONFIG,
68
+ };
69
+
70
+ function buildConfigLookupFilters(payload: GetConfigPayload): QueryFilter[] {
71
+ const filters: QueryFilter[] = [configCategoryFilter];
72
+
73
+ if (payload.id == null || payload.id === "") {
74
+ filters.push({ field: "value", operator: "eq", value: payload.value! });
75
+ }
76
+
77
+ return filters;
78
+ }
79
+
80
+ /** Build EMPTY {@link ServiceSlot} rows from seed entries (one slot per array item). */
81
+ export function buildEmptyServiceSlots(seedSlots: readonly SystemRegistrySeedSlot[]): ServiceSlot[] {
82
+ return seedSlots.map(({ serviceValue }) => ({
83
+ serviceValue,
84
+ serviceId: null,
85
+ status: ServiceSlotStatus.EMPTY,
86
+ }));
87
+ }
88
+
89
+ function parseRegistryRevision(rawMeta: unknown): number {
90
+ const source = typeof rawMeta === "object" && rawMeta !== null ? (rawMeta as Record<string, unknown>) : null;
91
+ const revision = source?.revision;
92
+ return typeof revision === "number" && Number.isFinite(revision) ? revision : 0;
93
+ }
94
+
95
+ function lockOnRegistryRevision(revision: number): QueryFilter[] {
96
+ return [{ field: "details->meta->>revision", operator: "eq", value: String(revision) }];
97
+ }
98
+
99
+ function sleep(ms: number): Promise<void> {
100
+ return new Promise((resolve) => setTimeout(resolve, ms));
101
+ }
102
+
103
+ /** Build `ConfigDetails` for the globally unique system registry row. */
104
+ export function buildSystemRegistryConfigDetails(slots: readonly ServiceSlot[]): ConfigDetails {
105
+ return {
106
+ manifestVersion: 0,
107
+ loaderKey: TARGET_SYSTEM_REGISTRY_KEY,
108
+ meta: { revision: 0 },
109
+ objects: [...slots],
110
+ };
111
+ }
112
+
113
+ /** Fetch a Config by id or by {@link Config.value} key (`category=config`). */
114
+ export const getConfig = validateWithSchema(
115
+ getConfigSchema,
116
+ "getConfigSchema",
117
+ )(async (payload) => {
118
+ const filterList = buildConfigLookupFilters(payload);
119
+
120
+ if (payload.id != null && payload.id !== "") {
121
+ const result = await getTarget({
122
+ id: payload.id,
123
+ filterList,
124
+ });
125
+ return {
126
+ ...result,
127
+ data: result.data as Config,
128
+ };
129
+ }
130
+
131
+ const result = await getPossibleTarget({
132
+ filterList,
133
+ });
134
+
135
+ if (result.data == null) {
136
+ return {
137
+ ...result,
138
+ data: undefined,
139
+ };
140
+ }
141
+
142
+ return {
143
+ ...result,
144
+ data: result.data as Config,
145
+ };
146
+ });
147
+
148
+ /**
149
+ * Insert the globally unique system registry Config (`category=config`,
150
+ * `value=target-system-registry`). Rejects duplicates via `checkRedundancyFilterList`.
151
+ */
152
+ export const postSystemRegistryConfig = validateWithSchema(
153
+ postSystemRegistryConfigSchema,
154
+ "postSystemRegistryConfigSchema",
155
+ )(async ({ slots, tagList }) => {
156
+ const seedSlots = [...(slots ?? DEFAULT_SYSTEM_REGISTRY_SEED_SLOTS)];
157
+ const serviceSlots = buildEmptyServiceSlots(seedSlots);
158
+ const details = buildSystemRegistryConfigDetails(serviceSlots);
159
+
160
+ return createTarget<Config, PostSystemRegistryConfigPayload>({
161
+ payload: { slots: seedSlots, tagList },
162
+ checkRedundancyFilterList: [
163
+ configCategoryFilter,
164
+ { field: "value", operator: "eq", value: TARGET_SYSTEM_REGISTRY_KEY },
165
+ ],
166
+ createFn: () => ({
167
+ name: TARGET_SYSTEM_REGISTRY_KEY,
168
+ value: TARGET_SYSTEM_REGISTRY_KEY,
169
+ category: CategoryConfig.CONFIG,
170
+ tagList,
171
+ details,
172
+ }),
173
+ });
174
+ });
175
+
176
+ /**
177
+ * Replace the system registry slot layout with fresh EMPTY rows.
178
+ * Creates the row when missing (same as {@link postSystemRegistryConfig}).
179
+ * Clears ACTIVE slot bindings — use for dev recovery after crashes or layout changes.
180
+ */
181
+ export const resetSystemRegistryConfig = validateWithSchema(
182
+ resetSystemRegistryConfigSchema,
183
+ "resetSystemRegistryConfigSchema",
184
+ )(async ({ slots, tagList }) => {
185
+ const seedSlots = [...(slots ?? DEFAULT_SYSTEM_REGISTRY_SEED_SLOTS)];
186
+ const serviceSlots = buildEmptyServiceSlots(seedSlots);
187
+
188
+ const existing = await getConfig({ value: TARGET_SYSTEM_REGISTRY_KEY });
189
+ if (existing.data == null) {
190
+ return postSystemRegistryConfig({ slots: seedSlots, tagList });
191
+ }
192
+
193
+ const configId = existing.data.id;
194
+
195
+ for (let attempt = 1; attempt <= DEFAULT_RESET_RETRY_ATTEMPTS; attempt += 1) {
196
+ try {
197
+ const fresh = await getConfig({ id: configId });
198
+ if (fresh.data == null) {
199
+ throw new Error(`System registry config disappeared during reset (id=${configId})`);
200
+ }
201
+
202
+ const revision = parseRegistryRevision(fresh.data.details.meta);
203
+ const updated = await updateTargetDetails<Config, ConfigDetails>({
204
+ id: configId,
205
+ optimisticLockFilterList: lockOnRegistryRevision(revision),
206
+ updateFn: (details) => ({
207
+ ...details,
208
+ meta: { revision: revision + 1 },
209
+ objects: serviceSlots,
210
+ }),
211
+ });
212
+
213
+ return generateResponse.success<Config>(updated);
214
+ } catch (error) {
215
+ if (isOptimisticLockError(error) && attempt < DEFAULT_RESET_RETRY_ATTEMPTS) {
216
+ await sleep(RESET_RETRY_DELAY_MS * attempt);
217
+ continue;
218
+ }
219
+ throw error;
220
+ }
221
+ }
222
+
223
+ throw new Error("[resetSystemRegistryConfig] Optimistic lock retries exhausted");
224
+ });
@@ -0,0 +1,25 @@
1
+ import type { Target } from "../core.interface";
2
+
3
+ export interface Config extends Target {
4
+ /** Human readable name */
5
+ name: string;
6
+ /** Unique key, like TARGET_SYSTEM_REGISTRY_KEY */
7
+ value: string;
8
+ category: CategoryConfig;
9
+ details: ConfigDetails;
10
+ }
11
+
12
+ export enum CategoryConfig {
13
+ CONFIG = "config",
14
+ }
15
+
16
+ /** Globally unique Config key for the declarative system service registry. */
17
+ export const TARGET_SYSTEM_REGISTRY_KEY = "target-system-registry";
18
+
19
+ export interface ConfigDetails {
20
+ manifestVersion: number;
21
+ /** How to resolve the Config */
22
+ loaderKey: string;
23
+ meta: unknown;
24
+ objects: Array<unknown>;
25
+ }
@@ -1,9 +1,6 @@
1
- import { scanTargetList } from "../core.api";
2
- import { generateResponse, type SupabaseResponse } from "../core.interface";
3
- import { createLogger } from "../shared/log";
4
- import { ServiceLifecycleStatus } from "./base.interface";
5
- import { getService } from "./service.api";
6
- import { CategoryService, type Service } from "./service.interface";
1
+ /**
2
+ * Service domain public API — curated re-exports only.
3
+ */
7
4
 
8
5
  export type {
9
6
  EnumMembers,
@@ -12,6 +9,63 @@ export type {
12
9
  ServiceLifecycle,
13
10
  } from "./base.interface";
14
11
  export { ServiceLifecycleStatus } from "./base.interface";
12
+ export type {
13
+ GetConfigPayload,
14
+ PostSystemRegistryConfigPayload,
15
+ ResetSystemRegistryConfigPayload,
16
+ SystemRegistrySeedSlot,
17
+ } from "./config.api";
18
+ export {
19
+ buildEmptyServiceSlots,
20
+ buildSystemRegistryConfigDetails,
21
+ DEFAULT_SYSTEM_REGISTRY_SEED_SLOTS,
22
+ getConfig,
23
+ getConfigSchema,
24
+ postSystemRegistryConfig,
25
+ postSystemRegistryConfigSchema,
26
+ resetSystemRegistryConfig,
27
+ resetSystemRegistryConfigSchema,
28
+ systemRegistrySeedSlotSchema,
29
+ } from "./config.api";
30
+ export type { Config, ConfigDetails } from "./config.interface";
31
+ export { CategoryConfig, TARGET_SYSTEM_REGISTRY_KEY } from "./config.interface";
32
+ export type {
33
+ PatchServiceRuntimeInput,
34
+ RegisterServiceInput,
35
+ ReleasedRegistrySlot,
36
+ ReleaseSystemRegistrySlotsInput,
37
+ ReleaseSystemRegistrySlotsOutcome,
38
+ TargetSystemRegistrySlotView,
39
+ TargetSystemRegistryView,
40
+ } from "./registry.service";
41
+ export {
42
+ assertRegistrySlotAvailable,
43
+ assertRegistrySlotOwner,
44
+ getTargetSystemRegistry,
45
+ parseServiceSlot,
46
+ parseServiceSlots,
47
+ patchServiceRuntime,
48
+ registerService,
49
+ registerServiceAtStartup,
50
+ releaseSystemRegistrySlots,
51
+ resolveActiveRegistryServiceId,
52
+ ServiceRegistryError,
53
+ unregisterService,
54
+ unregisterServiceAtShutdown,
55
+ } from "./registry.service";
56
+ export type {
57
+ ClaimRegistrySlotInput,
58
+ RegistrySlotGuardResult,
59
+ RegistrySlotRuntimeState,
60
+ ServiceRegistrySession,
61
+ } from "./registry-lifecycle";
62
+ export {
63
+ claimServiceRegistrySlot,
64
+ createClaimedRegistrySlotRuntimeState,
65
+ EMPTY_REGISTRY_SLOT_RUNTIME_STATE,
66
+ registrySlotRuntimePatchFromGuardResult,
67
+ runRegistrySlotGuardCheck,
68
+ } from "./registry-lifecycle";
15
69
  export type { GetApiPayload, GetServicePayload, PostApiPayload, PostServicePayload } from "./service.api";
16
70
  export {
17
71
  apiDetailsSchema,
@@ -27,147 +81,22 @@ export {
27
81
  schemaDefinitionSchema,
28
82
  serviceDetailsSchema,
29
83
  serviceLifecycleSchema,
84
+ serviceNodeSnapshotSchema,
85
+ serviceRuntimeSchema,
30
86
  } from "./service.api";
31
- export type { Api, ApiDetails, Service, ServiceDetails } from "./service.interface";
32
- export { ApiMethod, CategoryApi, CategoryService } from "./service.interface";
33
-
34
- export interface DiscoverServiceInput {
35
- /** {@link Service.value} */
36
- value: string;
37
- traceId?: string;
38
- }
39
-
40
- const DISCOVER_LIFECYCLE_STATUS = ServiceLifecycleStatus.ACTIVE;
41
- const SERVICE_LIFECYCLE_STATUS_FIELD = "details->lifecycle->>status" as const;
42
-
43
- async function lookupServicePrimary(value: string): Promise<Service | null> {
44
- const response = await getService({ value, lifecycleStatus: DISCOVER_LIFECYCLE_STATUS });
45
- return response.data ?? null;
46
- }
47
-
48
- async function lookupServiceByScan(value: string): Promise<Service | null> {
49
- const { data } = await scanTargetList<Service>({
50
- category: CategoryService.SERVICE,
51
- orderBy: { field: "value", ascending: true },
52
- maxRows: 1,
53
- filterList: [
54
- { field: "value", operator: "eq", value },
55
- {
56
- field: SERVICE_LIFECYCLE_STATUS_FIELD,
57
- operator: "eq",
58
- value: DISCOVER_LIFECYCLE_STATUS,
59
- },
60
- ],
61
- });
62
-
63
- return data?.[0] ?? null;
64
- }
65
-
66
- async function resolveDiscoverFailureReason(value: string): Promise<"not-found" | "not-available"> {
67
- const response = await getService({ value });
68
- if (response.data == null) {
69
- return "not-found";
70
- }
71
- return "not-available";
72
- }
73
-
74
- /**
75
- * Discover a single service by {@link Service.value}.
76
- * Only returns services with `lifecycle.status === ACTIVE` (filtered at query time).
77
- *
78
- * Lookup: primary `getService` → fallback `scanTargetList` by value.
79
- */
80
- export async function discoverService(input: DiscoverServiceInput): Promise<SupabaseResponse<Service>> {
81
- const value = input.value.trim();
82
- const logger = createLogger({
83
- module: "discoverService",
84
- traceId: input.traceId,
85
- labels: { serviceValue: value },
86
- });
87
-
88
- if (value === "") {
89
- const message = "discoverService: value must not be empty";
90
- logger.warn(message, { topic: "service", data: { value: input.value } });
91
- return generateResponse.error(message, undefined, "SERVICE_VALUE_REQUIRED") as SupabaseResponse<Service>;
92
- }
93
-
94
- try {
95
- logger.info("开始发现服务", {
96
- topic: "service",
97
- data: { value, lifecycleStatus: DISCOVER_LIFECYCLE_STATUS },
98
- });
99
-
100
- let service = await lookupServicePrimary(value);
101
- let source: "primary" | "scan" = "primary";
102
-
103
- if (service == null) {
104
- logger.warn("主路径未命中,尝试 catalog 扫描回退", {
105
- topic: "service",
106
- data: { value, step: "scan-fallback", lifecycleStatus: DISCOVER_LIFECYCLE_STATUS },
107
- });
108
- service = await lookupServiceByScan(value);
109
- source = "scan";
110
- }
111
-
112
- if (service == null) {
113
- const reason = await resolveDiscoverFailureReason(value);
114
- if (reason === "not-available") {
115
- const message = `Service ${value} is not available (lifecycle is not ACTIVE)`;
116
- logger.warn("服务已注册但不可用", {
117
- topic: "service",
118
- data: { value, step: "not-available", lifecycleStatus: DISCOVER_LIFECYCLE_STATUS },
119
- });
120
- return generateResponse.error(message, undefined, "SERVICE_NOT_AVAILABLE") as SupabaseResponse<Service>;
121
- }
122
-
123
- const message = `Service not found: ${value}`;
124
- logger.error("服务未发现", {
125
- topic: "service",
126
- data: { value, step: "not-found", tried: ["primary", "scan"] },
127
- });
128
- return generateResponse.error(message, undefined, "SERVICE_NOT_FOUND") as SupabaseResponse<Service>;
129
- }
130
-
131
- logger.info("服务发现成功", {
132
- topic: "service",
133
- data: {
134
- value,
135
- source,
136
- serviceId: service.id,
137
- lifecycleStatus: service.details.lifecycle.status,
138
- apiKeyCount: service.details.apiKeys.length,
139
- dependencyCount: service.details.dependencies.length,
140
- },
141
- });
142
-
143
- return generateResponse.success(service);
144
- } catch (error) {
145
- const message = error instanceof Error ? error.message : String(error);
146
- logger.error("服务发现失败", {
147
- topic: "service",
148
- data: { value, message },
149
- });
150
-
151
- let service: Service | null = null;
152
- try {
153
- service = await lookupServiceByScan(value);
154
- } catch (fallbackError) {
155
- const fallbackMessage = fallbackError instanceof Error ? fallbackError.message : String(fallbackError);
156
- logger.error("扫描回退失败", {
157
- topic: "service",
158
- data: { value, message: fallbackMessage },
159
- });
160
- return generateResponse.error(message, undefined, "SERVICE_DISCOVER_FAILED") as SupabaseResponse<Service>;
161
- }
162
-
163
- if (service != null) {
164
- logger.warn("主路径异常后扫描回退成功", {
165
- topic: "service",
166
- data: { value, serviceId: service.id, primaryError: message },
167
- });
168
- return generateResponse.success(service);
169
- }
170
-
171
- return generateResponse.error(message, undefined, "SERVICE_DISCOVER_FAILED") as SupabaseResponse<Service>;
172
- }
173
- }
87
+ export type {
88
+ Api,
89
+ ApiDetails,
90
+ Service,
91
+ ServiceDetails,
92
+ ServiceNodeSnapshot,
93
+ ServiceRuntime,
94
+ ServiceSlot,
95
+ } from "./service.interface";
96
+ export { ApiMethod, CategoryApi, CategoryService, ServiceSlotStatus } from "./service.interface";
97
+ export type { PostServiceInstanceOptions, ServiceBootstrapResult } from "./service-bootstrap";
98
+ export {
99
+ createActiveServiceLifecycle,
100
+ defaultL3ServiceDetails,
101
+ postServiceInstance,
102
+ } from "./service-bootstrap";