target-supabase-sdk 0.2.12 → 0.2.14

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 (197) hide show
  1. package/dist/browser.d.ts +1 -1
  2. package/dist/browser.d.ts.map +1 -1
  3. package/dist/browser.js +1 -1
  4. package/dist/chunks/enable-C7lFooTG.js +874 -0
  5. package/dist/chunks/enable-C7lFooTG.js.map +1 -0
  6. package/dist/chunks/list.api-BzbTJBsM.js.map +1 -1
  7. package/dist/chunks/{task-queue-H4mpSW8R.js → task-queue-qSnsfiIg.js} +111 -4
  8. package/dist/chunks/task-queue-qSnsfiIg.js.map +1 -0
  9. package/dist/node/env/index.d.ts +1 -1
  10. package/dist/node/env/index.d.ts.map +1 -1
  11. package/dist/node/node-runtime.base.d.ts +14 -1
  12. package/dist/node/node-runtime.base.d.ts.map +1 -1
  13. package/dist/node/node.api.d.ts.map +1 -1
  14. package/dist/node/node.constant.d.ts +3 -0
  15. package/dist/node/node.constant.d.ts.map +1 -0
  16. package/dist/node/node.utils.d.ts +0 -2
  17. package/dist/node/node.utils.d.ts.map +1 -1
  18. package/dist/node/preload/run-service-preload.d.ts.map +1 -1
  19. package/dist/node/preload/service-preload.interface.d.ts +3 -1
  20. package/dist/node/preload/service-preload.interface.d.ts.map +1 -1
  21. package/dist/node/process/managed-child-processes.d.ts.map +1 -1
  22. package/dist/node/readiness/index.d.ts +2 -0
  23. package/dist/node/readiness/index.d.ts.map +1 -1
  24. package/dist/node/{service-guard → readiness}/run-readiness-gate.d.ts +1 -1
  25. package/dist/node/readiness/run-readiness-gate.d.ts.map +1 -0
  26. package/dist/node/readiness/service-ready-gate.d.ts.map +1 -1
  27. package/dist/node/runtime-state/create-service-runtime-state-store.d.ts.map +1 -1
  28. package/dist/node/runtime-state/service-runtime-state.types.d.ts +16 -0
  29. package/dist/node/runtime-state/service-runtime-state.types.d.ts.map +1 -1
  30. package/dist/node/service-guard/index.d.ts +4 -4
  31. package/dist/node/service-guard/index.d.ts.map +1 -1
  32. package/dist/node/service-guard/register-service-guard-runner.d.ts +1 -2
  33. package/dist/node/service-guard/register-service-guard-runner.d.ts.map +1 -1
  34. package/dist/node/service-guard/registry-slot-guard-step.d.ts.map +1 -0
  35. package/dist/node/service-guard/run-service-guard-tick.d.ts.map +1 -1
  36. package/dist/node/service-guard/service-guard-node.d.ts +25 -2
  37. package/dist/node/service-guard/service-guard-node.d.ts.map +1 -1
  38. package/dist/node/service-guard/service-guard.interface.d.ts +25 -10
  39. package/dist/node/service-guard/service-guard.interface.d.ts.map +1 -1
  40. package/dist/node/service-host/claim-registry-slot.d.ts +15 -0
  41. package/dist/node/service-host/claim-registry-slot.d.ts.map +1 -0
  42. package/dist/node/service-host/create-l3-child-launcher.d.ts +38 -0
  43. package/dist/node/service-host/create-l3-child-launcher.d.ts.map +1 -0
  44. package/dist/node/service-host/index.d.ts +2 -4
  45. package/dist/node/service-host/index.d.ts.map +1 -1
  46. package/dist/node/service-host/service-host.d.ts +8 -4
  47. package/dist/node/service-host/service-host.d.ts.map +1 -1
  48. package/dist/node/service-host/single-process-service.d.ts +3 -3
  49. package/dist/node/service-host/single-process-service.d.ts.map +1 -1
  50. package/dist/node.d.ts +17 -10
  51. package/dist/node.d.ts.map +1 -1
  52. package/dist/node.js +927 -119
  53. package/dist/node.js.map +1 -1
  54. package/dist/preload.js +9 -6
  55. package/dist/preload.js.map +1 -1
  56. package/dist/service/index.d.ts +2 -2
  57. package/dist/service/index.d.ts.map +1 -1
  58. package/dist/service/registry.service.d.ts +19 -0
  59. package/dist/service/registry.service.d.ts.map +1 -1
  60. package/dist/shared/log/core/create-logger.d.ts.map +1 -0
  61. package/dist/shared/log/{log-batch.d.ts → core/log-batch.d.ts} +4 -4
  62. package/dist/shared/log/core/log-batch.d.ts.map +1 -0
  63. package/dist/shared/log/core/log-manager.d.ts.map +1 -0
  64. package/dist/shared/log/core/log-min-level.d.ts.map +1 -0
  65. package/dist/shared/log/core/log-scope.d.ts.map +1 -0
  66. package/dist/shared/log/index.d.ts +13 -13
  67. package/dist/shared/log/index.d.ts.map +1 -1
  68. package/dist/shared/log/spool/collector.d.ts +21 -0
  69. package/dist/shared/log/spool/collector.d.ts.map +1 -0
  70. package/dist/shared/log/spool/config.d.ts +7 -0
  71. package/dist/shared/log/spool/config.d.ts.map +1 -0
  72. package/dist/shared/log/spool/coordinator.d.ts +18 -0
  73. package/dist/shared/log/spool/coordinator.d.ts.map +1 -0
  74. package/dist/shared/log/spool/enable.d.ts +23 -0
  75. package/dist/shared/log/spool/enable.d.ts.map +1 -0
  76. package/dist/shared/log/spool/file.d.ts +21 -0
  77. package/dist/shared/log/spool/file.d.ts.map +1 -0
  78. package/dist/shared/log/spool/interface.d.ts +55 -0
  79. package/dist/shared/log/spool/interface.d.ts.map +1 -0
  80. package/dist/shared/log/spool/paths.d.ts +6 -0
  81. package/dist/shared/log/spool/paths.d.ts.map +1 -0
  82. package/dist/shared/log/spool/process-roles.d.ts +17 -0
  83. package/dist/shared/log/spool/process-roles.d.ts.map +1 -0
  84. package/dist/shared/log/spool/register-collect-log-runner.d.ts +15 -0
  85. package/dist/shared/log/spool/register-collect-log-runner.d.ts.map +1 -0
  86. package/dist/shared/log/spool/service-lifecycle.d.ts +13 -0
  87. package/dist/shared/log/spool/service-lifecycle.d.ts.map +1 -0
  88. package/dist/shared/log/spool/writer.d.ts +32 -0
  89. package/dist/shared/log/spool/writer.d.ts.map +1 -0
  90. package/dist/shared/log/{log-persist-batch-id.d.ts → upload/batch-id.d.ts} +3 -3
  91. package/dist/shared/log/upload/batch-id.d.ts.map +1 -0
  92. package/dist/shared/log/upload/env.d.ts +7 -0
  93. package/dist/shared/log/upload/env.d.ts.map +1 -0
  94. package/dist/shared/log/{log-persist-flush.d.ts → upload/flush.d.ts} +3 -3
  95. package/dist/shared/log/upload/flush.d.ts.map +1 -0
  96. package/dist/shared/log/{log-persist-hook.d.ts → upload/hook.d.ts} +2 -2
  97. package/dist/shared/log/upload/hook.d.ts.map +1 -0
  98. package/dist/shared/log/upload/interface.d.ts +33 -0
  99. package/dist/shared/log/upload/interface.d.ts.map +1 -0
  100. package/dist/shared/log/upload/logger.d.ts +22 -0
  101. package/dist/shared/log/upload/logger.d.ts.map +1 -0
  102. package/package.json +1 -1
  103. package/src/browser.ts +1 -0
  104. package/src/node/env/index.ts +0 -4
  105. package/src/node/node-runtime.base.ts +33 -5
  106. package/src/node/node.api.ts +1 -1
  107. package/src/node/node.constant.ts +2 -0
  108. package/src/node/node.utils.ts +2 -2
  109. package/src/node/preload/run-service-preload.ts +11 -6
  110. package/src/node/preload/service-preload.interface.ts +3 -1
  111. package/src/node/process/create-managed-child-processes.ts +1 -1
  112. package/src/node/process/managed-child-processes.ts +8 -1
  113. package/src/node/readiness/index.ts +2 -0
  114. package/src/node/{service-guard → readiness}/run-readiness-gate.ts +2 -2
  115. package/src/node/readiness/service-ready-gate.ts +27 -23
  116. package/src/node/runtime-state/create-service-runtime-state-store.ts +11 -0
  117. package/src/node/runtime-state/service-runtime-state.types.ts +12 -0
  118. package/src/node/service-guard/index.ts +7 -8
  119. package/src/node/service-guard/register-service-guard-runner.ts +0 -2
  120. package/src/node/service-guard/run-service-guard-tick.ts +5 -2
  121. package/src/node/service-guard/service-guard-node.ts +234 -6
  122. package/src/node/service-guard/service-guard.interface.ts +35 -10
  123. package/src/node/service-host/claim-registry-slot.ts +33 -0
  124. package/src/node/service-host/create-l3-child-launcher.ts +157 -0
  125. package/src/node/service-host/index.ts +5 -20
  126. package/src/node/service-host/service-host.ts +33 -21
  127. package/src/node/service-host/single-process-service.ts +10 -20
  128. package/src/node.ts +45 -35
  129. package/src/service/index.ts +3 -0
  130. package/src/service/registry.service.ts +142 -0
  131. package/src/shared/log/README.md +206 -0
  132. package/src/shared/log/{log-batch.ts → core/log-batch.ts} +4 -4
  133. package/src/shared/log/{log-manager.ts → core/log-manager.ts} +3 -3
  134. package/src/shared/log/{log-min-level.ts → core/log-min-level.ts} +1 -1
  135. package/src/shared/log/{log-scope.ts → core/log-scope.ts} +1 -1
  136. package/src/shared/log/index.ts +13 -18
  137. package/src/shared/log/spool/collector.ts +330 -0
  138. package/src/shared/log/spool/config.ts +56 -0
  139. package/src/shared/log/spool/coordinator.ts +55 -0
  140. package/src/shared/log/spool/enable.ts +136 -0
  141. package/src/shared/log/spool/file.ts +75 -0
  142. package/src/shared/log/spool/interface.ts +62 -0
  143. package/src/shared/log/spool/paths.ts +30 -0
  144. package/src/shared/log/spool/process-roles.ts +75 -0
  145. package/src/shared/log/spool/register-collect-log-runner.ts +63 -0
  146. package/src/shared/log/spool/service-lifecycle.ts +35 -0
  147. package/src/shared/log/spool/writer.ts +273 -0
  148. package/src/shared/log/{log-persist-batch-id.ts → upload/batch-id.ts} +2 -2
  149. package/src/shared/log/upload/env.ts +26 -0
  150. package/src/shared/log/{log-persist-flush.ts → upload/flush.ts} +8 -7
  151. package/src/shared/log/{log-persist-hook.ts → upload/hook.ts} +1 -1
  152. package/src/shared/log/upload/interface.ts +38 -0
  153. package/src/shared/log/upload/logger.ts +37 -0
  154. package/dist/chunks/enable-log-persist-Dl55_mv2.js +0 -1674
  155. package/dist/chunks/enable-log-persist-Dl55_mv2.js.map +0 -1
  156. package/dist/chunks/task-queue-H4mpSW8R.js.map +0 -1
  157. package/dist/node/service-guard/run-readiness-gate.d.ts.map +0 -1
  158. package/dist/node/service-host/registry-slot-guard-step.d.ts.map +0 -1
  159. package/dist/shared/log/create-logger.d.ts.map +0 -1
  160. package/dist/shared/log/enable-log-persist.d.ts +0 -28
  161. package/dist/shared/log/enable-log-persist.d.ts.map +0 -1
  162. package/dist/shared/log/log-batch.d.ts.map +0 -1
  163. package/dist/shared/log/log-manager.d.ts.map +0 -1
  164. package/dist/shared/log/log-min-level.d.ts.map +0 -1
  165. package/dist/shared/log/log-persist-batch-id.d.ts.map +0 -1
  166. package/dist/shared/log/log-persist-coordinator.d.ts +0 -37
  167. package/dist/shared/log/log-persist-coordinator.d.ts.map +0 -1
  168. package/dist/shared/log/log-persist-errors.d.ts +0 -4
  169. package/dist/shared/log/log-persist-errors.d.ts.map +0 -1
  170. package/dist/shared/log/log-persist-flush.d.ts.map +0 -1
  171. package/dist/shared/log/log-persist-hook.d.ts.map +0 -1
  172. package/dist/shared/log/log-persist-logger.d.ts +0 -16
  173. package/dist/shared/log/log-persist-logger.d.ts.map +0 -1
  174. package/dist/shared/log/log-persist-registry.d.ts +0 -18
  175. package/dist/shared/log/log-persist-registry.d.ts.map +0 -1
  176. package/dist/shared/log/log-persist.config.d.ts +0 -9
  177. package/dist/shared/log/log-persist.config.d.ts.map +0 -1
  178. package/dist/shared/log/log-persist.d.ts +0 -62
  179. package/dist/shared/log/log-persist.d.ts.map +0 -1
  180. package/dist/shared/log/log-persist.interface.d.ts +0 -132
  181. package/dist/shared/log/log-persist.interface.d.ts.map +0 -1
  182. package/dist/shared/log/log-scope.d.ts.map +0 -1
  183. package/src/shared/log/enable-log-persist.ts +0 -225
  184. package/src/shared/log/log-persist-coordinator.ts +0 -107
  185. package/src/shared/log/log-persist-errors.ts +0 -16
  186. package/src/shared/log/log-persist-logger.ts +0 -61
  187. package/src/shared/log/log-persist-registry.ts +0 -252
  188. package/src/shared/log/log-persist.config.ts +0 -115
  189. package/src/shared/log/log-persist.interface.ts +0 -150
  190. package/src/shared/log/log-persist.ts +0 -822
  191. /package/dist/node/{service-host → service-guard}/registry-slot-guard-step.d.ts +0 -0
  192. /package/dist/shared/log/{create-logger.d.ts → core/create-logger.d.ts} +0 -0
  193. /package/dist/shared/log/{log-manager.d.ts → core/log-manager.d.ts} +0 -0
  194. /package/dist/shared/log/{log-min-level.d.ts → core/log-min-level.d.ts} +0 -0
  195. /package/dist/shared/log/{log-scope.d.ts → core/log-scope.d.ts} +0 -0
  196. /package/src/node/{service-host → service-guard}/registry-slot-guard-step.ts +0 -0
  197. /package/src/shared/log/{create-logger.ts → core/create-logger.ts} +0 -0
@@ -1,6 +1,7 @@
1
- import { createLogger, type Service, ServiceRegistryError } from "../../browser";
2
- import { claimServiceRegistrySlot, type ServiceRegistrySession } from "../../service/registry-lifecycle";
3
- import type { LoggerWithScope } from "../../shared/log";
1
+ import type { ServiceRegistrySession } from "../../service/registry-lifecycle";
2
+ import type { Service } from "../../service/service.interface";
3
+ import { createLogger, type LoggerWithScope } from "../../shared/log";
4
+ import { claimRegistrySlotOrExit } from "./claim-registry-slot";
4
5
 
5
6
  export interface SingleProcessServiceContext {
6
7
  service: Service;
@@ -29,23 +30,12 @@ export async function runSingleProcessService(options: SingleProcessServiceOptio
29
30
  await options.prepare();
30
31
  }
31
32
 
32
- let session: ServiceRegistrySession | null = null;
33
-
34
- try {
35
- session = await claimServiceRegistrySlot({
36
- serviceValue: options.serviceValue,
37
- createInstance: options.createInstance,
38
- });
39
- } catch (error) {
40
- if (error instanceof ServiceRegistryError && error.code === "SERVICE_SLOTS_FULL") {
41
- logger.critical("No EMPTY registry slot — refusing to start", {
42
- topic: logTopic,
43
- data: { serviceValue: options.serviceValue, code: error.code },
44
- });
45
- process.exit(1);
46
- }
47
- throw error;
48
- }
33
+ const session = await claimRegistrySlotOrExit({
34
+ serviceValue: options.serviceValue,
35
+ createInstance: options.createInstance,
36
+ logger,
37
+ logTopic,
38
+ });
49
39
 
50
40
  try {
51
41
  await options.run({ service: session.service, session });
package/src/node.ts CHANGED
@@ -25,9 +25,6 @@ export {
25
25
  envProfileFromProcess,
26
26
  initSupabaseFromStandardEnv,
27
27
  loadEnvFiles,
28
- parseEnvFile,
29
- parseEnvLine,
30
- pinEnvProfileFromArgv,
31
28
  publicBaseUrlFromEnv,
32
29
  readEnv,
33
30
  requireEnv,
@@ -77,6 +74,7 @@ export type {
77
74
  ReadinessCheckResult,
78
75
  ReadinessReport,
79
76
  RequiredEnvCheckOptions,
77
+ RunReadinessGateInput,
80
78
  ServiceReadyGate,
81
79
  ServiceReadySnapshot,
82
80
  SupabaseReachableCheckOptions,
@@ -88,6 +86,7 @@ export {
88
86
  createSupabaseReachableCheck,
89
87
  pollUntil,
90
88
  runReadinessChecks,
89
+ runReadinessGate,
91
90
  waitForServiceReady,
92
91
  } from "./node/readiness";
93
92
  export type {
@@ -109,51 +108,63 @@ export type {
109
108
  ApplyRegistrySlotGuardInput,
110
109
  ApplyRegistrySlotGuardResult,
111
110
  RegisterServiceGuardRunnerOptions,
112
- RunReadinessGateInput,
113
111
  ServiceGuardNodeOptions,
114
112
  ServiceGuardTickInput,
115
113
  ServiceGuardTickResult,
116
- ServiceHost,
117
- ServiceHostClosable,
118
- ServiceHostContext,
119
- ServiceHostOptions,
120
- SingleProcessServiceContext,
121
- SingleProcessServiceOptions,
122
- } from "./node/service-host";
114
+ } from "./node/service-guard";
123
115
  export {
124
116
  applyRegistrySlotGuardStep,
125
- createServiceHost,
126
- getWorkerSpawnCooldownLastAt,
117
+ guardRetryAfterSec,
118
+ isGuardAvailable,
127
119
  markWorkerSpawned,
128
120
  registerServiceGuardRunner,
129
- runReadinessGate,
130
121
  runServiceGuardTick,
131
- runSingleProcessService,
132
122
  SERVICE_GUARD_RUNNER_KEY,
133
123
  ServiceGuardNode,
124
+ } from "./node/service-guard";
125
+ export type {
126
+ CreateL3ChildLauncherOptions,
127
+ L3ChildLauncher,
128
+ L3ChildLauncherRuntimeStore,
129
+ ServiceHost,
130
+ ServiceHostClosable,
131
+ ServiceHostContext,
132
+ ServiceHostOptions,
133
+ SingleProcessServiceContext,
134
+ SingleProcessServiceOptions,
134
135
  } from "./node/service-host";
136
+ export { createL3ChildLauncher, createServiceHost, runSingleProcessService } from "./node/service-host";
135
137
  export { RepoManager } from "./repo/repo-manager";
138
+ export { runCollectLogTick } from "./shared/log/spool/collector";
139
+ export { LOG_SPOOL_SERVICE_ID_ENV } from "./shared/log/spool/config";
140
+ export type { LogSpoolCoordinator, LogSpoolCoordinatorOptions } from "./shared/log/spool/coordinator";
141
+ export { createLogSpoolCoordinator } from "./shared/log/spool/coordinator";
136
142
  export {
137
- disableLogPersist,
138
- enableLogPersist,
139
- ensureLogPersistFromEnv,
140
- getLogPersistStats,
141
- logPersistEnabledFromEnv,
142
- resolveLogPersistRegistryPath,
143
- snapshotLogPersistReady,
144
- validateLogPersistPreloadEnv,
145
- waitForLogPersistReady,
146
- } from "./shared/log/enable-log-persist";
143
+ buildLogSpoolSpawnEnv,
144
+ ensureLogSpoolFromEnv,
145
+ getLogSpoolStats,
146
+ logSpoolEnabledFromEnv,
147
+ shutdownLogSpoolFromEnv,
148
+ validateLogSpoolPreloadEnv,
149
+ } from "./shared/log/spool/enable";
147
150
  export type {
148
- EnableLogPersistOptions,
149
- EnsureLogPersistFromEnvOptions,
150
- LogPersistLane,
151
- LogPersistReadySnapshot,
152
- LogPersistStats,
153
- WaitForLogPersistReadyOptions,
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";
151
+ EnableLogSpoolOptions,
152
+ LogSpoolCoreProcessRole,
153
+ LogSpoolProcessRole,
154
+ LogSpoolWriterStats,
155
+ } from "./shared/log/spool/interface";
156
+ export { resolveLogSpoolRoot } from "./shared/log/spool/paths";
157
+ export {
158
+ COLLECT_LOG_RUNNER_KEY,
159
+ registerCollectLogRunner,
160
+ } from "./shared/log/spool/register-collect-log-runner";
161
+ export {
162
+ enableLogSpoolFromEnvInChild,
163
+ getMainLogSpoolWriterStats,
164
+ isLogSpoolEnabled,
165
+ shutdownLogSpool,
166
+ } from "./shared/log/spool/service-lifecycle";
167
+ export type { LogBatchMeta, LogPersistLane } from "./shared/log/upload/interface";
157
168
  export type {
158
169
  ConfigSchema,
159
170
  LoadCachedJsConfigOptions,
@@ -170,7 +181,6 @@ export {
170
181
  resolvePathFromCwd,
171
182
  toFileImportHref,
172
183
  } from "./shared/utils/config-path.utils";
173
- export { getValueAtPath } from "./shared/utils/get-value-at-path";
174
184
  export type {
175
185
  BootstrapLocalTasksResult,
176
186
  BootstrapLocalTasksStatus,
@@ -35,6 +35,8 @@ export type {
35
35
  PatchServiceRuntimeInput,
36
36
  RegisterServiceInput,
37
37
  ReleasedRegistrySlot,
38
+ ReleaseSystemRegistrySlotsByServiceIdInput,
39
+ ReleaseSystemRegistrySlotsByServiceIdOutcome,
38
40
  ReleaseSystemRegistrySlotsInput,
39
41
  ReleaseSystemRegistrySlotsOutcome,
40
42
  TargetSystemRegistrySlotView,
@@ -51,6 +53,7 @@ export {
51
53
  registerService,
52
54
  registerServiceAtStartup,
53
55
  releaseSystemRegistrySlots,
56
+ releaseSystemRegistrySlotsByServiceId,
54
57
  resolveActiveRegistryServiceId,
55
58
  ServiceRegistryError,
56
59
  unregisterService,
@@ -58,6 +58,13 @@ export interface ReleaseSystemRegistrySlotsInput {
58
58
  maxAttempts?: number;
59
59
  }
60
60
 
61
+ export interface ReleaseSystemRegistrySlotsByServiceIdInput {
62
+ /** Runtime Service row ids bound to ACTIVE slots (one slot per id). */
63
+ serviceIds: string[];
64
+ traceId?: string;
65
+ maxAttempts?: number;
66
+ }
67
+
61
68
  export interface ReleasedRegistrySlot {
62
69
  serviceValue: string;
63
70
  serviceId: string;
@@ -71,6 +78,13 @@ export interface ReleaseSystemRegistrySlotsOutcome {
71
78
  unchangedServiceValues: string[];
72
79
  }
73
80
 
81
+ export interface ReleaseSystemRegistrySlotsByServiceIdOutcome {
82
+ config: Config;
83
+ released: ReleasedRegistrySlot[];
84
+ /** Requested `serviceIds` with no ACTIVE slot released (unknown id, already EMPTY, or never bound). */
85
+ unchangedServiceIds: string[];
86
+ }
87
+
74
88
  export interface AppendSystemRegistrySlotsInput {
75
89
  /** Logical service keys to declare with one new EMPTY slot each when missing. */
76
90
  serviceValues: string[];
@@ -365,6 +379,34 @@ function releaseActiveSlotsForServiceValues(
365
379
  return { nextSlots, released };
366
380
  }
367
381
 
382
+ function releaseActiveSlotsForServiceIds(
383
+ slots: ServiceSlot[],
384
+ serviceIdSet: ReadonlySet<string>,
385
+ ): { nextSlots: ServiceSlot[]; released: ReleasedRegistrySlot[] } {
386
+ const nextSlots = [...slots];
387
+ const released: ReleasedRegistrySlot[] = [];
388
+
389
+ for (let slotIndex = 0; slotIndex < nextSlots.length; slotIndex += 1) {
390
+ const slot = nextSlots[slotIndex];
391
+ if (slot.serviceId == null || !serviceIdSet.has(slot.serviceId) || slot.status !== ServiceSlotStatus.ACTIVE) {
392
+ continue;
393
+ }
394
+
395
+ released.push({
396
+ serviceValue: slot.serviceValue,
397
+ serviceId: slot.serviceId,
398
+ slotIndex,
399
+ });
400
+ nextSlots[slotIndex] = {
401
+ ...slot,
402
+ serviceId: null,
403
+ status: ServiceSlotStatus.EMPTY,
404
+ };
405
+ }
406
+
407
+ return { nextSlots, released };
408
+ }
409
+
368
410
  /**
369
411
  * Force-release ACTIVE registry slots for the given logical service keys (`ACTIVE → EMPTY`).
370
412
  * Ops/dev recovery when a process crashed without {@link unregisterService}.
@@ -475,6 +517,106 @@ export async function releaseSystemRegistrySlots(
475
517
  );
476
518
  }
477
519
 
520
+ /**
521
+ * Force-release ACTIVE registry slots for the given runtime Service row ids (`ACTIVE → EMPTY`).
522
+ * Targets one slot per `serviceId` — use when multiple slots share the same `serviceValue`.
523
+ * Ops/dev recovery when a process crashed without {@link unregisterService}.
524
+ * Does not delete Service rows or mutate `details.runtime`.
525
+ */
526
+ export async function releaseSystemRegistrySlotsByServiceId(
527
+ input: ReleaseSystemRegistrySlotsByServiceIdInput,
528
+ ): Promise<ReleaseSystemRegistrySlotsByServiceIdOutcome> {
529
+ const serviceIds = [...new Set(input.serviceIds.map((value) => value.trim()).filter((value) => value !== ""))];
530
+ if (serviceIds.length === 0) {
531
+ throw new Error("[releaseSystemRegistrySlotsByServiceId] serviceIds must not be empty");
532
+ }
533
+
534
+ const serviceIdSet = new Set(serviceIds);
535
+ const maxAttempts = input.maxAttempts ?? DEFAULT_REGISTER_RETRY_ATTEMPTS;
536
+ const logger = createLogger({
537
+ module: "releaseSystemRegistrySlotsByServiceId",
538
+ traceId: input.traceId,
539
+ labels: { serviceIds: serviceIds.join(",") },
540
+ });
541
+
542
+ logger.info("开始按 serviceId 强制释放 registry 槽位", {
543
+ topic: LOG_TOPIC_REGISTRY,
544
+ data: { serviceIds },
545
+ });
546
+
547
+ for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
548
+ try {
549
+ const config = await loadSystemRegistryConfig();
550
+ const revision = parseRegistryRevision(config.details.meta);
551
+ const slots = parseServiceSlots(config);
552
+
553
+ const { nextSlots, released } = releaseActiveSlotsForServiceIds(slots, serviceIdSet);
554
+ const releasedIdSet = new Set(released.map((entry) => entry.serviceId));
555
+ const unchangedServiceIds = serviceIds.filter((serviceId) => !releasedIdSet.has(serviceId));
556
+
557
+ if (released.length === 0) {
558
+ logger.info("无 ACTIVE 槽位需要释放", {
559
+ topic: LOG_TOPIC_REGISTRY,
560
+ data: { serviceIds, attempt },
561
+ });
562
+ return { config, released, unchangedServiceIds: serviceIds };
563
+ }
564
+
565
+ await persistSlotClaim({
566
+ configId: config.id,
567
+ revision,
568
+ slots: nextSlots,
569
+ });
570
+
571
+ const updated = await loadSystemRegistryConfig();
572
+ logger.info("槽位强制释放成功", {
573
+ topic: LOG_TOPIC_REGISTRY,
574
+ data: {
575
+ released,
576
+ unchangedServiceIds,
577
+ attempt,
578
+ revision: revision + 1,
579
+ },
580
+ });
581
+
582
+ return {
583
+ config: updated,
584
+ released,
585
+ unchangedServiceIds,
586
+ };
587
+ } catch (error) {
588
+ if (error instanceof ServiceRegistryError) {
589
+ logger.error("槽位强制释放被拒绝", {
590
+ topic: LOG_TOPIC_REGISTRY,
591
+ data: { serviceIds, code: error.code, message: error.message },
592
+ });
593
+ throw error;
594
+ }
595
+
596
+ if (isOptimisticLockError(error) && attempt < maxAttempts) {
597
+ logger.warn("registry 乐观锁冲突,重试", {
598
+ topic: LOG_TOPIC_REGISTRY,
599
+ data: { serviceIds, attempt, maxAttempts },
600
+ });
601
+ await sleep(50 * attempt);
602
+ continue;
603
+ }
604
+
605
+ const message = error instanceof Error ? error.message : String(error);
606
+ logger.error("槽位强制释放失败", {
607
+ topic: LOG_TOPIC_REGISTRY,
608
+ data: { serviceIds, attempt, message },
609
+ });
610
+ throw new ServiceRegistryError(message, "REGISTRY_UPDATE_FAILED");
611
+ }
612
+ }
613
+
614
+ throw new ServiceRegistryError(
615
+ "[releaseSystemRegistrySlotsByServiceId] Optimistic lock retries exhausted",
616
+ "REGISTRY_UPDATE_FAILED",
617
+ );
618
+ }
619
+
478
620
  /**
479
621
  * Append EMPTY {@link ServiceSlot} rows for logical service keys not yet declared.
480
622
  * Idempotent — skips keys that already appear in `details.objects`.
@@ -0,0 +1,206 @@
1
+ # Log module (`src/shared/log`)
2
+
3
+ Structured logging, optional file-backed persistence, and Supabase `LogBatch` upload for L3 services.
4
+
5
+ ## Layout
6
+
7
+ ```text
8
+ src/shared/log/
9
+ README.md
10
+ index.ts # browser-safe public API (re-exports core + upload types)
11
+
12
+ core/ # in-process logging (browser + Node)
13
+ log-manager.ts # LogManager singleton, LogEntry, levels
14
+ create-logger.ts # createLogger({ module, scope, … })
15
+ log-scope.ts # traceId / labels / patchScope
16
+ log-min-level.ts # LOG_MIN_LEVEL env
17
+ log-batch.ts # decode persisted LogBatch Lists (read side)
18
+
19
+ upload/ # shared Supabase upload pipeline (Node)
20
+ env.ts # LOG_PERSIST_ENABLED, SERVICE, PROCESS, runtime dir
21
+ interface.ts # LogBatch meta, loader keys, lane type
22
+ batch-id.ts # computeLogBatchIdempotencyKey
23
+ flush.ts # buildLogListDraft, postLogBatch
24
+ hook.ts # LogManager → spool writer offer bridge
25
+ logger.ts # internal pipeline loggers (no feedback loop)
26
+
27
+ spool/ # file-backed persistence (Node only)
28
+ enable.ts # ensureLogSpoolFromEnv, spawn env helpers
29
+ service-lifecycle.ts # isLogSpoolEnabled, enableLogSpoolFromEnvInChild, shutdownLogSpool
30
+ writer.ts # per-process memory buffer → .tmp files
31
+ collector.ts # guard: upload .tmp, rename .json, periodic GC
32
+ paths.ts # {RUNTIME_DATA_DIR}/log-spool/{serviceId}/…
33
+ file.ts # batch filename parse/build
34
+ process-roles.ts # main|guard|scheduler|worker + extras
35
+ config.ts # writer / GC / collect interval env
36
+ coordinator.ts # createLogSpoolCoordinator facade
37
+ register-collect-log-runner.ts
38
+ ```
39
+
40
+ **Package exports**
41
+
42
+ | Entry | Scope |
43
+ |-------|--------|
44
+ | `target-supabase-sdk` / `index.ts` | `core/` + decode types from `upload/interface` |
45
+ | `target-supabase-sdk/node` | spool + upload symbols used by L3 services |
46
+
47
+ Node-only code must not be imported from the browser bundle. Spool files use `node:fs`.
48
+
49
+ ---
50
+
51
+ ## Data flow
52
+
53
+ ```text
54
+ App code
55
+ → createLogger / logManager
56
+ → offerToLogPersist (when spool enabled)
57
+ → LogSpoolWriter (memory buffer)
58
+ → {spoolRoot}/{serviceId}/{role}/*.tmp
59
+
60
+ Guard collect-log runner (1 min tick)
61
+ → read *.tmp → postLogBatch → rename *.json
62
+ → GC old tmp/json (once per day; 7 d retention)
63
+
64
+ log-service (downstream)
65
+ → decodeLogBatch / LogTrace merge by traceId
66
+ ```
67
+
68
+ **One-line rule:** producers flush `LogEntry[]` to `.tmp`; only the guard uploads `LogBatch` and renames to `.json`.
69
+
70
+ ---
71
+
72
+ ## Environment
73
+
74
+ | Key | Role |
75
+ |-----|------|
76
+ | `LOG_PERSIST_ENABLED` | Master switch (`true` → file spool) |
77
+ | `LOG_PERSIST_SERVICE` | Logical service value in List meta (e.g. `watch-service`) |
78
+ | `LOG_PERSIST_PROCESS` | This process role: `main` \| `guard` \| `scheduler` \| `worker` or extra |
79
+ | `LOG_SPOOL_SERVICE_ID` | Instance id — set by main after registry claim |
80
+ | `LOG_SPOOL_EXTRA_PROCESS_ROLES` | Comma-separated extras (e.g. `chrome-sidecar`) |
81
+ | `RUNTIME_DATA_DIR` | Runtime root; spool lives at `{dir}/log-spool/` |
82
+ | `LOG_SPOOL_DIR` | Optional override for spool root parent |
83
+
84
+ ### Writer tuning
85
+
86
+ | Key | Default |
87
+ |-----|---------|
88
+ | `LOG_SPOOL_MAX_ENTRIES` | 2000 |
89
+ | `LOG_SPOOL_MAX_BYTES` | 2 MB |
90
+ | `LOG_SPOOL_FLUSH_DEBOUNCE_MS` | 3 s (after count/byte threshold) |
91
+ | `LOG_SPOOL_MAX_AGE_MS` | 60 s (flush buffered logs even when below threshold) |
92
+ | `LOG_PERSIST_POST_TIMEOUT_MS` | 30 s |
93
+
94
+ ### Collector / GC
95
+
96
+ | Key | Default |
97
+ |-----|---------|
98
+ | `LOG_SPOOL_COLLECT_INTERVAL_MS` | 60 s |
99
+ | `LOG_SPOOL_GC_INTERVAL_MS` | 24 h (how often guard runs tmp/json GC) |
100
+ | `LOG_SPOOL_SYNCED_RETENTION_MS` | 7 d (delete `.json` when mtime older than this) |
101
+ | `LOG_SPOOL_TMP_RETENTION_MS` | 7 d (delete stale `.tmp` by filename timestamp) |
102
+
103
+ ---
104
+
105
+ ## On-disk layout
106
+
107
+ ```text
108
+ {RUNTIME_DATA_DIR}/log-spool/{serviceId}/
109
+ main/main.{YYYYMMDDHHmmss}.{hash8}.tmp → .json after upload
110
+ guard/…
111
+ scheduler/…
112
+ worker/…
113
+ {extra}/…
114
+ ```
115
+
116
+ Upload state: `.tmp` = pending, `.json` = uploaded (no central index file).
117
+
118
+ Batch file JSON: `{ entries: LogEntry[], meta?: { serviceId, processRole, serviceValue } }`.
119
+
120
+ Uploaded List meta:
121
+
122
+ - `meta.process` = `{serviceId}:{processRole}` (e.g. `abc123:worker`)
123
+ - `meta.service` = logical value (`watch-service`)
124
+ - `meta.lane` = `"slow"` (legacy transport field; required for decode today)
125
+
126
+ ---
127
+
128
+ ## L3 integration
129
+
130
+ ### Preload (`runServicePreload`)
131
+
132
+ Sync phases set `LOG_PERSIST_SERVICE`, `RUNTIME_DATA_DIR`, validate env, merge `logSpoolExtraProcessRoles`.
133
+ **Do not** call `ensureLogSpoolFromEnv` in preload — it is async and needs `LOG_SPOOL_SERVICE_ID`.
134
+
135
+ ### Main (`createServiceHost`)
136
+
137
+ After registry claim, main sets `LOG_SPOOL_SERVICE_ID` and calls `ensureLogSpoolFromEnv({ processRole: "main", … })`.
138
+
139
+ ### Child processes
140
+
141
+ Guard / scheduler / worker `main()`:
142
+
143
+ ```typescript
144
+ import { enableLogSpoolFromEnvInChild } from "target-supabase-sdk/node";
145
+
146
+ await enableLogSpoolFromEnvInChild();
147
+ ```
148
+
149
+ ### Shutdown
150
+
151
+ ```typescript
152
+ import { shutdownLogSpool } from "target-supabase-sdk/node";
153
+
154
+ await shutdownLogSpool();
155
+ ```
156
+
157
+ Flushes remaining memory buffer to `.tmp`.
158
+
159
+ ### Extra process roles (e.g. download-service `chrome-sidecar`)
160
+
161
+ ```javascript
162
+ // scripts/preload.mjs
163
+ runServicePreload({
164
+ // …
165
+ logSpoolExtraProcessRoles: ["chrome-sidecar"],
166
+ });
167
+ ```
168
+
169
+ ---
170
+
171
+ ## Public Node API (curated)
172
+
173
+ | Symbol | Role |
174
+ |--------|------|
175
+ | `ensureLogSpoolFromEnv` | Enable writer in current process |
176
+ | `enableLogSpoolFromEnvInChild` | Child entry: no-op when disabled, else `ensureLogSpoolFromEnv` |
177
+ | `isLogSpoolEnabled` | Read master switch (`LOG_PERSIST_ENABLED`) |
178
+ | `getMainLogSpoolWriterStats` | Writer stats or `null` when disabled (main observability) |
179
+ | `shutdownLogSpool` | No-op when disabled, else flush + disable |
180
+ | `shutdownLogSpoolFromEnv` | Flush buffer + disable (unconditional) |
181
+ | `getLogSpoolStats` | Writer buffer stats |
182
+ | `buildLogSpoolSpawnEnv` | Manual child env (usually unnecessary) |
183
+ | `validateLogSpoolPreloadEnv` | Preload validation |
184
+ | `logSpoolEnabledFromEnv` | Read master switch |
185
+ | `createLogSpoolCoordinator` | Service-bound lifecycle facade |
186
+ | `registerCollectLogRunner` | Guard TriggerNode runner (via `ServiceGuardNode`) |
187
+ | `runCollectLogTick` | Manual / tests |
188
+ | `resolveLogSpoolRoot` | Spool directory path |
189
+
190
+ Internal helpers (`resolveLogSpoolSpawnEnvForLabel`, `resolveAllLogSpoolProcessRoles`, etc.) are not exported from `node` — use preload `logSpoolExtraProcessRoles` or env instead.
191
+
192
+ ---
193
+
194
+ ## Concurrency (Windows)
195
+
196
+ - One writer per `.tmp` file — producers only create new files.
197
+ - Guard renames after successful upload; does not RMW batch contents.
198
+ - GC scans directories; no shared JSON index file.
199
+
200
+ ---
201
+
202
+ ## Related skills
203
+
204
+ - [log-spool](../../../.cursor/skills/log-spool/SKILL.md) — agent quick reference
205
+ - [service-preload](../../../.cursor/skills/service-preload/SKILL.md) — preload protocol
206
+ - [l3-service-host](../../../.cursor/skills/l3-service-host/SKILL.md) — `createServiceHost` integration
@@ -1,12 +1,12 @@
1
1
  /**
2
2
  * Read side of the log-persist pipeline: decode persisted `LogBatch` Lists into
3
3
  * structured batches and flat entries. Pure and defensive — malformed rows are
4
- * skipped rather than thrown. Mirrors the write side in `log-persist-flush.ts`.
4
+ * skipped rather than thrown. Mirrors the write side in `upload/flush.ts`.
5
5
  */
6
6
 
7
- import type { List } from "../../list/list.interface";
8
- import type { LogEntry } from "./log-manager";
9
- import { LOG_PERSIST_LOADER_KEY, type LogBatchMeta, type LogPersistLane } from "./log-persist.interface";
7
+ import type { List } from "../../../list/list.interface";
8
+ import type { LogEntry } from "../core/log-manager";
9
+ import { LOG_PERSIST_LOADER_KEY, type LogBatchMeta, type LogPersistLane } from "../upload/interface";
10
10
 
11
11
  const LANES: ReadonlySet<string> = new Set<LogPersistLane>(["fast", "medium", "slow"]);
12
12
 
@@ -1,6 +1,6 @@
1
- import { isDevEnvironment } from "../../core.utils";
2
- import { generateUniqueId } from "../utils/id.utils";
3
- import { offerToLogPersist } from "./log-persist-hook";
1
+ import { isDevEnvironment } from "../../../core.utils";
2
+ import { generateUniqueId } from "../../utils/id.utils";
3
+ import { offerToLogPersist } from "../upload/hook";
4
4
  import { formatScopeLabels, type LoggerResetScopePatch, type LogScope, patchScope, resolveLogData } from "./log-scope";
5
5
 
6
6
  /**
@@ -1,4 +1,4 @@
1
- import { isDevEnvironment } from "../../core.utils";
1
+ import { isDevEnvironment } from "../../../core.utils";
2
2
  import { LogLevel } from "./log-manager";
3
3
 
4
4
  /** Env key for global {@link LogManager} min level (console + log-persist when enabled). */
@@ -1,4 +1,4 @@
1
- import { generateUniqueId } from "../utils/id.utils";
1
+ import { generateUniqueId } from "../../utils/id.utils";
2
2
 
3
3
  /** Logger-bound scope: module + trace chain + optional labels. */
4
4
  export interface LogScope {
@@ -1,16 +1,14 @@
1
1
  /**
2
- * Log domain public API — curated re-exports only.
2
+ * Log domain public API — curated re-exports only (browser-safe).
3
3
  */
4
4
 
5
5
  export type {
6
6
  CreateLoggerFromModuleInput,
7
7
  CreateLoggerFromScopeInput,
8
8
  CreateLoggerInput,
9
- } from "./create-logger";
10
- // create-logger
11
- export { createLogger } from "./create-logger";
12
- export type { DecodedLogBatch, FlatLogEntry } from "./log-batch";
13
- // log-batch (persisted LogBatch decode — read side of log-persist)
9
+ } from "./core/create-logger";
10
+ export { createLogger } from "./core/create-logger";
11
+ export type { DecodedLogBatch, FlatLogEntry } from "./core/log-batch";
14
12
  export {
15
13
  decodeLogBatch,
16
14
  decodeLogBatchList,
@@ -19,19 +17,15 @@ export {
19
17
  isLogBatchList,
20
18
  isLogEntry,
21
19
  parseLogBatchMeta,
22
- } from "./log-batch";
23
- export type { LogEntry, LoggerWithScope, LogOptions, LogRestParams, WithScopeOptions } from "./log-manager";
24
- // log-manager
25
- export { LogLevel, LogManager, logManager } from "./log-manager";
26
- export type { ResolveLogMinLevelOptions } from "./log-min-level";
27
- // log-min-level
20
+ } from "./core/log-batch";
21
+ export type { LogEntry, LoggerWithScope, LogOptions, LogRestParams, WithScopeOptions } from "./core/log-manager";
22
+ export { LogLevel, LogManager, logManager } from "./core/log-manager";
23
+ export type { ResolveLogMinLevelOptions } from "./core/log-min-level";
28
24
  export {
29
25
  LOG_MIN_LEVEL_ENV_KEY,
30
26
  logMinLevelFromEnv,
31
27
  resolveLogMinLevel,
32
- } from "./log-min-level";
33
- export type { LogBatchMeta, LogPersistLane } from "./log-persist.interface";
34
- export { LOG_BATCH_LOADER_KEY, LOG_PERSIST_LOADER_KEY } from "./log-persist.interface";
28
+ } from "./core/log-min-level";
35
29
  export type {
36
30
  CreateScopeInput,
37
31
  LoggerResetScopePatch,
@@ -39,8 +33,7 @@ export type {
39
33
  LogScopeInput,
40
34
  LogScopePatch,
41
35
  PatchScopeInput,
42
- } from "./log-scope";
43
- // log-scope
36
+ } from "./core/log-scope";
44
37
  export {
45
38
  createScope,
46
39
  formatScopeLabels,
@@ -48,4 +41,6 @@ export {
48
41
  patchScope,
49
42
  resolveLogData,
50
43
  withModule,
51
- } from "./log-scope";
44
+ } from "./core/log-scope";
45
+ export type { LogBatchMeta, LogPersistLane } from "./upload/interface";
46
+ export { LOG_BATCH_LOADER_KEY, LOG_PERSIST_LOADER_KEY } from "./upload/interface";