@reliantlabs/forge-web-runtime 0.9.2 → 0.10.1
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/README.md +64 -0
- package/dist/node-exception.d.ts +73 -0
- package/dist/node-exception.js +278 -0
- package/dist/node-exception.js.map +1 -0
- package/dist/node-otlp.d.ts +168 -0
- package/dist/node-otlp.js +235 -0
- package/dist/node-otlp.js.map +1 -0
- package/dist/node-trace.d.ts +41 -0
- package/dist/node-trace.js +331 -0
- package/dist/node-trace.js.map +1 -0
- package/dist/node.d.ts +153 -0
- package/dist/node.js +576 -0
- package/dist/node.js.map +1 -0
- package/dist/service-hooks.d.ts +88 -4
- package/dist/service-hooks.js +60 -2
- package/dist/service-hooks.js.map +1 -1
- package/dist/service-name.d.ts +2 -0
- package/dist/service-name.js +14 -0
- package/dist/service-name.js.map +1 -0
- package/package.json +5 -1
package/dist/node.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node.js","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"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","sourcesContent":["// Part of @reliantlabs/forge-web-runtime — the web twin of forge/pkg.\n//\n// Node / Electron-main telemetry: logs, errors and spans over OTLP/HTTP to the\n// same ingest the browser entry (`/telemetry`) ships to — usually the KEYED\n// ingest, `https://<ingest host>/k/<key>`, since a desktop app's main process\n// has no same-origin `/_otel`.\n//\n// ── What it records ──────────────────────────────────────────────────────\n//\n// - uncaught exceptions and unhandled rejections, as ERROR log records in\n// the shape forge/pkg/observe gives a server error (node-exception.ts), so\n// `forge obs issues` groups them with sfp1;\n// - what the app logs through `telemetry.logger`, and errors it hands to\n// `telemetry.reportError` (and to the barrel's `reportException`);\n// - spans: the global @opentelemetry/api tracer is this one (node-trace.ts).\n//\n// Records carry no `rum.sessionId`. That is what makes the issues pipeline\n// treat them as server-side errors (obsquery.ServerErrorFilterSQL), which is\n// what a main process is.\n//\n// ── What it changes about the process ────────────────────────────────────\n//\n// Nothing an app can observe, by design. Exceptions are watched through\n// `uncaughtExceptionMonitor`, which leaves the process's fate to whoever owns\n// it (the app's own handler, Electron's dialog, Node's exit). Rejections have\n// no monitor event, and any `unhandledRejection` listener — this one included\n// — switches off Node's default of raising the rejection as an uncaught\n// exception. So when this listener is the only one, it puts the default back:\n// it flushes the record, then raises the rejection as Node would have\n// (`--unhandled-rejections` is honoured). In plain Node with no\n// `uncaughtException` handler of the app's own, the process would die before\n// an async export could finish, so the runtime flushes first and then exits\n// as Node does (stderr, code 1). Under Electron the main process outlives an\n// uncaught exception by default, and nothing is installed.\n//\n// ── Batching and quitting ────────────────────────────────────────────────\n//\n// Records are queued and exported in batches (delay and size below), with\n// unref'd timers, so telemetry never keeps a process alive. A fatal record\n// starts its export at once. `flush(timeoutMs)` exports everything queued and\n// resolves by the timeout whatever the network does; `flushOnQuit(app)` runs\n// it from Electron's `before-quit`. An idle Node process flushes on\n// `beforeExit`.\n//\n// ── Privacy ──────────────────────────────────────────────────────────────\n//\n// Nothing about the user beyond what the browser entry sends: an opaque user\n// id when the app sets one, the app client, and the record itself. Messages,\n// bodies and string attributes have credential shapes redacted with the same\n// patterns `track()` uses; an exception keeps only its message's first line;\n// stack paths lose the home directory and the install location; object-valued\n// attributes are dropped, never serialized. No host name, no IP, no argv, no\n// environment.\nimport { createRequire } from \"node:module\";\nimport { homedir } from \"node:os\";\nimport { inspect } from \"node:util\";\n\nimport {\n context as contextApi,\n propagation,\n trace,\n type Tracer,\n} from \"@opentelemetry/api\";\n\nimport { setExceptionReporter } from \"./error-reporter.js\";\nimport {\n bound,\n boundMessage,\n ERROR_GROUP,\n exceptionAttributes,\n type PathScrub,\n} from \"./node-exception.js\";\nimport {\n type Attributes,\n type AttributeValue,\n BatchQueue,\n encodeAttributes,\n exportSignal,\n type ExporterOptions,\n type FetchLike,\n type KeyValue,\n type LogRecord,\n logsPayload,\n MAX_ATTRIBUTE_CHARS,\n nowMs,\n type Scope,\n SEVERITY,\n type SeverityText,\n type SpanRecord,\n tracesPayload,\n unixNanos,\n} from \"./node-otlp.js\";\nimport {\n AsyncLocalContextManager,\n type ContextOps,\n NodeTracerProvider,\n TraceparentPropagator,\n} from \"./node-trace.js\";\nimport { redactSecrets } from \"./track.js\";\n\nexport { frontendServiceName } from \"./service-name.js\";\nexport {\n CODE_FILE,\n CODE_FUNCTION,\n CODE_LINE,\n ERROR_GROUP,\n EXCEPTION_MESSAGE,\n EXCEPTION_STACKTRACE,\n EXCEPTION_TYPE,\n exceptionAttributes,\n type PathScrub,\n} from \"./node-exception.js\";\n\n/** The instrumentation scope of every log record this entry writes. */\nexport const NODE_SCOPE_NAME = \"@reliantlabs/forge-web-runtime/node\";\n\n/** Body of the record for an uncaught exception. */\nexport const UNCAUGHT_EXCEPTION_BODY = \"uncaught exception\";\n/** Body of the record for an unhandled rejection. */\nexport const UNHANDLED_REJECTION_BODY = \"unhandled rejection\";\n/** Body of the record for an error passed to reportError / reportException. */\nexport const REPORTED_EXCEPTION_BODY = \"caught exception\";\n\n/** Longest log body. */\nexport const MAX_BODY_CHARS = 4096;\n/** Longest user id, as the browser entry bounds it. */\nexport const MAX_USER_ID_CHARS = 128;\n\nexport const DEFAULT_FLUSH_TIMEOUT_MS = 2_000;\nexport const DEFAULT_BATCH_DELAY_MS = 5_000;\nexport const DEFAULT_MAX_BATCH = 256;\nexport const DEFAULT_MAX_QUEUE = 2_048;\nexport const DEFAULT_EXPORT_TIMEOUT_MS = 10_000;\n/**\n * Most records of ONE fatal error (same type, message and frame) per minute.\n * A handler that throws while handling — an EPIPE logger writing to the pipe\n * that just broke — raises the same exception in a tight loop, and each one\n * would otherwise be a record and a request.\n */\nexport const MAX_REPEATS_PER_MINUTE = 5;\n\n/** A value a caller may attach to a log record; anything else is dropped. */\nexport type LogAttributes = Record<string, unknown>;\n\nexport interface NodeTelemetryConfig {\n /** `service.name`. For a forge frontend: frontendServiceName(project, frontend). */\n serviceName: string;\n /** `service.version` — the release. */\n serviceVersion?: string;\n /** `service.namespace`, conventionally the project name. */\n serviceNamespace?: string;\n /** Emitted as `deployment.environment.name` and the legacy `deployment.environment`. */\n environment?: string;\n /** The forge frontend this process belongs to, as `forge.frontend`. */\n frontend?: string;\n /** `app.client` on every record and span (`electron`, `cli`, ...). */\n appClient?: string;\n /**\n * The OTLP base URL: `${endpoint}/v1/logs` and `/v1/traces` are posted to.\n * The keyed ingest is `https://<ingest host>/k/<key>`. Unset, empty, `off`\n * or not an absolute http(s) URL disables telemetry: init returns null and\n * installs nothing.\n */\n endpoint?: string;\n /**\n * The `Origin` header sent with every export. The keyed ingest admits a\n * request only when its Origin is EXACTLY one of the key's allowed origins,\n * so a desktop app sends its renderer's origin (`app://bundle`).\n */\n origin?: string;\n /** Extra request headers. */\n headers?: Record<string, string>;\n /** Files below it are reported relative to it. Electron: app.getAppPath(). Default process.cwd(). */\n appRoot?: string;\n /** Extra resource attributes. They cannot override `service.name`. */\n resourceAttributes?: Record<string, string>;\n /** Record uncaught exceptions and unhandled rejections. Default true. */\n captureProcessErrors?: boolean;\n /** Register the tracer, context manager and propagator globally. Default true. */\n registerGlobal?: boolean;\n /** Least severe level the logger exports. Default `INFO`. */\n minSeverity?: SeverityText;\n /** How long a record may wait for its batch. Default 5s. */\n batchDelayMs?: number;\n /** Most records in one request. Default 256. */\n maxBatchSize?: number;\n /** Most records held per signal; more are dropped and counted. Default 2048. */\n maxQueueSize?: number;\n /** One request's budget. Default 10s. */\n exportTimeoutMs?: number;\n /** How long a fatal error's record may delay the process's default exit. Default 2s. */\n fatalFlushTimeoutMs?: number;\n /** Told when a batch is dropped (the ingest refused it or was unreachable). */\n onExportError?: (error: Error) => void;\n /** Test seam: the fetch exports go through. Default globalThis.fetch. */\n fetch?: FetchLike;\n}\n\nexport interface NodeLogger {\n debug(body: string, attributes?: LogAttributes): void;\n info(body: string, attributes?: LogAttributes): void;\n warn(body: string, attributes?: LogAttributes): void;\n /** An ERROR record. An Error among the attributes supplies its exception.* keys. */\n error(body: string, attributes?: LogAttributes): void;\n}\n\nexport interface NodeTelemetry {\n readonly logger: NodeLogger;\n /** The tracer to open spans on (also the global one, unless registerGlobal is false). */\n readonly tracer: Tracer;\n /** One ERROR record for an error the app caught. */\n reportError(error: unknown, attributes?: LogAttributes): void;\n /** The opaque `userId` on every later record and span; null clears it. Never an email. */\n setUser(id: string | null): void;\n /** Export everything queued; resolves by `timeoutMs` (default 2s) whatever the network does. */\n flush(timeoutMs?: number): Promise<void>;\n /** Flush, then stop: every later call is a no-op. init may run again afterwards. */\n shutdown(timeoutMs?: number): Promise<void>;\n /** Records refused because a queue was full. */\n readonly dropped: number;\n}\n\nlet current: NodeTelemetry | null = null;\n\n/** The running instance, or null before init / after shutdown. */\nexport function getNodeTelemetry(): NodeTelemetry | null {\n return current;\n}\n\n/**\n * The absolute OTLP base for `endpoint`, or null when telemetry is off: unset,\n * empty, `off`, or not an absolute http(s) URL. Trailing slashes are dropped.\n */\nexport function resolveNodeIngestUrl(\n endpoint: string | undefined,\n): string | null {\n const value = (endpoint ?? \"\").trim();\n if (value === \"\" || value.toLowerCase() === \"off\") {\n return null;\n }\n try {\n const url = new URL(value);\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n return null;\n }\n url.search = \"\";\n url.hash = \"\";\n return url.toString().replace(/\\/+$/, \"\");\n } catch {\n return null;\n }\n}\n\nfunction sdkVersion(): string {\n try {\n const req = createRequire(import.meta.url);\n const v = (req(\"../package.json\") as { version?: unknown }).version;\n return typeof v === \"string\" ? v : \"\";\n } catch {\n return \"\";\n }\n}\n\nconst OS_TYPE: Record<string, string> = { win32: \"windows\", sunos: \"solaris\" };\nconst HOST_ARCH: Record<string, string> = {\n x64: \"amd64\",\n ia32: \"x86\",\n ppc64: \"ppc64\",\n};\n\n/**\n * The resource every record and span carries. Pure given its inputs;\n * exported for tests and for an app that wants to see exactly what is sent.\n */\nexport function buildNodeResource(\n config: Pick<\n NodeTelemetryConfig,\n | \"serviceName\"\n | \"serviceVersion\"\n | \"serviceNamespace\"\n | \"environment\"\n | \"frontend\"\n | \"resourceAttributes\"\n >,\n runtime: {\n versions: Record<string, string | undefined>;\n platform: string;\n arch: string;\n },\n version = sdkVersion(),\n): Record<string, string> {\n const electron = runtime.versions.electron;\n const out: Record<string, string> = {\n \"telemetry.sdk.name\": \"@reliantlabs/forge-web-runtime\",\n \"telemetry.sdk.language\": \"nodejs\",\n \"process.runtime.name\": electron ? \"electron\" : \"nodejs\",\n \"process.runtime.version\": (electron ??\n runtime.versions.node ??\n \"\") as string,\n \"os.type\": OS_TYPE[runtime.platform] ?? runtime.platform,\n \"host.arch\": HOST_ARCH[runtime.arch] ?? runtime.arch,\n };\n if (version) out[\"telemetry.sdk.version\"] = version;\n if (config.serviceVersion) out[\"service.version\"] = config.serviceVersion;\n if (config.serviceNamespace)\n out[\"service.namespace\"] = config.serviceNamespace;\n if (config.frontend) out[\"forge.frontend\"] = config.frontend;\n if (config.environment) {\n out[\"deployment.environment.name\"] = config.environment;\n out[\"deployment.environment\"] = config.environment;\n }\n Object.assign(out, config.resourceAttributes ?? {});\n out[\"service.name\"] = config.serviceName;\n return out;\n}\n\nfunction scrubString(value: string, max: number): string {\n return bound(redactSecrets(value.slice(0, max * 2)), max);\n}\n\n/**\n * Reduce caller attributes to what a record may carry: strings redacted and\n * bounded, finite numbers, booleans, arrays of those; an Error becomes its\n * bounded message (its stack goes in exception.*). Objects are dropped.\n */\nfunction sanitizeAttributes(attrs: LogAttributes | undefined): {\n attributes: Attributes;\n error: unknown;\n} {\n const out: Attributes = {};\n let error: unknown = undefined;\n if (!attrs || typeof attrs !== \"object\") {\n return { attributes: out, error };\n }\n for (const [key, v] of Object.entries(attrs)) {\n if (v instanceof Error) {\n if (error === undefined) error = v;\n out[key] = boundMessage(v.message ?? \"\");\n } else if (typeof v === \"string\") {\n out[key] = scrubString(v, MAX_ATTRIBUTE_CHARS);\n } else if (\n (typeof v === \"number\" && Number.isFinite(v)) ||\n typeof v === \"boolean\"\n ) {\n out[key] = v;\n } else if (Array.isArray(v)) {\n const kept = v\n .filter(\n (x) =>\n typeof x === \"string\" ||\n typeof x === \"boolean\" ||\n (typeof x === \"number\" && Number.isFinite(x)),\n )\n .map((x) =>\n typeof x === \"string\" ? scrubString(x, MAX_ATTRIBUTE_CHARS) : x,\n );\n out[key] = kept as AttributeValue;\n }\n }\n return { attributes: out, error };\n}\n\nfunction withTimeout(p: Promise<unknown>, ms: number): Promise<void> {\n return new Promise((resolve) => {\n const t = setTimeout(resolve, Math.max(0, ms));\n (t as { unref?: () => void }).unref?.();\n void p.then(\n () => {\n clearTimeout(t);\n resolve();\n },\n () => {\n clearTimeout(t);\n resolve();\n },\n );\n });\n}\n\n/** What `--unhandled-rejections` says Node does with a rejection nobody handles. */\nexport function unhandledRejectionMode(\n execArgv: readonly string[],\n nodeOptions: string | undefined,\n): string {\n const args = [...execArgv, ...(nodeOptions ?? \"\").split(/\\s+/)];\n let mode = \"throw\";\n for (let i = 0; i < args.length; i++) {\n const a = args[i] ?? \"\";\n if (a.startsWith(\"--unhandled-rejections=\")) {\n mode = a.slice(\"--unhandled-rejections=\".length);\n } else if (a === \"--unhandled-rejections\" && args[i + 1]) {\n mode = args[i + 1] as string;\n }\n }\n return mode;\n}\n\n/** The error Node raises for a rejection whose reason is not an Error. */\nfunction rejectionError(reason: unknown): Error {\n const err = new Error(\n \"This error originated either by throwing inside of an async function without a catch block, \" +\n \"or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason \" +\n `\"${inspect(reason)}\".`,\n );\n err.name = \"UnhandledPromiseRejection\";\n (err as { code?: string }).code = \"ERR_UNHANDLED_REJECTION\";\n return err;\n}\n\n/**\n * initNodeTelemetry starts telemetry for this process and returns it, or null\n * when it is off (no usable endpoint, no fetch, not Node). Idempotent: a\n * second call returns the running instance and ignores its config. Never\n * throws.\n */\nexport function initNodeTelemetry(\n config: NodeTelemetryConfig,\n): NodeTelemetry | null {\n if (current) {\n return current;\n }\n try {\n const instance = start(config);\n current = instance;\n return instance;\n } catch {\n // Telemetry must never break the app.\n return null;\n }\n}\n\nfunction start(config: NodeTelemetryConfig): NodeTelemetry | null {\n if (typeof process === \"undefined\" || !process.versions?.node) {\n return null;\n }\n const endpoint = resolveNodeIngestUrl(config.endpoint);\n const fetchFn: FetchLike | undefined =\n config.fetch ??\n (typeof globalThis.fetch === \"function\"\n ? (globalThis.fetch as unknown as FetchLike)\n : undefined);\n if (!endpoint || !fetchFn || !config.serviceName) {\n return null;\n }\n\n const isElectron = Boolean(process.versions.electron);\n const scrub: PathScrub = {\n appRoot: config.appRoot ?? process.cwd(),\n homeDir: safeHomedir(),\n caseInsensitive: process.platform === \"win32\",\n };\n const resource: KeyValue[] = encodeAttributes(\n buildNodeResource(config, {\n versions: process.versions,\n platform: process.platform,\n arch: process.arch,\n }),\n );\n const headers: Record<string, string> = { ...(config.headers ?? {}) };\n const origin = config.origin?.trim().replace(/\\/+$/, \"\");\n if (origin) {\n headers[\"origin\"] = origin;\n }\n const exporter: ExporterOptions = {\n endpoint,\n headers,\n fetch: fetchFn,\n timeoutMs: config.exportTimeoutMs ?? DEFAULT_EXPORT_TIMEOUT_MS,\n retries: 2,\n onError: config.onExportError,\n };\n const batch = {\n maxQueue: config.maxQueueSize ?? DEFAULT_MAX_QUEUE,\n maxBatch: config.maxBatchSize ?? DEFAULT_MAX_BATCH,\n delayMs: config.batchDelayMs ?? DEFAULT_BATCH_DELAY_MS,\n };\n const logScope: Scope = {\n name: NODE_SCOPE_NAME,\n version: sdkVersion() || undefined,\n };\n const logs = new BatchQueue<LogRecord>({\n ...batch,\n send: (records) =>\n exportSignal(exporter, \"logs\", logsPayload(resource, logScope, records)),\n });\n const spans = new BatchQueue<SpanRecord>({\n ...batch,\n send: (records) =>\n exportSignal(exporter, \"traces\", tracesPayload(resource, records)),\n });\n\n let stopped = false;\n let userId: string | null = null;\n const globals = (): Attributes => {\n const g: Attributes = {};\n if (config.appClient) g[\"app.client\"] = config.appClient;\n if (userId) g[\"userId\"] = userId;\n return g;\n };\n\n // Context: ours, registered globally when allowed. If another manager got\n // there first, spans follow ITS context so the app's context.active() and\n // ours agree.\n const manager = new AsyncLocalContextManager();\n const registerGlobal = config.registerGlobal ?? true;\n const ownsContext =\n registerGlobal && contextApi.setGlobalContextManager(manager);\n const ctxOps: ContextOps = registerGlobal\n ? {\n active: () => contextApi.active(),\n with: (c, fn) => contextApi.with(c, fn),\n }\n : { active: () => manager.active(), with: (c, fn) => manager.with(c, fn) };\n const provider = new NodeTracerProvider(\n (span) => {\n if (!stopped) spans.push(span);\n },\n globals,\n ctxOps,\n );\n const ownsTrace = registerGlobal && trace.setGlobalTracerProvider(provider);\n const ownsPropagation =\n registerGlobal &&\n propagation.setGlobalPropagator(new TraceparentPropagator());\n const tracer = provider.getTracer(NODE_SCOPE_NAME, sdkVersion() || undefined);\n\n const minSeverity = SEVERITY[config.minSeverity ?? \"INFO\"] ?? SEVERITY.INFO;\n\n function emit(\n severity: SeverityText,\n body: string,\n attributes: Attributes,\n ): void {\n if (stopped || SEVERITY[severity] < minSeverity) {\n return;\n }\n const now = unixNanos(nowMs());\n const record: LogRecord = {\n timeUnixNano: now,\n observedTimeUnixNano: now,\n severityNumber: SEVERITY[severity],\n severityText: severity,\n body: { stringValue: scrubString(body, MAX_BODY_CHARS) },\n attributes: encodeAttributes({ ...globals(), ...attributes }),\n };\n const sc = trace.getSpanContext(ctxOps.active());\n if (sc && trace.isSpanContextValid(sc)) {\n record.traceId = sc.traceId;\n record.spanId = sc.spanId;\n record.flags = sc.traceFlags;\n }\n logs.push(record);\n }\n\n function log(\n severity: SeverityText,\n body: string,\n attrs?: LogAttributes,\n ): void {\n try {\n const { attributes, error } = sanitizeAttributes(attrs);\n // As observe: only an ERROR record gets exception inputs, and an\n // attribute the caller set wins over the derived one.\n const derived =\n severity === \"ERROR\" && error !== undefined\n ? exceptionAttributes(error, scrub)\n : {};\n emit(severity, body, { ...derived, ...attributes });\n } catch {\n // Telemetry must never break the app.\n }\n }\n\n const logger: NodeLogger = {\n debug: (b, a) => log(\"DEBUG\", b, a),\n info: (b, a) => log(\"INFO\", b, a),\n warn: (b, a) => log(\"WARN\", b, a),\n error: (b, a) => log(\"ERROR\", b, a),\n };\n\n function reportError(error: unknown, attrs?: LogAttributes): void {\n try {\n const { attributes } = sanitizeAttributes(attrs);\n emit(\"ERROR\", REPORTED_EXCEPTION_BODY, {\n ...exceptionAttributes(error, scrub),\n ...attributes,\n });\n } catch {\n // Telemetry must never break the app.\n }\n }\n\n // ── Process errors ──────────────────────────────────────────────────────\n const recorded = new WeakSet<object>();\n const repeats = new Map<string, { since: number; count: number }>();\n let drainScheduled = false;\n function recordFatal(value: unknown, body: string): void {\n if (typeof value === \"object\" && value !== null) {\n if (recorded.has(value)) return;\n recorded.add(value);\n }\n try {\n const attributes = exceptionAttributes(value, scrub);\n const key = [\n body,\n attributes[\"exception.type\"],\n attributes[\"code.function.name\"],\n attributes[\"exception.message\"],\n ].join(\"\\u001f\");\n const now = Date.now();\n let seen = repeats.get(key);\n if (!seen || now - seen.since >= 60_000) {\n if (repeats.size >= 256) repeats.clear();\n seen = { since: now, count: 0 };\n repeats.set(key, seen);\n }\n if (++seen.count > MAX_REPEATS_PER_MINUTE) {\n return;\n }\n emit(\"ERROR\", body, attributes);\n // A fatal record does not wait for its batch; a burst in one turn of the\n // event loop goes out as one request.\n if (!drainScheduled) {\n drainScheduled = true;\n setImmediate(() => {\n drainScheduled = false;\n logs.drain();\n }).unref();\n }\n } catch {\n // Telemetry must never break the app.\n }\n }\n const fatalFlushMs = config.fatalFlushTimeoutMs ?? DEFAULT_FLUSH_TIMEOUT_MS;\n\n const onMonitor = (err: unknown, origin: string): void => {\n recordFatal(\n err,\n origin === \"unhandledRejection\"\n ? UNHANDLED_REJECTION_BODY\n : UNCAUGHT_EXCEPTION_BODY,\n );\n };\n const onRejection = (reason: unknown): void => {\n recordFatal(reason, UNHANDLED_REJECTION_BODY);\n if (process.listenerCount(\"unhandledRejection\") > 1) {\n return; // The app handles rejections; it decides what happens next.\n }\n const mode = unhandledRejectionMode(\n process.execArgv,\n process.env.NODE_OPTIONS,\n );\n if (mode === \"warn\" || mode === \"none\") {\n return;\n }\n if (mode === \"warn-with-error-code\") {\n process.exitCode = 1;\n return;\n }\n // throw / strict: what Node does with no listener at all — raise it as an\n // uncaught exception — once the record is out.\n const err = reason instanceof Error ? reason : rejectionError(reason);\n recorded.add(err);\n void withTimeout(flushAll(), fatalFlushMs).then(() =>\n process.nextTick(() => {\n throw err;\n }),\n );\n };\n let exiting = false;\n const onUncaught = (err: unknown): void => {\n if (process.listenerCount(\"uncaughtException\") > 1 || exiting) {\n return; // The app's own handler owns the process's fate.\n }\n // Node's default (print, exit 1), after the record is out.\n exiting = true;\n void withTimeout(flushAll(), fatalFlushMs).then(() => {\n try {\n process.stderr.write(\n `${err instanceof Error && err.stack ? err.stack : inspect(err)}\\n`,\n );\n } catch {\n // stderr may be gone; the exit code still says what happened.\n }\n process.exit(1);\n });\n };\n const onBeforeExit = (): void => {\n if (logs.size > 0 || spans.size > 0) {\n void flushAll();\n }\n };\n\n const captureErrors = config.captureProcessErrors ?? true;\n if (captureErrors) {\n process.on(\"uncaughtExceptionMonitor\", onMonitor);\n process.on(\"unhandledRejection\", onRejection);\n if (!isElectron) {\n process.on(\"uncaughtException\", onUncaught);\n }\n }\n process.on(\"beforeExit\", onBeforeExit);\n setExceptionReporter((error, attributes) => reportError(error, attributes));\n\n function flushAll(): Promise<void> {\n return Promise.all([logs.flush(), spans.flush()]).then(() => undefined);\n }\n\n const instance: NodeTelemetry = {\n logger,\n tracer,\n reportError,\n setUser(id) {\n userId =\n typeof id === \"string\" && id !== \"\"\n ? id.slice(0, MAX_USER_ID_CHARS)\n : null;\n },\n flush(timeoutMs = DEFAULT_FLUSH_TIMEOUT_MS) {\n return withTimeout(flushAll(), timeoutMs);\n },\n async shutdown(timeoutMs = DEFAULT_FLUSH_TIMEOUT_MS) {\n if (stopped) return;\n await withTimeout(flushAll(), timeoutMs);\n stopped = true;\n process.removeListener(\"uncaughtExceptionMonitor\", onMonitor);\n process.removeListener(\"unhandledRejection\", onRejection);\n process.removeListener(\"uncaughtException\", onUncaught);\n process.removeListener(\"beforeExit\", onBeforeExit);\n setExceptionReporter(null);\n if (ownsTrace) trace.disable();\n if (ownsPropagation) propagation.disable();\n if (ownsContext) contextApi.disable();\n if (current === instance) current = null;\n },\n get dropped() {\n return logs.dropped + spans.dropped;\n },\n };\n return instance;\n}\n\nfunction safeHomedir(): string | undefined {\n try {\n return homedir() || undefined;\n } catch {\n return undefined;\n }\n}\n\n/** The slice of Electron's `app` flushOnQuit needs. */\nexport interface QuitApp {\n on(\n event: \"before-quit\",\n listener: (event: { preventDefault(): void }) => void,\n ): unknown;\n removeListener?(\n event: \"before-quit\",\n listener: (event: { preventDefault(): void }) => void,\n ): unknown;\n quit(): void;\n}\n\n/**\n * Hold Electron's quit until the running telemetry has flushed (bounded by\n * `timeoutMs`, default 2s), then quit. Returns a function that removes the\n * hook.\n *\n * It defers the FIRST quit and calls app.quit() again when the flush is done.\n * An app that already defers quit for its own shutdown (stops a backend, then\n * exits) should instead `await telemetry.flush()` as the last step of that\n * sequence: two listeners that each defer and re-quit cut each other short.\n */\nexport function flushOnQuit(\n app: QuitApp,\n options: { timeoutMs?: number } = {},\n): () => void {\n let flushed = false;\n const listener = (event: { preventDefault(): void }): void => {\n const t = current;\n if (flushed || !t) {\n return;\n }\n flushed = true;\n event.preventDefault();\n void t\n .flush(options.timeoutMs ?? DEFAULT_FLUSH_TIMEOUT_MS)\n .finally(() => app.quit());\n };\n app.on(\"before-quit\", listener);\n return () => {\n app.removeListener?.(\"before-quit\", listener);\n };\n}\n"]}
|
package/dist/service-hooks.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type DescMessage, type MessageInitShape } from "@bufbuild/protobuf";
|
|
2
|
-
import { type UseMutationOptions, type UseMutationResult, type UseQueryOptions, type UseQueryResult } from "@tanstack/react-query";
|
|
2
|
+
import { type InfiniteData, type UseInfiniteQueryOptions, type UseInfiniteQueryResult, type UseMutationOptions, type UseMutationResult, type UseQueryOptions, type UseQueryResult } from "@tanstack/react-query";
|
|
3
3
|
import type { ConnectClientError } from "./errors.js";
|
|
4
4
|
/**
|
|
5
5
|
* A generated query key. The tuple is [service, entity?, method,
|
|
@@ -32,6 +32,37 @@ export interface ServiceKeyBuilders {
|
|
|
32
32
|
* call-site prefetch/setQueryData use.
|
|
33
33
|
*/
|
|
34
34
|
query<Schema extends DescMessage>(method: string, schema: Schema, entityScope?: string): (req: MessageInitShape<Schema>) => ServiceQueryKey;
|
|
35
|
+
/**
|
|
36
|
+
* One paged read: [service, entity?, method, protojson(req), "infinite"],
|
|
37
|
+
* where req is the request WITHOUT its page token — the hook owns the
|
|
38
|
+
* token, so every page of one listing shares one cache entry.
|
|
39
|
+
*
|
|
40
|
+
* It nests under the same scopes as `query`, so an entity or service-wide
|
|
41
|
+
* invalidation refetches it. The "infinite" suffix keeps it OFF the plain
|
|
42
|
+
* query's entry for the same request: an infinite query caches
|
|
43
|
+
* `{ pages, pageParams }`, not one response, and a plain hook reading that
|
|
44
|
+
* entry would get the wrong shape.
|
|
45
|
+
*/
|
|
46
|
+
infinite<Schema extends DescMessage>(method: string, schema: Schema, entityScope?: string): (req: PageRequest<Schema>) => ServiceQueryKey;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Omit distributed over a union. MessageInitShape is `Message | init
|
|
50
|
+
* object`, and a plain Omit over a union keeps only the keys both members
|
|
51
|
+
* share — which would silently drop every field from the init side.
|
|
52
|
+
*/
|
|
53
|
+
type DistributiveOmit<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never;
|
|
54
|
+
/**
|
|
55
|
+
* The request a generated infinite hook takes: the rpc's request without
|
|
56
|
+
* `pageToken`, which the hook supplies page by page.
|
|
57
|
+
*/
|
|
58
|
+
export type PageRequest<Schema extends DescMessage> = DistributiveOmit<MessageInitShape<Schema>, "pageToken">;
|
|
59
|
+
/**
|
|
60
|
+
* The response shape forge's list-pagination convention (AIP-158) gives a
|
|
61
|
+
* paged read: `string next_page_token`, empty on the last page. Optional so
|
|
62
|
+
* an `optional string next_page_token` response satisfies it too.
|
|
63
|
+
*/
|
|
64
|
+
export interface PagedResponse {
|
|
65
|
+
nextPageToken?: string;
|
|
35
66
|
}
|
|
36
67
|
/**
|
|
37
68
|
* serviceKeys returns the builders for one service's query-key factory.
|
|
@@ -44,8 +75,44 @@ export interface ServiceKeyBuilders {
|
|
|
44
75
|
* what forge previously inlined into every generated hook file.
|
|
45
76
|
*/
|
|
46
77
|
export declare function serviceKeys(service: string): ServiceKeyBuilders;
|
|
47
|
-
/**
|
|
48
|
-
|
|
78
|
+
/**
|
|
79
|
+
* How a generated file calls one rpc. `signal` is React Query's: a query
|
|
80
|
+
* that is unmounted or superseded (a new key while typing) aborts its
|
|
81
|
+
* request instead of letting it land on a cache entry nobody reads.
|
|
82
|
+
*/
|
|
83
|
+
export type ServiceCall<Schema extends DescMessage, Response> = (req: MessageInitShape<Schema>, signal?: AbortSignal) => Promise<Response>;
|
|
84
|
+
/**
|
|
85
|
+
* A generated query hook: `useGetOrder(req, options?)`.
|
|
86
|
+
*
|
|
87
|
+
* TData is what the hook's `data` is, exactly as in React Query's own
|
|
88
|
+
* useQuery: the response by default, or whatever `select` returns. A call
|
|
89
|
+
* site mapping the proto response to a view model passes
|
|
90
|
+
* `select: (r) => toView(r)` and gets `data: View` — no useMemo over `data`,
|
|
91
|
+
* and React Query re-runs the mapping only when the response changes (or
|
|
92
|
+
* when `select` itself does, so hoist it or wrap it in useCallback when it
|
|
93
|
+
* is expensive). TData is inferred from `select` and is a parameter of the
|
|
94
|
+
* HOOK, not of the factory, so every call site picks its own.
|
|
95
|
+
*/
|
|
96
|
+
export type ServiceQueryHook<Schema extends DescMessage, Response> = <TData = Response>(req: MessageInitShape<Schema>, options?: Partial<UseQueryOptions<Response, ConnectClientError, TData>>) => UseQueryResult<TData, ConnectClientError>;
|
|
97
|
+
/**
|
|
98
|
+
* The options a generated infinite hook takes: React Query's own, minus the
|
|
99
|
+
* four the hook owns — the key, the fetch, and the page-token plumbing.
|
|
100
|
+
* `getNextPageParam` defaults to the response's `nextPageToken` (empty means
|
|
101
|
+
* last page) and may be overridden; everything else (`select`,
|
|
102
|
+
* `placeholderData`, `staleTime`, `enabled`, `maxPages`, …) passes through.
|
|
103
|
+
*/
|
|
104
|
+
export type ServiceInfiniteQueryOptions<Response, TData> = Partial<Omit<UseInfiniteQueryOptions<Response, ConnectClientError, TData, ServiceQueryKey, string>, "queryKey" | "queryFn" | "initialPageParam">>;
|
|
105
|
+
/**
|
|
106
|
+
* A generated infinite-query hook: `useListOrdersInfinite(req, options?)`,
|
|
107
|
+
* for a read that follows forge's list-pagination shape (`string page_token`
|
|
108
|
+
* on the request, `string next_page_token` on the response).
|
|
109
|
+
*
|
|
110
|
+
* `req` is the first page's request without its token. `data` is React
|
|
111
|
+
* Query's `{ pages, pageParams }` by default; `select` reshapes it, so
|
|
112
|
+
* flattening the pages into one list is
|
|
113
|
+
* `select: (d) => d.pages.flatMap((p) => p.orders)`.
|
|
114
|
+
*/
|
|
115
|
+
export type ServiceInfiniteQueryHook<Schema extends DescMessage, Response extends PagedResponse> = <TData = InfiniteData<Response, string>>(req: PageRequest<Schema>, options?: ServiceInfiniteQueryOptions<Response, TData>) => UseInfiniteQueryResult<TData, ConnectClientError>;
|
|
49
116
|
/**
|
|
50
117
|
* A generated mutation hook: `useCreateOrder(options?)`.
|
|
51
118
|
*
|
|
@@ -71,7 +138,23 @@ export type ServiceMutationHook<Schema extends DescMessage, Response> = <TContex
|
|
|
71
138
|
* and `.retryable`, and left `err.message.includes(...)` as the only
|
|
72
139
|
* expression that compiled — the one thing the error contract forbids.
|
|
73
140
|
*/
|
|
74
|
-
export declare function createQueryHook<Schema extends DescMessage, Response>(keyFor: (req: MessageInitShape<Schema>) => ServiceQueryKey, call:
|
|
141
|
+
export declare function createQueryHook<Schema extends DescMessage, Response>(keyFor: (req: MessageInitShape<Schema>) => ServiceQueryKey, call: ServiceCall<Schema, Response>): ServiceQueryHook<Schema, Response>;
|
|
142
|
+
/**
|
|
143
|
+
* createInfiniteQueryHook builds one useInfiniteQuery wrapper over a paged
|
|
144
|
+
* read.
|
|
145
|
+
*
|
|
146
|
+
* The page token is the hook's: the first page is fetched with the caller's
|
|
147
|
+
* request as given (no token, so an `optional string page_token` stays
|
|
148
|
+
* unset), each later one with the previous response's `nextPageToken`, and
|
|
149
|
+
* an empty token ends the listing. The key is `keys.infinite(...)`, which
|
|
150
|
+
* strips the token and sits under the service and entity scopes, so the
|
|
151
|
+
* mutations that invalidate a plain list refetch this one too.
|
|
152
|
+
*
|
|
153
|
+
* The caller's options are spread BETWEEN the default getNextPageParam and
|
|
154
|
+
* the four fields the hook owns: a caller may replace the default, never the
|
|
155
|
+
* key or the fetch.
|
|
156
|
+
*/
|
|
157
|
+
export declare function createInfiniteQueryHook<Schema extends DescMessage, Response extends PagedResponse>(keyFor: (req: PageRequest<Schema>) => ServiceQueryKey, call: ServiceCall<Schema, Response>): ServiceInfiniteQueryHook<Schema, Response>;
|
|
75
158
|
/**
|
|
76
159
|
* createMutationHook builds one useMutation wrapper with scoped invalidation.
|
|
77
160
|
*
|
|
@@ -87,3 +170,4 @@ export declare function createQueryHook<Schema extends DescMessage, Response>(ke
|
|
|
87
170
|
* spread over a default onSuccess would do.
|
|
88
171
|
*/
|
|
89
172
|
export declare function createMutationHook<Schema extends DescMessage, Response>(invalidateKey: ServiceQueryKey, call: (req: MessageInitShape<Schema>) => Promise<Response>): ServiceMutationHook<Schema, Response>;
|
|
173
|
+
export {};
|
package/dist/service-hooks.js
CHANGED
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
// either: "CreateOrder succeeded" leaks RPC names into the UI, so the toast /
|
|
37
37
|
// redirect / inline confirmation stays the call site's via options.onSuccess.
|
|
38
38
|
import { create, toJson, } from "@bufbuild/protobuf";
|
|
39
|
-
import { useMutation, useQuery, useQueryClient, } from "@tanstack/react-query";
|
|
39
|
+
import { useInfiniteQuery, useMutation, useQuery, useQueryClient, } from "@tanstack/react-query";
|
|
40
40
|
/**
|
|
41
41
|
* requestKey projects a request init into protojson for use inside a query
|
|
42
42
|
* key. Two reasons this is not the raw request object:
|
|
@@ -52,6 +52,21 @@ import { useMutation, useQuery, useQueryClient, } from "@tanstack/react-query";
|
|
|
52
52
|
export function requestKey(schema, req) {
|
|
53
53
|
return toJson(schema, create(schema, req));
|
|
54
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* pageRequestKey is requestKey with the page token dropped, so every page of
|
|
57
|
+
* one listing hashes to one key even when a caller (JS, or a cast) passes a
|
|
58
|
+
* token anyway. It is dropped from the protojson rather than from the init
|
|
59
|
+
* object: a spread Message keeps its $typeName, and create() would hand that
|
|
60
|
+
* token-less copy back as if it were a complete message.
|
|
61
|
+
*/
|
|
62
|
+
function pageRequestKey(schema, req) {
|
|
63
|
+
const json = requestKey(schema, req);
|
|
64
|
+
if (json === null || typeof json !== "object" || Array.isArray(json)) {
|
|
65
|
+
return json;
|
|
66
|
+
}
|
|
67
|
+
const { pageToken: _pageToken, ...rest } = json;
|
|
68
|
+
return rest;
|
|
69
|
+
}
|
|
55
70
|
/**
|
|
56
71
|
* serviceKeys returns the builders for one service's query-key factory.
|
|
57
72
|
*
|
|
@@ -69,6 +84,20 @@ export function serviceKeys(service) {
|
|
|
69
84
|
query: (method, schema, entityScope) => (req) => entityScope === undefined
|
|
70
85
|
? [service, method, requestKey(schema, req)]
|
|
71
86
|
: [service, entityScope, method, requestKey(schema, req)],
|
|
87
|
+
infinite: (method, schema, entityScope) => (req) => entityScope === undefined
|
|
88
|
+
? [
|
|
89
|
+
service,
|
|
90
|
+
method,
|
|
91
|
+
pageRequestKey(schema, req),
|
|
92
|
+
"infinite",
|
|
93
|
+
]
|
|
94
|
+
: [
|
|
95
|
+
service,
|
|
96
|
+
entityScope,
|
|
97
|
+
method,
|
|
98
|
+
pageRequestKey(schema, req),
|
|
99
|
+
"infinite",
|
|
100
|
+
],
|
|
72
101
|
};
|
|
73
102
|
}
|
|
74
103
|
/**
|
|
@@ -86,10 +115,39 @@ export function serviceKeys(service) {
|
|
|
86
115
|
export function createQueryHook(keyFor, call) {
|
|
87
116
|
return (req, options) => useQuery({
|
|
88
117
|
queryKey: keyFor(req),
|
|
89
|
-
queryFn: () => call(req),
|
|
118
|
+
queryFn: ({ signal }) => call(req, signal),
|
|
90
119
|
...options,
|
|
91
120
|
});
|
|
92
121
|
}
|
|
122
|
+
/**
|
|
123
|
+
* createInfiniteQueryHook builds one useInfiniteQuery wrapper over a paged
|
|
124
|
+
* read.
|
|
125
|
+
*
|
|
126
|
+
* The page token is the hook's: the first page is fetched with the caller's
|
|
127
|
+
* request as given (no token, so an `optional string page_token` stays
|
|
128
|
+
* unset), each later one with the previous response's `nextPageToken`, and
|
|
129
|
+
* an empty token ends the listing. The key is `keys.infinite(...)`, which
|
|
130
|
+
* strips the token and sits under the service and entity scopes, so the
|
|
131
|
+
* mutations that invalidate a plain list refetch this one too.
|
|
132
|
+
*
|
|
133
|
+
* The caller's options are spread BETWEEN the default getNextPageParam and
|
|
134
|
+
* the four fields the hook owns: a caller may replace the default, never the
|
|
135
|
+
* key or the fetch.
|
|
136
|
+
*/
|
|
137
|
+
export function createInfiniteQueryHook(keyFor, call) {
|
|
138
|
+
return (req, options) => useInfiniteQuery({
|
|
139
|
+
getNextPageParam: (last) => last.nextPageToken || undefined,
|
|
140
|
+
...options,
|
|
141
|
+
queryKey: keyFor(req),
|
|
142
|
+
queryFn: ({ pageParam, signal }) => call((pageParam === ""
|
|
143
|
+
? req
|
|
144
|
+
: {
|
|
145
|
+
...req,
|
|
146
|
+
pageToken: pageParam,
|
|
147
|
+
}), signal),
|
|
148
|
+
initialPageParam: "",
|
|
149
|
+
});
|
|
150
|
+
}
|
|
93
151
|
/**
|
|
94
152
|
* createMutationHook builds one useMutation wrapper with scoped invalidation.
|
|
95
153
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service-hooks.js","sourceRoot":"","sources":["../src/service-hooks.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,sEAAsE;AACtE,EAAE;AACF,8EAA8E;AAC9E,6EAA6E;AAC7E,uEAAuE;AACvE,6EAA6E;AAC7E,+EAA+E;AAC/E,yEAAyE;AACzE,gEAAgE;AAChE,EAAE;AACF,8EAA8E;AAC9E,kDAAkD;AAClD,EAAE;AACF,6EAA6E;AAC7E,2EAA2E;AAC3E,qEAAqE;AACrE,qEAAqE;AACrE,+EAA+E;AAC/E,4EAA4E;AAC5E,8EAA8E;AAC9E,sEAAsE;AACtE,EAAE;AACF,+EAA+E;AAC/E,2EAA2E;AAC3E,sEAAsE;AACtE,wEAAwE;AACxE,6EAA6E;AAC7E,4EAA4E;AAC5E,mCAAmC;AACnC,EAAE;AACF,wEAAwE;AACxE,8EAA8E;AAC9E,uDAAuD;AACvD,yEAAyE;AACzE,8EAA8E;AAC9E,8EAA8E;AAC9E,OAAO,EACL,MAAM,EACN,MAAM,GAGP,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,WAAW,EACX,QAAQ,EACR,cAAc,GAKf,MAAM,uBAAuB,CAAC;AAW/B;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,UAAU,CACxB,MAAc,EACd,GAA6B;IAE7B,OAAO,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;AAC7C,CAAC;AAoBD;;;;;;;;;GASG;AACH,MAAM,UAAU,WAAW,CAAC,OAAe;IACzC,OAAO;QACL,GAAG,EAAE,CAAC,OAAO,CAAU;QACvB,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,IAAI,CAAU;QAClD,KAAK,EACH,CACE,MAAc,EACd,MAAc,EACd,WAAoB,EACpB,EAAE,CACJ,CAAC,GAA6B,EAAmB,EAAE,CACjD,WAAW,KAAK,SAAS;YACvB,CAAC,CAAE,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,GAAG,CAAC,CAAW;YACvD,CAAC,CAAE,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,GAAG,CAAC,CAAW;KAC3E,CAAC;AACJ,CAAC;AAsCD;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,eAAe,CAC7B,MAA0D,EAC1D,IAA0D;IAE1D,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,CACtB,QAAQ,CAAC;QACP,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC;QACrB,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC;QACxB,GAAG,OAAO;KACX,CAAC,CAAC;AACP,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,kBAAkB,CAChC,aAA8B,EAC9B,IAA0D;IAE1D,OAAO,CACL,OAOC,EACD,EAAE;QACF,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;QACrC,MAAM,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,GAAG,OAAO,IAAI,EAAE,CAAC;QAC7C,OAAO,WAAW,CAKhB;YACA,UAAU,EAAE,CAAC,GAA6B,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC;YACxD,SAAS,EAAE,CAAC,GAAG,IAAI,EAAE,EAAE;gBACrB,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,aAAa,EAAE,CAAC,CAAC;gBAC3D,SAAS,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;YACvB,CAAC;YACD,GAAG,IAAI;SACR,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC","sourcesContent":["\"use client\";\n\n// Part of @reliantlabs/forge-web-runtime — the web twin of forge/pkg.\n//\n// Every export below is a React hook or builds one, so this module belongs in\n// the CLIENT graph. Without the directive the Next.js App Router compiles it\n// into the SERVER graph, where it binds a SECOND @tanstack/react-query\n// instance and every generated hook throws \"No QueryClient set\" at runtime —\n// invisible to tsc, eslint AND `next build`. published-surface.test.ts asserts\n// the directive survives into dist/. It is NOT applied package-wide: the\n// ./interceptors subpath exists to be importable without React.\n//\n// The React Query wrapper machinery behind forge's generated per-service hook\n// files (`src/hooks/<svc>-service-hooks_gen.ts`).\n//\n// WHAT WAS HERE BEFORE. Each generated file re-emitted the same three things\n// per RPC: a query-key entry, a useQuery or useMutation wrapper, and — for\n// mutations — the entity-scoped invalidateQueries plus the onSuccess\n// composition, with the reasoning for each re-inlined as comments. A\n// five-service project rendered five copies of machinery that differed only in\n// RPC names and message types. This module IS that machinery, written once.\n// The generated file keeps exactly what varies per RPC: the name, the request\n// schema, the response type, query-vs-mutation, and the entity scope.\n//\n// WHY A SUBPATH AND NOT THE BARREL. This module imports @tanstack/react-query.\n// Every browser frontend forge scaffolds depends on it — but the barrel is\n// also what a consumer imports for interceptors and errors alone, and\n// anchoring React Query there would make a non-React consumer resolve a\n// package it never installed. Same reasoning as ./mock-transport and ./otel:\n// an engine with its own dependency footprint gets its own entry point, and\n// React Query is an OPTIONAL peer.\n//\n// WHAT IT DELIBERATELY DOES NOT DO. It does not emit error toasts — the\n// app-wide MutationCache in src/lib/query-client.ts is the single error-toast\n// chokepoint, and pages that render errors inline pass\n// `meta: { silenceErrorToast: true }`. It never defaults success-side UX\n// either: \"CreateOrder succeeded\" leaks RPC names into the UI, so the toast /\n// redirect / inline confirmation stays the call site's via options.onSuccess.\nimport {\n create,\n toJson,\n type DescMessage,\n type MessageInitShape,\n} from \"@bufbuild/protobuf\";\nimport {\n useMutation,\n useQuery,\n useQueryClient,\n type UseMutationOptions,\n type UseMutationResult,\n type UseQueryOptions,\n type UseQueryResult,\n} from \"@tanstack/react-query\";\n\nimport type { ConnectClientError } from \"./errors.js\";\n\n/**\n * A generated query key. The tuple is [service, entity?, method,\n * protojson(req)] for a method key and [service] / [service, entity] for the\n * broader scopes.\n */\nexport type ServiceQueryKey = readonly unknown[];\n\n/**\n * requestKey projects a request init into protojson for use inside a query\n * key. Two reasons this is not the raw request object:\n *\n * - React Query's default hasher is JSON.stringify, which THROWS on bigint\n * fields (any proto int64) — the raw message crashes the cache.\n * - protojson normalizes representations, so { id: 1 } and { id: \"1\" } land\n * in ONE cache entry instead of silently splitting the cache.\n *\n * Exported because a hand-written hook that wants to share a generated hook's\n * cache entry has to hash its request the identical way.\n */\nexport function requestKey<Schema extends DescMessage>(\n schema: Schema,\n req: MessageInitShape<Schema>,\n): unknown {\n return toJson(schema, create(schema, req));\n}\n\n/** The three key-scope builders a generated key factory is assembled from. */\nexport interface ServiceKeyBuilders {\n /** Every query on this service: [service]. */\n readonly all: readonly [string];\n /** Every query for one CRUD entity: [service, entity]. Mutations invalidate this. */\n entity(name: string): readonly [string, string];\n /**\n * One query: [service, entity?, method, protojson(req)]. Returns the\n * per-request key FUNCTION, which is what both the query hook and any\n * call-site prefetch/setQueryData use.\n */\n query<Schema extends DescMessage>(\n method: string,\n schema: Schema,\n entityScope?: string,\n ): (req: MessageInitShape<Schema>) => ServiceQueryKey;\n}\n\n/**\n * serviceKeys returns the builders for one service's query-key factory.\n *\n * Cache-key semantics are a compatibility contract, not an implementation\n * detail: an existing app's\n * `invalidateQueries({ queryKey: orderServiceKeys.order })` has to keep\n * matching the keys its queries were registered under across a version bump.\n * So the tuple order and contents produced here are fixed, and identical to\n * what forge previously inlined into every generated hook file.\n */\nexport function serviceKeys(service: string): ServiceKeyBuilders {\n return {\n all: [service] as const,\n entity: (name: string) => [service, name] as const,\n query:\n <Schema extends DescMessage>(\n method: string,\n schema: Schema,\n entityScope?: string,\n ) =>\n (req: MessageInitShape<Schema>): ServiceQueryKey =>\n entityScope === undefined\n ? ([service, method, requestKey(schema, req)] as const)\n : ([service, entityScope, method, requestKey(schema, req)] as const),\n };\n}\n\n/** A generated query hook: `useGetOrder(req, options?)`. */\nexport type ServiceQueryHook<Schema extends DescMessage, Response> = (\n req: MessageInitShape<Schema>,\n options?: Partial<UseQueryOptions<Response, ConnectClientError>>,\n) => UseQueryResult<Response, ConnectClientError>;\n\n/**\n * A generated mutation hook: `useCreateOrder(options?)`.\n *\n * TContext is React Query's fourth type parameter — what `onMutate` returns\n * and `onError` / `onSettled` receive back. It is a parameter of the HOOK,\n * not of the factory, so each call site gets its own: TypeScript infers it\n * from the `onMutate` the caller passes, and an optimistic update reads its\n * rollback off `context` with no cast. Fixing it at the factory (or leaving\n * it out, which pinned it to `unknown`) forced every such call site to\n * narrow `unknown` by hand. It defaults to `unknown`, so a call without\n * `onMutate` types exactly as before.\n */\nexport type ServiceMutationHook<Schema extends DescMessage, Response> = <\n TContext = unknown,\n>(\n options?: Partial<\n UseMutationOptions<\n Response,\n ConnectClientError,\n MessageInitShape<Schema>,\n TContext\n >\n >,\n) => UseMutationResult<\n Response,\n ConnectClientError,\n MessageInitShape<Schema>,\n TContext\n>;\n\n/**\n * createQueryHook builds one useQuery wrapper.\n *\n * The signature it returns is the one call sites already use — `(req,\n * options?)`, with the error typed as ConnectClientError rather than React\n * Query's default `Error`. That type is declared on the OPTIONS parameter\n * because React Query takes the result's error type from the same TError it\n * reads there, so `query.error` is a ConnectClientError at every call site\n * with nothing to pass. Typing it as `Error` hid `.reason`, `.codeName`, `.status`\n * and `.retryable`, and left `err.message.includes(...)` as the only\n * expression that compiled — the one thing the error contract forbids.\n */\nexport function createQueryHook<Schema extends DescMessage, Response>(\n keyFor: (req: MessageInitShape<Schema>) => ServiceQueryKey,\n call: (req: MessageInitShape<Schema>) => Promise<Response>,\n): ServiceQueryHook<Schema, Response> {\n return (req, options) =>\n useQuery({\n queryKey: keyFor(req),\n queryFn: () => call(req),\n ...options,\n });\n}\n\n/**\n * createMutationHook builds one useMutation wrapper with scoped invalidation.\n *\n * invalidateKey is the entity scope when the RPC maps to a CRUD entity, and\n * the whole-service scope otherwise — a bespoke mutation may touch anything,\n * so over-invalidating is the safe default there.\n *\n * The invalidation is composed BEFORE the caller's onSuccess and is never\n * replaced by it: onSuccess is destructured out and re-invoked after the\n * invalidate, while the rest of the options object is spread separately. A\n * caller passing onSuccess therefore ADDS behaviour, rather than silently\n * disabling the cache refresh — which is exactly what a plain `...options`\n * spread over a default onSuccess would do.\n */\nexport function createMutationHook<Schema extends DescMessage, Response>(\n invalidateKey: ServiceQueryKey,\n call: (req: MessageInitShape<Schema>) => Promise<Response>,\n): ServiceMutationHook<Schema, Response> {\n return <TContext = unknown>(\n options?: Partial<\n UseMutationOptions<\n Response,\n ConnectClientError,\n MessageInitShape<Schema>,\n TContext\n >\n >,\n ) => {\n const queryClient = useQueryClient();\n const { onSuccess, ...rest } = options ?? {};\n return useMutation<\n Response,\n ConnectClientError,\n MessageInitShape<Schema>,\n TContext\n >({\n mutationFn: (req: MessageInitShape<Schema>) => call(req),\n onSuccess: (...args) => {\n queryClient.invalidateQueries({ queryKey: invalidateKey });\n onSuccess?.(...args);\n },\n ...rest,\n });\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"service-hooks.js","sourceRoot":"","sources":["../src/service-hooks.ts"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\n\n// Part of @reliantlabs/forge-web-runtime — the web twin of forge/pkg.\n//\n// Every export below is a React hook or builds one, so this module belongs in\n// the CLIENT graph. Without the directive the Next.js App Router compiles it\n// into the SERVER graph, where it binds a SECOND @tanstack/react-query\n// instance and every generated hook throws \"No QueryClient set\" at runtime —\n// invisible to tsc, eslint AND `next build`. published-surface.test.ts asserts\n// the directive survives into dist/. It is NOT applied package-wide: the\n// ./interceptors subpath exists to be importable without React.\n//\n// The React Query wrapper machinery behind forge's generated per-service hook\n// files (`src/hooks/<svc>-service-hooks_gen.ts`).\n//\n// WHAT WAS HERE BEFORE. Each generated file re-emitted the same three things\n// per RPC: a query-key entry, a useQuery or useMutation wrapper, and — for\n// mutations — the entity-scoped invalidateQueries plus the onSuccess\n// composition, with the reasoning for each re-inlined as comments. A\n// five-service project rendered five copies of machinery that differed only in\n// RPC names and message types. This module IS that machinery, written once.\n// The generated file keeps exactly what varies per RPC: the name, the request\n// schema, the response type, query-vs-mutation, and the entity scope.\n//\n// WHY A SUBPATH AND NOT THE BARREL. This module imports @tanstack/react-query.\n// Every browser frontend forge scaffolds depends on it — but the barrel is\n// also what a consumer imports for interceptors and errors alone, and\n// anchoring React Query there would make a non-React consumer resolve a\n// package it never installed. Same reasoning as ./mock-transport and ./otel:\n// an engine with its own dependency footprint gets its own entry point, and\n// React Query is an OPTIONAL peer.\n//\n// WHAT IT DELIBERATELY DOES NOT DO. It does not emit error toasts — the\n// app-wide MutationCache in src/lib/query-client.ts is the single error-toast\n// chokepoint, and pages that render errors inline pass\n// `meta: { silenceErrorToast: true }`. It never defaults success-side UX\n// either: \"CreateOrder succeeded\" leaks RPC names into the UI, so the toast /\n// redirect / inline confirmation stays the call site's via options.onSuccess.\nimport {\n create,\n toJson,\n type DescMessage,\n type MessageInitShape,\n} from \"@bufbuild/protobuf\";\nimport {\n useInfiniteQuery,\n useMutation,\n useQuery,\n useQueryClient,\n type InfiniteData,\n type UseInfiniteQueryOptions,\n type UseInfiniteQueryResult,\n type UseMutationOptions,\n type UseMutationResult,\n type UseQueryOptions,\n type UseQueryResult,\n} from \"@tanstack/react-query\";\n\nimport type { ConnectClientError } from \"./errors.js\";\n\n/**\n * A generated query key. The tuple is [service, entity?, method,\n * protojson(req)] for a method key and [service] / [service, entity] for the\n * broader scopes.\n */\nexport type ServiceQueryKey = readonly unknown[];\n\n/**\n * requestKey projects a request init into protojson for use inside a query\n * key. Two reasons this is not the raw request object:\n *\n * - React Query's default hasher is JSON.stringify, which THROWS on bigint\n * fields (any proto int64) — the raw message crashes the cache.\n * - protojson normalizes representations, so { id: 1 } and { id: \"1\" } land\n * in ONE cache entry instead of silently splitting the cache.\n *\n * Exported because a hand-written hook that wants to share a generated hook's\n * cache entry has to hash its request the identical way.\n */\nexport function requestKey<Schema extends DescMessage>(\n schema: Schema,\n req: MessageInitShape<Schema>,\n): unknown {\n return toJson(schema, create(schema, req));\n}\n\n/** The three key-scope builders a generated key factory is assembled from. */\nexport interface ServiceKeyBuilders {\n /** Every query on this service: [service]. */\n readonly all: readonly [string];\n /** Every query for one CRUD entity: [service, entity]. Mutations invalidate this. */\n entity(name: string): readonly [string, string];\n /**\n * One query: [service, entity?, method, protojson(req)]. Returns the\n * per-request key FUNCTION, which is what both the query hook and any\n * call-site prefetch/setQueryData use.\n */\n query<Schema extends DescMessage>(\n method: string,\n schema: Schema,\n entityScope?: string,\n ): (req: MessageInitShape<Schema>) => ServiceQueryKey;\n /**\n * One paged read: [service, entity?, method, protojson(req), \"infinite\"],\n * where req is the request WITHOUT its page token — the hook owns the\n * token, so every page of one listing shares one cache entry.\n *\n * It nests under the same scopes as `query`, so an entity or service-wide\n * invalidation refetches it. The \"infinite\" suffix keeps it OFF the plain\n * query's entry for the same request: an infinite query caches\n * `{ pages, pageParams }`, not one response, and a plain hook reading that\n * entry would get the wrong shape.\n */\n infinite<Schema extends DescMessage>(\n method: string,\n schema: Schema,\n entityScope?: string,\n ): (req: PageRequest<Schema>) => ServiceQueryKey;\n}\n\n/**\n * Omit distributed over a union. MessageInitShape is `Message | init\n * object`, and a plain Omit over a union keeps only the keys both members\n * share — which would silently drop every field from the init side.\n */\ntype DistributiveOmit<T, K extends PropertyKey> = T extends unknown\n ? Omit<T, K>\n : never;\n\n/**\n * The request a generated infinite hook takes: the rpc's request without\n * `pageToken`, which the hook supplies page by page.\n */\nexport type PageRequest<Schema extends DescMessage> = DistributiveOmit<\n MessageInitShape<Schema>,\n \"pageToken\"\n>;\n\n/**\n * The response shape forge's list-pagination convention (AIP-158) gives a\n * paged read: `string next_page_token`, empty on the last page. Optional so\n * an `optional string next_page_token` response satisfies it too.\n */\nexport interface PagedResponse {\n nextPageToken?: string;\n}\n\n/**\n * pageRequestKey is requestKey with the page token dropped, so every page of\n * one listing hashes to one key even when a caller (JS, or a cast) passes a\n * token anyway. It is dropped from the protojson rather than from the init\n * object: a spread Message keeps its $typeName, and create() would hand that\n * token-less copy back as if it were a complete message.\n */\nfunction pageRequestKey<Schema extends DescMessage>(\n schema: Schema,\n req: PageRequest<Schema>,\n): unknown {\n const json = requestKey(schema, req as unknown as MessageInitShape<Schema>);\n if (json === null || typeof json !== \"object\" || Array.isArray(json)) {\n return json;\n }\n const { pageToken: _pageToken, ...rest } = json as Record<string, unknown>;\n return rest;\n}\n\n/**\n * serviceKeys returns the builders for one service's query-key factory.\n *\n * Cache-key semantics are a compatibility contract, not an implementation\n * detail: an existing app's\n * `invalidateQueries({ queryKey: orderServiceKeys.order })` has to keep\n * matching the keys its queries were registered under across a version bump.\n * So the tuple order and contents produced here are fixed, and identical to\n * what forge previously inlined into every generated hook file.\n */\nexport function serviceKeys(service: string): ServiceKeyBuilders {\n return {\n all: [service] as const,\n entity: (name: string) => [service, name] as const,\n query:\n <Schema extends DescMessage>(\n method: string,\n schema: Schema,\n entityScope?: string,\n ) =>\n (req: MessageInitShape<Schema>): ServiceQueryKey =>\n entityScope === undefined\n ? ([service, method, requestKey(schema, req)] as const)\n : ([service, entityScope, method, requestKey(schema, req)] as const),\n infinite:\n <Schema extends DescMessage>(\n method: string,\n schema: Schema,\n entityScope?: string,\n ) =>\n (req: PageRequest<Schema>): ServiceQueryKey =>\n entityScope === undefined\n ? ([\n service,\n method,\n pageRequestKey(schema, req),\n \"infinite\",\n ] as const)\n : ([\n service,\n entityScope,\n method,\n pageRequestKey(schema, req),\n \"infinite\",\n ] as const),\n };\n}\n\n/**\n * How a generated file calls one rpc. `signal` is React Query's: a query\n * that is unmounted or superseded (a new key while typing) aborts its\n * request instead of letting it land on a cache entry nobody reads.\n */\nexport type ServiceCall<Schema extends DescMessage, Response> = (\n req: MessageInitShape<Schema>,\n signal?: AbortSignal,\n) => Promise<Response>;\n\n/**\n * A generated query hook: `useGetOrder(req, options?)`.\n *\n * TData is what the hook's `data` is, exactly as in React Query's own\n * useQuery: the response by default, or whatever `select` returns. A call\n * site mapping the proto response to a view model passes\n * `select: (r) => toView(r)` and gets `data: View` — no useMemo over `data`,\n * and React Query re-runs the mapping only when the response changes (or\n * when `select` itself does, so hoist it or wrap it in useCallback when it\n * is expensive). TData is inferred from `select` and is a parameter of the\n * HOOK, not of the factory, so every call site picks its own.\n */\nexport type ServiceQueryHook<Schema extends DescMessage, Response> = <\n TData = Response,\n>(\n req: MessageInitShape<Schema>,\n options?: Partial<UseQueryOptions<Response, ConnectClientError, TData>>,\n) => UseQueryResult<TData, ConnectClientError>;\n\n/**\n * The options a generated infinite hook takes: React Query's own, minus the\n * four the hook owns — the key, the fetch, and the page-token plumbing.\n * `getNextPageParam` defaults to the response's `nextPageToken` (empty means\n * last page) and may be overridden; everything else (`select`,\n * `placeholderData`, `staleTime`, `enabled`, `maxPages`, …) passes through.\n */\nexport type ServiceInfiniteQueryOptions<Response, TData> = Partial<\n Omit<\n UseInfiniteQueryOptions<\n Response,\n ConnectClientError,\n TData,\n ServiceQueryKey,\n string\n >,\n \"queryKey\" | \"queryFn\" | \"initialPageParam\"\n >\n>;\n\n/**\n * A generated infinite-query hook: `useListOrdersInfinite(req, options?)`,\n * for a read that follows forge's list-pagination shape (`string page_token`\n * on the request, `string next_page_token` on the response).\n *\n * `req` is the first page's request without its token. `data` is React\n * Query's `{ pages, pageParams }` by default; `select` reshapes it, so\n * flattening the pages into one list is\n * `select: (d) => d.pages.flatMap((p) => p.orders)`.\n */\nexport type ServiceInfiniteQueryHook<\n Schema extends DescMessage,\n Response extends PagedResponse,\n> = <TData = InfiniteData<Response, string>>(\n req: PageRequest<Schema>,\n options?: ServiceInfiniteQueryOptions<Response, TData>,\n) => UseInfiniteQueryResult<TData, ConnectClientError>;\n\n/**\n * A generated mutation hook: `useCreateOrder(options?)`.\n *\n * TContext is React Query's fourth type parameter — what `onMutate` returns\n * and `onError` / `onSettled` receive back. It is a parameter of the HOOK,\n * not of the factory, so each call site gets its own: TypeScript infers it\n * from the `onMutate` the caller passes, and an optimistic update reads its\n * rollback off `context` with no cast. Fixing it at the factory (or leaving\n * it out, which pinned it to `unknown`) forced every such call site to\n * narrow `unknown` by hand. It defaults to `unknown`, so a call without\n * `onMutate` types exactly as before.\n */\nexport type ServiceMutationHook<Schema extends DescMessage, Response> = <\n TContext = unknown,\n>(\n options?: Partial<\n UseMutationOptions<\n Response,\n ConnectClientError,\n MessageInitShape<Schema>,\n TContext\n >\n >,\n) => UseMutationResult<\n Response,\n ConnectClientError,\n MessageInitShape<Schema>,\n TContext\n>;\n\n/**\n * createQueryHook builds one useQuery wrapper.\n *\n * The signature it returns is the one call sites already use — `(req,\n * options?)`, with the error typed as ConnectClientError rather than React\n * Query's default `Error`. That type is declared on the OPTIONS parameter\n * because React Query takes the result's error type from the same TError it\n * reads there, so `query.error` is a ConnectClientError at every call site\n * with nothing to pass. Typing it as `Error` hid `.reason`, `.codeName`, `.status`\n * and `.retryable`, and left `err.message.includes(...)` as the only\n * expression that compiled — the one thing the error contract forbids.\n */\nexport function createQueryHook<Schema extends DescMessage, Response>(\n keyFor: (req: MessageInitShape<Schema>) => ServiceQueryKey,\n call: ServiceCall<Schema, Response>,\n): ServiceQueryHook<Schema, Response> {\n return <TData = Response>(\n req: MessageInitShape<Schema>,\n options?: Partial<UseQueryOptions<Response, ConnectClientError, TData>>,\n ) =>\n useQuery<Response, ConnectClientError, TData>({\n queryKey: keyFor(req),\n queryFn: ({ signal }) => call(req, signal),\n ...options,\n });\n}\n\n/**\n * createInfiniteQueryHook builds one useInfiniteQuery wrapper over a paged\n * read.\n *\n * The page token is the hook's: the first page is fetched with the caller's\n * request as given (no token, so an `optional string page_token` stays\n * unset), each later one with the previous response's `nextPageToken`, and\n * an empty token ends the listing. The key is `keys.infinite(...)`, which\n * strips the token and sits under the service and entity scopes, so the\n * mutations that invalidate a plain list refetch this one too.\n *\n * The caller's options are spread BETWEEN the default getNextPageParam and\n * the four fields the hook owns: a caller may replace the default, never the\n * key or the fetch.\n */\nexport function createInfiniteQueryHook<\n Schema extends DescMessage,\n Response extends PagedResponse,\n>(\n keyFor: (req: PageRequest<Schema>) => ServiceQueryKey,\n call: ServiceCall<Schema, Response>,\n): ServiceInfiniteQueryHook<Schema, Response> {\n return <TData = InfiniteData<Response, string>>(\n req: PageRequest<Schema>,\n options?: ServiceInfiniteQueryOptions<Response, TData>,\n ) =>\n useInfiniteQuery<\n Response,\n ConnectClientError,\n TData,\n ServiceQueryKey,\n string\n >({\n getNextPageParam: (last) => last.nextPageToken || undefined,\n ...options,\n queryKey: keyFor(req),\n queryFn: ({ pageParam, signal }) =>\n call(\n (pageParam === \"\"\n ? req\n : {\n ...req,\n pageToken: pageParam,\n }) as unknown as MessageInitShape<Schema>,\n signal,\n ),\n initialPageParam: \"\",\n });\n}\n\n/**\n * createMutationHook builds one useMutation wrapper with scoped invalidation.\n *\n * invalidateKey is the entity scope when the RPC maps to a CRUD entity, and\n * the whole-service scope otherwise — a bespoke mutation may touch anything,\n * so over-invalidating is the safe default there.\n *\n * The invalidation is composed BEFORE the caller's onSuccess and is never\n * replaced by it: onSuccess is destructured out and re-invoked after the\n * invalidate, while the rest of the options object is spread separately. A\n * caller passing onSuccess therefore ADDS behaviour, rather than silently\n * disabling the cache refresh — which is exactly what a plain `...options`\n * spread over a default onSuccess would do.\n */\nexport function createMutationHook<Schema extends DescMessage, Response>(\n invalidateKey: ServiceQueryKey,\n call: (req: MessageInitShape<Schema>) => Promise<Response>,\n): ServiceMutationHook<Schema, Response> {\n return <TContext = unknown>(\n options?: Partial<\n UseMutationOptions<\n Response,\n ConnectClientError,\n MessageInitShape<Schema>,\n TContext\n >\n >,\n ) => {\n const queryClient = useQueryClient();\n const { onSuccess, ...rest } = options ?? {};\n return useMutation<\n Response,\n ConnectClientError,\n MessageInitShape<Schema>,\n TContext\n >({\n mutationFn: (req: MessageInitShape<Schema>) => call(req),\n onSuccess: (...args) => {\n queryClient.invalidateQueries({ queryKey: invalidateKey });\n onSuccess?.(...args);\n },\n ...rest,\n });\n };\n}\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Part of @reliantlabs/forge-web-runtime — the web twin of forge/pkg.
|
|
2
|
+
//
|
|
3
|
+
// A frontend's `service.name`, derived exactly as forge derives it
|
|
4
|
+
// (internal/naming.FrontendServiceName): `<project>-<frontend>`. The generated
|
|
5
|
+
// observability — the frontend dashboard's panel scope and the frontend alert
|
|
6
|
+
// defaults — filters on that name, so telemetry reporting anything else is
|
|
7
|
+
// invisible to both. The cases in testdata/frontend-service-names.json are
|
|
8
|
+
// read by this package's tests AND by internal/naming's, so the two spellings
|
|
9
|
+
// cannot drift apart.
|
|
10
|
+
/** `<project>-<frontend>`: the service.name forge's observability filters on. */
|
|
11
|
+
export function frontendServiceName(project, frontend) {
|
|
12
|
+
return `${project}-${frontend}`;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=service-name.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-name.js","sourceRoot":"","sources":["../src/service-name.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,EAAE;AACF,mEAAmE;AACnE,+EAA+E;AAC/E,8EAA8E;AAC9E,2EAA2E;AAC3E,2EAA2E;AAC3E,8EAA8E;AAC9E,sBAAsB;AAEtB,iFAAiF;AACjF,MAAM,UAAU,mBAAmB,CAAC,OAAe,EAAE,QAAgB;IACnE,OAAO,GAAG,OAAO,IAAI,QAAQ,EAAE,CAAC;AAClC,CAAC","sourcesContent":["// Part of @reliantlabs/forge-web-runtime — the web twin of forge/pkg.\n//\n// A frontend's `service.name`, derived exactly as forge derives it\n// (internal/naming.FrontendServiceName): `<project>-<frontend>`. The generated\n// observability — the frontend dashboard's panel scope and the frontend alert\n// defaults — filters on that name, so telemetry reporting anything else is\n// invisible to both. The cases in testdata/frontend-service-names.json are\n// read by this package's tests AND by internal/naming's, so the two spellings\n// cannot drift apart.\n\n/** `<project>-<frontend>`: the service.name forge's observability filters on. */\nexport function frontendServiceName(project: string, frontend: string): string {\n return `${project}-${frontend}`;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reliantlabs/forge-web-runtime",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.1",
|
|
4
4
|
"description": "The forge frontend runtime: Connect interceptor stack, session, error boundary, toast queue, <Resource> container, W3C trace propagation and the HyperDX browser SDK wiring (errors, console, network, traces; replay off by default). The web twin of forge/pkg.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"//repository note": "REQUIRED for `npm publish --provenance`, not decoration. npm cross-checks this against the repository in the signed provenance statement and rejects the publish with a 422 if they disagree — an absent field reads as \"\" and fails that comparison. `directory` names the subdirectory this package lives in, so the provenance points at the real source. Omitting this is what made the first 0.3.1 publish fail AFTER the tarball had been signed and written to the sigstore transparency log.",
|
|
@@ -42,6 +42,10 @@
|
|
|
42
42
|
"types": "./dist/interceptors.d.ts",
|
|
43
43
|
"default": "./dist/interceptors.js"
|
|
44
44
|
},
|
|
45
|
+
"./node": {
|
|
46
|
+
"types": "./dist/node.d.ts",
|
|
47
|
+
"default": "./dist/node.js"
|
|
48
|
+
},
|
|
45
49
|
"./mock-transport": {
|
|
46
50
|
"types": "./dist/mock-transport.d.ts",
|
|
47
51
|
"default": "./dist/mock-transport.js"
|