@agent-native/core 0.114.2 → 0.114.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +24 -0
- package/corpus/core/package.json +2 -1
- package/corpus/core/src/db/request-telemetry.ts +32 -8
- package/corpus/core/src/settings/store.ts +15 -6
- package/corpus/core/src/shared/optional-node-builtins.ts +66 -0
- package/corpus/core/src/templates/default/.agents/skills/feature-flags/SKILL.md +1 -1
- package/corpus/core/src/templates/headless/.agents/skills/feature-flags/SKILL.md +1 -1
- package/corpus/core/src/templates/workspace-core/.agents/skills/feature-flags/SKILL.md +1 -1
- package/corpus/core/src/vite/client.ts +5 -0
- package/corpus/templates/analytics/.agents/skills/feature-flags/SKILL.md +1 -1
- package/corpus/templates/assets/.agents/skills/feature-flags/SKILL.md +1 -1
- package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +2 -2
- package/corpus/templates/brain/.agents/skills/feature-flags/SKILL.md +1 -1
- package/corpus/templates/calendar/.agents/skills/feature-flags/SKILL.md +1 -1
- package/corpus/templates/chat/.agents/skills/feature-flags/SKILL.md +1 -1
- package/corpus/templates/clips/.agents/skills/feature-flags/SKILL.md +1 -1
- package/corpus/templates/clips/shared/feature-flags.ts +1 -1
- package/corpus/templates/content/.agents/skills/feature-flags/SKILL.md +1 -1
- package/corpus/templates/design/.agents/skills/feature-flags/SKILL.md +1 -1
- package/corpus/templates/design/actions/update-file.ts +10 -1
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +30 -1
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +14 -1
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +547 -50
- package/corpus/templates/design/app/components/design/dnd-debug.ts +27 -0
- package/corpus/templates/design/app/components/design/multi-screen/draft-primitives.ts +19 -2
- package/corpus/templates/design/app/i18n-data.ts +19 -0
- package/corpus/templates/design/app/lib/design-save-outbox.ts +46 -2
- package/corpus/templates/design/app/pages/design-editor/canvas-primitive-insert.ts +4 -9
- package/corpus/templates/design/app/pages/design-editor/history.ts +14 -1
- package/corpus/templates/design/changelog/2026-07-17-drawn-shapes-stay-free-positioned-when-dragged.md +6 -0
- package/corpus/templates/design/changelog/2026-07-17-shapes-show-a-live-outline-while-you-draw.md +6 -0
- package/corpus/templates/design/shared/drag-reflow.ts +375 -0
- package/corpus/templates/design/shared/full-app.ts +1 -1
- package/corpus/templates/dispatch/.agents/skills/feature-flags/SKILL.md +1 -1
- package/corpus/templates/forms/.agents/skills/feature-flags/SKILL.md +1 -1
- package/corpus/templates/macros/.agents/skills/feature-flags/SKILL.md +1 -1
- package/corpus/templates/mail/.agents/skills/feature-flags/SKILL.md +1 -1
- package/corpus/templates/plan/.agents/skills/feature-flags/SKILL.md +1 -1
- package/corpus/templates/slides/.agents/skills/feature-flags/SKILL.md +1 -1
- package/corpus/templates/tasks/.agents/skills/feature-flags/SKILL.md +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/db/request-telemetry.d.ts.map +1 -1
- package/dist/db/request-telemetry.js +24 -6
- package/dist/db/request-telemetry.js.map +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +3 -3
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/settings/store.d.ts +1 -1
- package/dist/settings/store.d.ts.map +1 -1
- package/dist/settings/store.js +14 -6
- package/dist/settings/store.js.map +1 -1
- package/dist/shared/optional-node-builtins.d.ts +23 -0
- package/dist/shared/optional-node-builtins.d.ts.map +1 -0
- package/dist/shared/optional-node-builtins.js +35 -0
- package/dist/shared/optional-node-builtins.js.map +1 -0
- package/dist/templates/chat/.agents/skills/feature-flags/SKILL.md +1 -1
- package/dist/templates/default/.agents/skills/feature-flags/SKILL.md +1 -1
- package/dist/templates/headless/.agents/skills/feature-flags/SKILL.md +1 -1
- package/dist/templates/workspace-core/.agents/skills/feature-flags/SKILL.md +1 -1
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +2 -0
- package/dist/vite/client.js.map +1 -1
- package/package.json +2 -1
- package/src/db/request-telemetry.ts +32 -8
- package/src/settings/store.ts +15 -6
- package/src/shared/optional-node-builtins.ts +66 -0
- package/src/templates/chat/.agents/skills/feature-flags/SKILL.md +1 -1
- package/src/templates/default/.agents/skills/feature-flags/SKILL.md +1 -1
- package/src/templates/headless/.agents/skills/feature-flags/SKILL.md +1 -1
- package/src/templates/workspace-core/.agents/skills/feature-flags/SKILL.md +1 -1
- package/src/vite/client.ts +5 -0
|
@@ -37,7 +37,7 @@ Keep definitions in a shared TypeScript module so server and client code use the
|
|
|
37
37
|
same stable key. Flags are boolean and default-off.
|
|
38
38
|
|
|
39
39
|
```ts
|
|
40
|
-
import { defineFeatureFlag } from "@agent-native/core/feature-flags";
|
|
40
|
+
import { defineFeatureFlag } from "@agent-native/core/feature-flags/registry";
|
|
41
41
|
|
|
42
42
|
export const FULL_APP_BUILDING = defineFeatureFlag({
|
|
43
43
|
key: "full-app-building",
|
|
@@ -37,7 +37,7 @@ Keep definitions in a shared TypeScript module so server and client code use the
|
|
|
37
37
|
same stable key. Flags are boolean and default-off.
|
|
38
38
|
|
|
39
39
|
```ts
|
|
40
|
-
import { defineFeatureFlag } from "@agent-native/core/feature-flags";
|
|
40
|
+
import { defineFeatureFlag } from "@agent-native/core/feature-flags/registry";
|
|
41
41
|
|
|
42
42
|
export const FULL_APP_BUILDING = defineFeatureFlag({
|
|
43
43
|
key: "full-app-building",
|
|
@@ -37,7 +37,7 @@ Keep definitions in a shared TypeScript module so server and client code use the
|
|
|
37
37
|
same stable key. Flags are boolean and default-off.
|
|
38
38
|
|
|
39
39
|
```ts
|
|
40
|
-
import { defineFeatureFlag } from "@agent-native/core/feature-flags";
|
|
40
|
+
import { defineFeatureFlag } from "@agent-native/core/feature-flags/registry";
|
|
41
41
|
|
|
42
42
|
export const FULL_APP_BUILDING = defineFeatureFlag({
|
|
43
43
|
key: "full-app-building",
|
|
@@ -37,7 +37,7 @@ Keep definitions in a shared TypeScript module so server and client code use the
|
|
|
37
37
|
same stable key. Flags are boolean and default-off.
|
|
38
38
|
|
|
39
39
|
```ts
|
|
40
|
-
import { defineFeatureFlag } from "@agent-native/core/feature-flags";
|
|
40
|
+
import { defineFeatureFlag } from "@agent-native/core/feature-flags/registry";
|
|
41
41
|
|
|
42
42
|
export const FULL_APP_BUILDING = defineFeatureFlag({
|
|
43
43
|
key: "full-app-building",
|
|
@@ -37,7 +37,7 @@ Keep definitions in a shared TypeScript module so server and client code use the
|
|
|
37
37
|
same stable key. Flags are boolean and default-off.
|
|
38
38
|
|
|
39
39
|
```ts
|
|
40
|
-
import { defineFeatureFlag } from "@agent-native/core/feature-flags";
|
|
40
|
+
import { defineFeatureFlag } from "@agent-native/core/feature-flags/registry";
|
|
41
41
|
|
|
42
42
|
export const FULL_APP_BUILDING = defineFeatureFlag({
|
|
43
43
|
key: "full-app-building",
|
|
@@ -37,7 +37,7 @@ Keep definitions in a shared TypeScript module so server and client code use the
|
|
|
37
37
|
same stable key. Flags are boolean and default-off.
|
|
38
38
|
|
|
39
39
|
```ts
|
|
40
|
-
import { defineFeatureFlag } from "@agent-native/core/feature-flags";
|
|
40
|
+
import { defineFeatureFlag } from "@agent-native/core/feature-flags/registry";
|
|
41
41
|
|
|
42
42
|
export const FULL_APP_BUILDING = defineFeatureFlag({
|
|
43
43
|
key: "full-app-building",
|
|
@@ -37,7 +37,7 @@ Keep definitions in a shared TypeScript module so server and client code use the
|
|
|
37
37
|
same stable key. Flags are boolean and default-off.
|
|
38
38
|
|
|
39
39
|
```ts
|
|
40
|
-
import { defineFeatureFlag } from "@agent-native/core/feature-flags";
|
|
40
|
+
import { defineFeatureFlag } from "@agent-native/core/feature-flags/registry";
|
|
41
41
|
|
|
42
42
|
export const FULL_APP_BUILDING = defineFeatureFlag({
|
|
43
43
|
key: "full-app-building",
|
package/dist/collab/routes.d.ts
CHANGED
|
@@ -26,8 +26,8 @@ export declare const getCollabState: import("h3").EventHandlerWithFetch<import("
|
|
|
26
26
|
* Body: { update: string (base64), requestSource?: string }
|
|
27
27
|
*/
|
|
28
28
|
export declare const postCollabUpdate: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
29
|
-
error: string;
|
|
30
29
|
ok?: undefined;
|
|
30
|
+
error: string;
|
|
31
31
|
} | {
|
|
32
32
|
error?: undefined;
|
|
33
33
|
ok: boolean;
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
* Body: { json: any, fieldName?: string, type?: "map"|"array", requestSource?: string }
|
|
14
14
|
*/
|
|
15
15
|
export declare const postCollabJson: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
16
|
-
ok?: undefined;
|
|
17
16
|
error: string;
|
|
17
|
+
ok?: undefined;
|
|
18
18
|
} | {
|
|
19
19
|
error?: undefined;
|
|
20
20
|
ok: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request-telemetry.d.ts","sourceRoot":"","sources":["../../src/db/request-telemetry.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,qBAAqB,GAAG,SAAS,GAAG,OAAO,CAAC;AAExD,MAAM,WAAW,wBAAwB;IACvC,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;
|
|
1
|
+
{"version":3,"file":"request-telemetry.d.ts","sourceRoot":"","sources":["../../src/db/request-telemetry.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,qBAAqB,GAAG,SAAS,GAAG,OAAO,CAAC;AAExD,MAAM,WAAW,wBAAwB;IACvC,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAgDD,wBAAgB,8BAA8B,IAAI,wBAAwB,CAezE;AAmBD,wBAAgB,6BAA6B,IACzC,wBAAwB,GACxB,SAAS,CAIZ;AAED,wBAAgB,+BAA+B,CAAC,CAAC,EAC/C,SAAS,EAAE,wBAAwB,EACnC,EAAE,EAAE,MAAM,CAAC,GACV,CAAC,CAEH;AAED,wBAAgB,6BAA6B,CAC3C,SAAS,EAAE,wBAAwB,GAClC,IAAI,CAEN;AAED,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,qBAAqB,GAC/B,CAAC,OAAO,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,KAAK,IAAI,CAiDpD;AAED,wBAAgB,mBAAmB,IAAI,IAAI,CAG1C"}
|
|
@@ -1,10 +1,28 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getAsyncLocalStorageCtor } from "../shared/optional-node-builtins.js";
|
|
2
2
|
const STORAGE_KEY = Symbol.for("@agent-native/core/db.request-telemetry-storage");
|
|
3
3
|
const STARTUP_STATE_KEY = Symbol.for("@agent-native/core/db.startup-telemetry-state");
|
|
4
4
|
const STARTUP_CAPTURE_WINDOW_MS = 120_000;
|
|
5
5
|
const globalRef = globalThis;
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
// AsyncLocalStorage is resolved lazily, never at module load: this module can
|
|
7
|
+
// land in the browser dev graph, where a top-level `new AsyncLocalStorage()`
|
|
8
|
+
// would throw against Vite's externalized `node:async_hooks` stub. On non-Node
|
|
9
|
+
// runtimes telemetry no-ops.
|
|
10
|
+
const NOOP_STORAGE = {
|
|
11
|
+
getStore: () => undefined,
|
|
12
|
+
run: (_store, fn) => fn(),
|
|
13
|
+
enterWith: () => { },
|
|
14
|
+
};
|
|
15
|
+
function getStorage() {
|
|
16
|
+
const existing = globalRef[STORAGE_KEY];
|
|
17
|
+
if (existing)
|
|
18
|
+
return existing;
|
|
19
|
+
const Ctor = getAsyncLocalStorageCtor();
|
|
20
|
+
const created = Ctor
|
|
21
|
+
? new Ctor()
|
|
22
|
+
: NOOP_STORAGE;
|
|
23
|
+
globalRef[STORAGE_KEY] = created;
|
|
24
|
+
return created;
|
|
25
|
+
}
|
|
8
26
|
export function createDatabaseRequestTelemetry() {
|
|
9
27
|
return {
|
|
10
28
|
operationCount: 0,
|
|
@@ -28,7 +46,7 @@ const startupState = globalRef[STARTUP_STATE_KEY] ??
|
|
|
28
46
|
telemetry: createDatabaseRequestTelemetry(),
|
|
29
47
|
});
|
|
30
48
|
function currentDatabaseTelemetry() {
|
|
31
|
-
const requestTelemetry =
|
|
49
|
+
const requestTelemetry = getStorage().getStore();
|
|
32
50
|
if (requestTelemetry)
|
|
33
51
|
return requestTelemetry;
|
|
34
52
|
if (!startupState.claimed && Date.now() <= startupState.captureUntil) {
|
|
@@ -43,10 +61,10 @@ export function claimStartupDatabaseTelemetry() {
|
|
|
43
61
|
return startupState.telemetry;
|
|
44
62
|
}
|
|
45
63
|
export function runWithDatabaseRequestTelemetry(telemetry, fn) {
|
|
46
|
-
return
|
|
64
|
+
return getStorage().run(telemetry, fn);
|
|
47
65
|
}
|
|
48
66
|
export function enterDatabaseRequestTelemetry(telemetry) {
|
|
49
|
-
|
|
67
|
+
getStorage().enterWith(telemetry);
|
|
50
68
|
}
|
|
51
69
|
export function beginDatabaseOperation(operation) {
|
|
52
70
|
const telemetry = currentDatabaseTelemetry();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request-telemetry.js","sourceRoot":"","sources":["../../src/db/request-telemetry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"request-telemetry.js","sourceRoot":"","sources":["../../src/db/request-telemetry.ts"],"names":[],"mappings":"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","sourcesContent":["import { getAsyncLocalStorageCtor } from \"../shared/optional-node-builtins.js\";\n\nexport type DatabaseOperationKind = \"connect\" | \"query\";\n\nexport interface DatabaseRequestTelemetry {\n operationCount: number;\n queryCount: number;\n connectCount: number;\n retryCount: number;\n errorCount: number;\n timeoutCount: number;\n operationTotalMs: number;\n operationWallMs: number;\n queryTotalMs: number;\n connectTotalMs: number;\n slowestOperationMs: number;\n activeOperationCount: number;\n activeWindowStartedAt?: number;\n}\n\nconst STORAGE_KEY = Symbol.for(\n \"@agent-native/core/db.request-telemetry-storage\",\n);\nconst STARTUP_STATE_KEY = Symbol.for(\n \"@agent-native/core/db.startup-telemetry-state\",\n);\nconst STARTUP_CAPTURE_WINDOW_MS = 120_000;\ninterface StartupDatabaseTelemetryState {\n captureUntil: number;\n claimed: boolean;\n telemetry: DatabaseRequestTelemetry;\n}\ninterface TelemetryStorage {\n getStore(): DatabaseRequestTelemetry | undefined;\n run<T>(store: DatabaseRequestTelemetry, fn: () => T): T;\n enterWith(store: DatabaseRequestTelemetry): void;\n}\n\ntype GlobalWithDatabaseTelemetry = typeof globalThis & {\n [STORAGE_KEY]?: TelemetryStorage;\n [STARTUP_STATE_KEY]?: StartupDatabaseTelemetryState;\n};\n\nconst globalRef = globalThis as GlobalWithDatabaseTelemetry;\n\n// AsyncLocalStorage is resolved lazily, never at module load: this module can\n// land in the browser dev graph, where a top-level `new AsyncLocalStorage()`\n// would throw against Vite's externalized `node:async_hooks` stub. On non-Node\n// runtimes telemetry no-ops.\nconst NOOP_STORAGE: TelemetryStorage = {\n getStore: () => undefined,\n run: (_store, fn) => fn(),\n enterWith: () => {},\n};\n\nfunction getStorage(): TelemetryStorage {\n const existing = globalRef[STORAGE_KEY];\n if (existing) return existing;\n const Ctor = getAsyncLocalStorageCtor();\n const created: TelemetryStorage = Ctor\n ? new Ctor<DatabaseRequestTelemetry>()\n : NOOP_STORAGE;\n globalRef[STORAGE_KEY] = created;\n return created;\n}\n\nexport function createDatabaseRequestTelemetry(): DatabaseRequestTelemetry {\n return {\n operationCount: 0,\n queryCount: 0,\n connectCount: 0,\n retryCount: 0,\n errorCount: 0,\n timeoutCount: 0,\n operationTotalMs: 0,\n operationWallMs: 0,\n queryTotalMs: 0,\n connectTotalMs: 0,\n slowestOperationMs: 0,\n activeOperationCount: 0,\n };\n}\n\nconst startupState =\n globalRef[STARTUP_STATE_KEY] ??\n (globalRef[STARTUP_STATE_KEY] = {\n captureUntil: Date.now() + STARTUP_CAPTURE_WINDOW_MS,\n claimed: false,\n telemetry: createDatabaseRequestTelemetry(),\n });\n\nfunction currentDatabaseTelemetry(): DatabaseRequestTelemetry | undefined {\n const requestTelemetry = getStorage().getStore();\n if (requestTelemetry) return requestTelemetry;\n if (!startupState.claimed && Date.now() <= startupState.captureUntil) {\n return startupState.telemetry;\n }\n return undefined;\n}\n\nexport function claimStartupDatabaseTelemetry():\n | DatabaseRequestTelemetry\n | undefined {\n if (startupState.claimed) return undefined;\n startupState.claimed = true;\n return startupState.telemetry;\n}\n\nexport function runWithDatabaseRequestTelemetry<T>(\n telemetry: DatabaseRequestTelemetry,\n fn: () => T,\n): T {\n return getStorage().run(telemetry, fn);\n}\n\nexport function enterDatabaseRequestTelemetry(\n telemetry: DatabaseRequestTelemetry,\n): void {\n getStorage().enterWith(telemetry);\n}\n\nexport function beginDatabaseOperation(\n operation: DatabaseOperationKind,\n): (outcome: \"success\" | \"error\" | \"timeout\") => void {\n const telemetry = currentDatabaseTelemetry();\n if (!telemetry) return () => {};\n\n const startedAt = Date.now();\n if (telemetry.activeOperationCount === 0) {\n telemetry.activeWindowStartedAt = startedAt;\n }\n telemetry.activeOperationCount += 1;\n let completed = false;\n\n return (outcome) => {\n if (completed) return;\n completed = true;\n const completedAt = Date.now();\n const duration = Math.max(0, completedAt - startedAt);\n telemetry.operationCount += 1;\n telemetry.operationTotalMs += duration;\n telemetry.slowestOperationMs = Math.max(\n telemetry.slowestOperationMs,\n duration,\n );\n\n if (operation === \"connect\") {\n telemetry.connectCount += 1;\n telemetry.connectTotalMs += duration;\n } else {\n telemetry.queryCount += 1;\n telemetry.queryTotalMs += duration;\n }\n\n if (outcome !== \"success\") telemetry.errorCount += 1;\n if (outcome === \"timeout\") telemetry.timeoutCount += 1;\n\n telemetry.activeOperationCount = Math.max(\n 0,\n telemetry.activeOperationCount - 1,\n );\n if (\n telemetry.activeOperationCount === 0 &&\n telemetry.activeWindowStartedAt !== undefined\n ) {\n telemetry.operationWallMs += Math.max(\n 0,\n completedAt - telemetry.activeWindowStartedAt,\n );\n telemetry.activeWindowStartedAt = undefined;\n }\n };\n}\n\nexport function recordDatabaseRetry(): void {\n const telemetry = currentDatabaseTelemetry();\n if (telemetry) telemetry.retryCount += 1;\n}\n"]}
|
|
@@ -17,12 +17,12 @@ declare const _default: import("../../action.js").ActionDefinition<{
|
|
|
17
17
|
id?: undefined;
|
|
18
18
|
provider?: undefined;
|
|
19
19
|
} | {
|
|
20
|
-
error?: undefined;
|
|
21
20
|
configured?: undefined;
|
|
22
21
|
connectPath?: undefined;
|
|
23
22
|
url: string;
|
|
24
23
|
id: string;
|
|
25
24
|
provider: string;
|
|
25
|
+
error?: undefined;
|
|
26
26
|
}>;
|
|
27
27
|
export default _default;
|
|
28
28
|
//# sourceMappingURL=upload-image.d.ts.map
|
|
@@ -41,16 +41,16 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
|
|
|
41
41
|
thumbsUpRate: number;
|
|
42
42
|
avgEvalScore: number;
|
|
43
43
|
} | {
|
|
44
|
-
error?: undefined;
|
|
45
44
|
summary: import("./types.js").TraceSummary;
|
|
46
45
|
spans: import("./types.js").TraceSpan[];
|
|
47
46
|
id?: undefined;
|
|
47
|
+
error?: undefined;
|
|
48
48
|
ok?: undefined;
|
|
49
49
|
} | {
|
|
50
|
-
error?: undefined;
|
|
51
50
|
summary?: undefined;
|
|
52
51
|
spans?: undefined;
|
|
53
52
|
id: string;
|
|
53
|
+
error?: undefined;
|
|
54
54
|
ok?: undefined;
|
|
55
55
|
} | {
|
|
56
56
|
summary?: undefined;
|
|
@@ -59,10 +59,10 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
|
|
|
59
59
|
error: any;
|
|
60
60
|
ok?: undefined;
|
|
61
61
|
} | {
|
|
62
|
-
error?: undefined;
|
|
63
62
|
summary?: undefined;
|
|
64
63
|
spans?: undefined;
|
|
65
64
|
id?: undefined;
|
|
65
|
+
error?: undefined;
|
|
66
66
|
ok: boolean;
|
|
67
67
|
}>>;
|
|
68
68
|
//# sourceMappingURL=routes.d.ts.map
|
|
@@ -27,11 +27,11 @@ export declare function resolveAgentEngineApiKeyWriteTarget(event: H3Event, scop
|
|
|
27
27
|
export declare function createAgentEngineApiKeyHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
28
28
|
error: any;
|
|
29
29
|
} | {
|
|
30
|
+
error?: undefined;
|
|
30
31
|
ok: boolean;
|
|
31
32
|
key: string;
|
|
32
33
|
baseUrlKey?: string;
|
|
33
34
|
scope: AgentEngineApiKeyScope;
|
|
34
|
-
error?: undefined;
|
|
35
35
|
}>>;
|
|
36
36
|
export {};
|
|
37
37
|
//# sourceMappingURL=agent-engine-api-key-route.d.ts.map
|
package/dist/settings/store.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EventEmitter } from "events";
|
|
1
|
+
import type { EventEmitter } from "node:events";
|
|
2
2
|
export declare function getSettingsEmitter(): EventEmitter;
|
|
3
3
|
export declare function getSetting(key: string): Promise<Record<string, unknown> | null>;
|
|
4
4
|
export interface StoreWriteOptions {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/settings/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/settings/store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AA0ChD,wBAAgB,kBAAkB,IAAI,YAAY,CAEjD;AAsED,wBAAsB,UAAU,CAC9B,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAgBzC;AAED,MAAM,WAAW,iBAAiB;IAChC,gEAAgE;IAChE,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAID;;;;;;GAMG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,CACP,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,KACpC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EAC/D,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAwClC;AAED,wBAAsB,UAAU,CAC9B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAiBf;AAED,wBAAsB,aAAa,CACjC,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,OAAO,CAAC,CAmBlB;AAED,wBAAsB,cAAc,IAAI,OAAO,CAC7C,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CACxC,CAUA"}
|
package/dist/settings/store.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { EventEmitter } from "events";
|
|
2
1
|
import { getDbExec, isPostgres, intType } from "../db/client.js";
|
|
3
2
|
import { ensureIndexExists, ensureTableExists } from "../db/ddl-guard.js";
|
|
4
3
|
import { widenIntColumnsToBigInt } from "../db/widen-columns.js";
|
|
5
4
|
import { getRequestContext } from "../server/request-context.js";
|
|
5
|
+
import { createEventEmitter } from "../shared/optional-node-builtins.js";
|
|
6
6
|
let _initPromise;
|
|
7
7
|
// Per-request memoization of settings reads, keyed on the active
|
|
8
8
|
// AsyncLocalStorage RequestContext (WeakMap → freed with the request). One
|
|
@@ -25,10 +25,18 @@ function requestSettingsCache() {
|
|
|
25
25
|
}
|
|
26
26
|
return cache;
|
|
27
27
|
}
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
// Created lazily so this module can be evaluated in the browser dev graph
|
|
29
|
+
// without a top-level `new EventEmitter()` tripping Vite's externalized
|
|
30
|
+
// `node:events` stub. The emitter drives server-side SSE fan-out only.
|
|
31
|
+
let _emitter;
|
|
32
|
+
function settingsEmitter() {
|
|
33
|
+
if (!_emitter)
|
|
34
|
+
_emitter = createEventEmitter();
|
|
30
35
|
return _emitter;
|
|
31
36
|
}
|
|
37
|
+
export function getSettingsEmitter() {
|
|
38
|
+
return settingsEmitter();
|
|
39
|
+
}
|
|
32
40
|
function settingsTable() {
|
|
33
41
|
return isPostgres() ? "public.settings" : "settings";
|
|
34
42
|
}
|
|
@@ -144,7 +152,7 @@ export async function mutateSetting(key, updater, options) {
|
|
|
144
152
|
if (result.rowsAffected === 0)
|
|
145
153
|
continue;
|
|
146
154
|
requestSettingsCache()?.set(key, nextRaw);
|
|
147
|
-
|
|
155
|
+
settingsEmitter().emit("settings", {
|
|
148
156
|
source: "settings",
|
|
149
157
|
type: "change",
|
|
150
158
|
key,
|
|
@@ -165,7 +173,7 @@ export async function putSetting(key, value, options) {
|
|
|
165
173
|
args: [key, JSON.stringify(value), Date.now()],
|
|
166
174
|
});
|
|
167
175
|
requestSettingsCache()?.set(key, JSON.stringify(value));
|
|
168
|
-
|
|
176
|
+
settingsEmitter().emit("settings", {
|
|
169
177
|
source: "settings",
|
|
170
178
|
type: "change",
|
|
171
179
|
key,
|
|
@@ -182,7 +190,7 @@ export async function deleteSetting(key, options) {
|
|
|
182
190
|
});
|
|
183
191
|
requestSettingsCache()?.set(key, null);
|
|
184
192
|
if (result.rowsAffected > 0) {
|
|
185
|
-
|
|
193
|
+
settingsEmitter().emit("settings", {
|
|
186
194
|
source: "settings",
|
|
187
195
|
type: "delete",
|
|
188
196
|
key,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/settings/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC1E,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAEjE,IAAI,YAAuC,CAAC;AAE5C,iEAAiE;AACjE,2EAA2E;AAC3E,0EAA0E;AAC1E,qEAAqE;AACrE,qEAAqE;AACrE,2EAA2E;AAC3E,0EAA0E;AAC1E,0EAA0E;AAC1E,8BAA8B;AAC9B,MAAM,qBAAqB,GAAG,IAAI,OAAO,EAAsC,CAAC;AAEhF,SAAS,oBAAoB;IAC3B,MAAM,GAAG,GAAG,iBAAiB,EAAE,CAAC;IAChC,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACjD,IAAI,KAAK,GAAG,qBAAqB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC3C,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,KAAK,GAAG,IAAI,GAAG,EAAE,CAAC;QAClB,qBAAqB,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACxC,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,QAAQ,GAAG,IAAI,YAAY,EAAE,CAAC;AAEpC,MAAM,UAAU,kBAAkB;IAChC,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,aAAa;IACpB,OAAO,UAAU,EAAE,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,UAAU,CAAC;AACvD,CAAC;AAED,KAAK,UAAU,WAAW;IACxB,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,YAAY,GAAG,CAAC,KAAK,IAAI,EAAE;YACzB,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;YAC3B,MAAM,KAAK,GAAG,aAAa,EAAE,CAAC;YAC9B,MAAM,SAAS,GAAG;qCACa,KAAK;;;uBAGnB,OAAO,EAAE;;OAEzB,CAAC;YAEF,IAAI,UAAU,EAAE,EAAE,CAAC;gBACjB,kEAAkE;gBAClE,gEAAgE;gBAChE,uEAAuE;gBACvE,oEAAoE;gBACpE,mEAAmE;gBACnE,+DAA+D;gBAC/D,oEAAoE;gBACpE,wEAAwE;gBACxE,uEAAuE;gBACvE,qEAAqE;gBACrE,sEAAsE;gBACtE,sEAAsE;gBACtE,uDAAuD;gBACvD,MAAM,iBAAiB,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;gBAC/C,uEAAuE;gBACvE,wEAAwE;gBACxE,qEAAqE;gBACrE,qEAAqE;gBACrE,MAAM,uBAAuB,CAAC,UAAU,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC;gBAC1D,gEAAgE;gBAChE,MAAM,iBAAiB,CACrB,yBAAyB,EACzB,yDAAyD,KAAK,eAAe,CAC9E,CAAC;gBACF,OAAO;YACT,CAAC;YAED,qEAAqE;YACrE,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YAChC,+CAA+C;YAC/C,MAAM,uBAAuB,CAAC,UAAU,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC;YAC1D,8EAA8E;YAC9E,yEAAyE;YACzE,2DAA2D;YAC3D,IAAI,CAAC;gBACH,MAAM,MAAM,CAAC,OAAO,CAClB,yDAAyD,KAAK,eAAe,CAC9E,CAAC;YACJ,CAAC;YAAC,MAAM,CAAC;gBACP,4DAA4D;YAC9D,CAAC;QACH,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACjB,sDAAsD;YACtD,YAAY,GAAG,SAAS,CAAC;YACzB,MAAM,GAAG,CAAC;QACZ,CAAC,CAAC,CAAC;IACL,CAAC;IACD,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,GAAW;IAEX,MAAM,KAAK,GAAG,oBAAoB,EAAE,CAAC;IACrC,IAAI,KAAK,EAAE,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;QACpB,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC9B,OAAO,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACpD,CAAC;IACD,MAAM,WAAW,EAAE,CAAC;IACpB,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,KAAK,GAAG,aAAa,EAAE,CAAC;IAC9B,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC;QACpC,GAAG,EAAE,qBAAqB,KAAK,gBAAgB;QAC/C,IAAI,EAAE,CAAC,GAAG,CAAC;KACZ,CAAC,CAAC;IACH,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAE,IAAI,CAAC,CAAC,CAAC,CAAC,KAAgB,CAAC;IACjE,KAAK,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IACrB,OAAO,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;AAC9C,CAAC;AAOD,MAAM,0BAA0B,GAAG,EAAE,CAAC;AAEtC;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,GAAW,EACX,OAE+D,EAC/D,OAA2B;IAE3B,MAAM,WAAW,EAAE,CAAC;IACpB,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,KAAK,GAAG,aAAa,EAAE,CAAC;IAC9B,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,0BAA0B,EAAE,OAAO,IAAI,CAAC,EAAE,CAAC;QACzE,oEAAoE;QACpE,uEAAuE;QACvE,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC;YACpC,GAAG,EAAE,qBAAqB,KAAK,gBAAgB;YAC/C,IAAI,EAAE,CAAC,GAAG,CAAC;SACZ,CAAC,CAAC;QACH,MAAM,GAAG,GACP,QAAQ,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,KAAgB,CAAC;QAC1E,MAAM,OAAO,GAAG,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACrD,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;QACpC,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QACrC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,MAAM,MAAM,GACV,GAAG,IAAI,IAAI;YACT,CAAC,CAAC,MAAM,MAAM,CAAC,OAAO,CAAC;gBACnB,GAAG,EAAE,UAAU,EAAE;oBACf,CAAC,CAAC,eAAe,KAAK,yEAAyE;oBAC/F,CAAC,CAAC,yBAAyB,KAAK,4CAA4C;gBAC9E,IAAI,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,SAAS,CAAC;aAChC,CAAC;YACJ,CAAC,CAAC,MAAM,MAAM,CAAC,OAAO,CAAC;gBACnB,GAAG,EAAE,UAAU,KAAK,4DAA4D;gBAChF,IAAI,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,GAAG,CAAC;aACrC,CAAC,CAAC;QACT,IAAI,MAAM,CAAC,YAAY,KAAK,CAAC;YAAE,SAAS;QACxC,oBAAoB,EAAE,EAAE,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAC1C,QAAQ,CAAC,IAAI,CAAC,UAAU,EAAE;YACxB,MAAM,EAAE,UAAU;YAClB,IAAI,EAAE,QAAQ;YACd,GAAG;YACH,GAAG,CAAC,OAAO,EAAE,aAAa,IAAI,EAAE,aAAa,EAAE,OAAO,CAAC,aAAa,EAAE,CAAC;SACxE,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,WAAW,GAAG,8CAA8C,CAAC,CAAC;AAChF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,GAAW,EACX,KAA8B,EAC9B,OAA2B;IAE3B,MAAM,WAAW,EAAE,CAAC;IACpB,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,KAAK,GAAG,aAAa,EAAE,CAAC;IAC9B,MAAM,MAAM,CAAC,OAAO,CAAC;QACnB,GAAG,EAAE,UAAU,EAAE;YACf,CAAC,CAAC,eAAe,KAAK,iIAAiI;YACvJ,CAAC,CAAC,0BAA0B,KAAK,4CAA4C;QAC/E,IAAI,EAAE,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC;KAC/C,CAAC,CAAC;IACH,oBAAoB,EAAE,EAAE,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;IACxD,QAAQ,CAAC,IAAI,CAAC,UAAU,EAAE;QACxB,MAAM,EAAE,UAAU;QAClB,IAAI,EAAE,QAAQ;QACd,GAAG;QACH,GAAG,CAAC,OAAO,EAAE,aAAa,IAAI,EAAE,aAAa,EAAE,OAAO,CAAC,aAAa,EAAE,CAAC;KACxE,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,GAAW,EACX,OAA2B;IAE3B,MAAM,WAAW,EAAE,CAAC;IACpB,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,KAAK,GAAG,aAAa,EAAE,CAAC;IAC9B,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC;QAClC,GAAG,EAAE,eAAe,KAAK,gBAAgB;QACzC,IAAI,EAAE,CAAC,GAAG,CAAC;KACZ,CAAC,CAAC;IACH,oBAAoB,EAAE,EAAE,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACvC,IAAI,MAAM,CAAC,YAAY,GAAG,CAAC,EAAE,CAAC;QAC5B,QAAQ,CAAC,IAAI,CAAC,UAAU,EAAE;YACxB,MAAM,EAAE,UAAU;YAClB,IAAI,EAAE,QAAQ;YACd,GAAG;YACH,GAAG,CAAC,OAAO,EAAE,aAAa,IAAI,EAAE,aAAa,EAAE,OAAO,CAAC,aAAa,EAAE,CAAC;SACxE,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc;IAGlC,MAAM,WAAW,EAAE,CAAC;IACpB,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,KAAK,GAAG,aAAa,EAAE,CAAC;IAC9B,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,0BAA0B,KAAK,EAAE,CAAC,CAAC;IACzE,MAAM,MAAM,GAA4C,EAAE,CAAC;IAC3D,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,CAAC,GAAG,CAAC,GAAa,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAe,CAAC,CAAC;IAC9D,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["import { EventEmitter } from \"events\";\n\nimport { getDbExec, isPostgres, intType } from \"../db/client.js\";\nimport { ensureIndexExists, ensureTableExists } from \"../db/ddl-guard.js\";\nimport { widenIntColumnsToBigInt } from \"../db/widen-columns.js\";\nimport { getRequestContext } from \"../server/request-context.js\";\n\nlet _initPromise: Promise<void> | undefined;\n\n// Per-request memoization of settings reads, keyed on the active\n// AsyncLocalStorage RequestContext (WeakMap → freed with the request). One\n// action request can read the same setting several times (org resolution,\n// guards, the action body), and each read is a network round trip on\n// serverless Postgres. Mirrors the per-request session/org caches on\n// event.context. The cache holds the raw JSON string and re-parses per hit\n// so callers can't mutate a shared object; writes in the same request are\n// written through, while other in-flight requests keep their snapshot for\n// their own (short) lifetime.\nconst _requestSettingsCache = new WeakMap<object, Map<string, string | null>>();\n\nfunction requestSettingsCache(): Map<string, string | null> | null {\n const ctx = getRequestContext();\n if (!ctx || typeof ctx !== \"object\") return null;\n let cache = _requestSettingsCache.get(ctx);\n if (!cache) {\n cache = new Map();\n _requestSettingsCache.set(ctx, cache);\n }\n return cache;\n}\n\nconst _emitter = new EventEmitter();\n\nexport function getSettingsEmitter(): EventEmitter {\n return _emitter;\n}\n\nfunction settingsTable(): string {\n return isPostgres() ? \"public.settings\" : \"settings\";\n}\n\nasync function ensureTable(): Promise<void> {\n if (!_initPromise) {\n _initPromise = (async () => {\n const client = getDbExec();\n const table = settingsTable();\n const createSql = `\n CREATE TABLE IF NOT EXISTS ${table} (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL,\n updated_at ${intType()} NOT NULL\n )\n `;\n\n if (isPostgres()) {\n // Hot path: the `settings` table and its poll index are virtually\n // always already present in production. Issuing `CREATE TABLE`/\n // `CREATE INDEX` still takes a lock that, in a fresh background-worker\n // process behind a concurrent connection on the shared Neon DB, can\n // block ~indefinitely (ACCESS EXCLUSIVE for CREATE TABLE; a write-\n // blocking SHARE lock for CREATE INDEX). `ensureTableExists` /\n // `ensureIndexExists` probe `information_schema`/`pg_indexes` first\n // (plain reads, no lock) and run DDL ONLY for what is actually missing,\n // bounding any DDL with a transaction-scoped `lock_timeout`. They also\n // re-probe after a swallowed lock-timeout and THROW if the schema is\n // still missing, so a timed-out DDL never poisons this init memo with\n // missing schema. `settingsTable()` is `public.settings` on Postgres;\n // the existence checks use the unqualified table name.\n await ensureTableExists(\"settings\", createSql);\n // Older deployments (pre BIGINT-compat) have a 32-bit `updated_at`; on\n // Postgres the `Date.now()` written on every setSetting overflows int4.\n // widenIntColumnsToBigInt already probes information_schema and only\n // ALTERs columns that are still int4 — a no-op on fresh/widened DBs.\n await widenIntColumnsToBigInt(\"settings\", [\"updated_at\"]);\n // Index for the poll watermark query: `SELECT MAX(updated_at)`.\n await ensureIndexExists(\n \"settings_updated_at_idx\",\n `CREATE INDEX IF NOT EXISTS settings_updated_at_idx ON ${table} (updated_at)`,\n );\n return;\n }\n\n // SQLite (local dev): no lock problem — keep the original behaviour.\n await client.execute(createSql);\n // No-op on SQLite (INTEGER is already 64-bit).\n await widenIntColumnsToBigInt(\"settings\", [\"updated_at\"]);\n // Index for the poll watermark query: `SELECT MAX(updated_at) FROM settings`.\n // MAX on an indexed column avoids a full-table scan on every poll cycle.\n // IF NOT EXISTS makes it idempotent on existing databases.\n try {\n await client.execute(\n `CREATE INDEX IF NOT EXISTS settings_updated_at_idx ON ${table} (updated_at)`,\n );\n } catch {\n // Index already exists or the dialect rejected a duplicate.\n }\n })().catch((err) => {\n // Retry init on the next call after a failed startup.\n _initPromise = undefined;\n throw err;\n });\n }\n return _initPromise;\n}\n\nexport async function getSetting(\n key: string,\n): Promise<Record<string, unknown> | null> {\n const cache = requestSettingsCache();\n if (cache?.has(key)) {\n const cached = cache.get(key);\n return cached == null ? null : JSON.parse(cached);\n }\n await ensureTable();\n const client = getDbExec();\n const table = settingsTable();\n const { rows } = await client.execute({\n sql: `SELECT value FROM ${table} WHERE key = ?`,\n args: [key],\n });\n const raw = rows.length === 0 ? null : (rows[0].value as string);\n cache?.set(key, raw);\n return raw == null ? null : JSON.parse(raw);\n}\n\nexport interface StoreWriteOptions {\n /** Tag identifying who initiated this write (e.g. a tab ID). */\n requestSource?: string;\n}\n\nconst SETTINGS_MUTATION_ATTEMPTS = 25;\n\n/**\n * Atomically derive and persist one setting with an optimistic raw-value CAS.\n * This works across SQLite/libSQL and Postgres and remains safe across\n * horizontally scaled processes where an in-memory mutex would not.\n * The updater may run more than once after contention and must not perform\n * external side effects.\n */\nexport async function mutateSetting(\n key: string,\n updater: (\n current: Record<string, unknown> | null,\n ) => Record<string, unknown> | Promise<Record<string, unknown>>,\n options?: StoreWriteOptions,\n): Promise<Record<string, unknown>> {\n await ensureTable();\n const client = getDbExec();\n const table = settingsTable();\n for (let attempt = 0; attempt < SETTINGS_MUTATION_ATTEMPTS; attempt += 1) {\n // Deliberately bypass the request cache: a failed CAS means another\n // request committed a newer value and the next attempt must reread it.\n const snapshot = await client.execute({\n sql: `SELECT value FROM ${table} WHERE key = ?`,\n args: [key],\n });\n const raw =\n snapshot.rows.length === 0 ? null : (snapshot.rows[0]?.value as string);\n const current = raw == null ? null : JSON.parse(raw);\n const next = await updater(current);\n const nextRaw = JSON.stringify(next);\n const timestamp = Date.now();\n const result =\n raw == null\n ? await client.execute({\n sql: isPostgres()\n ? `INSERT INTO ${table} (key, value, updated_at) VALUES (?, ?, ?) ON CONFLICT (key) DO NOTHING`\n : `INSERT OR IGNORE INTO ${table} (key, value, updated_at) VALUES (?, ?, ?)`,\n args: [key, nextRaw, timestamp],\n })\n : await client.execute({\n sql: `UPDATE ${table} SET value = ?, updated_at = ? WHERE key = ? AND value = ?`,\n args: [nextRaw, timestamp, key, raw],\n });\n if (result.rowsAffected === 0) continue;\n requestSettingsCache()?.set(key, nextRaw);\n _emitter.emit(\"settings\", {\n source: \"settings\",\n type: \"change\",\n key,\n ...(options?.requestSource && { requestSource: options.requestSource }),\n });\n return JSON.parse(nextRaw);\n }\n throw new Error(`Setting ${key} changed too many times; retry the mutation.`);\n}\n\nexport async function putSetting(\n key: string,\n value: Record<string, unknown>,\n options?: StoreWriteOptions,\n): Promise<void> {\n await ensureTable();\n const client = getDbExec();\n const table = settingsTable();\n await client.execute({\n sql: isPostgres()\n ? `INSERT INTO ${table} (key, value, updated_at) VALUES (?, ?, ?) ON CONFLICT (key) DO UPDATE SET value=EXCLUDED.value, updated_at=EXCLUDED.updated_at`\n : `INSERT OR REPLACE INTO ${table} (key, value, updated_at) VALUES (?, ?, ?)`,\n args: [key, JSON.stringify(value), Date.now()],\n });\n requestSettingsCache()?.set(key, JSON.stringify(value));\n _emitter.emit(\"settings\", {\n source: \"settings\",\n type: \"change\",\n key,\n ...(options?.requestSource && { requestSource: options.requestSource }),\n });\n}\n\nexport async function deleteSetting(\n key: string,\n options?: StoreWriteOptions,\n): Promise<boolean> {\n await ensureTable();\n const client = getDbExec();\n const table = settingsTable();\n const result = await client.execute({\n sql: `DELETE FROM ${table} WHERE key = ?`,\n args: [key],\n });\n requestSettingsCache()?.set(key, null);\n if (result.rowsAffected > 0) {\n _emitter.emit(\"settings\", {\n source: \"settings\",\n type: \"delete\",\n key,\n ...(options?.requestSource && { requestSource: options.requestSource }),\n });\n return true;\n }\n return false;\n}\n\nexport async function getAllSettings(): Promise<\n Record<string, Record<string, unknown>>\n> {\n await ensureTable();\n const client = getDbExec();\n const table = settingsTable();\n const { rows } = await client.execute(`SELECT key, value FROM ${table}`);\n const result: Record<string, Record<string, unknown>> = {};\n for (const row of rows) {\n result[row.key as string] = JSON.parse(row.value as string);\n }\n return result;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/settings/store.ts"],"names":[],"mappings":"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","sourcesContent":["import type { EventEmitter } from \"node:events\";\n\nimport { getDbExec, isPostgres, intType } from \"../db/client.js\";\nimport { ensureIndexExists, ensureTableExists } from \"../db/ddl-guard.js\";\nimport { widenIntColumnsToBigInt } from \"../db/widen-columns.js\";\nimport { getRequestContext } from \"../server/request-context.js\";\nimport { createEventEmitter } from \"../shared/optional-node-builtins.js\";\n\nlet _initPromise: Promise<void> | undefined;\n\n// Per-request memoization of settings reads, keyed on the active\n// AsyncLocalStorage RequestContext (WeakMap → freed with the request). One\n// action request can read the same setting several times (org resolution,\n// guards, the action body), and each read is a network round trip on\n// serverless Postgres. Mirrors the per-request session/org caches on\n// event.context. The cache holds the raw JSON string and re-parses per hit\n// so callers can't mutate a shared object; writes in the same request are\n// written through, while other in-flight requests keep their snapshot for\n// their own (short) lifetime.\nconst _requestSettingsCache = new WeakMap<object, Map<string, string | null>>();\n\nfunction requestSettingsCache(): Map<string, string | null> | null {\n const ctx = getRequestContext();\n if (!ctx || typeof ctx !== \"object\") return null;\n let cache = _requestSettingsCache.get(ctx);\n if (!cache) {\n cache = new Map();\n _requestSettingsCache.set(ctx, cache);\n }\n return cache;\n}\n\n// Created lazily so this module can be evaluated in the browser dev graph\n// without a top-level `new EventEmitter()` tripping Vite's externalized\n// `node:events` stub. The emitter drives server-side SSE fan-out only.\nlet _emitter: EventEmitter | undefined;\n\nfunction settingsEmitter(): EventEmitter {\n if (!_emitter) _emitter = createEventEmitter();\n return _emitter;\n}\n\nexport function getSettingsEmitter(): EventEmitter {\n return settingsEmitter();\n}\n\nfunction settingsTable(): string {\n return isPostgres() ? \"public.settings\" : \"settings\";\n}\n\nasync function ensureTable(): Promise<void> {\n if (!_initPromise) {\n _initPromise = (async () => {\n const client = getDbExec();\n const table = settingsTable();\n const createSql = `\n CREATE TABLE IF NOT EXISTS ${table} (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL,\n updated_at ${intType()} NOT NULL\n )\n `;\n\n if (isPostgres()) {\n // Hot path: the `settings` table and its poll index are virtually\n // always already present in production. Issuing `CREATE TABLE`/\n // `CREATE INDEX` still takes a lock that, in a fresh background-worker\n // process behind a concurrent connection on the shared Neon DB, can\n // block ~indefinitely (ACCESS EXCLUSIVE for CREATE TABLE; a write-\n // blocking SHARE lock for CREATE INDEX). `ensureTableExists` /\n // `ensureIndexExists` probe `information_schema`/`pg_indexes` first\n // (plain reads, no lock) and run DDL ONLY for what is actually missing,\n // bounding any DDL with a transaction-scoped `lock_timeout`. They also\n // re-probe after a swallowed lock-timeout and THROW if the schema is\n // still missing, so a timed-out DDL never poisons this init memo with\n // missing schema. `settingsTable()` is `public.settings` on Postgres;\n // the existence checks use the unqualified table name.\n await ensureTableExists(\"settings\", createSql);\n // Older deployments (pre BIGINT-compat) have a 32-bit `updated_at`; on\n // Postgres the `Date.now()` written on every setSetting overflows int4.\n // widenIntColumnsToBigInt already probes information_schema and only\n // ALTERs columns that are still int4 — a no-op on fresh/widened DBs.\n await widenIntColumnsToBigInt(\"settings\", [\"updated_at\"]);\n // Index for the poll watermark query: `SELECT MAX(updated_at)`.\n await ensureIndexExists(\n \"settings_updated_at_idx\",\n `CREATE INDEX IF NOT EXISTS settings_updated_at_idx ON ${table} (updated_at)`,\n );\n return;\n }\n\n // SQLite (local dev): no lock problem — keep the original behaviour.\n await client.execute(createSql);\n // No-op on SQLite (INTEGER is already 64-bit).\n await widenIntColumnsToBigInt(\"settings\", [\"updated_at\"]);\n // Index for the poll watermark query: `SELECT MAX(updated_at) FROM settings`.\n // MAX on an indexed column avoids a full-table scan on every poll cycle.\n // IF NOT EXISTS makes it idempotent on existing databases.\n try {\n await client.execute(\n `CREATE INDEX IF NOT EXISTS settings_updated_at_idx ON ${table} (updated_at)`,\n );\n } catch {\n // Index already exists or the dialect rejected a duplicate.\n }\n })().catch((err) => {\n // Retry init on the next call after a failed startup.\n _initPromise = undefined;\n throw err;\n });\n }\n return _initPromise;\n}\n\nexport async function getSetting(\n key: string,\n): Promise<Record<string, unknown> | null> {\n const cache = requestSettingsCache();\n if (cache?.has(key)) {\n const cached = cache.get(key);\n return cached == null ? null : JSON.parse(cached);\n }\n await ensureTable();\n const client = getDbExec();\n const table = settingsTable();\n const { rows } = await client.execute({\n sql: `SELECT value FROM ${table} WHERE key = ?`,\n args: [key],\n });\n const raw = rows.length === 0 ? null : (rows[0].value as string);\n cache?.set(key, raw);\n return raw == null ? null : JSON.parse(raw);\n}\n\nexport interface StoreWriteOptions {\n /** Tag identifying who initiated this write (e.g. a tab ID). */\n requestSource?: string;\n}\n\nconst SETTINGS_MUTATION_ATTEMPTS = 25;\n\n/**\n * Atomically derive and persist one setting with an optimistic raw-value CAS.\n * This works across SQLite/libSQL and Postgres and remains safe across\n * horizontally scaled processes where an in-memory mutex would not.\n * The updater may run more than once after contention and must not perform\n * external side effects.\n */\nexport async function mutateSetting(\n key: string,\n updater: (\n current: Record<string, unknown> | null,\n ) => Record<string, unknown> | Promise<Record<string, unknown>>,\n options?: StoreWriteOptions,\n): Promise<Record<string, unknown>> {\n await ensureTable();\n const client = getDbExec();\n const table = settingsTable();\n for (let attempt = 0; attempt < SETTINGS_MUTATION_ATTEMPTS; attempt += 1) {\n // Deliberately bypass the request cache: a failed CAS means another\n // request committed a newer value and the next attempt must reread it.\n const snapshot = await client.execute({\n sql: `SELECT value FROM ${table} WHERE key = ?`,\n args: [key],\n });\n const raw =\n snapshot.rows.length === 0 ? null : (snapshot.rows[0]?.value as string);\n const current = raw == null ? null : JSON.parse(raw);\n const next = await updater(current);\n const nextRaw = JSON.stringify(next);\n const timestamp = Date.now();\n const result =\n raw == null\n ? await client.execute({\n sql: isPostgres()\n ? `INSERT INTO ${table} (key, value, updated_at) VALUES (?, ?, ?) ON CONFLICT (key) DO NOTHING`\n : `INSERT OR IGNORE INTO ${table} (key, value, updated_at) VALUES (?, ?, ?)`,\n args: [key, nextRaw, timestamp],\n })\n : await client.execute({\n sql: `UPDATE ${table} SET value = ?, updated_at = ? WHERE key = ? AND value = ?`,\n args: [nextRaw, timestamp, key, raw],\n });\n if (result.rowsAffected === 0) continue;\n requestSettingsCache()?.set(key, nextRaw);\n settingsEmitter().emit(\"settings\", {\n source: \"settings\",\n type: \"change\",\n key,\n ...(options?.requestSource && { requestSource: options.requestSource }),\n });\n return JSON.parse(nextRaw);\n }\n throw new Error(`Setting ${key} changed too many times; retry the mutation.`);\n}\n\nexport async function putSetting(\n key: string,\n value: Record<string, unknown>,\n options?: StoreWriteOptions,\n): Promise<void> {\n await ensureTable();\n const client = getDbExec();\n const table = settingsTable();\n await client.execute({\n sql: isPostgres()\n ? `INSERT INTO ${table} (key, value, updated_at) VALUES (?, ?, ?) ON CONFLICT (key) DO UPDATE SET value=EXCLUDED.value, updated_at=EXCLUDED.updated_at`\n : `INSERT OR REPLACE INTO ${table} (key, value, updated_at) VALUES (?, ?, ?)`,\n args: [key, JSON.stringify(value), Date.now()],\n });\n requestSettingsCache()?.set(key, JSON.stringify(value));\n settingsEmitter().emit(\"settings\", {\n source: \"settings\",\n type: \"change\",\n key,\n ...(options?.requestSource && { requestSource: options.requestSource }),\n });\n}\n\nexport async function deleteSetting(\n key: string,\n options?: StoreWriteOptions,\n): Promise<boolean> {\n await ensureTable();\n const client = getDbExec();\n const table = settingsTable();\n const result = await client.execute({\n sql: `DELETE FROM ${table} WHERE key = ?`,\n args: [key],\n });\n requestSettingsCache()?.set(key, null);\n if (result.rowsAffected > 0) {\n settingsEmitter().emit(\"settings\", {\n source: \"settings\",\n type: \"delete\",\n key,\n ...(options?.requestSource && { requestSource: options.requestSource }),\n });\n return true;\n }\n return false;\n}\n\nexport async function getAllSettings(): Promise<\n Record<string, Record<string, unknown>>\n> {\n await ensureTable();\n const client = getDbExec();\n const table = settingsTable();\n const { rows } = await client.execute(`SELECT key, value FROM ${table}`);\n const result: Record<string, Record<string, unknown>> = {};\n for (const row of rows) {\n result[row.key as string] = JSON.parse(row.value as string);\n }\n return result;\n}\n"]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser-safe accessors for optional Node builtins.
|
|
3
|
+
*
|
|
4
|
+
* `node:async_hooks` and `node:events` are server-only, but the modules that
|
|
5
|
+
* use them (db telemetry, settings/resource emitters) can land in the browser
|
|
6
|
+
* dev graph before tree-shaking runs. A static `import { X } from "node:..."`
|
|
7
|
+
* resolves to Vite's externalized stub and throws the instant the value is
|
|
8
|
+
* touched at module load. We read the builtin through `process.getBuiltinModule`
|
|
9
|
+
* instead — the same guard `server/request-context.ts` uses — so there is no
|
|
10
|
+
* static `node:` import to evaluate in the browser, and callers fall back to a
|
|
11
|
+
* no-op on non-Node runtimes (browser, or Node without getBuiltinModule).
|
|
12
|
+
*/
|
|
13
|
+
import type { AsyncLocalStorage } from "node:async_hooks";
|
|
14
|
+
import type { EventEmitter } from "node:events";
|
|
15
|
+
export type AsyncLocalStorageCtor = new <T>() => AsyncLocalStorage<T>;
|
|
16
|
+
export declare function getAsyncLocalStorageCtor(): AsyncLocalStorageCtor | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* Returns a real Node EventEmitter on Node, or a no-op emitter elsewhere. The
|
|
19
|
+
* emitters that use this drive server-side SSE fan-out; nothing subscribes in
|
|
20
|
+
* the browser, so the no-op fallback is inert rather than wrong.
|
|
21
|
+
*/
|
|
22
|
+
export declare function createEventEmitter(): EventEmitter;
|
|
23
|
+
//# sourceMappingURL=optional-node-builtins.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"optional-node-builtins.d.ts","sourceRoot":"","sources":["../../src/shared/optional-node-builtins.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAqBhD,MAAM,MAAM,qBAAqB,GAAG,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC,CAAC,CAAC;AAEtE,wBAAgB,wBAAwB,IAAI,qBAAqB,GAAG,SAAS,CAI5E;AAID;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,YAAY,CAgBjD"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
function nodeBuiltin(name) {
|
|
2
|
+
const proc = typeof process === "undefined" ? undefined : process;
|
|
3
|
+
if (typeof window !== "undefined" ||
|
|
4
|
+
!proc ||
|
|
5
|
+
!proc.versions?.node ||
|
|
6
|
+
typeof proc.getBuiltinModule !== "function") {
|
|
7
|
+
return undefined;
|
|
8
|
+
}
|
|
9
|
+
return proc.getBuiltinModule(name);
|
|
10
|
+
}
|
|
11
|
+
export function getAsyncLocalStorageCtor() {
|
|
12
|
+
return nodeBuiltin("node:async_hooks")?.AsyncLocalStorage;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Returns a real Node EventEmitter on Node, or a no-op emitter elsewhere. The
|
|
16
|
+
* emitters that use this drive server-side SSE fan-out; nothing subscribes in
|
|
17
|
+
* the browser, so the no-op fallback is inert rather than wrong.
|
|
18
|
+
*/
|
|
19
|
+
export function createEventEmitter() {
|
|
20
|
+
const Ctor = nodeBuiltin("node:events")?.EventEmitter;
|
|
21
|
+
if (Ctor)
|
|
22
|
+
return new Ctor();
|
|
23
|
+
const noop = {
|
|
24
|
+
on: () => noop,
|
|
25
|
+
off: () => noop,
|
|
26
|
+
once: () => noop,
|
|
27
|
+
addListener: () => noop,
|
|
28
|
+
removeListener: () => noop,
|
|
29
|
+
removeAllListeners: () => noop,
|
|
30
|
+
setMaxListeners: () => noop,
|
|
31
|
+
emit: () => false,
|
|
32
|
+
};
|
|
33
|
+
return noop;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=optional-node-builtins.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"optional-node-builtins.js","sourceRoot":"","sources":["../../src/shared/optional-node-builtins.ts"],"names":[],"mappings":"AAoBA,SAAS,WAAW,CAAI,IAAY;IAClC,MAAM,IAAI,GACR,OAAO,OAAO,KAAK,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAE,OAA0B,CAAC;IAC3E,IACE,OAAO,MAAM,KAAK,WAAW;QAC7B,CAAC,IAAI;QACL,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI;QACpB,OAAO,IAAI,CAAC,gBAAgB,KAAK,UAAU,EAC3C,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAkB,CAAC;AACtD,CAAC;AAID,MAAM,UAAU,wBAAwB;IACtC,OAAO,WAAW,CAChB,kBAAkB,CACnB,EAAE,iBAAiB,CAAC;AACvB,CAAC;AAID;;;;GAIG;AACH,MAAM,UAAU,kBAAkB;IAChC,MAAM,IAAI,GAAG,WAAW,CACtB,aAAa,CACd,EAAE,YAAY,CAAC;IAChB,IAAI,IAAI;QAAE,OAAO,IAAI,IAAI,EAAE,CAAC;IAC5B,MAAM,IAAI,GAAG;QACX,EAAE,EAAE,GAAG,EAAE,CAAC,IAAI;QACd,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI;QACf,IAAI,EAAE,GAAG,EAAE,CAAC,IAAI;QAChB,WAAW,EAAE,GAAG,EAAE,CAAC,IAAI;QACvB,cAAc,EAAE,GAAG,EAAE,CAAC,IAAI;QAC1B,kBAAkB,EAAE,GAAG,EAAE,CAAC,IAAI;QAC9B,eAAe,EAAE,GAAG,EAAE,CAAC,IAAI;QAC3B,IAAI,EAAE,GAAG,EAAE,CAAC,KAAK;KAClB,CAAC;IACF,OAAO,IAA+B,CAAC;AACzC,CAAC","sourcesContent":["/**\n * Browser-safe accessors for optional Node builtins.\n *\n * `node:async_hooks` and `node:events` are server-only, but the modules that\n * use them (db telemetry, settings/resource emitters) can land in the browser\n * dev graph before tree-shaking runs. A static `import { X } from \"node:...\"`\n * resolves to Vite's externalized stub and throws the instant the value is\n * touched at module load. We read the builtin through `process.getBuiltinModule`\n * instead — the same guard `server/request-context.ts` uses — so there is no\n * static `node:` import to evaluate in the browser, and callers fall back to a\n * no-op on non-Node runtimes (browser, or Node without getBuiltinModule).\n */\nimport type { AsyncLocalStorage } from \"node:async_hooks\";\nimport type { EventEmitter } from \"node:events\";\n\ntype BuiltinProcess = {\n versions?: { node?: string };\n getBuiltinModule?: (name: string) => unknown;\n};\n\nfunction nodeBuiltin<T>(name: string): T | undefined {\n const proc =\n typeof process === \"undefined\" ? undefined : (process as BuiltinProcess);\n if (\n typeof window !== \"undefined\" ||\n !proc ||\n !proc.versions?.node ||\n typeof proc.getBuiltinModule !== \"function\"\n ) {\n return undefined;\n }\n return proc.getBuiltinModule(name) as T | undefined;\n}\n\nexport type AsyncLocalStorageCtor = new <T>() => AsyncLocalStorage<T>;\n\nexport function getAsyncLocalStorageCtor(): AsyncLocalStorageCtor | undefined {\n return nodeBuiltin<{ AsyncLocalStorage: AsyncLocalStorageCtor }>(\n \"node:async_hooks\",\n )?.AsyncLocalStorage;\n}\n\ntype EventEmitterCtor = new () => EventEmitter;\n\n/**\n * Returns a real Node EventEmitter on Node, or a no-op emitter elsewhere. The\n * emitters that use this drive server-side SSE fan-out; nothing subscribes in\n * the browser, so the no-op fallback is inert rather than wrong.\n */\nexport function createEventEmitter(): EventEmitter {\n const Ctor = nodeBuiltin<{ EventEmitter: EventEmitterCtor }>(\n \"node:events\",\n )?.EventEmitter;\n if (Ctor) return new Ctor();\n const noop = {\n on: () => noop,\n off: () => noop,\n once: () => noop,\n addListener: () => noop,\n removeListener: () => noop,\n removeAllListeners: () => noop,\n setMaxListeners: () => noop,\n emit: () => false,\n };\n return noop as unknown as EventEmitter;\n}\n"]}
|
|
@@ -37,7 +37,7 @@ Keep definitions in a shared TypeScript module so server and client code use the
|
|
|
37
37
|
same stable key. Flags are boolean and default-off.
|
|
38
38
|
|
|
39
39
|
```ts
|
|
40
|
-
import { defineFeatureFlag } from "@agent-native/core/feature-flags";
|
|
40
|
+
import { defineFeatureFlag } from "@agent-native/core/feature-flags/registry";
|
|
41
41
|
|
|
42
42
|
export const FULL_APP_BUILDING = defineFeatureFlag({
|
|
43
43
|
key: "full-app-building",
|
|
@@ -37,7 +37,7 @@ Keep definitions in a shared TypeScript module so server and client code use the
|
|
|
37
37
|
same stable key. Flags are boolean and default-off.
|
|
38
38
|
|
|
39
39
|
```ts
|
|
40
|
-
import { defineFeatureFlag } from "@agent-native/core/feature-flags";
|
|
40
|
+
import { defineFeatureFlag } from "@agent-native/core/feature-flags/registry";
|
|
41
41
|
|
|
42
42
|
export const FULL_APP_BUILDING = defineFeatureFlag({
|
|
43
43
|
key: "full-app-building",
|
|
@@ -37,7 +37,7 @@ Keep definitions in a shared TypeScript module so server and client code use the
|
|
|
37
37
|
same stable key. Flags are boolean and default-off.
|
|
38
38
|
|
|
39
39
|
```ts
|
|
40
|
-
import { defineFeatureFlag } from "@agent-native/core/feature-flags";
|
|
40
|
+
import { defineFeatureFlag } from "@agent-native/core/feature-flags/registry";
|
|
41
41
|
|
|
42
42
|
export const FULL_APP_BUILDING = defineFeatureFlag({
|
|
43
43
|
key: "full-app-building",
|
|
@@ -37,7 +37,7 @@ Keep definitions in a shared TypeScript module so server and client code use the
|
|
|
37
37
|
same stable key. Flags are boolean and default-off.
|
|
38
38
|
|
|
39
39
|
```ts
|
|
40
|
-
import { defineFeatureFlag } from "@agent-native/core/feature-flags";
|
|
40
|
+
import { defineFeatureFlag } from "@agent-native/core/feature-flags/registry";
|
|
41
41
|
|
|
42
42
|
export const FULL_APP_BUILDING = defineFeatureFlag({
|
|
43
43
|
key: "full-app-building",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/vite/client.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAIV,MAAM,EACN,UAAU,EACX,MAAM,MAAM,CAAC;AAqBd,OAAO,EAEL,KAAK,0BAA0B,EAChC,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAEL,KAAK,iCAAiC,EACvC,MAAM,kCAAkC,CAAC;AAmN1C;;;;;;;;;;;;;GAaG;AACH,iBAAS,gCAAgC,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAoFhE;AAuRD;;;;;GAKG;AACH,iBAAS,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAgE9C;AAED;;;;;;GAMG;AACH,iBAAS,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkCvD;AAOD;;;;;GAKG;AACH,iBAAS,qBAAqB,CAC5B,GAAG,EAAE,MAAM,GACV,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC,CAc9C;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/vite/client.ts"],"names":[],"mappings":"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"}
|
package/dist/vite/client.js
CHANGED
|
@@ -683,6 +683,7 @@ const CORE_CLIENT_SUBPATHS = [
|
|
|
683
683
|
"@agent-native/core/client/components/RemoteSelectionRings",
|
|
684
684
|
"@agent-native/core/client/visual-style-controls",
|
|
685
685
|
"@agent-native/core/client/feature-flags",
|
|
686
|
+
"@agent-native/core/feature-flags/registry",
|
|
686
687
|
"@agent-native/core/client/hooks",
|
|
687
688
|
"@agent-native/core/client/host",
|
|
688
689
|
"@agent-native/core/client/i18n",
|
|
@@ -951,6 +952,7 @@ function getCoreSourceAliases(cwd) {
|
|
|
951
952
|
"@agent-native/core/client/components/RemoteSelectionRings": path.join(coreSrc, "client/tombstone/remote-selection-rings.ts"),
|
|
952
953
|
"@agent-native/core/client/visual-style-controls": path.join(coreSrc, "client/tombstone/visual-style-controls.ts"),
|
|
953
954
|
"@agent-native/core/client/feature-flags": path.join(coreSrc, "client/feature-flags/index.ts"),
|
|
955
|
+
"@agent-native/core/feature-flags/registry": path.join(coreSrc, "feature-flags/registry.ts"),
|
|
954
956
|
"@agent-native/core/client/hooks": path.join(coreSrc, "client/hooks/index.ts"),
|
|
955
957
|
"@agent-native/core/client/host": path.join(coreSrc, "client/host/index.ts"),
|
|
956
958
|
"@agent-native/core/client/i18n": path.join(coreSrc, "client/i18n.tsx"),
|