@datadog/apps-frontend 0.0.1 → 0.0.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/LICENSES-3rdparty.csv +6 -0
- package/README.md +10 -4
- package/dist/src/_chunks/chunk-2V2HASKF.js +7 -0
- package/dist/src/_chunks/chunk-2V2HASKF.js.map +7 -0
- package/dist/src/_chunks/chunk-NCWC7QOQ.js +7 -0
- package/dist/src/_chunks/chunk-NCWC7QOQ.js.map +7 -0
- package/dist/src/_chunks/chunk-X34MSTJH.js +7 -0
- package/dist/src/_chunks/chunk-X34MSTJH.js.map +7 -0
- package/dist/src/embedding/index.d.ts +6 -0
- package/dist/src/embedding/index.js +6 -0
- package/dist/src/embedding/index.js.map +7 -0
- package/dist/src/embedding/react/index.d.ts +8 -0
- package/dist/src/embedding/react/index.js +7 -0
- package/dist/src/embedding/react/index.js.map +7 -0
- package/dist/src/embedding/react/provider.d.ts +8 -0
- package/dist/src/embedding/react/use-datadog-app-embedding.d.ts +29 -0
- package/dist/src/embedding/types.d.ts +392 -0
- package/dist/src/embedding/versioning.d.ts +104 -0
- package/dist/src/inputs/published-definition.d.ts +146 -0
- package/dist/src/inputs/react/index.d.ts +7 -0
- package/dist/src/inputs/react/index.js +7 -0
- package/dist/src/inputs/react/index.js.map +7 -0
- package/dist/src/inputs/react/use-datadog-app-input.d.ts +54 -0
- package/dist/src/inputs/schemas/dashboard.d.ts +30 -0
- package/dist/src/inputs/schemas/index.d.ts +25 -0
- package/dist/src/inputs/schemas/index.js +7 -0
- package/dist/src/inputs/schemas/index.js.map +7 -0
- package/dist/src/inputs/schemas/theme.d.ts +15 -0
- package/dist/src/inputs/types.d.ts +50 -0
- package/package.json +44 -2
package/LICENSES-3rdparty.csv
CHANGED
|
@@ -1 +1,7 @@
|
|
|
1
1
|
Component,Origin,Licence,Copyright,Reference
|
|
2
|
+
@standard-schema/spec,npm,MIT,Colin McDonnell (https://standardschema.dev),npm:1.1.0
|
|
3
|
+
js-tokens,npm,MIT,Simon Lydell (lydell/js-tokens),npm:4.0.0
|
|
4
|
+
loose-envify,npm,MIT,Andres Suarez (https://github.com/zertosh/loose-envify),npm:1.4.0
|
|
5
|
+
penpal,npm,MIT,Aaron Hardy (https://github.com/Aaronius/penpal),npm:7.0.6
|
|
6
|
+
react,npm,MIT,(https://reactjs.org/),npm:18.3.1
|
|
7
|
+
zod,npm,MIT,Colin McDonnell (https://zod.dev),npm:4.3.6
|
package/README.md
CHANGED
|
@@ -6,11 +6,17 @@ Frontend capabilities for Datadog Apps.
|
|
|
6
6
|
npm install @datadog/apps-frontend
|
|
7
7
|
```
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
connection and typed inputs are introduced in follow-up releases.
|
|
9
|
+
The package root intentionally exposes no runtime API; capabilities are reached
|
|
10
|
+
through its subpath entries:
|
|
12
11
|
|
|
13
|
-
|
|
12
|
+
- `@datadog/apps-frontend/embedding/react` — `DatadogAppProvider` connects an
|
|
13
|
+
app to its host, and `useDatadogAppEmbedding` reads that connection's state.
|
|
14
|
+
- `@datadog/apps-frontend/inputs/react` — `useDatadogAppInput` reads a typed
|
|
15
|
+
input the host provides.
|
|
16
|
+
- `@datadog/apps-frontend/inputs/schema` — the input schemas themselves, such
|
|
17
|
+
as `datadogTheme` and `datadogDashboard`, passed to `useDatadogAppInput`.
|
|
18
|
+
|
|
19
|
+
React 18 and 19 are supported as peer dependencies.
|
|
14
20
|
|
|
15
21
|
## Development
|
|
16
22
|
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/* Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0.
|
|
2
|
+
* This product includes software developed at Datadog (https://www.datadoghq.com/).
|
|
3
|
+
* Copyright 2019-Present Datadog, Inc.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
var n=new WeakMap,o=3e4;function l(e){let t=n.get(e);if(t)return t.cleanupTimer!==void 0&&(globalThis.clearTimeout(t.cleanupTimer),t.cleanupTimer=void 0),t;let r={release:e.start()};return n.set(e,r),r}function p(e){let t=n.get(e);return t?(n.delete(e),t.cleanupTimer!==void 0&&globalThis.clearTimeout(t.cleanupTimer),t.release):e.start()}function c(e,t){n.get(e)!==t||t.cleanupTimer!==void 0||(t.cleanupTimer=globalThis.setTimeout(()=>{n.get(e)===t&&(n.delete(e),t.release())},o))}import{createContext as a,createElement as s,useContext as u,useEffect as d}from"react";var i=a(null);function g(e){return function({children:r}){return d(()=>p(e),[]),s(i.Provider,{value:e},r)}}function A(){let e=u(i);if(!e)throw new Error("Datadog App hooks must be used within DatadogAppProvider.");return e}export{l as a,c as b,g as c,A as d};
|
|
7
|
+
//# sourceMappingURL=chunk-2V2HASKF.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/embedding/react/start-lease.ts", "../../../src/embedding/react/context.ts"],
|
|
4
|
+
"sourcesContent": ["import type { AppEmbedding, Unsubscribe } from '../types';\n\ninterface SuspenseStartLease {\n readonly release: Unsubscribe;\n cleanupTimer?: ReturnType<typeof globalThis.setTimeout>;\n}\n\nconst suspenseStartLeases = new WeakMap<AppEmbedding, SuspenseStartLease>();\nconst UNADOPTED_LEASE_GRACE_MS = 30_000;\n\n/** Starts an embedding while a descendant is suspended before effects commit. */\nexport function startAppEmbeddingForSuspense(\n embedding: AppEmbedding,\n): SuspenseStartLease {\n const existing = suspenseStartLeases.get(embedding);\n if (existing) {\n if (existing.cleanupTimer !== undefined) {\n globalThis.clearTimeout(existing.cleanupTimer);\n existing.cleanupTimer = undefined;\n }\n return existing;\n }\n\n const created = { release: embedding.start() };\n suspenseStartLeases.set(embedding, created);\n return created;\n}\n\n/** Gives the provider ownership of a render-time lease, or starts a new one. */\nexport function acquireAppEmbeddingLease(embedding: AppEmbedding): Unsubscribe {\n const suspenseLease = suspenseStartLeases.get(embedding);\n if (!suspenseLease) {\n return embedding.start();\n }\n\n suspenseStartLeases.delete(embedding);\n if (suspenseLease.cleanupTimer !== undefined) {\n globalThis.clearTimeout(suspenseLease.cleanupTimer);\n }\n return suspenseLease.release;\n}\n\n/** Releases a settled render-time lease if its provider was abandoned. */\nexport function scheduleUnadoptedLeaseCleanup(\n embedding: AppEmbedding,\n suspenseLease: SuspenseStartLease,\n): void {\n if (\n suspenseStartLeases.get(embedding) !== suspenseLease ||\n suspenseLease.cleanupTimer !== undefined\n ) {\n return;\n }\n\n suspenseLease.cleanupTimer = globalThis.setTimeout(() => {\n if (suspenseStartLeases.get(embedding) === suspenseLease) {\n suspenseStartLeases.delete(embedding);\n suspenseLease.release();\n }\n }, UNADOPTED_LEASE_GRACE_MS);\n}\n", "import { createContext, createElement, useContext, useEffect } from 'react';\nimport type {\n ComponentType,\n Context,\n PropsWithChildren,\n ReactElement,\n} from 'react';\n\nimport type { AppEmbedding } from '../types';\n\nimport { acquireAppEmbeddingLease } from './start-lease';\n\nconst appEmbeddingContext: Context<AppEmbedding | null> =\n createContext<AppEmbedding | null>(null);\n\nexport function createDatadogAppProvider(\n embedding: AppEmbedding,\n): ComponentType<PropsWithChildren> {\n return function DatadogAppProvider({\n children,\n }: PropsWithChildren): ReactElement {\n // `embedding` is captured from the factory, not a prop, so it is fixed\n // for the lifetime of this component type. The empty dependency list is\n // deliberate: the connection must start once per mount and tear down on\n // unmount, never restart mid-life.\n useEffect(() => acquireAppEmbeddingLease(embedding), []);\n return createElement(\n appEmbeddingContext.Provider,\n { value: embedding },\n children,\n );\n };\n}\n\nexport function useAppEmbedding(): AppEmbedding {\n const embedding = useContext(appEmbeddingContext);\n if (!embedding) {\n throw new Error(\n 'Datadog App hooks must be used within DatadogAppProvider.',\n );\n }\n return embedding;\n}\n"],
|
|
5
|
+
"mappings": "AAOA,IAAMA,EAAsB,IAAI,QAC1BC,EAA2B,IAG1B,SAASC,EACZC,EACkB,CAClB,IAAMC,EAAWJ,EAAoB,IAAIG,CAAS,EAClD,GAAIC,EACA,OAAIA,EAAS,eAAiB,SAC1B,WAAW,aAAaA,EAAS,YAAY,EAC7CA,EAAS,aAAe,QAErBA,EAGX,IAAMC,EAAU,CAAE,QAASF,EAAU,MAAM,CAAE,EAC7C,OAAAH,EAAoB,IAAIG,EAAWE,CAAO,EACnCA,CACX,CAGO,SAASC,EAAyBH,EAAsC,CAC3E,IAAMI,EAAgBP,EAAoB,IAAIG,CAAS,EACvD,OAAKI,GAILP,EAAoB,OAAOG,CAAS,EAChCI,EAAc,eAAiB,QAC/B,WAAW,aAAaA,EAAc,YAAY,EAE/CA,EAAc,SAPVJ,EAAU,MAAM,CAQ/B,CAGO,SAASK,EACZL,EACAI,EACI,CAEAP,EAAoB,IAAIG,CAAS,IAAMI,GACvCA,EAAc,eAAiB,SAKnCA,EAAc,aAAe,WAAW,WAAW,IAAM,CACjDP,EAAoB,IAAIG,CAAS,IAAMI,IACvCP,EAAoB,OAAOG,CAAS,EACpCI,EAAc,QAAQ,EAE9B,EAAGN,CAAwB,EAC/B,CC5DA,OAAS,iBAAAQ,EAAe,iBAAAC,EAAe,cAAAC,EAAY,aAAAC,MAAiB,QAYpE,IAAMC,EACFC,EAAmC,IAAI,EAEpC,SAASC,EACZC,EACgC,CAChC,OAAO,SAA4B,CAC/B,SAAAC,CACJ,EAAoC,CAKhC,OAAAC,EAAU,IAAMC,EAAyBH,CAAS,EAAG,CAAC,CAAC,EAChDI,EACHP,EAAoB,SACpB,CAAE,MAAOG,CAAU,EACnBC,CACJ,CACJ,CACJ,CAEO,SAASI,GAAgC,CAC5C,IAAML,EAAYM,EAAWT,CAAmB,EAChD,GAAI,CAACG,EACD,MAAM,IAAI,MACN,2DACJ,EAEJ,OAAOA,CACX",
|
|
6
|
+
"names": ["suspenseStartLeases", "UNADOPTED_LEASE_GRACE_MS", "startAppEmbeddingForSuspense", "embedding", "existing", "created", "acquireAppEmbeddingLease", "suspenseLease", "scheduleUnadoptedLeaseCleanup", "createContext", "createElement", "useContext", "useEffect", "appEmbeddingContext", "createContext", "createDatadogAppProvider", "embedding", "children", "useEffect", "acquireAppEmbeddingLease", "createElement", "useAppEmbedding", "useContext"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/* Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0.
|
|
2
|
+
* This product includes software developed at Datadog (https://www.datadoghq.com/).
|
|
3
|
+
* Copyright 2019-Present Datadog, Inc.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import{A as d,E as s,F as O,G as p,H as C,I as A,J as I,r as u,s as l}from"./chunk-X34MSTJH.js";var F=["datadog.idp.homepage","datadog.idp.service-panel","datadog.idp.self-service","datadog.app-builder","datadog.appsec","datadog.notebook","datadog.dashboard"];function S(e,n,t){let o=Object.create(null),a=n;for(let[r,i]of Object.entries(e.fields))o[r]=i.kind==="value"?a[r]:Object.freeze({invoke:a[r]});return O(e,Object.freeze(o),t)}function V(e,n){let t=Object.create(null);for(let o of n)t[o]=e[o];return t}function E(e,n){if(e.kind!==n.kind)return!1;if(e.kind==="value"&&n.kind==="value")return e.schema===n.schema;if(e.kind==="function"&&n.kind==="function"){let t=Object.keys(e.inputs),o=Object.keys(n.inputs);return!(t.length!==o.length||e.result!==n.result||t.some(a=>!Object.prototype.hasOwnProperty.call(n.inputs,a)||e.inputs[a]!==n.inputs[a]))}return!1}function L(e,n){let t=Object.create(null);for(let[o,a]of Object.entries(e.fields))t[o]=a;for(let o of n)for(let[a,r]of Object.entries(o.extraInputs)){if(Object.prototype.hasOwnProperty.call(e.fields,a))throw new Error(`"${e.identifier}" v${o.contract.version} declares extra input "${a}", which already names a field of v${e.version}.`);let i=Object.prototype.hasOwnProperty.call(t,a)?t[a]:void 0;if(i&&!E(i,r))throw new Error(`"${e.identifier}" extra input "${a}" is declared with conflicting schemas by more than one older version.`);t[a]=r}return Object.freeze(t)}function R(e,...n){let t=new Set([e.version]);for(let r of n){if(r.contract.identifier!==e.identifier)throw new Error(`Older version "${r.contract.identifier}" v${r.contract.version} must share identifier "${e.identifier}" with its latest contract.`);if(r.contract.version>=e.version)throw new Error(`Older version "${e.identifier}" v${r.contract.version} must be older than latest v${e.version}.`);if(t.has(r.contract.version))throw new Error(`"${e.identifier}" declares version ${r.contract.version} more than once.`);t.add(r.contract.version)}let o=L(e,n),a=Object.keys(e.fields);return Object.freeze({identifier:e.identifier,latest:e,olderVersions:Object.freeze([...n]),fields:o,buildModules(r,i){let y=r,f=V(y,a),m=[S(e,f,i)];for(let c of n){let g=c.convert(f,V(y,Object.keys(c.extraInputs)));m.push(S(c.contract,g,i))}return Object.freeze(m)}})}var x=new WeakSet,h=/^[a-z][a-z0-9]*(?:[.-][a-z0-9]+)*$/;function b(e,n,t){if(!s.test(n)||n.length>l||!p(t))throw new Error(`Datadog App input field "${e}.${n}" must have a name matching ${String(s)} of at most ${l} characters and be a read-only value or function whose schemas implement Standard Schema V1.`);if(t.kind==="function"){for(let o of Object.keys(t.inputs))if(!s.test(o))throw new Error(`Datadog App input function parameter "${e}.${n}.${o}" must have a name matching ${String(s)}.`);if(!C(t))throw new Error(`Datadog App input function field "${e}.${n}" declares a timeoutMs no call could meet. It must be greater than 0 and at most ${2147483647}.`)}}function T(e){if(!d(e)||typeof e.identifier!="string"||!h.test(e.identifier))throw new Error(`Datadog App input contract identifier "${String(d(e)?e.identifier:void 0)}" must match ${String(h)}.`);if(typeof e.version!="number"||!Number.isSafeInteger(e.version)||e.version<1)throw new Error(`Datadog App input contract "${e.identifier}" must have a positive integer version.`);if(!d(e.fields)||Object.keys(e.fields).length===0||Object.keys(e.fields).length>u)throw new Error(`Datadog App input contract "${e.identifier}" must define between 1 and ${u} fields.`);for(let[n,t]of Object.entries(e.fields))b(e.identifier,n,t)}function N(e,n){if(!d(n))throw new Error(`Older Datadog App input contract "${e}" must declare its extra inputs as an object.`);for(let[t,o]of Object.entries(n))b(e,t,o)}var J=Object.freeze({readOnly(e){return A.readOnly(e)}});function D(e){let n=I(e);return T(n),n}function Y(e){let n=e,t="latest"in n?n.latest:D(n),o=n.olderVersions??[];T(t);for(let i of o)T(i.contract),N(t.identifier,i.extraInputs);let a=R(t,...o),r=Object.freeze({...a,surfaces:Object.freeze([...n.surfaces??F])});return x.add(r),r}function K(e){if(typeof e!="object"||e===null||!x.has(e))throw new Error("useDatadogAppInput() requires a definition exported by @datadog/apps-frontend/inputs/schema.")}export{J as a,Y as b,K as c};
|
|
7
|
+
//# sourceMappingURL=chunk-NCWC7QOQ.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/embedding/types.ts", "../../../src/embedding/versioning.ts", "../../../src/inputs/published-definition.ts"],
|
|
4
|
+
"sourcesContent": ["import type { StandardSchemaV1 } from '@standard-schema/spec';\n\nexport type Unsubscribe = () => void;\n\nexport type Result<TValue, TError> =\n | Readonly<{ ok: true; value: TValue }>\n | Readonly<{ ok: false; error: TError }>;\n\n/**\n * A synchronous, deterministic, validation-only Standard Schema.\n *\n * Both embedding peers validate independently. Schemas must therefore have\n * identical input/output types and must not coerce or transform accepted\n * values.\n */\nexport type ValueSchema<TValue> = StandardSchemaV1<TValue, TValue>;\n\nexport type AnySchema = StandardSchemaV1;\n\nexport type InferOf<TSchema extends AnySchema> =\n StandardSchemaV1.InferOutput<TSchema>;\n\nexport type ValidationOnlySchema<TSchema extends AnySchema> =\n StandardSchemaV1.InferInput<TSchema> extends StandardSchemaV1.InferOutput<TSchema>\n ? StandardSchemaV1.InferOutput<TSchema> extends StandardSchemaV1.InferInput<TSchema>\n ? TSchema\n : never\n : never;\n\nexport type ContractVersion = number;\n\nexport interface ValueField<TSchema extends AnySchema> {\n readonly kind: 'value';\n readonly schema: ValidationOnlySchema<TSchema>;\n}\n\nexport interface FunctionField<\n TInputs extends Readonly<Record<string, AnySchema>>,\n TResult extends AnySchema,\n> {\n readonly kind: 'function';\n readonly inputs: {\n readonly [TName in keyof TInputs]: ValidationOnlySchema<TInputs[TName]>;\n };\n readonly result: ValidationOnlySchema<TResult>;\n /**\n * How long this function may run before it times out, overriding the\n * default `FUNCTION_CALL_TIMEOUT_MS`. A fast lookup can ask for seconds\n * instead of inheriting a ten-minute budget.\n *\n * Never sent over the wire. The app arms its wait from the contract it\n * claims and the host arms its watchdog from the contract it registers, so\n * two peers on different contract revisions may use different numbers.\n * That needs no reconciling: whichever watchdog fires first wins through\n * the normal `TIMED_OUT` path, as it already did with the default alone.\n *\n * Must be positive and no larger than `MAX_TIMER_DELAY_MS`. Outside that\n * range no call could ever meet it -- at `0` the host's deadline checks are\n * already past, and beyond the timer ceiling `setTimeout` overflows and\n * fires almost at once -- so `defineContract()` rejects it outright.\n */\n readonly timeoutMs?: number;\n}\n\nexport type AnyFunctionField = FunctionField<\n Readonly<Record<string, AnySchema>>,\n AnySchema\n>;\n\nexport type AnyField = ValueField<AnySchema> | AnyFunctionField;\n\nexport interface Contract<TFields extends Record<string, AnyField>> {\n readonly identifier: string;\n readonly version: ContractVersion;\n readonly fields: TFields;\n}\n\nexport type AnyContract = Contract<Record<string, AnyField>>;\n\nexport interface LiveValue<TValue> {\n get(): TValue;\n subscribe(onChange: () => void): Unsubscribe;\n}\n\nexport interface HostFunctionContext {\n /**\n * Aborts once the call is cancelled or its deadline passes. An async\n * implementation should check or listen for this to stop early. A\n * *synchronous* implementation has no way to observe it mid-call: JS\n * can't preempt a running function, so a synchronous handler that blocks\n * past the deadline still runs to completion and produces its value --\n * the caller is simply told the call timed out and never sees that\n * value, rather than the value being prevented from being computed.\n */\n readonly signal: AbortSignal;\n}\n\nexport interface HostFunction {\n invoke(\n inputs: Readonly<Record<string, unknown>>,\n context: HostFunctionContext,\n ): unknown;\n}\n\nexport type FunctionInputs<\n TInputs extends Readonly<Record<string, AnySchema>>,\n> = {\n readonly [TName in keyof TInputs as undefined extends InferOf<\n TInputs[TName]\n >\n ? TName\n : never]?: InferOf<TInputs[TName]>;\n} & {\n readonly [TName in keyof TInputs as undefined extends InferOf<\n TInputs[TName]\n >\n ? never\n : TName]: InferOf<TInputs[TName]>;\n};\n\n/** Resolves a contract field to the plain value/callable shape a claimant receives, ignoring subscription. */\ntype FieldValue<TField extends AnyField> =\n TField extends ValueField<infer TSchema>\n ? InferOf<TSchema>\n : TField extends FunctionField<infer TInputs, infer TResult>\n ? (inputs: FunctionInputs<TInputs>) => Promise<InferOf<TResult>>\n : never;\n\ntype ClaimedField<TField extends AnyField> =\n TField extends ValueField<infer TSchema>\n ? LiveValue<InferOf<TSchema>>\n : FieldValue<TField>;\n\n/** The live, per-field view of a claim: subscribable `LiveValue`s for value fields, callables for function fields. */\nexport type ClaimedFields<TContract extends AnyContract> = {\n readonly [TKey in keyof TContract['fields']]: ClaimedField<\n TContract['fields'][TKey]\n >;\n};\n\ndeclare const hostModuleBrand: unique symbol;\n\n/**\n * One contract version, live and ready to serve claims. Nominally branded --\n * `hostModuleBrand` is declared but never exported, so only this package can\n * produce a `HostModule`, and only through `createHostModule()`. That is what\n * keeps a host from assembling a module for one hand-picked version: the\n * single supported way in is to provide an inputs definition, which mints a\n * module for *every* version that definition still converts to. The brand has\n * no runtime representation.\n */\nexport interface HostModule {\n readonly [hostModuleBrand]: true;\n readonly contract: AnyContract;\n readonly implementation: Readonly<\n Record<string, LiveValue<unknown> | HostFunction>\n >;\n readonly signal?: AbortSignal;\n}\n\nexport interface Issue {\n readonly message: string;\n readonly path: readonly (string | number)[];\n}\n\nexport type AnyError =\n | Readonly<{ code: 'ORIGIN_REJECTED'; origin: string }>\n | Readonly<{\n code: 'APP_PROTOCOL_TOO_OLD';\n appProtocols: readonly number[];\n hostProtocols: readonly number[];\n }>\n | Readonly<{\n code: 'HOST_PROTOCOL_TOO_OLD';\n appProtocols: readonly number[];\n hostProtocols: readonly number[];\n }>\n | Readonly<{\n code: 'PROTOCOL_INCOMPATIBLE';\n appProtocols: readonly number[];\n hostProtocols: readonly number[];\n }>\n | Readonly<{ code: 'PEER_LACKS_MODULE'; identifier: string }>\n | Readonly<{\n code: 'APP_MAJOR_TOO_OLD';\n wanted: ContractVersion;\n hostVersions: readonly ContractVersion[];\n }>\n | Readonly<{\n code: 'HOST_MAJOR_TOO_OLD';\n wanted: ContractVersion;\n hostVersions: readonly ContractVersion[];\n }>\n | Readonly<{ code: 'CONTRACT_INCOMPATIBLE'; field: string }>\n | Readonly<{ code: 'INVALID_ARGUMENT'; issues: readonly Issue[] }>\n | Readonly<{ code: 'FUNCTION_FAILED'; field: string }>\n | Readonly<{ code: 'INVALID_RESULT'; issues: readonly Issue[] }>\n | Readonly<{ code: 'TIMED_OUT'; timeoutMs: number }>\n | Readonly<{ code: 'TRANSPORT_FAILED'; cause: unknown }>\n | Readonly<{ code: 'ABORTED' }>\n | Readonly<{ code: 'DISCONNECTED' }>\n | Readonly<{ code: 'UNRECOGNIZED'; rawCode: string; raw: unknown }>;\n\nexport type ErrorOf<TCode extends AnyError['code']> = Extract<\n AnyError,\n { code: TCode }\n>;\n\nexport type ConnectError = ErrorOf<\n | 'ORIGIN_REJECTED'\n | 'APP_PROTOCOL_TOO_OLD'\n | 'HOST_PROTOCOL_TOO_OLD'\n | 'PROTOCOL_INCOMPATIBLE'\n | 'TIMED_OUT'\n | 'TRANSPORT_FAILED'\n | 'ABORTED'\n | 'DISCONNECTED'\n | 'UNRECOGNIZED'\n>;\n\nexport type WireClaimError = ErrorOf<\n | 'PEER_LACKS_MODULE'\n | 'APP_MAJOR_TOO_OLD'\n | 'HOST_MAJOR_TOO_OLD'\n | 'CONTRACT_INCOMPATIBLE'\n | 'INVALID_RESULT'\n | 'TIMED_OUT'\n | 'ABORTED'\n | 'DISCONNECTED'\n | 'UNRECOGNIZED'\n>;\n\nexport type WireFunctionError = ErrorOf<\n | 'CONTRACT_INCOMPATIBLE'\n | 'INVALID_ARGUMENT'\n | 'FUNCTION_FAILED'\n | 'INVALID_RESULT'\n | 'TIMED_OUT'\n | 'ABORTED'\n | 'DISCONNECTED'\n | 'UNRECOGNIZED'\n>;\n\nexport type ClaimInvalidationError = ErrorOf<\n 'INVALID_RESULT' | 'DISCONNECTED' | 'UNRECOGNIZED'\n>;\n\nexport interface Claimed<TContract extends AnyContract> {\n readonly fields: ClaimedFields<TContract>;\n release(): void;\n onValuesChanged(listener: () => void): Unsubscribe;\n onInvalidated(\n listener: (error: ClaimInvalidationError) => void,\n ): Unsubscribe;\n}\n\nexport interface ClaimOptions {\n /**\n * Local claim deadline. Must be finite, non-negative, and no larger than\n * the platform timer ceiling (`2_147_483_647`).\n */\n readonly timeoutMs?: number;\n readonly signal?: AbortSignal;\n}\n\nexport interface AppConnection {\n claim<TContract extends AnyContract>(\n contract: TContract,\n options?: ClaimOptions,\n ): Promise<Result<Claimed<TContract>, WireClaimError>>;\n}\n\n/**\n * Identifies which product surface a Datadog App is embedded into (e.g. the\n * Service Catalog side panel vs. IDP), so an app can render surface-specific\n * content. Each value matches the `identifier` of the inputs schema that\n * surface provides -- see `../inputs/schemas`. Sent host-to-app as part of\n * the embedding connection handshake.\n */\n/**\n * Every surface, as a tuple rather than a bare union so it can also serve as a\n * type: `DatadogAppInputsSchema` defaults its `surfaces` to this, which makes\n * an IDE print the members in full on hover instead of collapsing them to the\n * `SurfaceId` alias.\n */\nexport const EVERY_SURFACE: readonly [\n 'datadog.idp.homepage',\n 'datadog.idp.service-panel',\n 'datadog.idp.self-service',\n 'datadog.app-builder',\n 'datadog.appsec',\n 'datadog.notebook',\n 'datadog.dashboard',\n] = [\n 'datadog.idp.homepage',\n 'datadog.idp.service-panel',\n 'datadog.idp.self-service',\n 'datadog.app-builder',\n 'datadog.appsec',\n 'datadog.notebook',\n 'datadog.dashboard',\n];\n\n/**\n * Where an app is running. Derived from `EVERY_SURFACE`, so there is one\n * list, but widened to arbitrary strings: it is inert metadata forwarded to\n * `listen()`, never used to gate whether embedding connects, so a host is\n * free to pass a value with no matching surface (e.g. an unmapped view\n * context) rather than going without one.\n */\nexport type SurfaceId = (typeof EVERY_SURFACE)[number] | (string & {});\n\nexport type AppConnectionState =\n | Readonly<{ state: 'connecting'; error?: ConnectError }>\n | Readonly<{\n state: 'connected';\n connection: AppConnection;\n surfaceId?: SurfaceId;\n }>\n | Readonly<{ state: 'reconnecting'; lastError: ConnectError }>\n | Readonly<{ state: 'rejected'; error: ConnectError }>\n | Readonly<{ state: 'not-embedded' }>\n | Readonly<{ state: 'closed' }>;\n\n/**\n * Public-safe view of `AppConnectionState`: the same lifecycle cases, minus\n * the raw `AppConnection` a consumer would otherwise have no use for outside\n * of claiming a contract.\n */\nexport type EmbeddingMetadata =\n | Readonly<{ state: 'connecting'; error?: ConnectError }>\n | Readonly<{ state: 'connected'; surfaceId?: SurfaceId }>\n | Readonly<{ state: 'reconnecting'; lastError: ConnectError }>\n | Readonly<{ state: 'rejected'; error: ConnectError }>\n | Readonly<{ state: 'not-embedded' }>\n | Readonly<{ state: 'closed' }>;\n\nexport interface EmbeddingMetadataStore {\n readonly getSnapshot: () => EmbeddingMetadata;\n readonly subscribe: (onChange: () => void) => Unsubscribe;\n}\n\nexport interface AppConnectionHandle {\n getSnapshot(): AppConnectionState;\n subscribe(onChange: () => void): Unsubscribe;\n close(): void;\n}\n\nexport interface AppConnectionFactory {\n connect(): AppConnectionHandle;\n}\n\nexport interface HostListenOptions {\n /** Security boundary for the app-created bootstrap port. */\n readonly peer: Readonly<{\n frame: HTMLIFrameElement;\n appOrigin: string;\n /**\n * Set when the iframe is intentionally configured with an opaque\n * sandboxed origin, so the host should accept a `\"null\"` origin from\n * it in place of an exact match against `appOrigin`.\n */\n allowOpaqueOrigin?: boolean;\n }>;\n readonly modules: readonly HostModule[];\n readonly surfaceId?: SurfaceId;\n /**\n * Local compatibility and establishment deadline for each phase. Must be\n * finite, non-negative, and no larger than the platform timer ceiling\n * (`2_147_483_647`).\n */\n readonly timeoutMs?: number;\n readonly signal?: AbortSignal;\n}\n\nexport interface HostListener {\n onError(listener: (error: ConnectError) => void): Unsubscribe;\n /**\n * Fires exactly once per successful operational session: after permanent\n * bootstrap and compatibility negotiation complete, before any\n * per-module claim resolves. Not a one-shot for the listener's whole\n * lifetime -- if this session is later superseded (a new bootstrap\n * replaces it, see `close()`'s effect on an active connection) and a new\n * session establishes, this fires again for that new session. Never\n * fires for an attempt that fails, or after `close()`. A subscriber that\n * calls `onReady` while a session is already active is notified\n * immediately upon subscribing, so a late subscriber cannot miss an\n * already-established session.\n */\n onReady(listener: () => void): Unsubscribe;\n close(): void;\n}\n\nexport type EmbeddingError =\n | Readonly<{ code: 'TIMED_OUT'; message: string; action: 'retry' }>\n | Readonly<{\n code: 'ORIGIN_REJECTED';\n message: string;\n action: 'contact-support';\n }>\n | Readonly<{\n code: 'APP_PROTOCOL_TOO_OLD';\n message: string;\n action: 'update-app';\n }>\n | Readonly<{\n code: 'HOST_PROTOCOL_TOO_OLD' | 'PROTOCOL_INCOMPATIBLE';\n message: string;\n action: 'contact-support';\n }>\n | Readonly<{\n code: 'CONNECTION_LOST';\n message: string;\n action: 'retry';\n }>\n | Readonly<{\n code: 'UNKNOWN';\n message: string;\n action: 'contact-support';\n }>;\n\nexport type ClaimError =\n | EmbeddingError\n | Readonly<{\n code: 'APP_MAJOR_TOO_OLD';\n action: 'update-app';\n requestedVersion: ContractVersion;\n availableVersions: readonly ContractVersion[];\n message: string;\n }>\n | Readonly<{\n code: 'HOST_MAJOR_TOO_OLD';\n action: 'contact-support';\n requestedVersion: ContractVersion;\n availableVersions: readonly ContractVersion[];\n message: string;\n }>;\n\nexport type ClaimedValues<TContract extends AnyContract> = Readonly<{\n [TKey in keyof TContract['fields']]: FieldValue<TContract['fields'][TKey]>;\n}>;\n\nexport type ClaimState<TContract extends AnyContract> =\n | Readonly<{ status: 'pending' }>\n | Readonly<{\n status: 'ready';\n fields: ClaimedValues<TContract>;\n }>\n | Readonly<{ status: 'unavailable' }>\n | Readonly<{ status: 'failed'; error: ClaimError }>;\n\nexport interface ClaimStore<TContract extends AnyContract> {\n readonly getSnapshot: () => ClaimState<TContract>;\n readonly subscribe: (onChange: () => void) => Unsubscribe;\n}\n\n/** Framework-neutral claim capability consumed by feature modules. */\nexport interface AppClaims {\n getClaim<TContract extends AnyContract>(\n contract: TContract,\n ): ClaimStore<TContract>;\n}\n\n/** Owns the lifecycle of one concrete embedding implementation. */\nexport interface AppEmbedding extends AppClaims {\n start(): Unsubscribe;\n getEmbeddingMetadata(): EmbeddingMetadataStore;\n}\n\n/**\n * One established connection, owned by the caller that opened it. These say\n * nothing about which operational protocol produced them, so the connection\n * lifecycle does not change when a protocol is added or retired.\n */\nexport type ManagedAppConnection = Readonly<{\n connection: AppConnection;\n surfaceId?: SurfaceId;\n closeSignal: AbortSignal;\n close(): void;\n}>;\n\nexport type ManagedHostConnection = Readonly<{\n closeSignal: AbortSignal;\n close(): void;\n}>;\n", "import { MAX_CLAIM_FIELD_NAME_LENGTH } from './config';\nimport {\n createHostModule,\n isAnyFieldShape,\n VALID_FIELD_NAME,\n} from './contract';\nimport { teardown } from './shared';\nimport type {\n AnyContract,\n AnyField,\n ContractVersion,\n FunctionField,\n FunctionInputs,\n HostFunction,\n HostFunctionContext,\n HostModule,\n InferOf,\n LiveValue,\n Unsubscribe,\n ValueField,\n} from './types';\n\ntype HostFieldImplementation<TField extends AnyField> =\n TField extends ValueField<infer TSchema>\n ? LiveValue<InferOf<TSchema>>\n : TField extends FunctionField<infer TInputs, infer TResult>\n ? (\n inputs: FunctionInputs<TInputs>,\n context: HostFunctionContext,\n ) => InferOf<TResult> | Promise<InferOf<TResult>>\n : never;\n\n/** The live host-side implementation of a raw field map: `LiveValue`s for value fields, plain callables for function fields. */\nexport type HostFieldsFor<TFields extends Record<string, AnyField>> = Readonly<{\n [TName in keyof TFields]: HostFieldImplementation<TFields[TName]>;\n}>;\n\n/** The live host-side implementation of a whole contract's fields. */\nexport type HostFields<TContract extends AnyContract> = HostFieldsFor<\n TContract['fields']\n>;\n\n/**\n * A `LiveValue` that recomputes from `sources` on every `get()` rather than\n * caching, so it always reflects whichever of `sources` last changed without\n * needing its own dedupe or disposal bookkeeping -- that already lives on\n * `sources` themselves.\n */\nexport function deriveLiveValue<TValue>(\n sources: readonly LiveValue<unknown>[],\n compute: () => TValue,\n): LiveValue<TValue> {\n return Object.freeze({\n get: compute,\n subscribe(onChange: () => void): Unsubscribe {\n // Acquired sequentially (not via `sources.map()`) so a later\n // source throwing rolls back every subscription already made.\n const unsubscribes: Unsubscribe[] = [];\n try {\n for (const source of sources) {\n unsubscribes.push(source.subscribe(onChange));\n }\n } catch (error) {\n for (const unsubscribe of unsubscribes) {\n teardown(\n 'deriveLiveValue subscription rollback',\n unsubscribe,\n );\n }\n throw error;\n }\n // Routed through `teardown()` so one throwing unsubscribe can't\n // skip the rest.\n return () => {\n for (const unsubscribe of unsubscribes) {\n teardown('deriveLiveValue unsubscribe', unsubscribe);\n }\n };\n },\n });\n}\n\n/**\n * One older version of `TLatest`: its own frozen contract, the extra live\n * inputs its `convert` needs beyond what `TLatest` already carries, and the\n * function that derives its fields from `TLatest` plus those extras. Runs\n * once, at `buildModules()` time, and must return live fields -- typically\n * built with `deriveLiveValue()` -- so the older version stays exactly as\n * reactive as `TLatest`, with `TLatest`'s own implementation untouched.\n */\nexport interface OlderContractVersion<\n TLatest extends AnyContract,\n TOlder extends AnyContract,\n TExtraInputs extends Record<string, AnyField>,\n> {\n readonly contract: TOlder;\n readonly extraInputs: TExtraInputs;\n convert(\n latest: HostFields<TLatest>,\n extra: HostFieldsFor<TExtraInputs>,\n ): HostFields<TOlder>;\n}\n\nexport type AnyOlderContractVersion<TLatest extends AnyContract> =\n OlderContractVersion<TLatest, AnyContract, Record<string, AnyField>>;\n\n/**\n * Declares and validates one `OlderContractVersion`. Takes `latest` as its\n * own argument -- rather than only through `definition.convert`'s parameter\n * type -- so `TLatest` can be inferred directly from a value in covariant\n * position; inference can't otherwise recover it from `convert`'s parameter,\n * a contravariant position, and silently falls back to `AnyContract`.\n */\nexport function olderVersion<\n TLatest extends AnyContract,\n TOlder extends AnyContract,\n const TExtraInputs extends Record<string, AnyField>,\n>(\n _latest: TLatest,\n definition: OlderContractVersion<TLatest, TOlder, TExtraInputs>,\n): OlderContractVersion<TLatest, TOlder, TExtraInputs> {\n for (const [name, field] of Object.entries(definition.extraInputs)) {\n if (\n !VALID_FIELD_NAME.test(name) ||\n name.length > MAX_CLAIM_FIELD_NAME_LENGTH ||\n !isAnyFieldShape(field)\n ) {\n throw new Error(\n `Older-version extra input \"${definition.contract.identifier}.${name}\" must be a named read-only value or function whose schemas implement Standard Schema V1.`,\n );\n }\n }\n return Object.freeze({\n contract: definition.contract,\n extraInputs: Object.freeze({ ...definition.extraInputs }),\n convert: definition.convert,\n });\n}\n\nexport interface VersionedContract<\n TLatest extends AnyContract,\n TOlderVersions extends readonly AnyOlderContractVersion<TLatest>[],\n> {\n readonly identifier: TLatest['identifier'];\n /**\n * The version an up-to-date peer claims. Read by the claiming side to\n * know what it is asking for; never a way to *provide* one version alone,\n * since `buildModules()` is all-or-nothing.\n */\n readonly latest: TLatest;\n readonly olderVersions: TOlderVersions;\n /**\n * `X`: every field needed to serve every version, in one flat namespace.\n * A provider populates exactly this and learns nothing about how many\n * versions sit behind it.\n */\n readonly fields: VersionedContractFields<TLatest, TOlderVersions>;\n /**\n * Mints one live module per version -- latest plus every version that\n * still has a converter -- from one flat field record. There is\n * deliberately no way to ask for a subset: supporting a version and\n * serving it are the same act.\n */\n buildModules(\n fields: HostFieldsFor<VersionedContractFields<TLatest, TOlderVersions>>,\n signal?: AbortSignal,\n ): readonly HostModule[];\n}\n\n/**\n * Structural bound for \"some versioned contract\", used where generic code\n * needs to accept any of them. Deliberately forgetful about `buildModules`'s\n * parameter and about `olderVersions`' element type: both are contravariant,\n * so naming them would make every concrete contract fail to satisfy this.\n * Callers recover the precise field types from the generic parameter itself\n * (see `DatadogAppInputImplementations`), not from this bound.\n */\nexport type AnyVersionedContract = Readonly<{\n identifier: string;\n latest: AnyContract;\n olderVersions: readonly unknown[];\n fields: Readonly<Record<string, AnyField>>;\n buildModules: (\n fields: never,\n signal?: AbortSignal,\n ) => readonly HostModule[];\n}>;\n\nexport type UnionToIntersection<TUnion> = (\n TUnion extends unknown ? (key: TUnion) => void : never\n) extends (key: infer TIntersection) => void\n ? TIntersection\n : never;\n\ntype OlderVersionsExtraFieldsUnion<\n TLatest extends AnyContract,\n TOlderVersions extends readonly AnyOlderContractVersion<TLatest>[],\n> = {\n [TIndex in keyof TOlderVersions]: TOlderVersions[TIndex] extends OlderContractVersion<\n TLatest,\n AnyContract,\n infer TExtraInputs\n >\n ? TExtraInputs\n : never;\n}[number];\n\n/**\n * Every field needed to construct every version this contract declares,\n * flattened into one namespace: `latest`'s own fields plus each older\n * version's `extraInputs`. This is `giving` values' whole contract with\n * versioning -- a caller populates this one flat record with no notion that\n * more than one version exists behind it. Field names must therefore be\n * unique across `latest` and every older version's `extraInputs`; two older\n * versions may reuse the same name only when it means the same schema, since\n * flattening gives it exactly one slot.\n */\nexport type VersionedContractFields<\n TLatest extends AnyContract,\n TOlderVersions extends readonly AnyOlderContractVersion<TLatest>[],\n> =\n OlderVersionsExtraFieldsUnion<TLatest, TOlderVersions> extends never\n ? TLatest['fields']\n : TLatest['fields'] &\n UnionToIntersection<\n OlderVersionsExtraFieldsUnion<TLatest, TOlderVersions>\n >;\n\nfunction toHostModule<TContract extends AnyContract>(\n contract: TContract,\n fields: HostFields<TContract>,\n signal: AbortSignal | undefined,\n): HostModule {\n // Null-prototype as defence in depth. `olderVersion` already rejects an\n // extra input named \"__proto__\" via `VALID_FIELD_NAME`, so no such name\n // should reach here; a plain `{}` would silently drop it through the\n // legacy setter rather than defining an own property if one ever did.\n const implementation: Record<string, LiveValue<unknown> | HostFunction> =\n Object.create(null);\n const rawFields: Record<string, unknown> = fields;\n for (const [name, field] of Object.entries(contract.fields)) {\n implementation[name] =\n field.kind === 'value'\n ? (rawFields[name] as LiveValue<unknown>)\n : Object.freeze({\n invoke: rawFields[name] as HostFunction['invoke'],\n });\n }\n return createHostModule(contract, Object.freeze(implementation), signal);\n}\n\n/** Narrows a flat field record to the names one version actually reads. */\nfunction pickFields(\n fields: Readonly<Record<string, unknown>>,\n names: readonly string[],\n): Readonly<Record<string, unknown>> {\n // Null-prototype for the same defence-in-depth reason as `toHostModule`\n // above: `names` can include an older version's extra-input name, which\n // `olderVersion` already shape-checks with `VALID_FIELD_NAME`.\n const picked: Record<string, unknown> = Object.create(null);\n for (const name of names) {\n picked[name] = fields[name];\n }\n return picked;\n}\n\n/**\n * Whether two versions asking for the same field name mean the same thing.\n * Flattening gives a name exactly one slot, so a disagreement has to be an\n * authoring error rather than something a provider could satisfy twice.\n */\nfunction isSameField(left: AnyField, right: AnyField): boolean {\n if (left.kind !== right.kind) {\n return false;\n }\n if (left.kind === 'value' && right.kind === 'value') {\n return left.schema === right.schema;\n }\n if (left.kind === 'function' && right.kind === 'function') {\n const leftNames = Object.keys(left.inputs);\n const rightNames = Object.keys(right.inputs);\n // Deliberately does not compare `timeoutMs`. This check exists so one\n // provider implementation can serve every version sharing a flattened\n // slot, which a mismatched schema or input name would prevent. A\n // deadline cannot prevent it: the flattened descriptor is only used to\n // type the provider record and to slice it by name, and `buildModules`\n // hands each version `toHostModule(older.contract, ...)`, so every\n // deadline is resolved from that version's own contract field. Two\n // versions reusing one extra-input name may declare different\n // deadlines with no runtime consequence whatsoever.\n return !(\n leftNames.length !== rightNames.length ||\n left.result !== right.result ||\n leftNames.some(\n (name) =>\n !Object.prototype.hasOwnProperty.call(right.inputs, name) ||\n left.inputs[name] !== right.inputs[name],\n )\n );\n }\n return false;\n}\n\n/**\n * Flattens `latest`'s own fields together with every older version's extra\n * inputs into the one namespace a provider populates, rejecting the two ways\n * that flattening can go wrong: an extra input that shadows a real field of\n * `latest`, and two older versions claiming one name for different schemas.\n */\nfunction mergeVersionedFields<TLatest extends AnyContract>(\n latest: TLatest,\n olderVersions: readonly AnyOlderContractVersion<TLatest>[],\n): Readonly<Record<string, AnyField>> {\n // Null-prototype as defence in depth: `VALID_FIELD_NAME` already excludes\n // an extra input named \"__proto__\", but were one to reach here it must\n // become an own property rather than invoke the inherited legacy setter\n // and silently repoint `merged`'s prototype.\n const merged: Record<string, AnyField> = Object.create(null);\n for (const [name, field] of Object.entries(latest.fields)) {\n merged[name] = field;\n }\n for (const older of olderVersions) {\n for (const [name, field] of Object.entries(older.extraInputs)) {\n if (Object.prototype.hasOwnProperty.call(latest.fields, name)) {\n throw new Error(\n `\"${latest.identifier}\" v${older.contract.version} declares extra input \"${name}\", which already names a field of v${latest.version}.`,\n );\n }\n const existing = Object.prototype.hasOwnProperty.call(merged, name)\n ? merged[name]\n : undefined;\n if (existing && !isSameField(existing, field)) {\n throw new Error(\n `\"${latest.identifier}\" extra input \"${name}\" is declared with conflicting schemas by more than one older version.`,\n );\n }\n merged[name] = field;\n }\n }\n return Object.freeze(merged);\n}\n\n/**\n * Ties a latest contract to any number of older versions it stays willing to\n * serve. `buildModules()` derives each older version's fields from the\n * latest implementation plus that version's own extra inputs and returns one\n * independent, fully live `HostModule` per version -- ready to hand to a\n * host listener alongside modules for any other contract.\n */\nexport function defineVersionedContract<\n TLatest extends AnyContract,\n const TOlderVersions extends readonly AnyOlderContractVersion<TLatest>[],\n>(\n latest: TLatest,\n ...olderVersions: TOlderVersions\n): VersionedContract<TLatest, TOlderVersions> {\n const versions = new Set<ContractVersion>([latest.version]);\n for (const older of olderVersions) {\n if (older.contract.identifier !== latest.identifier) {\n throw new Error(\n `Older version \"${older.contract.identifier}\" v${older.contract.version} must share identifier \"${latest.identifier}\" with its latest contract.`,\n );\n }\n if (older.contract.version >= latest.version) {\n throw new Error(\n `Older version \"${latest.identifier}\" v${older.contract.version} must be older than latest v${latest.version}.`,\n );\n }\n if (versions.has(older.contract.version)) {\n throw new Error(\n `\"${latest.identifier}\" declares version ${older.contract.version} more than once.`,\n );\n }\n versions.add(older.contract.version);\n }\n\n const fields = mergeVersionedFields(latest, olderVersions);\n const latestNames = Object.keys(latest.fields);\n\n return Object.freeze({\n identifier: latest.identifier,\n latest,\n // `Object.freeze` on the returned object is shallow: exposing the\n // validated array by reference would let a caller mutate it (push,\n // sort, splice) after the fact despite the wrapper looking frozen.\n olderVersions: Object.freeze([...olderVersions]) as TOlderVersions,\n fields: fields as VersionedContractFields<TLatest, TOlderVersions>,\n buildModules(\n allFields: HostFieldsFor<\n VersionedContractFields<TLatest, TOlderVersions>\n >,\n signal?: AbortSignal,\n ): readonly HostModule[] {\n const flat: Readonly<Record<string, unknown>> = allFields;\n // Slicing by each version's own field names is what lets two\n // versions share one slot: both reads hit the same live value.\n const latestImplementation = pickFields(\n flat,\n latestNames,\n ) as HostFields<TLatest>;\n const modules: HostModule[] = [\n toHostModule(latest, latestImplementation, signal),\n ];\n for (const older of olderVersions) {\n const derived = older.convert(\n latestImplementation,\n pickFields(\n flat,\n Object.keys(older.extraInputs),\n ) as HostFieldsFor<Record<string, AnyField>>,\n );\n modules.push(toHostModule(older.contract, derived, signal));\n }\n return Object.freeze(modules);\n },\n });\n}\n", "import {\n MAX_CLAIM_FIELD_NAME_LENGTH,\n MAX_CLAIM_FIELDS,\n MAX_TIMER_DELAY_MS,\n} from '../embedding/config';\nimport {\n defineContract,\n fn as defineFunctionField,\n hasUsableFunctionTimeout,\n isAnyFieldShape,\n VALID_FIELD_NAME,\n value as defineValueField,\n} from '../embedding/contract';\nimport { isRecord } from '../embedding/shared';\nimport { EVERY_SURFACE } from '../embedding/types';\nimport type {\n AnyContract,\n AnyField,\n AnySchema,\n Contract,\n ContractVersion,\n FunctionField,\n InferOf,\n SurfaceId,\n ValidationOnlySchema,\n ValueField,\n ValueSchema,\n} from '../embedding/types';\nimport { defineVersionedContract } from '../embedding/versioning';\nimport type {\n AnyOlderContractVersion,\n AnyVersionedContract,\n VersionedContract,\n} from '../embedding/versioning';\n\ndeclare const publishedDefinitionBrand: unique symbol;\n\n/**\n * One published inputs definition: every version it serves, and the surfaces\n * it is offered on.\n *\n * `surfaces` exists for development ergonomics only -- discovery while writing\n * code, and type errors when a host forgets an input its surface offers.\n * Nothing reads it at runtime, and inputs and surfaces are otherwise unrelated:\n * an input is a complete thing without any surface, which is why declaring them\n * is optional. Omitted resolves to every `SurfaceId`, so the hint reads as\n * \"available everywhere\" rather than as an empty list.\n */\nexport type DatadogAppInputsSchema<\n TLatest extends AnyContract,\n TSurfaces extends readonly SurfaceId[] = typeof EVERY_SURFACE,\n TOlderVersions extends readonly AnyOlderContractVersion<TLatest>[] =\n readonly [],\n> = VersionedContract<TLatest, TOlderVersions> &\n Readonly<{ surfaces: TSurfaces }>;\n\nexport type AnyDatadogAppInputsSchema = AnyVersionedContract &\n Readonly<{ surfaces: readonly SurfaceId[] }>;\n\nexport type PublishedDatadogAppInputsDefinition<\n TSchema extends AnyDatadogAppInputsSchema,\n> = TSchema &\n Readonly<{\n [publishedDefinitionBrand]: (\n fields: TSchema['latest']['fields'],\n ) => TSchema['latest']['fields'];\n }>;\n\nconst publishedDefinitions = new WeakSet<object>();\n\ntype PortableSchema<TSchema extends AnySchema> = ValueSchema<InferOf<TSchema>>;\n\nconst CONTRACT_IDENTIFIER_PATTERN = /^[a-z][a-z0-9]*(?:[.-][a-z0-9]+)*$/;\n\nfunction assertValidField(\n contractIdentifier: string,\n name: string,\n field: unknown,\n): asserts field is AnyField {\n if (\n !VALID_FIELD_NAME.test(name) ||\n name.length > MAX_CLAIM_FIELD_NAME_LENGTH ||\n !isAnyFieldShape(field)\n ) {\n throw new Error(\n `Datadog App input field \"${contractIdentifier}.${name}\" must have a name matching ${String(VALID_FIELD_NAME)} of at most ${MAX_CLAIM_FIELD_NAME_LENGTH} characters and be a read-only value or function whose schemas implement Standard Schema V1.`,\n );\n }\n if (field.kind === 'function') {\n for (const inputName of Object.keys(field.inputs)) {\n if (!VALID_FIELD_NAME.test(inputName)) {\n throw new Error(\n `Datadog App input function parameter \"${contractIdentifier}.${name}.${inputName}\" must have a name matching ${String(VALID_FIELD_NAME)}.`,\n );\n }\n }\n if (!hasUsableFunctionTimeout(field)) {\n throw new Error(\n `Datadog App input function field \"${contractIdentifier}.${name}\" declares a timeoutMs no call could meet. It must be greater than 0 and at most ${MAX_TIMER_DELAY_MS}.`,\n );\n }\n }\n}\n\nfunction assertValidContract(\n contract: unknown,\n): asserts contract is AnyContract {\n if (\n !isRecord(contract) ||\n typeof contract.identifier !== 'string' ||\n !CONTRACT_IDENTIFIER_PATTERN.test(contract.identifier)\n ) {\n throw new Error(\n `Datadog App input contract identifier \"${String(isRecord(contract) ? contract.identifier : undefined)}\" must match ${String(CONTRACT_IDENTIFIER_PATTERN)}.`,\n );\n }\n if (\n typeof contract.version !== 'number' ||\n !Number.isSafeInteger(contract.version) ||\n contract.version < 1\n ) {\n throw new Error(\n `Datadog App input contract \"${contract.identifier}\" must have a positive integer version.`,\n );\n }\n if (\n !isRecord(contract.fields) ||\n Object.keys(contract.fields).length === 0 ||\n Object.keys(contract.fields).length > MAX_CLAIM_FIELDS\n ) {\n throw new Error(\n `Datadog App input contract \"${contract.identifier}\" must define between 1 and ${MAX_CLAIM_FIELDS} fields.`,\n );\n }\n for (const [name, field] of Object.entries(contract.fields)) {\n assertValidField(contract.identifier, name, field);\n }\n}\n\nfunction assertValidExtraInputs(\n contractIdentifier: string,\n extraInputs: unknown,\n): void {\n if (!isRecord(extraInputs)) {\n throw new Error(\n `Older Datadog App input contract \"${contractIdentifier}\" must declare its extra inputs as an object.`,\n );\n }\n for (const [name, field] of Object.entries(extraInputs)) {\n assertValidField(contractIdentifier, name, field);\n }\n}\n\ninterface PortableValueBuilder {\n readOnly<TSchema extends AnySchema>(\n schema: ValidationOnlySchema<TSchema>,\n ): ValueField<PortableSchema<TSchema>>;\n}\n\ninterface PortableFunctionBuilder {\n readOnly<\n const TInputs extends Readonly<Record<string, AnySchema>>,\n TResult extends AnySchema,\n >(\n definition: Readonly<{\n inputs: {\n readonly [TName in keyof TInputs]: ValidationOnlySchema<\n TInputs[TName]\n >;\n };\n result: ValidationOnlySchema<TResult>;\n /**\n * Optional per-function override of `FUNCTION_CALL_TIMEOUT_MS`.\n * See `FunctionField.timeoutMs`.\n */\n timeoutMs?: number;\n }>,\n ): FunctionField<\n {\n readonly [TName in keyof TInputs]: PortableSchema<TInputs[TName]>;\n },\n PortableSchema<TResult>\n >;\n}\n\n/** Builds an input value field while hiding its concrete validator type. */\nexport const value: PortableValueBuilder = /* @__PURE__ */ Object.freeze({\n readOnly<TSchema extends AnySchema>(\n schema: ValidationOnlySchema<TSchema>,\n ): ValueField<PortableSchema<TSchema>> {\n return defineValueField.readOnly(schema) as unknown as ValueField<\n PortableSchema<TSchema>\n >;\n },\n});\n\n/** Builds an input function field while hiding its concrete validator types. */\nexport const fn: PortableFunctionBuilder = /* @__PURE__ */ Object.freeze({\n readOnly<\n const TInputs extends Readonly<Record<string, AnySchema>>,\n TResult extends AnySchema,\n >(\n definition: Readonly<{\n inputs: {\n readonly [TName in keyof TInputs]: ValidationOnlySchema<\n TInputs[TName]\n >;\n };\n result: ValidationOnlySchema<TResult>;\n timeoutMs?: number;\n }>,\n ): FunctionField<\n {\n readonly [TName in keyof TInputs]: PortableSchema<TInputs[TName]>;\n },\n PortableSchema<TResult>\n > {\n return defineFunctionField.readOnly(\n definition,\n ) as unknown as FunctionField<\n {\n readonly [TName in keyof TInputs]: PortableSchema<\n TInputs[TName]\n >;\n },\n PortableSchema<TResult>\n >;\n },\n});\n\ntype ValidationOnlyFields<TFields extends Record<string, AnyField>> = {\n readonly [TName in keyof TFields]: TFields[TName] extends ValueField<\n infer TSchema\n >\n ? ValueField<ValidationOnlySchema<TSchema>>\n : TFields[TName] extends FunctionField<infer TInputs, infer TResult>\n ? FunctionField<\n {\n readonly [TInputName in keyof TInputs]: ValidationOnlySchema<\n TInputs[TInputName]\n >;\n },\n ValidationOnlySchema<TResult>\n >\n : never;\n};\n\ntype PortableFields<TFields extends Record<string, AnyField>> = {\n readonly [TName in keyof TFields]: TFields[TName] extends ValueField<\n infer TSchema\n >\n ? ValueField<PortableSchema<TSchema>>\n : TFields[TName] extends FunctionField<infer TInputs, infer TResult>\n ? FunctionField<\n {\n readonly [TInputName in keyof TInputs]: PortableSchema<\n TInputs[TInputName]\n >;\n },\n PortableSchema<TResult>\n >\n : never;\n};\n\nexport type PortableContract<\n TIdentifier extends string,\n TVersion extends ContractVersion,\n TFields extends Record<string, AnyField>,\n> = Contract<PortableFields<TFields>> &\n Readonly<{ identifier: TIdentifier; version: TVersion }>;\n\n/**\n * Defines one version of a package-owned input contract. Concrete validator\n * types are deliberately erased at this boundary: schema authors keep full\n * inference while public declarations expose only Standard Schema.\n *\n * A contract on its own cannot be provided to an app -- only\n * `datadogAppInputsDefinition()`'s output can -- so declaring a version is\n * never the same as offering to serve it.\n */\nexport function datadogAppInputsVersion<\n const TIdentifier extends string,\n const TVersion extends ContractVersion,\n const TFields extends Record<string, AnyField>,\n>(\n definition: Contract<TFields> &\n Readonly<{\n identifier: TIdentifier;\n version: TVersion;\n fields: ValidationOnlyFields<TFields>;\n }>,\n): PortableContract<TIdentifier, TVersion, TFields> {\n const contract = defineContract<TIdentifier, TVersion, TFields>(\n definition as unknown as Parameters<\n typeof defineContract<TIdentifier, TVersion, TFields>\n >[0],\n ) as unknown as PortableContract<TIdentifier, TVersion, TFields>;\n assertValidContract(contract);\n return contract;\n}\n\n/**\n * Publishes one package-owned inputs definition.\n *\n * The common case is one version, declared inline -- `identifier`, `version`,\n * `fields`, and optionally the `surfaces` it is offered on. A schema that has\n * to keep serving older versions instead passes `latest` plus `olderVersions`,\n * so the extra step is paid only where extra versions exist.\n *\n * Either way the result is the single unit both sides deal in: an app claims it\n * without naming a version, and a host provides it without learning that more\n * than one exists. Dropping an `olderVersion()` is how support for that version\n * ends, and simultaneously how the fields a host must supply get smaller.\n */\nexport function datadogAppInputsDefinition<\n const TIdentifier extends string,\n const TVersion extends ContractVersion,\n const TFields extends Record<string, AnyField>,\n const TSurfaces extends readonly SurfaceId[] = typeof EVERY_SURFACE,\n>(\n // `Contract<TFields> &` is the inference site for `TFields`: TS cannot\n // recover it from the mapped `ValidationOnlyFields<TFields>` alone, and\n // silently widens to `Record<string, AnyField>` without this.\n definition: Contract<TFields> &\n Readonly<{\n identifier: TIdentifier;\n version: TVersion;\n fields: ValidationOnlyFields<TFields>;\n /** Surfaces this input is offered on -- a development-time hint, read by nothing at runtime. */\n surfaces?: TSurfaces;\n }>,\n): PublishedDatadogAppInputsDefinition<\n DatadogAppInputsSchema<\n PortableContract<TIdentifier, TVersion, TFields>,\n TSurfaces\n >\n>;\nexport function datadogAppInputsDefinition<\n TLatest extends AnyContract,\n const TSurfaces extends readonly SurfaceId[] = typeof EVERY_SURFACE,\n const TOlderVersions extends readonly AnyOlderContractVersion<TLatest>[] =\n readonly [],\n>(\n definition: Readonly<{\n latest: TLatest;\n surfaces?: TSurfaces;\n olderVersions?: TOlderVersions;\n }>,\n): PublishedDatadogAppInputsDefinition<\n DatadogAppInputsSchema<TLatest, TSurfaces, TOlderVersions>\n>;\nexport function datadogAppInputsDefinition(definitionInput: object): unknown {\n const definition = definitionInput as Readonly<Record<string, unknown>>;\n const latest =\n 'latest' in definition\n ? (definition.latest as AnyContract)\n : datadogAppInputsVersion(\n definition as unknown as Parameters<\n typeof datadogAppInputsVersion\n >[0],\n );\n const olderVersions = (definition.olderVersions ??\n []) as readonly AnyOlderContractVersion<AnyContract>[];\n assertValidContract(latest);\n for (const olderVersion of olderVersions) {\n assertValidContract(olderVersion.contract);\n assertValidExtraInputs(latest.identifier, olderVersion.extraInputs);\n }\n const schema = defineVersionedContract(latest, ...olderVersions);\n const published = Object.freeze({\n ...schema,\n surfaces: Object.freeze([\n ...((definition.surfaces as readonly SurfaceId[] | undefined) ??\n EVERY_SURFACE),\n ]),\n });\n publishedDefinitions.add(published);\n return published;\n}\n\n/** Rejects copied or user-authored definitions at the public React boundary. */\nexport function assertPublishedDatadogAppInputsDefinition(\n definition: unknown,\n): asserts definition is PublishedDatadogAppInputsDefinition<AnyDatadogAppInputsSchema> {\n if (\n typeof definition !== 'object' ||\n definition === null ||\n !publishedDefinitions.has(definition)\n ) {\n throw new Error(\n 'useDatadogAppInput() requires a definition exported by @datadog/apps-frontend/inputs/schema.',\n );\n }\n}\n\n/**\n * Turns one plain value into the field descriptor that carries it: a function\n * becomes a callable field with validated inputs and result, anything else a\n * read-only value field. This is the inverse of the erasure `value.readOnly()`\n * and `fn.readOnly()` perform, which is what lets a schema be *declared* in the\n * terms a consumer thinks in while being *built* from real validators.\n */\n// `[TValue] extends [...]` rather than a naked parameter: a naked one\n// distributes, so a union value like `'light' | 'dark'` would become a *union of\n// fields* instead of one field carrying a union.\ntype FieldFor<TValue> = [TValue] extends [\n (inputs: infer TInputs) => infer TResult,\n]\n ? FunctionField<\n { readonly [TName in keyof TInputs]: ValueSchema<TInputs[TName]> },\n ValueSchema<Awaited<TResult>>\n >\n : ValueField<ValueSchema<TValue>>;\n\ntype FieldsFor<TShape extends Readonly<Record<string, unknown>>> = {\n readonly [TName in keyof TShape]: FieldFor<TShape[TName]>;\n};\n\n/**\n * One Datadog App input, described the way it is used rather than the way it is\n * built: its identifier, the values a claim hands you, and the surfaces it is\n * offered on.\n *\n * This is the type a schema annotates itself with, so it is also what an editor\n * shows on hover. Versions are deliberately absent -- how many exist, and which\n * one a given peer gets, is settled by the package and is not a caller's\n * concern.\n *\n * @example\n * ```ts\n * DatadogAppInput<\n * 'datadog.idp.homepage',\n * { position: number; move: (inputs: { delta: number }) => number },\n * readonly ['datadog.idp.homepage']\n * >\n * ```\n */\nexport type DatadogAppInput<\n TIdentifier extends string,\n TShape extends Readonly<Record<string, unknown>>,\n TSurfaces extends readonly SurfaceId[] = typeof EVERY_SURFACE,\n> = PublishedDatadogAppInputsDefinition<\n DatadogAppInputsSchema<\n Contract<FieldsFor<TShape>> &\n Readonly<{ identifier: TIdentifier; version: ContractVersion }>,\n TSurfaces\n >\n>;\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["EVERY_SURFACE", "toHostModule", "contract", "fields", "signal", "implementation", "rawFields", "name", "field", "createHostModule", "pickFields", "names", "picked", "isSameField", "left", "right", "leftNames", "rightNames", "mergeVersionedFields", "latest", "olderVersions", "merged", "older", "existing", "defineVersionedContract", "versions", "latestNames", "allFields", "flat", "latestImplementation", "modules", "derived", "publishedDefinitions", "CONTRACT_IDENTIFIER_PATTERN", "assertValidField", "contractIdentifier", "name", "field", "VALID_FIELD_NAME", "MAX_CLAIM_FIELD_NAME_LENGTH", "isAnyFieldShape", "inputName", "hasUsableFunctionTimeout", "assertValidContract", "contract", "isRecord", "MAX_CLAIM_FIELDS", "assertValidExtraInputs", "extraInputs", "value", "schema", "datadogAppInputsVersion", "definition", "contract", "defineContract", "assertValidContract", "datadogAppInputsDefinition", "definitionInput", "latest", "olderVersions", "olderVersion", "assertValidExtraInputs", "schema", "defineVersionedContract", "published", "EVERY_SURFACE", "publishedDefinitions", "assertPublishedDatadogAppInputsDefinition"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/* Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0.
|
|
2
|
+
* This product includes software developed at Datadog (https://www.datadoghq.com/).
|
|
3
|
+
* Copyright 2019-Present Datadog, Inc.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
var _=Object.defineProperty;var u=e=>{throw TypeError(e)};var A=(e,n,t)=>n in e?_(e,n,{enumerable:!0,configurable:!0,writable:!0,value:t}):e[n]=t;var I=(e,n,t)=>A(e,typeof n!="symbol"?n+"":n,t),s=(e,n,t)=>n.has(e)||u("Cannot "+t);var w=(e,n,t)=>(s(e,n,"read from private field"),t?t.call(e):n.get(e)),v=(e,n,t)=>n.has(e)?u("Cannot add the same private member more than once"):n instanceof WeakSet?n.add(e):n.set(e,t),V=(e,n,t,r)=>(s(e,n,"write to private field"),r?r.call(e,t):n.set(e,t),t),L=(e,n,t)=>(s(e,n,"access private method"),t);function k(e,n){if(!Number.isFinite(n)||n<0||n>2147483647)throw new RangeError(`${e} must be a finite number between 0 and 2147483647.`)}var C=1e4,D=5e3,j=250,H=1e3,$=1e4,X=45e3,z=128,U=256,P=256,B=128,Y=32,a=128,f=256;var g="[Datadog Apps embedding]";function o(e,n=0){if(!(e instanceof Error))return e;try{let t={name:e.name,message:e.message};return typeof e.stack=="string"&&(t.stack=e.stack),e.cause!==void 0&&(t.cause=n<3?o(e.cause,n+1):"(cause chain truncated)"),t}catch{return"(cause could not be described)"}}function W(e){return"cause"in e?{...e,cause:o(e.cause)}:e}function p(e,n,t){try{globalThis.console?.[e](`${g} ${n}`,t)}catch{}}function Z(e,n={}){p("warn",e,n)}function c(e,n={}){p("error",e,n)}var m=0;function K(e){return m+=1,`${e}:${S()}:${m.toString(36)}`}function S(){let e=new Uint8Array(8);globalThis.crypto.getRandomValues(e);let n="";for(let t of e)n+=t.toString(16).padStart(2,"0");return n}function Q(e){return{ok:!0,value:e}}function ee(e){return{ok:!1,error:e}}function i(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function y(e,n){return typeof e=="string"&&e.length>0&&(n===void 0||e.length<=n)}function ne(e,n){try{n()}catch(t){c("a teardown step failed",{description:e,cause:o(t)})}}function te(e,...n){for(let t of[...e])try{t(...n)}catch(r){c("an embedding listener threw",{cause:o(r)}),globalThis.queueMicrotask(()=>{throw r})}}var O=/^[A-Za-z][A-Za-z0-9_]*$/,b=new WeakSet;function se(e,n,t){let r=Object.create(null);for(let[h,E]of Object.entries(n))r[h]=E;Object.freeze(r);let l=Object.freeze(t===void 0?{contract:e,implementation:r}:{contract:e,implementation:r,signal:t});return b.add(l),l}function d(e){if(!(typeof e=="object"&&e!==null||typeof e=="function"))return!1;let n=e["~standard"];return i(n)&&n.version===1&&typeof n.validate=="function"}function M(e){return i(e)&&e.kind==="value"&&d(e.schema)}function R(e){return i(e)&&e.kind==="function"&&i(e.inputs)&&Object.entries(e.inputs).every(([n,t])=>n.length>0&&d(t))&&d(e.result)}function x(e){return M(e)||R(e)}function F(e){return e.kind!=="function"||e.timeoutMs===void 0||typeof e.timeoutMs=="number"&&Number.isFinite(e.timeoutMs)&&e.timeoutMs>0&&e.timeoutMs<=2147483647}var ae=Object.freeze({readOnly(e){return Object.freeze({kind:"value",schema:e})}});function ce(e){if(!y(e.identifier))throw new Error(`Invalid embedding contract identifier "${String(e.identifier)}".`);if(!Number.isSafeInteger(e.version)||e.version<1)throw new Error(`Embedding contract "${e.identifier}" must have a positive integer version.`);let n=Object.entries(e.fields);if(n.length===0||n.length>a)throw new Error(`Embedding contract "${e.identifier}" must define between 1 and ${a} fields.`);for(let[t,r]of n){if(!O.test(t)||t.length>f||!x(r))throw new Error(`Embedding contract field "${e.identifier}.${t}" must be a named read-only value or function whose schemas implement Standard Schema V1.`);if(!F(r))throw new Error(`Embedding contract field "${e.identifier}.${t}" declares a timeoutMs no call could meet. It must be greater than 0 and at most ${2147483647}.`)}return Object.freeze({identifier:e.identifier,version:e.version,fields:Object.freeze(Object.fromEntries(n.map(([t,r])=>[t,r.kind==="value"?Object.freeze({...r,schema:r.schema}):Object.freeze({...r,inputs:Object.freeze({...r.inputs}),result:r.result})])))})}export{I as a,w as b,v as c,V as d,L as e,k as f,C as g,D as h,j as i,H as j,$ as k,X as l,z as m,U as n,P as o,B as p,Y as q,a as r,f as s,o as t,W as u,Z as v,c as w,K as x,Q as y,ee as z,i as A,y as B,ne as C,te as D,O as E,se as F,x as G,F as H,ae as I,ce as J};
|
|
7
|
+
//# sourceMappingURL=chunk-X34MSTJH.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/embedding/config.ts", "../../../src/embedding/diagnostics.ts", "../../../src/embedding/shared.ts", "../../../src/embedding/contract.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Every tunable the embedding protocol uses -- timeouts and the limits that\n * bound peer-influenced state -- together in one place with an obvious name\n * each, instead of scattered as same-looking magic numbers across unrelated\n * files.\n */\n\nexport const PROTOCOL_VERSION = 1;\n\n// --- Timeouts -----------------------------------------------------------\n//\n// Each one is a local decision made independently by whichever side enforces\n// it -- none of these are negotiated with, or need to match, the peer's own\n// value for the same phase.\n\n/** Phase 1: transferring the private control port across the window boundary. */\nexport const BOOTSTRAP_TIMEOUT_MS = 10_000;\n\n/** Phases 2 and 3: protocol compatibility negotiation and bringing up the\n * operational protocol on the transferred port. Each phase receives this\n * full deadline independently. */\nexport const CONNECT_TIMEOUT_MS = 10_000;\n\n/** How long the app waits for the host to answer its claim of a module. */\nexport const CLAIM_TIMEOUT_MS = 5_000;\n\n/** How long a function call is allowed to run (host side) or be waited on\n * (app side). Each side enforces this purely locally -- it is never sent\n * over the wire, and one side never needs to know the other's value: the\n * watchdog that fires first just wins through the normal error path, the\n * same way any other host/app-independent failure already does. */\nexport const FUNCTION_CALL_TIMEOUT_MS = 600_000;\n\n/**\n * Ceiling for a `FunctionField.timeoutMs` override: the largest delay\n * `setTimeout` accepts. Anything above it silently overflows the 32-bit\n * signed timer and fires almost immediately, inverting the longest deadline\n * an author can ask for into the shortest one they could get.\n */\nexport const MAX_TIMER_DELAY_MS = 2_147_483_647;\n\n/** Reject a public timeout override that `setTimeout` cannot represent. */\nexport function assertValidTimerDelay(name: string, timeoutMs: number): void {\n if (\n !Number.isFinite(timeoutMs) ||\n timeoutMs < 0 ||\n timeoutMs > MAX_TIMER_DELAY_MS\n ) {\n throw new RangeError(\n `${name} must be a finite number between 0 and ${MAX_TIMER_DELAY_MS}.`,\n );\n }\n}\n\n/** How often a heartbeat ping is sent, and how long a reply is awaited\n * before it counts as a miss. */\nexport const HEARTBEAT_INTERVAL_MS = 10_000;\nexport const HEARTBEAT_DEADLINE_MS = 5_000;\n\n/** Grace period between posting a close envelope and actually tearing down\n * the transport, so the envelope isn't truncated in flight. */\nexport const CLOSE_DELIVERY_TIMEOUT_MS = 250;\n\n/** Reconnection backoff: starting delay, cap, and how long to keep retrying\n * before giving up on the whole recovery attempt. */\nexport const RECONNECT_RETRY_MS = 1_000;\nexport const RECONNECT_MAX_RETRY_MS = 10_000;\nexport const RECONNECT_GIVE_UP_AFTER_MS = 45_000;\n\n// --- Limits ---------------------------------------------------------------\n//\n// These bound state retained at the request of iframe code, so an\n// adversarial or malformed peer can't grow it without limit. Both peers\n// validate against them independently.\n\nexport const MAX_LIVE_HOST_CLAIMS = 128;\nexport const MAX_CLAIM_ID_LENGTH = 256;\nexport const MAX_CALL_ID_LENGTH = 256;\nexport const MAX_LIVE_HOST_FUNCTION_CALLS = 128;\nexport const MAX_PENDING_ENDPOINT_OPERATIONS = 32;\nexport const MAX_CLAIM_FIELDS = 128;\nexport const MAX_CLAIM_FIELD_NAME_LENGTH = 256;\n", "/**\n * Console diagnostics for every embedding outcome that is not\n * starting -> connecting -> connected.\n *\n * Debugging an embedding failure means reasoning about two documents that each\n * see half of the connection: the Datadog page owns the host listener, the app\n * iframe owns the connection handle, and neither observes why the other gave\n * up. Every failure, rejection, timeout, and lost connection therefore reports\n * itself locally, naming the side that produced it and carrying the detail the\n * wire deliberately does not: raw causes, validation issues, claim and call\n * identifiers, attempt counts, and the deadline that expired.\n *\n * This module never throws. It runs on paths that are already failing, in\n * browsers we do not control, so a missing or hostile `console` must not\n * replace the failure being reported.\n */\n\nimport type { AnyError } from './types';\n\nconst PREFIX = '[Datadog Apps embedding]';\n\n/** How deep an `Error.cause` chain is described before it is truncated. */\nconst MAX_CAUSE_DEPTH = 3;\n\n/** Which peer produced a log line; both peers run this code. */\nexport type DiagnosticSide = 'app' | 'host';\n\nexport type DiagnosticDetail = Readonly<Record<string, unknown>>;\n\n/**\n * Renders an arbitrary thrown value as inspectable data. Errors lose their\n * `name`, `message`, `stack`, and `cause` when a console is handed a bare\n * `Error` inside an object in some environments, so those are spread out\n * explicitly; anything else is passed through for the console to format.\n */\nexport function describeCause(cause: unknown, depth = 0): unknown {\n if (!(cause instanceof Error)) {\n return cause;\n }\n // A peer-influenced Error may have hostile name/message/stack/cause\n // accessors; this module's \"never throws\" guarantee must hold even then.\n try {\n const described: Record<string, unknown> = {\n name: cause.name,\n message: cause.message,\n };\n if (typeof cause.stack === 'string') {\n described.stack = cause.stack;\n }\n if (cause.cause !== undefined) {\n described.cause =\n depth < MAX_CAUSE_DEPTH\n ? describeCause(cause.cause, depth + 1)\n : '(cause chain truncated)';\n }\n return described;\n } catch {\n return '(cause could not be described)';\n }\n}\n\n/**\n * Renders a wire error for logging. Every code carries structured-clone-safe\n * data already, except the local-only `cause` of `TRANSPORT_FAILED`, which is\n * where the actual explanation usually lives.\n */\nexport function describeError(error: AnyError): DiagnosticDetail {\n return 'cause' in error\n ? { ...error, cause: describeCause(error.cause) }\n : error;\n}\n\nfunction log(\n level: 'warn' | 'error',\n event: string,\n detail: DiagnosticDetail,\n): void {\n try {\n globalThis.console?.[level](`${PREFIX} ${event}`, detail);\n } catch {\n // A console that cannot be used is not a reason to lose the outcome\n // this call was reporting.\n }\n}\n\n/** A failure the connection expects to recover from, or a degraded outcome. */\nexport function logWarning(event: string, detail: DiagnosticDetail = {}): void {\n log('warn', event, detail);\n}\n\n/** A failure a consumer observes: terminal, unrecoverable, or data-losing. */\nexport function logFailure(event: string, detail: DiagnosticDetail = {}): void {\n log('error', event, detail);\n}\n", "import { describeCause, logFailure } from './diagnostics';\nimport type { Result } from './types';\n\nlet nextId = 0;\n\n/**\n * The counter prevents local reuse if randomness repeats; the random segment\n * makes heartbeat nonces difficult for the peer to predict.\n */\nexport function createId(prefix: string): string {\n nextId += 1;\n return `${prefix}:${randomSegment()}:${nextId.toString(36)}`;\n}\n\nfunction randomSegment(): string {\n const bytes = new Uint8Array(8);\n globalThis.crypto.getRandomValues(bytes);\n let segment = '';\n for (const byte of bytes) {\n segment += byte.toString(16).padStart(2, '0');\n }\n return segment;\n}\n\nexport function success<TValue>(value: TValue): Result<TValue, never> {\n return { ok: true, value };\n}\n\nexport function err<TError>(value: TError): Result<never, TError> {\n return { ok: false, error: value };\n}\n\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * True when `value` is a well-formed identifier: a non-empty string. Bounds\n * its length to at most `limit` characters only when a limit is supplied.\n */\nexport function isValidIdentifier(\n value: unknown,\n limit?: number,\n): value is string {\n return (\n typeof value === 'string' &&\n value.length > 0 &&\n (limit === undefined || value.length <= limit)\n );\n}\n\n/**\n * Runs a cleanup action that must not throw into its caller. Teardown runs on\n * paths that are already failing, so a secondary failure is reported and\n * swallowed instead of replacing the outcome the caller is about to return.\n */\nexport function teardown(description: string, action: () => void): void {\n try {\n action();\n } catch (error) {\n logFailure('a teardown step failed', {\n description,\n cause: describeCause(error),\n });\n }\n}\n\n/**\n * Calls every listener, isolating exceptions so one listener throwing doesn't\n * stop the rest from being notified or propagate into the caller that\n * triggered the notification.\n */\nexport function notifyListeners<TArgs extends readonly unknown[] = []>(\n listeners: Iterable<(...args: TArgs) => void>,\n ...args: TArgs\n): void {\n for (const listener of [...listeners]) {\n try {\n listener(...args);\n } catch (error) {\n // Rethrown out of band, where the stack no longer shows that\n // embedding was notifying a listener.\n logFailure('an embedding listener threw', {\n cause: describeCause(error),\n });\n globalThis.queueMicrotask(() => {\n throw error;\n });\n }\n }\n}\n", "import {\n MAX_CLAIM_FIELDS,\n MAX_CLAIM_FIELD_NAME_LENGTH,\n MAX_TIMER_DELAY_MS,\n} from './config';\nimport { isRecord, isValidIdentifier } from './shared';\nimport type {\n AnyContract,\n AnyField,\n AnyFunctionField,\n AnySchema,\n Contract,\n ContractVersion,\n FunctionField,\n HostFunction,\n HostModule,\n LiveValue,\n ValidationOnlySchema,\n ValueField,\n} from './types';\n\n/**\n * A field name must be a valid own-property identifier the wire protocol\n * will actually carry: excludes \"__proto__\" and other names that a plain\n * object assignment would resolve against the prototype chain instead of\n * creating an own property. Exported so every place a contract-shaped field\n * name is declared (e.g. an older version's `extraInputs`) enforces the same\n * shape, not just `defineContract` itself.\n */\nexport const VALID_FIELD_NAME: RegExp = /^[A-Za-z][A-Za-z0-9_]*$/;\n\n/**\n * Every module this package has minted. Backs the runtime half of\n * `HostModule`'s brand, so a structurally-identical object built elsewhere is\n * rejected at `listen()` even where types were bypassed.\n */\nconst mintedHostModules = new WeakSet<object>();\n\n/**\n * The only way a `HostModule` comes into existence. Kept here, beside the\n * validation it has to satisfy, and deliberately not re-exported from\n * `@datadog/apps-frontend/embedding/internal` -- a host reaches modules only\n * as the output of providing an inputs definition, never by naming a version\n * and building one itself.\n */\nexport function createHostModule(\n contract: AnyContract,\n implementation: Readonly<Record<string, LiveValue<unknown> | HostFunction>>,\n signal?: AbortSignal,\n): HostModule {\n // A null-prototype snapshot means a wire-supplied field name (e.g.\n // \"__proto__\" or \"constructor\") can never resolve to an inherited\n // Object.prototype member when this dict is later indexed by that name.\n const snapshot: Record<string, LiveValue<unknown> | HostFunction> =\n Object.create(null);\n for (const [name, provider] of Object.entries(implementation)) {\n snapshot[name] = provider;\n }\n Object.freeze(snapshot);\n const module = Object.freeze(\n signal === undefined\n ? { contract, implementation: snapshot }\n : { contract, implementation: snapshot, signal },\n ) as unknown as HostModule;\n mintedHostModules.add(module);\n return module;\n}\n\nfunction isSchemaShape(value: unknown): value is AnySchema {\n if (\n !(\n (typeof value === 'object' && value !== null) ||\n typeof value === 'function'\n )\n ) {\n return false;\n }\n const standard = (value as AnySchema)['~standard'];\n return (\n isRecord(standard) &&\n standard.version === 1 &&\n typeof standard.validate === 'function'\n );\n}\n\n/**\n * True when `field` has the generic shape of a read-only value field.\n * Ignores identifier-name rules and implementation matching, which are\n * caller-specific (e.g. host modules also validate against a provider).\n */\nexport function isValueFieldShape(\n field: unknown,\n): field is ValueField<AnySchema> {\n return (\n isRecord(field) && field.kind === 'value' && isSchemaShape(field.schema)\n );\n}\n\n/**\n * True when `field` has the generic shape of a callable function field.\n * Ignores identifier-name rules and implementation matching, which are\n * caller-specific (e.g. host modules also validate against a provider).\n */\nexport function isFunctionFieldShape(\n field: unknown,\n): field is AnyFunctionField {\n return (\n isRecord(field) &&\n field.kind === 'function' &&\n isRecord(field.inputs) &&\n Object.entries(field.inputs).every(\n ([name, schema]) => name.length > 0 && isSchemaShape(schema),\n ) &&\n isSchemaShape(field.result)\n );\n}\n\n/** True when `field` has the generic shape of any well-formed contract field. */\nexport function isAnyFieldShape(field: unknown): field is AnyField {\n return isValueFieldShape(field) || isFunctionFieldShape(field);\n}\n\n/**\n * True when a function field's optional `timeoutMs` is a deadline a call could\n * actually meet -- see `FunctionField.timeoutMs` for why each end is not.\n *\n * Deliberately separate from `isFunctionFieldShape`: this is about a value being\n * sensible, not about the field being a function, so folding it in would make an\n * out-of-range deadline report as a malformed shape or a mismatched provider.\n */\nexport function hasUsableFunctionTimeout(field: AnyField): boolean {\n return (\n field.kind !== 'function' ||\n field.timeoutMs === undefined ||\n (typeof field.timeoutMs === 'number' &&\n Number.isFinite(field.timeoutMs) &&\n field.timeoutMs > 0 &&\n field.timeoutMs <= MAX_TIMER_DELAY_MS)\n );\n}\n\ninterface ReadOnlyValueBuilder {\n readOnly<TSchema extends AnySchema>(\n schema: ValidationOnlySchema<TSchema>,\n ): ValueField<TSchema>;\n}\n\ninterface ReadOnlyFunctionBuilder {\n readOnly<\n const TInputs extends Readonly<Record<string, AnySchema>>,\n TResult extends AnySchema,\n >(\n definition: Readonly<{\n inputs: {\n readonly [TName in keyof TInputs]: ValidationOnlySchema<\n TInputs[TName]\n >;\n };\n result: ValidationOnlySchema<TResult>;\n /**\n * Optional per-function override of `FUNCTION_CALL_TIMEOUT_MS`.\n * See `FunctionField.timeoutMs`.\n */\n timeoutMs?: number;\n }>,\n ): FunctionField<TInputs, TResult>;\n}\n\n/**\n * Builds a value field for any embedding contract. `readOnly` is the only\n * builder today because no transport exists for an app to write a value\n * back to the host; the name leaves room for a future writable builder\n * without implying one exists yet.\n */\nexport const value: ReadOnlyValueBuilder = /* @__PURE__ */ Object.freeze({\n readOnly<TSchema extends AnySchema>(\n schema: ValidationOnlySchema<TSchema>,\n ): ValueField<TSchema> {\n return Object.freeze({ kind: 'value', schema });\n },\n});\n\n/** Builds a callable function field for any embedding contract. */\nexport const fn: ReadOnlyFunctionBuilder = /* @__PURE__ */ Object.freeze({\n readOnly<\n const TInputs extends Readonly<Record<string, AnySchema>>,\n TResult extends AnySchema,\n >({\n inputs,\n result,\n timeoutMs,\n }: Readonly<{\n inputs: {\n readonly [TName in keyof TInputs]: ValidationOnlySchema<\n TInputs[TName]\n >;\n };\n result: ValidationOnlySchema<TResult>;\n timeoutMs?: number;\n }>): FunctionField<TInputs, TResult> {\n // Omitted entirely rather than stored as an explicit `undefined`, so\n // `'timeoutMs' in field` answers whether an override was declared.\n return Object.freeze(\n timeoutMs === undefined\n ? { kind: 'function', inputs, result }\n : { kind: 'function', inputs, result, timeoutMs },\n );\n },\n});\n\ntype ValidationOnlyField<TField extends AnyField> =\n TField extends Readonly<{\n kind: 'value';\n schema: infer TSchema extends AnySchema;\n }>\n ? TField & Readonly<{ schema: ValidationOnlySchema<TSchema> }>\n : TField extends Readonly<{\n kind: 'function';\n inputs: infer TInputs extends Readonly<\n Record<string, AnySchema>\n >;\n result: infer TResult extends AnySchema;\n }>\n ? TField &\n Readonly<{\n inputs: {\n readonly [TName in keyof TInputs]: ValidationOnlySchema<\n TInputs[TName]\n >;\n };\n result: ValidationOnlySchema<TResult>;\n }>\n : never;\n\ntype ValidationOnlyFields<TFields extends Record<string, AnyField>> = {\n readonly [TName in keyof TFields]: ValidationOnlyField<TFields[TName]>;\n};\n\n/**\n * Assembles and validates a well-formed `Contract`: the one place any\n * claim-defining module builds an identifier, version, and fields into the\n * shape the embedding protocol requires. Field-shape correctness reuses\n * `isAnyFieldShape` so there is a single source of truth for what a\n * contract field looks like, shared with the host-registration gate above.\n */\nexport function defineContract<\n const TIdentifier extends string,\n const TVersion extends ContractVersion,\n const TFields extends Record<string, AnyField>,\n>(\n definition: Contract<TFields> &\n Readonly<{\n identifier: TIdentifier;\n version: TVersion;\n fields: ValidationOnlyFields<TFields>;\n }>,\n): Contract<TFields> &\n Readonly<{ identifier: TIdentifier; version: TVersion }> {\n if (!isValidIdentifier(definition.identifier)) {\n throw new Error(\n `Invalid embedding contract identifier \"${String(definition.identifier)}\".`,\n );\n }\n if (!Number.isSafeInteger(definition.version) || definition.version < 1) {\n throw new Error(\n `Embedding contract \"${definition.identifier}\" must have a positive integer version.`,\n );\n }\n\n const entries = Object.entries(definition.fields);\n if (entries.length === 0 || entries.length > MAX_CLAIM_FIELDS) {\n throw new Error(\n `Embedding contract \"${definition.identifier}\" must define between 1 and ${MAX_CLAIM_FIELDS} fields.`,\n );\n }\n for (const [name, field] of entries) {\n if (\n !VALID_FIELD_NAME.test(name) ||\n name.length > MAX_CLAIM_FIELD_NAME_LENGTH ||\n !isAnyFieldShape(field)\n ) {\n throw new Error(\n `Embedding contract field \"${definition.identifier}.${name}\" must be a named read-only value or function whose schemas implement Standard Schema V1.`,\n );\n }\n if (!hasUsableFunctionTimeout(field)) {\n throw new Error(\n `Embedding contract field \"${definition.identifier}.${name}\" declares a timeoutMs no call could meet. It must be greater than 0 and at most ${MAX_TIMER_DELAY_MS}.`,\n );\n }\n }\n\n return Object.freeze({\n identifier: definition.identifier,\n version: definition.version,\n fields: Object.freeze(\n Object.fromEntries(\n entries.map(([name, field]) => [\n name,\n field.kind === 'value'\n ? Object.freeze({ ...field, schema: field.schema })\n : Object.freeze({\n ...field,\n inputs: Object.freeze({ ...field.inputs }),\n result: field.result,\n }),\n ]),\n ),\n ) as unknown as TFields,\n });\n}\n\n/**\n * The host-side registration gate. Runs when a host registers its modules, so\n * a contract that does not match its implementation fails loudly at `listen()`\n * instead of as a confusing claim failure later.\n */\nexport function assertHostModule(module: HostModule): void {\n if (!isRecord(module) || !mintedHostModules.has(module)) {\n throw new Error(\n 'A host module must come from provideDatadogAppInputs(), which serves every version an inputs definition still converts to.',\n );\n }\n if (\n !isRecord(module.contract) ||\n !isValidIdentifier(module.contract.identifier) ||\n typeof module.contract.version !== 'number' ||\n !Number.isSafeInteger(module.contract.version) ||\n module.contract.version < 1 ||\n !isRecord(module.contract.fields) ||\n Object.keys(module.contract.fields).length === 0 ||\n !isRecord(module.implementation) ||\n (module.signal !== undefined &&\n (typeof module.signal.aborted !== 'boolean' ||\n typeof module.signal.addEventListener !== 'function' ||\n typeof module.signal.removeEventListener !== 'function'))\n ) {\n throw new Error('The host module has an invalid contract.');\n }\n\n for (const [name, field] of Object.entries(module.contract.fields)) {\n const provider = Object.hasOwn(module.implementation, name)\n ? module.implementation[name]\n : undefined;\n if (\n !VALID_FIELD_NAME.test(name) ||\n name.length > MAX_CLAIM_FIELD_NAME_LENGTH\n ) {\n throw new Error(\n `A host module field name \"${name}\" is not a valid claim field name.`,\n );\n }\n const isValue =\n isValueFieldShape(field) &&\n isRecord(provider) &&\n typeof provider.get === 'function' &&\n typeof provider.subscribe === 'function';\n const isFunction =\n isFunctionFieldShape(field) &&\n isRecord(provider) &&\n typeof provider.invoke === 'function';\n if (!isValue && !isFunction) {\n throw new Error(\n `The implementation of \"${module.contract.identifier}.${name}\" does not match its field contract.`,\n );\n }\n }\n}\n\n/**\n * Validates a whole registration: every module well-formed and no duplicate\n * `(identifier, version)`. Returns the failure rather than throwing so a\n * caller can report it over the connection.\n */\nexport function invalidHostModule(\n modules: readonly HostModule[],\n): Error | undefined {\n try {\n const versions = new Set<string>();\n for (const module of modules) {\n assertHostModule(module);\n const key = JSON.stringify([\n module.contract.identifier,\n module.contract.version,\n ]);\n if (versions.has(key)) {\n throw new Error(\n `The host registered \"${module.contract.identifier}\" v${module.contract.version} more than once.`,\n );\n }\n versions.add(key);\n }\n return undefined;\n } catch (error) {\n return error instanceof Error\n ? error\n : new Error('The host module is invalid.', { cause: error });\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["assertValidTimerDelay", "name", "timeoutMs", "HEARTBEAT_INTERVAL_MS", "HEARTBEAT_DEADLINE_MS", "CLOSE_DELIVERY_TIMEOUT_MS", "RECONNECT_RETRY_MS", "RECONNECT_MAX_RETRY_MS", "RECONNECT_GIVE_UP_AFTER_MS", "MAX_LIVE_HOST_CLAIMS", "MAX_CLAIM_ID_LENGTH", "MAX_CALL_ID_LENGTH", "MAX_LIVE_HOST_FUNCTION_CALLS", "MAX_PENDING_ENDPOINT_OPERATIONS", "MAX_CLAIM_FIELDS", "MAX_CLAIM_FIELD_NAME_LENGTH", "PREFIX", "describeCause", "cause", "depth", "described", "describeError", "error", "log", "level", "event", "detail", "PREFIX", "logWarning", "logFailure", "nextId", "createId", "prefix", "randomSegment", "bytes", "segment", "byte", "success", "value", "err", "isRecord", "isValidIdentifier", "limit", "teardown", "description", "action", "error", "logFailure", "describeCause", "notifyListeners", "listeners", "args", "listener", "VALID_FIELD_NAME", "mintedHostModules", "createHostModule", "contract", "implementation", "signal", "snapshot", "name", "provider", "module", "isSchemaShape", "value", "standard", "isRecord", "isValueFieldShape", "field", "isFunctionFieldShape", "schema", "isAnyFieldShape", "hasUsableFunctionTimeout", "defineContract", "definition", "isValidIdentifier", "entries", "MAX_CLAIM_FIELDS", "name", "field", "VALID_FIELD_NAME", "MAX_CLAIM_FIELD_NAME_LENGTH", "isAnyFieldShape", "hasUsableFunctionTimeout"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/* Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0.
|
|
2
|
+
* This product includes software developed at Datadog (https://www.datadoghq.com/).
|
|
3
|
+
* Copyright 2019-Present Datadog, Inc.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export type { EmbeddingMetadata } from './types.js';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/* Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0.
|
|
2
|
+
* This product includes software developed at Datadog (https://www.datadoghq.com/).
|
|
3
|
+
* Copyright 2019-Present Datadog, Inc.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/* Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0.
|
|
2
|
+
* This product includes software developed at Datadog (https://www.datadoghq.com/).
|
|
3
|
+
* Copyright 2019-Present Datadog, Inc.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export { DatadogAppProvider } from './provider.js';
|
|
7
|
+
export { useDatadogAppEmbedding } from './use-datadog-app-embedding.js';
|
|
8
|
+
export type { UseDatadogAppEmbeddingOptions } from './use-datadog-app-embedding.js';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/* Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0.
|
|
2
|
+
* This product includes software developed at Datadog (https://www.datadoghq.com/).
|
|
3
|
+
* Copyright 2019-Present Datadog, Inc.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import{a as yn,b as Rn,c as vn,d as An}from"../../_chunks/chunk-2V2HASKF.js";import{A as b,B as k,C as L,D as ge,a as Fe,b as r,c as p,d,e as a,f as qe,g as gn,h as En,i as xe,j as Tn,k as Cn,l as et,m as It,n as B,o as tt,p as On,q as bn,r as _t,s as Dt,t as S,u as J,v as x,w as y,x as me,y as w,z as l}from"../../_chunks/chunk-X34MSTJH.js";var ho=/^https:\/\/(?:[a-zA-Z0-9-]+\.)*(?:datadoghq\.(?:com|eu)|ddog-gov\.com)$/,fo=/^https:\/\/(?:[a-zA-Z0-9-]+\.)*(?:datad0g\.com|datad0g\.eu|staging\.dog|prod\.dog)$/,mo=/^https?:\/\/(?:localhost|127\.0\.0\.1)(?::\d+)?$/;function In(t){return ho.test(t)||fo.test(t)||mo.test(t)}var _n="dd-apps-frontend-bootstrap",Dn=1;function Eo(t,e,n){let{data:o}=n;return n.source!==t||n.ports.length!==0||!b(o)||o.namespace!==_n||o.version!==Dn||o.type!=="accepted"&&o.type!=="rejected-origin"||o.attemptId!==e?{status:"ignored"}:In(n.origin)?o.type==="rejected-origin"?typeof o.origin=="string"?{status:"rejected-origin",origin:o.origin}:{status:"ignored"}:{status:"accepted"}:{status:"rejected-origin",origin:n.origin}}function Mn(t,e,n,o=1e4){if(n.aborted)return Promise.resolve(l({code:"ABORTED"}));let i=t.parent;if(i===t)return Promise.resolve(l({code:"TRANSPORT_FAILED",cause:new Error("The app is not running in an iframe.")}));let s=me("bootstrap"),c=new MessageChannel;return new Promise(u=>{let h=!1,m=!1,f=!1,C,_=M=>{h||(h=!0,t.removeEventListener("message",O),n.removeEventListener("abort",D),C!==void 0&&globalThis.clearTimeout(C),M.ok||(L("failed app bootstrap port",()=>c.port1.close()),m||L("untransferred app bootstrap port",()=>c.port2.close())),u(M))},O=M=>{let T=Eo(i,s,M);T.status==="accepted"?_(w(c.port1)):T.status==="rejected-origin"&&_(l({code:"ORIGIN_REJECTED",origin:T.origin}))},D=()=>_(l({code:"ABORTED"})),H=()=>{if(!(f||h)){f=!0,C=globalThis.setTimeout(()=>_(l({code:"TIMED_OUT",timeoutMs:o})),Math.max(0,o));try{i.postMessage({namespace:_n,version:Dn,type:"request",attemptId:s,documentId:e},"*",[c.port2]),m=!0}catch(M){_(l({code:"TRANSPORT_FAILED",cause:M}))}}};if(t.addEventListener("message",O),n.addEventListener("abort",D,{once:!0}),n.aborted){D();return}H()})}var wn=me("document");var Ln="dd-apps-frontend-compatibility",Pn=1,To=64;function Co(t,e,n,o){return n.aborted?Promise.resolve({ok:!1,error:{code:"ABORTED"}}):new Promise(i=>{let s=!1,c,u=f=>{s||(s=!0,t.removeEventListener("message",h),n.removeEventListener("abort",m),c!==void 0&&globalThis.clearTimeout(c),i(f))},h=f=>u({ok:!0,value:f}),m=()=>u({ok:!1,error:{code:"ABORTED"}});t.addEventListener("message",h),n.addEventListener("abort",m,{once:!0}),c=globalThis.setTimeout(()=>u({ok:!1,error:{code:"TIMED_OUT",timeoutMs:e}}),Math.max(0,e));try{t.start(),o?.()}catch(f){u({ok:!1,error:{code:"TRANSPORT_FAILED",cause:f}})}})}function Nn(t){if(!(!Array.isArray(t)||t.length===0||t.length>To||!Array.from(t).every(e=>Number.isSafeInteger(e)&&e>0)||new Set(t).size!==t.length))return[...t].sort((e,n)=>e-n)}function Oo(t,e){let n=t.filter(u=>e.includes(u));if(n.length>0)return{ok:!0,value:Math.max(...n)};let o=Math.min(...t),i=Math.max(...t),s=Math.min(...e),c=Math.max(...e);return i<s?{ok:!1,error:{code:"APP_PROTOCOL_TOO_OLD",appProtocols:t,hostProtocols:e}}:c<o?{ok:!1,error:{code:"HOST_PROTOCOL_TOO_OLD",appProtocols:t,hostProtocols:e}}:{ok:!1,error:{code:"PROTOCOL_INCOMPATIBLE",appProtocols:t,hostProtocols:e}}}async function Sn(t,e,n,o){let i=Nn(e);if(!i)return t.close(),{ok:!1,error:{code:"TRANSPORT_FAILED",cause:new Error("The app protocol registry is invalid.")}};let s=await Co(t,n,o,()=>{t.postMessage({namespace:Ln,version:Pn,type:"offer",role:"app",protocols:i})});if(t.close(),!s.ok)return s;let{data:c,ports:u}=s.value;if(!b(c)||c.namespace!==Ln||c.version!==Pn||c.type!=="answer"||c.role!=="host"){for(let C of u)C.close();return{ok:!1,error:{code:"TRANSPORT_FAILED",cause:new Error("The host returned an invalid compatibility answer.")}}}let h=Nn(c.protocols);if(!h){for(let C of u)C.close();return{ok:!1,error:{code:"TRANSPORT_FAILED",cause:new Error("The host returned an invalid supported-protocol list.")}}}let m=Oo(i,h);if(!m.ok){for(let C of u)C.close();return m}let[f]=u;if(u.length!==1||f===void 0){for(let C of u)C.close();return{ok:!1,error:{code:"TRANSPORT_FAILED",cause:new Error("A compatible host must transfer exactly one operational port.")}}}return{ok:!0,value:{protocol:m.value,operationalPort:f}}}import{connect as Po,PortMessenger as No,Reply as So}from"penpal";var pt="dd-apps-frontend-heartbeat",ht=1,kn=Object.freeze({intervalMs:gn,timeoutMs:En});function rt(t){try{t.postMessage({namespace:pt,version:ht,type:"close"})}catch{}}function Un(t,e){rt(e),globalThis.setTimeout(()=>{L("failed Penpal connection",()=>t.destroy()),L("failed operational port",()=>e.close())},xe)}var K,re,ie,nt,Q,ot,V,Mt,wt,Lt,ft,mt=class{constructor(e,n,o,i){this.port=e;this.onDead=n;this.policy=o;this.side=i;p(this,V);p(this,K);p(this,re);p(this,ie,0);p(this,nt,!1);p(this,Q,!1);p(this,ot,e=>{let n=e.data;if(!(!b(n)||n.namespace!==pt||n.version!==ht)){if(n.type==="close"){a(this,V,ft).call(this,!1);return}if(k(n.nonce)){if(n.type==="ping"){try{this.port.postMessage({namespace:pt,version:ht,type:"pong",nonce:n.nonce})}catch(o){y("could not answer a heartbeat probe",{side:this.side,cause:S(o)}),a(this,V,ft).call(this,!0)}return}n.type!=="pong"||n.nonce!==r(this,re)||(d(this,re,void 0),d(this,ie,0),r(this,K)!==void 0&&(globalThis.clearTimeout(r(this,K)),d(this,K,void 0)),a(this,V,Mt).call(this,this.policy.intervalMs))}}});this.port.addEventListener("message",r(this,ot))}port;onDead;policy;side;start(){r(this,nt)||r(this,Q)||(d(this,nt,!0),a(this,V,Mt).call(this,this.policy.intervalMs))}stop(){r(this,Q)||(d(this,Q,!0),d(this,re,void 0),r(this,K)!==void 0&&(globalThis.clearTimeout(r(this,K)),d(this,K,void 0)),this.port.removeEventListener("message",r(this,ot)))}};K=new WeakMap,re=new WeakMap,ie=new WeakMap,nt=new WeakMap,Q=new WeakMap,ot=new WeakMap,V=new WeakSet,Mt=function(e){r(this,Q)||d(this,K,globalThis.setTimeout(()=>a(this,V,wt).call(this),Math.max(0,e)))},wt=function(){if(r(this,Q))return;let e=me("heartbeat");d(this,re,e);try{this.port.postMessage({namespace:pt,version:ht,type:"ping",nonce:e})}catch(n){x("could not send a heartbeat probe",{side:this.side,misses:r(this,ie),cause:S(n)}),a(this,V,Lt).call(this,e);return}d(this,K,globalThis.setTimeout(()=>a(this,V,Lt).call(this,e),Math.max(0,this.policy.timeoutMs)))},Lt=function(e){if(!(r(this,Q)||r(this,re)!==e)){if(d(this,re,void 0),d(this,ie,r(this,ie)+1),r(this,ie)>=2){y("the peer stopped answering heartbeats",{side:this.side,misses:r(this,ie),probeTimeoutMs:this.policy.timeoutMs,intervalMs:this.policy.intervalMs}),a(this,V,ft).call(this,!0);return}x("a heartbeat probe went unanswered",{side:this.side,misses:r(this,ie),probeTimeoutMs:this.policy.timeoutMs}),a(this,V,wt).call(this)}},ft=function(e){r(this,Q)||(this.stop(),this.onDead(e))};import{Reply as bo}from"penpal";function yo(t){return(typeof t=="object"&&t!==null||typeof t=="function")&&typeof t.then=="function"}function De(t){return typeof t=="number"&&Number.isSafeInteger(t)&&t>=1}function Nt(t){return Array.isArray(t)&&t.every(De)}function Me(t){return Array.isArray(t)&&t.every(e=>typeof e=="number"&&Number.isSafeInteger(e)&&e>0)}function Ro(t){return Array.isArray(t)&&t.every(e=>typeof e=="string"||typeof e=="number"&&Number.isSafeInteger(e)&&e>=0)}function St(t){return Array.isArray(t)&&t.every(e=>b(e)&&typeof e.message=="string"&&Ro(e.path))}function we(t,e){try{let n=t["~standard"].validate(e);return yo(n)?(Promise.resolve(n).catch(()=>{}),l([{message:"Embedding value schemas must be synchronous.",path:[]}])):n.issues?l(n.issues.map(o=>({message:o.message,path:vo(o.path)}))):w(n.value)}catch(n){return l([{message:n instanceof Error?n.message:"The value parser rejected this value.",path:[]}])}}function vo(t){return t?t.map(e=>{let n=typeof e=="object"&&e!==null&&"key"in e?e.key:e;return typeof n=="string"||typeof n=="number"&&Number.isSafeInteger(n)&&n>=0?n:String(n)}):[]}function it(t,e=[],n=new Set){try{globalThis.structuredClone(t);return}catch{if(typeof t!="object"&&typeof t!="function"||t===null||n.has(t))return e;n.add(t);let o;try{o=Object.entries(t)}catch{return e}for(let[i,s]of o){let c=it(s,[...e,Array.isArray(t)?Number(i):i],n);if(c)return c}return e}}function He(t,e){return e.map(n=>({message:n.message,path:[t,...n.path]}))}function gt(t){return Object.entries(t.fields).filter(([,e])=>e.kind==="value").map(([e])=>e)}function Vn(t,e,n){let o=new Set(t);if(n){let s=[...o].find(c=>!Object.prototype.hasOwnProperty.call(e,c));if(s!==void 0)return{field:s,kind:"missing"}}let i=Object.keys(e).find(s=>!o.has(s));return i===void 0?void 0:{field:i,kind:"unknown"}}function Fn(t){return{code:"INVALID_RESULT",issues:[{message:t.kind==="missing"?"The host value snapshot omitted a claimed field.":"The host value snapshot included an unclaimed field.",path:[t.field]}]}}function Et(t,e){let n=Vn(t,e,!0);return n&&Fn(n)}function kt(t,e){let n=Vn(t,e,!1);return n&&Fn(n)}function Ut(t,e,n){let o;try{o=n.get()}catch(s){return y("a host value provider threw while being read",{side:"host",field:t,cause:S(s)}),l([{message:"The host value provider threw while being read.",path:[t]}])}let i=we(e,o);if(!i.ok)return l(He(t,i.error));try{return w(globalThis.structuredClone(i.value))}catch{let s=it(i.value)??[];return l([{message:"The host value is not structured-clone-safe.",path:[t,...s]}])}}function Tt(t,e,n){return y("a host value could not be provided",{side:"host",target:`${t}.${e}`,details:S(n)}),[{message:"The host could not provide a value that satisfies this field schema.",path:[e]}]}function Vt(t,e,n){if(!b(n))return l([{message:"Expected a named inputs object.",path:[t,"inputs"]}]);let o=Object.keys(n).find(s=>!Object.hasOwn(e.inputs,s));if(o!==void 0)return l([{message:`Unknown function input "${o}".`,path:[t,"inputs",o]}]);let i=Object.create(null);for(let[s,c]of Object.entries(e.inputs)){let u=we(c,Object.hasOwn(n,s)?n[s]:void 0);if(!u.ok)return l(u.error.map(h=>({message:h.message,path:[t,"inputs",s,...h.path]})));i[s]=u.value}try{return w(globalThis.structuredClone(i))}catch{let s=it(i)??[];return l([{message:"The function inputs are not structured-clone-safe.",path:[t,"inputs",...s]}])}}function xn(t){if(typeof t!="object"||t===null||typeof globalThis.MessagePort!="function")return!1;if(t instanceof globalThis.MessagePort)return!0;let e=globalThis.MessagePort.prototype;for(;e;){let n=Object.getOwnPropertyDescriptor(e,"onmessage")?.get;if(n)try{return n.call(t),!0}catch{return!1}e=Object.getPrototypeOf(e)}return!1}var Hn=Object.freeze({"~standard":{version:1,vendor:"@datadog/apps-frontend",validate(t){return xn(t)?{value:t}:{issues:[{message:"Expected a MessagePort."}]}}}});function st(t){xn(t)&&L("discarded function result MessagePort",()=>t.close())}function Pt(t,e=[]){return l([{message:"The function result is not structured-clone-safe.",path:[t,...e]}])}function jn(t,e,n){let o=we(e.result,n);if(!o.ok)return l(He(t,o.error));if(e.result===Hn){let i=o.value;try{let s=globalThis.structuredClone(i,{transfer:[i]});return w(new bo(w(s),{transferables:[s]}))}catch{return Pt(t)}}try{return w(w(globalThis.structuredClone(o.value)))}catch{let i=it(o.value)??[];return Pt(t,i)}}function Bn(t,e,n){let o=we(e.result,n);if(!o.ok)return l(He(t,o.error));if(e.result===Hn)return w(o.value);try{return w(globalThis.structuredClone(o.value))}catch{let i=it(o.value)??[];return Pt(t,i)}}import{ErrorCode as Ao,PenpalError as Io}from"penpal";function _o(t){let e=t.wanted,n=t.hostVersions;return De(e)&&Nt(n)&&!n.includes(e)&&n.some(o=>o>e)}function Do(t){let e=t.wanted,n=t.hostVersions;return De(e)&&Nt(n)&&!n.includes(e)&&n.every(o=>o<e)}var Wn={ORIGIN_REJECTED:t=>typeof t.origin=="string",APP_PROTOCOL_TOO_OLD:t=>Me(t.appProtocols)&&Me(t.hostProtocols),HOST_PROTOCOL_TOO_OLD:t=>Me(t.appProtocols)&&Me(t.hostProtocols),PROTOCOL_INCOMPATIBLE:t=>Me(t.appProtocols)&&Me(t.hostProtocols),PEER_LACKS_MODULE:t=>typeof t.identifier=="string",APP_MAJOR_TOO_OLD:_o,HOST_MAJOR_TOO_OLD:Do,CONTRACT_INCOMPATIBLE:t=>typeof t.field=="string",INVALID_ARGUMENT:t=>St(t.issues),FUNCTION_FAILED:t=>typeof t.field=="string",INVALID_RESULT:t=>St(t.issues),TIMED_OUT:t=>typeof t.timeoutMs=="number"&&Number.isFinite(t.timeoutMs)&&t.timeoutMs>=0,TRANSPORT_FAILED:()=>!0,ABORTED:()=>!0,DISCONNECTED:()=>!0,UNRECOGNIZED:t=>typeof t.rawCode=="string"&&t.rawCode.length>0},Mo={ORIGIN_REJECTED:["origin"],APP_PROTOCOL_TOO_OLD:["appProtocols","hostProtocols"],HOST_PROTOCOL_TOO_OLD:["appProtocols","hostProtocols"],PROTOCOL_INCOMPATIBLE:["appProtocols","hostProtocols"],PEER_LACKS_MODULE:["identifier"],APP_MAJOR_TOO_OLD:["wanted","hostVersions"],HOST_MAJOR_TOO_OLD:["wanted","hostVersions"],CONTRACT_INCOMPATIBLE:["field"],INVALID_ARGUMENT:["issues"],FUNCTION_FAILED:["field"],INVALID_RESULT:["issues"],TIMED_OUT:["timeoutMs"],TRANSPORT_FAILED:[],ABORTED:[],DISCONNECTED:[],UNRECOGNIZED:["rawCode","raw"]};function Ct(t,e){if(b(t)&&typeof t.code=="string"){let n=t.code;if(e.includes(n)&&Object.prototype.hasOwnProperty.call(Wn,n)){let o=Wn[n];if(o(t)){if(n==="UNRECOGNIZED")return{code:n,rawCode:t.rawCode,raw:void 0};let i={code:n};for(let s of Mo[n])i[s]=t[s];return i}}}return{code:"UNRECOGNIZED",rawCode:b(t)&&typeof t.code=="string"?t.code:"MALFORMED_ERROR",raw:void 0}}function Ee(t,e,n){let o=`${t.identifier}.${e}`,i=n.code==="UNRECOGNIZED"?"UNKNOWN":n.code,s;switch(n.code){case"INVALID_ARGUMENT":s=`The inputs passed to "${o}" are invalid: ${n.issues[0]?.message??"the schema rejected them"}.`;break;case"INVALID_RESULT":s=`Datadog returned an invalid result from "${o}": ${n.issues[0]?.message??"the schema rejected it"}. The app and host may be using incompatible schema implementations.`;break;case"FUNCTION_FAILED":s=`Datadog could not complete "${o}". Screenshot this message and contact support if the problem continues.`;break;case"TIMED_OUT":s=`"${o}" did not finish within ${n.timeoutMs} ms. It may still complete in Datadog; do not automatically retry an action that is not idempotent.`;break;case"CONTRACT_INCOMPATIBLE":s=`The Datadog host contract for "${o}" does not match the schema compiled into this app. Update the app or contact support.`;break;case"ABORTED":s=`The inputs used by "${o}" were released before it completed. Its outcome is unknown; wait for the inputs to become ready before calling it again.`;break;case"DISCONNECTED":s=`The Datadog connection closed before "${o}" completed. Its outcome is unknown; reconnect before trying again.`;break;case"UNRECOGNIZED":s=`Datadog returned an unrecognized failure for "${o}" (${n.rawCode}). Screenshot this message and contact support.`;break;default:s=n}let c=new Error(`DATADOG_APP_INPUT_FUNCTION_${i}: ${s}`,{cause:n});return c.name="DatadogAppInputFunctionError",y("a Datadog host function call failed",{side:"app",target:o,error:J(n)}),Object.assign(c,{code:i})}function zn(t,e){return b(t)&&t.code==="ABORTED"?{code:"ABORTED"}:b(t)&&t.code==="TIMED_OUT"?{code:"TIMED_OUT",timeoutMs:e}:b(t)&&t.code==="DISCONNECTED"?{code:"DISCONNECTED"}:t instanceof Io&&t.code===Ao.ConnectionTimeout?{code:"TIMED_OUT",timeoutMs:e}:{code:"TRANSPORT_FAILED",cause:t}}function $n(t){if(!b(t))return{code:"INVALID_RESULT",issues:[{message:"Malformed __ddClaim envelope: expected an object.",path:[]}]};if(!k(t.claimId,B))return{code:"INVALID_RESULT",issues:[{message:`"claimId" must contain between 1 and ${B} characters.`,path:["claimId"]}]};if(!k(t.identifier))return{code:"INVALID_RESULT",issues:[{message:'"identifier" must be a non-empty string.',path:["identifier"]}]};if(!De(t.version))return{code:"INVALID_RESULT",issues:[{message:'"version" must be a positive integer.',path:["version"]}]};if(!Array.isArray(t.fields)||t.fields.length===0||t.fields.length>_t)return{code:"INVALID_RESULT",issues:[{message:`"fields" must contain between 1 and ${_t} entries.`,path:["fields"]}]};if(!t.fields.every(e=>typeof e=="string"&&e.length>0&&e.length<=Dt)||new Set(t.fields).size!==t.fields.length)return{code:"INVALID_RESULT",issues:[{message:`"fields" must contain unique non-empty strings of at most ${Dt} characters.`,path:["fields"]}]}}function Gn(t){if(!b(t))return{code:"INVALID_ARGUMENT",issues:[{message:"Malformed __ddCall envelope: expected an object.",path:[]}]};if(!k(t.claimId,B))return{code:"INVALID_ARGUMENT",issues:[{message:`"claimId" must contain between 1 and ${B} characters.`,path:["claimId"]}]};if(!k(t.callId,tt))return{code:"INVALID_ARGUMENT",issues:[{message:`"callId" must contain between 1 and ${tt} characters.`,path:["callId"]}]};if(!k(t.field))return{code:"INVALID_ARGUMENT",issues:[{message:'"field" must be a non-empty string.',path:["field"]}]};if(!b(t.inputs))return{code:"INVALID_ARGUMENT",issues:[{message:'"inputs" must be an object.',path:["inputs"]}]}}function Ft(t,e){let n=e.map(({version:s})=>s).sort((s,c)=>s-c),o=n[n.length-1];if(o===void 0)return l({code:"HOST_MAJOR_TOO_OLD",wanted:t,hostVersions:n});let i=e.find(({version:s})=>s===t);return i?w(i):l(t<o?{code:"APP_MAJOR_TOO_OLD",wanted:t,hostVersions:n}:{code:"HOST_MAJOR_TOO_OLD",wanted:t,hostVersions:n})}function Jn(t,e){let n=e.filter(({identifier:i})=>i===t.identifier);if(n.length===0)return{code:"PEER_LACKS_MODULE",identifier:t.identifier};let o=Ft(t.version,n);return o.ok?void 0:o.error}var Pe,Ht=class{constructor(e){this.value=e;p(this,Pe,new Set)}value;get(){return this.value}subscribe(e){return r(this,Pe).add(e),()=>{r(this,Pe).delete(e)}}set(e){return Object.is(this.value,e)?!1:(this.value=e,!0)}notify(){ge(r(this,Pe))}freeze(){r(this,Pe).clear()}};Pe=new WeakMap;var xt=0;function Kn(t){let e=t.timeoutMs;return typeof e=="number"&&Number.isFinite(e)&&e>0&&e<=2147483647?e:6e5}var at,F,se,Te,Ce,Z,q,Oe,Be,We,dt,I,jt,Le,Ot,je,Bt,bt=class{constructor(e,n,o,i,s,c){this.role=e;this.remote=n;this.penpal=o;this.port=i;this.modules=s;this.operationTimeoutMs=c;p(this,I);p(this,at,new AbortController);p(this,F,new Map);p(this,se,new Map);p(this,Te,new Map);p(this,Ce,new Map);p(this,Z,new Map);p(this,q,new Map);p(this,Oe,new Set);p(this,Be);p(this,We,!1);p(this,dt,!1)}role;remote;penpal;port;modules;operationTimeoutMs;get closed(){return r(this,We)}get closeSignal(){return r(this,at).signal}attachHeartbeat(e){if(this.closed){e.stop();return}d(this,Be,e),e.start()}send(e,n){if(this.closed)return;let o;try{o=n()}catch(c){y("an outbound embedding message could not be sent",{side:this.role,operation:e,cause:S(c)}),this.noteDisconnected();return}let i=globalThis.setTimeout(()=>{r(this,Oe).delete(i),y("an outbound embedding message was never acknowledged; closing the connection",{side:this.role,operation:e,timeoutMs:this.operationTimeoutMs}),this.close()},Math.max(0,this.operationTimeoutMs));r(this,Oe).add(i);let s=(c,u)=>{r(this,Oe).delete(i)&&(globalThis.clearTimeout(i),c&&(y("an outbound embedding message was rejected",{side:this.role,operation:e,cause:S(u)}),this.noteDisconnected()))};o.then(()=>s(!1),c=>s(!0,c))}noteDisconnected(e=!1){this.close(e)}close(e=!0){if(r(this,We))return;d(this,We,!0);let n;if(e){rt(this.port);try{n=this.remote.__ddClose()}catch{}}r(this,Be)?.stop(),d(this,Be,void 0);for(let o of r(this,Oe))globalThis.clearTimeout(o);r(this,Oe).clear(),r(this,at).abort();for(let o of[...r(this,F).keys()])this.receiveRelease(o);for(let[o,i]of[...r(this,Te).entries()])a(this,I,je).call(this,o,i,{code:"DISCONNECTED"},!1);if(r(this,Ce).clear(),r(this,Z).clear(),r(this,q).clear(),!e){a(this,I,jt).call(this);return}n?.catch(()=>{}),globalThis.setTimeout(()=>a(this,I,jt).call(this),xe)}async settleRemoteResult(e,n){return this.closed?(e.then(o=>{n.onDiscardedResult?.(o)},()=>{}),l(n.disconnectedError)):new Promise(o=>{let i=!1,s,c=m=>{i||(i=!0,s!==void 0&&globalThis.clearTimeout(s),n.signal?.removeEventListener("abort",u),this.closeSignal.removeEventListener("abort",h),o(m))},u=()=>{n.onCancel(),c(l(n.abortError))},h=()=>c(l(n.disconnectedError));if(n.signal?.addEventListener("abort",u,{once:!0}),this.closeSignal.addEventListener("abort",h,{once:!0}),n.signal?.aborted){u();return}if(this.closeSignal.aborted){h();return}s=globalThis.setTimeout(()=>{n.onCancel(),c(l(n.timeoutError(n.timeoutMs)))},Math.max(0,n.timeoutMs)),e.then(m=>{if(i){n.onDiscardedResult?.(m);return}if(b(m)&&m.ok===!0){c(w(m.value));return}n.onDiscardedResult?.(m),c(l(n.normalize(b(m)?m.error:m)))},()=>{this.noteDisconnected(),c(l(n.disconnectedError))})})}async claim(e,n={}){if(this.closed)return l({code:"DISCONNECTED"});if(n.signal?.aborted)return l({code:"ABORTED"});let o=n.timeoutMs??5e3;qe("ClaimOptions.timeoutMs",o);let i=me("claim");r(this,Ce).set(i,e);let s;try{s=this.remote.__ddClaim({claimId:i,identifier:e.identifier,version:e.version,fields:Object.keys(e.fields)})}catch(O){return y("a claim could not be sent to the Datadog host",{side:this.role,claimId:i,identifier:e.identifier,version:e.version,cause:S(O)}),a(this,I,Le).call(this,i),this.noteDisconnected(),l({code:"DISCONNECTED"})}s=s.then(O=>O,()=>(this.noteDisconnected(),l({code:"DISCONNECTED"})));let c=await this.settleRemoteResult(s,{timeoutMs:o,signal:n.signal,onCancel:()=>{this.send("__ddRelease",()=>this.remote.__ddRelease(i))},timeoutError:O=>({code:"TIMED_OUT",timeoutMs:O}),abortError:{code:"ABORTED"},disconnectedError:{code:"DISCONNECTED"},normalize:O=>Ct(O,["PEER_LACKS_MODULE","APP_MAJOR_TOO_OLD","HOST_MAJOR_TOO_OLD","CONTRACT_INCOMPATIBLE","INVALID_RESULT","TIMED_OUT","ABORTED","DISCONNECTED","UNRECOGNIZED"])});if(!c.ok)return a(this,I,Le).call(this,i),c;if(!b(c.value)||!b(c.value.values))return a(this,I,Le).call(this,i),this.send("__ddRelease",()=>this.remote.__ddRelease(i)),l({code:"INVALID_RESULT",issues:[{message:"Malformed claim success payload.",path:[]}]});let u=Et(gt(e),c.value.values);if(u)return a(this,I,Le).call(this,i),this.send("__ddRelease",()=>this.remote.__ddRelease(i)),l(u);let h=new Map,m={},f={contract:e,values:h,valueListeners:new Set,invalidationListeners:new Set,releaseController:new AbortController,released:!1,hydrated:!1};for(let[O,D]of Object.entries(e.fields)){if(D.kind==="function"){m[O]=(...T)=>this.callFunction(i,f,O,D,T);continue}let H=we(D.schema,c.value.values[O]);if(!H.ok)return a(this,I,Le).call(this,i),this.send("__ddRelease",()=>this.remote.__ddRelease(i)),l({code:"INVALID_RESULT",issues:He(O,H.error)});let M=new Ht(H.value);h.set(O,M),m[O]=M}r(this,Te).set(i,f);let C=r(this,Z).get(i);C&&this.receiveValues(i,C);let _=f.invalidation??r(this,q).get(i);return a(this,I,Le).call(this,i),_?(a(this,I,Ot).call(this,i,f,!0,_),l(_)):w({fields:m,release:()=>a(this,I,Ot).call(this,i,f,!0),onValuesChanged:O=>f.released?()=>{}:(f.valueListeners.add(O),()=>f.valueListeners.delete(O)),onInvalidated:O=>{let D=f.invalidation;return D?(globalThis.queueMicrotask(()=>O(D)),()=>{}):f.released?()=>{}:(f.invalidationListeners.add(O),()=>f.invalidationListeners.delete(O))}})}async callFunction(e,n,o,i,s){if(this.closed)throw Ee(n.contract,o,{code:"DISCONNECTED"});if(n.released)throw Ee(n.contract,o,{code:"ABORTED"});if(s.length!==1)throw Ee(n.contract,o,{code:"INVALID_ARGUMENT",issues:[{message:`Expected one named inputs object, received ${s.length} arguments.`,path:[o,"inputs"]}]});let c=Vt(o,i,s[0]);if(!c.ok)throw Ee(n.contract,o,{code:"INVALID_ARGUMENT",issues:c.error});let u=me("call"),h;try{h=this.remote.__ddCall({claimId:e,callId:u,field:o,inputs:c.value})}catch{throw this.noteDisconnected(),Ee(n.contract,o,{code:"DISCONNECTED"})}let m=await this.settleRemoteResult(h,{timeoutMs:Kn(i),signal:n.releaseController.signal,onCancel:()=>{this.send("__ddCancel",()=>this.remote.__ddCancel({claimId:e,callId:u}))},timeoutError:C=>({code:"TIMED_OUT",timeoutMs:C}),abortError:{code:"ABORTED"},disconnectedError:{code:"DISCONNECTED"},normalize:C=>Ct(C,["CONTRACT_INCOMPATIBLE","INVALID_ARGUMENT","FUNCTION_FAILED","INVALID_RESULT","TIMED_OUT","ABORTED","DISCONNECTED","UNRECOGNIZED"]),onDiscardedResult:C=>{b(C)&&C.ok===!0&&st(C.value)}});if(!m.ok){let C=m.error.code==="INVALID_ARGUMENT"?{code:"CONTRACT_INCOMPATIBLE",field:o}:m.error;throw Ee(n.contract,o,C)}let f=Bn(o,i,m.value);if(!f.ok)throw Ee(n.contract,o,{code:"INVALID_RESULT",issues:f.error});return f.value}receiveValues(e,n){if(!k(e,B)){y("ignored a __ddValues envelope with an invalid claim id",{side:this.role,claimId:e,maxClaimIdLength:B});return}let o=r(this,Te).get(e),i=r(this,Ce).get(e);if(!b(n)){let h={code:"INVALID_RESULT",issues:[{message:"The host value snapshot must be an object.",path:[]}]};o?a(this,I,je).call(this,e,o,h,!0):i?(r(this,q).set(e,h),r(this,Z).delete(e)):y("ignored a __ddValues envelope for an unknown claim",{side:this.role,claimId:e,receivedValues:typeof n});return}if(!o){if(!i)return;let m=r(this,Z).has(e)?kt(gt(i),n):Et(gt(i),n);if(m){r(this,q).set(e,m),r(this,Z).delete(e);return}if(!r(this,q).has(e)){let f=r(this,Z).get(e);r(this,Z).set(e,Object.freeze({...f,...n}))}return}let s=o.hydrated?kt(o.values.keys(),n):Et(o.values.keys(),n);if(s){a(this,I,je).call(this,e,o,s,!0);return}o.hydrated=!0;let c=[];for(let[h,m]of Object.entries(n)){let f=o.values.get(h),C=o.contract.fields[h];if(!f||!C||C.kind!=="value")continue;let _=we(C.schema,m);if(!_.ok){let O={code:"INVALID_RESULT",issues:He(h,_.error)};a(this,I,je).call(this,e,o,O,!0);return}c.push([f,_.value])}let u=[];for(let[h,m]of c)h.set(m)&&u.push(h);for(let h of u)h.notify();u.length>0&&ge(o.valueListeners)}receiveInvalidation(e,n){if(!k(e,B)){y("ignored a __ddInvalidate envelope with an invalid claim id",{side:this.role,claimId:e,maxClaimIdLength:B});return}let o=Ct(n,["INVALID_RESULT","UNRECOGNIZED"]),i=r(this,Te).get(e);if(i){a(this,I,je).call(this,e,i,o,!1);return}r(this,Ce).has(e)&&r(this,q).set(e,o)}async receiveClaim(e){if(this.closed)return l({code:"DISCONNECTED"});let n=$n(e);if(n)return l(n);if(r(this,F).has(e.claimId))return l({code:"INVALID_RESULT",issues:[{message:`Claim id "${e.claimId}" is already live.`,path:["claimId"]}]});if(r(this,F).size>=It)return l({code:"INVALID_RESULT",issues:[{message:`The peer exceeded the limit of ${It} simultaneous claims.`,path:["claimId"]}]});let o=this.modules.filter(({contract:T})=>T.identifier===e.identifier);if(o.length===0)return l({code:"PEER_LACKS_MODULE",identifier:e.identifier});let i=Ft(e.version,o.map(T=>({version:T.contract.version,module:T})));if(!i.ok)return i;let s=i.value.module;if(s.signal?.aborted)return l({code:"INVALID_RESULT",issues:[{message:`The host provider for "${e.identifier}" is disposed.`,path:[]}]});let c=new Map,u={releases:[],module:s,fields:c};if(r(this,F).set(e.claimId,u),s.signal){let T=()=>a(this,I,Bt).call(this,e.claimId,[{message:`The host provider for "${e.identifier}" was disposed.`,path:[]}]);s.signal.addEventListener("abort",T,{once:!0}),u.releases.push(()=>s.signal?.removeEventListener("abort",T))}let h={},m={ready:!1},f=!1,C=!1,_=!1,O=new Set,D=new Map,H=()=>{if(C=!1,!r(this,F).has(e.claimId))return;let T=!_;if(!T&&O.size===0)return;let A=T?[...D.keys()]:[...O];_=!0,O.clear();let U={};for(let z of A){let oe=D.get(z);if(!oe)continue;let j=Ut(z,oe.field.schema,oe.provider);if(!j.ok){a(this,I,Bt).call(this,e.claimId,Tt(e.identifier,z,j.error));return}U[z]=j.value}this.send("__ddValues",()=>this.remote.__ddValues(e.claimId,U))},M=()=>{if(r(this,F).has(e.claimId)){if(!m.ready){f=!0;return}C||(C=!0,globalThis.queueMicrotask(H))}};for(let T of e.fields){let A=s.contract.fields[T];if(!A)return this.receiveRelease(e.claimId),l({code:"CONTRACT_INCOMPATIBLE",field:T});if(c.set(T,A),A.kind==="function"){let j=Object.hasOwn(s.implementation,T)?s.implementation[T]:void 0;if(!b(j)||typeof j.invoke!="function")return this.receiveRelease(e.claimId),l({code:"INVALID_RESULT",issues:[{message:"The host implementation is not a callable function field.",path:[T]}]});continue}let U=Object.hasOwn(s.implementation,T)?s.implementation[T]:void 0;if(!U||typeof U.get!="function"||typeof U.subscribe!="function")return this.receiveRelease(e.claimId),l({code:"INVALID_RESULT",issues:[{message:"The host implementation is not a live value.",path:[T]}]});D.set(T,{field:A,provider:U});let z;try{z=U.subscribe(()=>{O.add(T),M()})}catch(j){return this.receiveRelease(e.claimId),l({code:"INVALID_RESULT",issues:Tt(e.identifier,T,j)})}if(typeof z!="function")return this.receiveRelease(e.claimId),l({code:"INVALID_RESULT",issues:[{message:"The host value provider did not return an unsubscribe function.",path:[T]}]});if(r(this,F).get(e.claimId)!==u)return L(`unsubscribe for interrupted claim ${e.claimId}`,z),this.closed?l({code:"DISCONNECTED"}):l({code:"INVALID_RESULT",issues:[{message:`The host provider for "${e.identifier}" was disposed during claim setup.`,path:[]}]});u.releases.push(z);let oe=Ut(T,A.schema,U);if(!oe.ok)return this.receiveRelease(e.claimId),l({code:"INVALID_RESULT",issues:Tt(e.identifier,T,oe.error)});h[T]=oe.value}return m.ready=!0,f&&M(),w({values:h})}async receiveFunctionCall(e){if(this.closed)return l({code:"DISCONNECTED"});let n=Gn(e);if(n)return l(n);let o=r(this,F).get(e.claimId);if(!o)return l({code:"DISCONNECTED"});let i=o.fields.get(e.field);if(!i||i.kind!=="function")return l({code:"CONTRACT_INCOMPATIBLE",field:e.field});if(r(this,se).has(e.callId))return l({code:"INVALID_ARGUMENT",issues:[{message:`Function call id "${e.callId}" is already active.`,path:["callId"]}]});if(xt>=On)return l({code:"FUNCTION_FAILED",field:e.field});let s=Vt(e.field,i,e.inputs);if(!s.ok)return y("the host rejected the inputs of a function call",{side:this.role,claimId:e.claimId,callId:e.callId,target:`${o.module.contract.identifier}.${e.field}`,issueCount:s.error.length}),l({code:"INVALID_ARGUMENT",issues:[{message:"The function inputs do not satisfy the host schema.",path:[e.field,"inputs"]}]});let c=Object.hasOwn(o.module.implementation,e.field)?o.module.implementation[e.field]:void 0;if(!b(c)||typeof c.invoke!="function")return l({code:"CONTRACT_INCOMPATIBLE",field:e.field});let u=new AbortController,h=()=>{},m=new Promise(A=>{h=A}),f={claimId:e.claimId,controller:u,interrupt(A){u.signal.aborted||(u.abort(),h({status:"interrupted",reason:A}))}};xt+=1,r(this,se).set(e.callId,f);let C=Kn(i),_=globalThis.performance.now()+C,O=globalThis.setTimeout(()=>f.interrupt("timed-out"),C),D;try{let A=c.invoke(s.value,Object.freeze({signal:u.signal}));globalThis.performance.now()>=_&&f.interrupt("timed-out"),D=Promise.resolve(A).then(U=>globalThis.performance.now()>=_?(f.interrupt("timed-out"),st(U),{status:"interrupted",reason:"timed-out"}):{status:"returned",value:U},U=>globalThis.performance.now()>=_?(f.interrupt("timed-out"),{status:"interrupted",reason:"timed-out"}):{status:"threw",cause:U})}catch(A){globalThis.performance.now()>=_&&f.interrupt("timed-out"),D=Promise.resolve({status:"threw",cause:A})}let H=D.finally(()=>{xt-=1,r(this,se).get(e.callId)===f&&r(this,se).delete(e.callId)}),M=await Promise.race([H,m]);if(globalThis.clearTimeout(O),M.status==="interrupted")return H.then(A=>{A.status==="returned"&&st(A.value)}),M.reason==="timed-out"?l({code:"TIMED_OUT",timeoutMs:C}):l({code:"DISCONNECTED"});if(this.closed||u.signal.aborted||r(this,F).get(e.claimId)!==o)return M.status==="returned"&&st(M.value),l({code:"DISCONNECTED"});if(M.status==="threw")return y("a host function implementation threw",{side:this.role,claimId:e.claimId,callId:e.callId,target:`${o.module.contract.identifier}.${e.field}`,cause:S(M.cause)}),l({code:"FUNCTION_FAILED",field:e.field});let T=jn(e.field,i,M.value);return T.ok?T.value:(y("a host function returned an invalid result",{side:this.role,claimId:e.claimId,callId:e.callId,target:`${o.module.contract.identifier}.${e.field}`,issues:T.error}),l({code:"INVALID_RESULT",issues:[{message:"The host function returned a result that does not satisfy its schema.",path:[e.field]}]}))}receiveFunctionCancel(e){if(!b(e)||!k(e.claimId,B)||!k(e.callId,tt)){y("ignored a malformed __ddCancel envelope",{side:this.role,request:b(e)?{claimId:e.claimId,callId:e.callId}:{malformed:!0,received:typeof e}});return}let n=r(this,se).get(e.callId);n?.claimId===e.claimId&&n.interrupt("cancelled")}receiveRelease(e){if(!k(e,B)){y("ignored a __ddRelease with an invalid claim id",{side:this.role,claimId:e,maxClaimIdLength:B});return}let n=r(this,F).get(e);if(n){r(this,F).delete(e);for(let o of r(this,se).values())o.claimId===e&&o.interrupt("cancelled");for(let o of n.releases)L(`unsubscribe for claim ${e}`,o)}}};at=new WeakMap,F=new WeakMap,se=new WeakMap,Te=new WeakMap,Ce=new WeakMap,Z=new WeakMap,q=new WeakMap,Oe=new WeakMap,Be=new WeakMap,We=new WeakMap,dt=new WeakMap,I=new WeakSet,jt=function(){r(this,dt)||(d(this,dt,!0),L("Penpal connection",()=>this.penpal.destroy()),L("operational port",()=>this.port.close()))},Le=function(e){r(this,Ce).delete(e),r(this,Z).delete(e),r(this,q).delete(e)},Ot=function(e,n,o,i){if(n.released)return!1;n.released=!0,n.invalidation=i,n.releaseController.abort();for(let s of n.values.values())s.freeze();return n.valueListeners.clear(),n.invalidationListeners.clear(),r(this,Te).delete(e),o&&this.send("__ddRelease",()=>this.remote.__ddRelease(e)),!0},je=function(e,n,o,i){let s=[...n.invalidationListeners];if(!a(this,I,Ot).call(this,e,n,i,o))return;(o.code==="DISCONNECTED"?x:y)("a live claim was invalidated",{side:this.role,claimId:e,identifier:n.contract.identifier,version:n.contract.version,observedListeners:s.length,error:J(o)}),ge(s,o)},Bt=function(e,n){let o=r(this,F).get(e);o&&(y("the host invalidated a claim it was serving",{side:this.role,claimId:e,identifier:o.module.contract.identifier,version:o.module.contract.version,issues:n}),this.receiveRelease(e),this.send("__ddInvalidate",()=>this.remote.__ddInvalidate(e,{code:"INVALID_RESULT",issues:n})))};function ko(t,e){if(!b(t))return{malformed:!0,received:typeof t};let n={};for(let o of e)n[o]=t[o];return n}var zt=class{constructor(e,n){this.endpoint=e;this.modules=n}endpoint;modules;async claim(e,n){if(this.endpoint.closed||n?.signal?.aborted)return this.endpoint.claim(e,n);qe("ClaimOptions.timeoutMs",n?.timeoutMs??5e3);let o=Jn(e,this.modules);return o?Promise.resolve(l(o)):this.endpoint.claim(e,n)}};function Uo(t){return b(t)&&t.role==="host"&&Array.isArray(t.modules)}function Vo(t){let e=new Set,n=[];for(let o of t){if(!b(o)||!k(o.identifier)||!De(o.version))continue;let i=JSON.stringify([o.identifier,o.version]);e.has(i)||(e.add(i),n.push({identifier:o.identifier,version:o.version}))}return n}async function Fo(t,e,n,o,i,s,c){let u,h,m=!1,f=!1,C,_=new Promise((g,R)=>{C=R});try{h=new mt(t,g=>{u?u.noteDisconnected(g):(m=!0,g||t.close(),C?.({code:"DISCONNECTED"}))},c,e)}catch(g){return L("failed operational port",()=>t.close()),l({code:"TRANSPORT_FAILED",cause:g})}let O=!1,D=0,H=()=>{},M=new Promise(g=>{H=g}),T=g=>{O||(O=!0,H(g))},A=(g,R)=>{let N=Y=>(x("an embedding operation was refused",{side:e,operation:R,expectedRole:g,reason:Y,pendingEndpointOperations:D}),new Error(Y));return u?u.role===g?Promise.resolve(u):Promise.reject(N("The embedding operation is not valid here.")):O||D>=bn?Promise.reject(N("The embedding endpoint is not ready for work.")):(D+=1,M.then(Y=>{if(!Y||Y.role!==g)throw N("The embedding operation is not valid here.");return Y}).finally(()=>{D-=1}))},U=e==="host"?{role:"host",modules:i.map(({contract:g})=>({identifier:g.identifier,version:g.version})),surfaceId:s}:{role:"app"},z=(g,R,N,Y)=>(Y.ok||x(`${g} was rejected`,{side:e,request:ko(R,N),error:J(Y.error)}),Y),oe={__ddDescribe:()=>U,__ddClaim:g=>A("host","__ddClaim").then(R=>R.receiveClaim(g).then(N=>z("__ddClaim",g,["claimId","identifier","version","fields"],N))),__ddRelease:g=>A("host","__ddRelease").then(R=>R.receiveRelease(g)),__ddValues:(g,R)=>A("app","__ddValues").then(N=>N.receiveValues(g,R)),__ddCall:g=>A("host","__ddCall").then(R=>R.receiveFunctionCall(g).then(N=>(z("__ddCall",g,["claimId","callId","field"],N instanceof So?N.value:N),N))),__ddCancel:g=>A("host","__ddCancel").then(R=>R.receiveFunctionCancel(g)),__ddInvalidate:(g,R)=>A("app","__ddInvalidate").then(N=>N.receiveInvalidation(g,R)),__ddClose:()=>(u||(f=!0),A(e,"__ddClose").then(g=>g.close(!1)))},j;try{j=Po({messenger:new No({port:t}),methods:oe,timeout:n})}catch(g){return h.stop(),rt(t),globalThis.setTimeout(()=>t.close(),xe),l({code:"TRANSPORT_FAILED",cause:g})}let un,pn,hn=()=>un?.({code:"ABORTED"}),fn=new Promise((g,R)=>{un=R}),mn=new Promise((g,R)=>{pn=R}),po=globalThis.setTimeout(()=>pn?.({code:"TIMED_OUT"}),Math.max(0,n));o.addEventListener("abort",hn,{once:!0});let At="handshake";try{if(o.aborted)throw Object.assign(new Error("The connection was aborted."),{code:"ABORTED"});let g=await Promise.race([j.promise,fn,mn,_]);At="peer-description";let R=await Promise.race([g.__ddDescribe(),fn,mn,_]);if(At="validation",!(e==="app"?Uo(R):b(R)&&R.role==="app"))throw new Error(`Expected an embedding ${e==="app"?"host":"app"} using the operational protocol.`);if(u=new bt(e,g,j,t,i,n),m)throw Object.assign(new Error("The transport disconnected before establishment completed."),{code:"DISCONNECTED"});if(f)throw Object.assign(new Error("The peer requested to close before establishment completed."),{code:"DISCONNECTED"});return T(u),u.attachHeartbeat(h),w({endpoint:u,description:R})}catch(g){let R=zn(g,n);return x("the operational protocol could not be established",{side:e,stage:At,timeoutMs:n,describedPeer:!!u,error:J(R),cause:S(g)}),h.stop(),u?u.close():Un(j,t),l(R)}finally{T(void 0),globalThis.clearTimeout(po),o.removeEventListener("abort",hn)}}function xo(t){let e=t.endpoint,n=t.description;return{connection:new zt(e,Vo(n.modules)),surfaceId:typeof n.surfaceId=="string"?n.surfaceId:void 0,closeSignal:e.closeSignal,close:()=>e.close()}}async function Zn(t,e,n,o){let i=await Fo(t,"app",e,n,[],void 0,o);return i.ok?w(xo(i.value)):i}var Bo=[1];async function Wo(t,e,n=1e4){if(e.aborted)return t.close(),l({code:"ABORTED"});let o=await Sn(t,Bo,n,e);return o.ok?Zn(o.value.operationalPort,n,e,kn):o}var ze,$t=class{constructor(){p(this,ze)}next(){let e=r(this,ze)??Tn;return d(this,ze,Math.min(e*2,Cn)),e}reset(){d(this,ze,void 0)}};ze=new WeakMap;function zo(){return typeof globalThis.window<"u"&&globalThis.window.parent!==globalThis.window}function $o(t){switch(t.code){case"TIMED_OUT":case"TRANSPORT_FAILED":case"DISCONNECTED":case"UNRECOGNIZED":return!0;case"ORIGIN_REJECTED":case"APP_PROTOCOL_TOO_OLD":case"HOST_PROTOCOL_TOO_OLD":case"PROTOCOL_INCOMPATIBLE":case"ABORTED":return!1;default:return t}}var ae,Se,ct,W,de,ee,ce,le,te,be,$e,ke,v,Xn,Jt,Kt,Zt,Xt,yt,Yn,Ne,Gt=class{constructor(){p(this,v);p(this,ae,new AbortController);p(this,Se,new Set);p(this,ct,new $t);p(this,W,{state:"connecting"});p(this,de);p(this,ee);p(this,ce);p(this,le);p(this,te);p(this,be,0);p(this,$e,!1);p(this,ke,!1);if(!zo()){d(this,W,{state:"not-embedded"});return}a(this,v,Xt).call(this),a(this,v,Jt).call(this)}getSnapshot(){return r(this,W)}subscribe(e){return r(this,Se).add(e),()=>{r(this,Se).delete(e)}}close(){if(r(this,W).state==="closed")return;r(this,ae).abort(),r(this,ee)?.abort(),d(this,ee,void 0),a(this,v,Zt).call(this),a(this,v,yt).call(this);let e=r(this,de);d(this,de,void 0),a(this,v,Ne).call(this,{state:"closed"}),e?.close(),r(this,Se).clear()}};ae=new WeakMap,Se=new WeakMap,ct=new WeakMap,W=new WeakMap,de=new WeakMap,ee=new WeakMap,ce=new WeakMap,le=new WeakMap,te=new WeakMap,be=new WeakMap,$e=new WeakMap,ke=new WeakMap,v=new WeakSet,Xn=async function(e){let n=await Mn(globalThis.window,wn,e);return n.ok?Wo(n.value,e):n},Jt=async function(){if(r(this,ae).signal.aborted||r(this,ke)||r(this,$e)||r(this,de))return;d(this,$e,!0),d(this,be,r(this,be)+1);let e=new AbortController;d(this,ee,e);let n;try{n=await a(this,v,Xn).call(this,e.signal)}catch(i){n={ok:!1,error:{code:"TRANSPORT_FAILED",cause:i}}}if(d(this,$e,!1),r(this,ee)===e&&d(this,ee,void 0),r(this,ae).signal.aborted||r(this,ke)){n.ok&&n.value.close();return}if(!n.ok){if(d(this,te,n.error),!$o(n.error)){a(this,v,yt).call(this),y("the app connection was rejected",{side:"app",attempt:r(this,be),retryable:!1,error:J(n.error)}),a(this,v,Ne).call(this,{state:"rejected",error:n.error});return}a(this,v,Ne).call(this,r(this,W).state==="reconnecting"?{state:"reconnecting",lastError:n.error}:{state:"connecting",error:n.error}),a(this,v,Kt).call(this);return}d(this,de,n.value),d(this,te,void 0),r(this,ct).reset(),a(this,v,yt).call(this);let o=()=>{r(this,ae).signal.aborted||r(this,de)!==n.value||(d(this,de,void 0),d(this,te,{code:"DISCONNECTED"}),x("the app lost its established connection",{side:"app",attempt:r(this,be),surfaceId:n.value.surfaceId}),a(this,v,Xt).call(this),a(this,v,Ne).call(this,{state:"reconnecting",lastError:r(this,te)}),a(this,v,Kt).call(this))};if(n.value.closeSignal.addEventListener("abort",o,{once:!0}),n.value.closeSignal.aborted){o();return}a(this,v,Ne).call(this,{state:"connected",connection:n.value.connection,surfaceId:n.value.surfaceId})},Kt=function(){if(r(this,ae).signal.aborted||r(this,ke)||r(this,ce)!==void 0)return;let e=r(this,ct).next();x("retrying the app connection",{side:"app",state:r(this,W).state,failedAttempts:r(this,be),retryInMs:e,giveUpAfterMs:et,error:r(this,te)&&J(r(this,te))}),d(this,ce,globalThis.setTimeout(()=>{d(this,ce,void 0),a(this,v,Jt).call(this)},e))},Zt=function(){r(this,ce)!==void 0&&(globalThis.clearTimeout(r(this,ce)),d(this,ce,void 0))},Xt=function(){r(this,le)===void 0&&d(this,le,globalThis.setTimeout(()=>{d(this,le,void 0),a(this,v,Yn).call(this)},et))},yt=function(){r(this,le)!==void 0&&(globalThis.clearTimeout(r(this,le)),d(this,le,void 0))},Yn=function(){if(r(this,ae).signal.aborted||r(this,W).state==="connected"||r(this,W).state==="closed")return;d(this,ke,!0),a(this,v,Zt).call(this),r(this,ee)?.abort(),d(this,ee,void 0);let e=r(this,te)??{code:"TIMED_OUT",timeoutMs:et};y("the app gave up connecting to its Datadog host",{side:"app",state:r(this,W).state,failedAttempts:r(this,be),gaveUpAfterMs:et,error:J(e)}),a(this,v,Ne).call(this,{state:"rejected",error:e})},Ne=function(e){r(this,W)!==e&&(d(this,W,e),ge(r(this,Se)))};var Qn=Object.freeze({connect(){return new Gt}});function qn(t){return t.join(", ")}function Go(t){return t.map(e=>`${e.path.length>0?e.path.join("."):"(root)"}: ${e.message}`).join("; ")}function Jo(t){let e;try{if(t instanceof Error)e=t.message||t.name;else if(typeof t=="string")e=t;else try{e=JSON.stringify(t)??String(t)}catch{e=Object.prototype.toString.call(t)}}catch{e="(cause could not be described)"}return e.length>200?`${e.slice(0,200)}\u2026`:e}function Yt(t){switch(t.code){case"TIMED_OUT":return{code:"TIMED_OUT",action:"retry",message:`TIMED_OUT: the Datadog host did not complete the connection within ${t.timeoutMs}ms. Reload the app to try again.`};case"ORIGIN_REJECTED":return{code:"ORIGIN_REJECTED",action:"contact-support",message:`ORIGIN_REJECTED: the embedding connection failed origin validation for "${t.origin}". Screenshot this message and contact support.`};case"APP_PROTOCOL_TOO_OLD":return{code:"APP_PROTOCOL_TOO_OLD",action:"update-app",message:`APP_PROTOCOL_TOO_OLD: this app supports embedding protocols ${t.appProtocols.join(", ")}, while the Datadog host requires ${t.hostProtocols.join(", ")}. Update @datadog/apps-frontend, rebuild this app, and upload the new bundle.`};case"HOST_PROTOCOL_TOO_OLD":return{code:"HOST_PROTOCOL_TOO_OLD",action:"contact-support",message:`HOST_PROTOCOL_TOO_OLD: this app supports embedding protocols ${t.appProtocols.join(", ")}, newer than the Datadog host's ${t.hostProtocols.join(", ")}. Rebuilding the app will not fix this; screenshot this message and contact support.`};case"PROTOCOL_INCOMPATIBLE":return{code:"PROTOCOL_INCOMPATIBLE",action:"contact-support",message:`PROTOCOL_INCOMPATIBLE: this app supports embedding protocols ${t.appProtocols.join(", ")}, while the Datadog host supports ${t.hostProtocols.join(", ")}. The sets do not overlap; screenshot this message and contact support.`};case"DISCONNECTED":return{code:"CONNECTION_LOST",action:"retry",message:"CONNECTION_LOST: the Datadog host stopped responding and the connection could not be re-established. Reload the app to try again."};case"TRANSPORT_FAILED":return{code:"UNKNOWN",action:"contact-support",message:`TRANSPORT_FAILED: the local embedding transport failed (${Jo(t.cause)}). Screenshot this message and contact support.`};case"UNRECOGNIZED":return{code:"UNKNOWN",action:"contact-support",message:`UNRECOGNIZED: the peer reported failure code "${t.rawCode}", which this app build does not know. Screenshot this message and contact support.`};case"ABORTED":return{code:"UNKNOWN",action:"contact-support",message:"ABORTED: the embedding connection was cancelled unexpectedly. Screenshot this message and contact support."};default:return t}}function Qt(t){switch(t.code){case"APP_MAJOR_TOO_OLD":return{code:"APP_MAJOR_TOO_OLD",action:"update-app",requestedVersion:t.wanted,availableVersions:t.hostVersions,message:`APP_MAJOR_TOO_OLD: this app's claim requests v${t.wanted}, while the host now offers ${qn(t.hostVersions)}. Update @datadog/apps-frontend, rebuild this app, and upload the new bundle.`};case"HOST_MAJOR_TOO_OLD":return{code:"HOST_MAJOR_TOO_OLD",action:"contact-support",requestedVersion:t.wanted,availableVersions:t.hostVersions,message:`HOST_MAJOR_TOO_OLD: this app's claim requests v${t.wanted}, newer than the host's ${qn(t.hostVersions)}. Rebuilding the app will not fix this; screenshot this message and contact support.`};case"CONTRACT_INCOMPATIBLE":return{code:"UNKNOWN",action:"contact-support",message:`CONTRACT_INCOMPATIBLE: the host omitted required field "${t.field}" despite advertising a compatible contract version. Screenshot this message and contact support.`};case"INVALID_RESULT":return{code:"UNKNOWN",action:"contact-support",message:`INVALID_RESULT: a host value failed this app's bundled parser (${Go(t.issues)}). Screenshot this message and contact support.`};case"TIMED_OUT":return{code:"TIMED_OUT",action:"retry",message:`TIMED_OUT: the Datadog host did not complete the claim request within ${t.timeoutMs}ms. Reload the app to try again.`};case"DISCONNECTED":case"UNRECOGNIZED":return Yt(t);default:return t}}var Ko=0,Zo=Object.freeze({status:"pending"}),Xo=Object.freeze({status:"unavailable"}),Yo=Object.freeze({code:"UNKNOWN",action:"contact-support",message:"EMBEDDING_CLOSED: the Datadog App connection closed while its provider was still mounted. Screenshot this message and contact support."}),qt=Object.freeze({code:"UNKNOWN",action:"contact-support",message:"CLAIM_REJECTED: the requested Datadog App claim failed unexpectedly. Screenshot this message and contact support."}),eo=Object.freeze({code:"UNKNOWN",action:"contact-support",message:"CONNECTION_START_FAILED: the Datadog App connection could not be started. Screenshot this message and contact support."});function en(){return Zo}function to(){return Xo}function Qo(t){let e="requestedVersion"in t?Object.freeze({...t,availableVersions:Object.freeze([...t.availableVersions])}):Object.freeze({...t});return Object.freeze({status:"failed",error:e})}var Re,pe,ve,vt=class{constructor(e,n){this.owner=e;this.resource=n;p(this,Re,new Set);p(this,pe);p(this,ve,!1);Fe(this,"subscribe",e=>{r(this,pe)!==void 0&&(globalThis.clearTimeout(r(this,pe)),d(this,pe,void 0));let n=()=>e();r(this,Re).add(n),r(this,ve)||(d(this,ve,!0),this.owner.activate(this.resource));let o=!0;return()=>{o&&(o=!1,r(this,Re).delete(n),r(this,Re).size===0&&r(this,pe)===void 0&&d(this,pe,globalThis.setTimeout(()=>{d(this,pe,void 0),r(this,Re).size===0&&r(this,ve)&&(d(this,ve,!1),this.owner.deactivate(this.resource))},Ko)))}})}owner;resource;notify(){ge(r(this,Re))}get isActive(){return r(this,ve)}};Re=new WeakMap,pe=new WeakMap,ve=new WeakMap;var Ae,$,Ie,G,ne,he,Je,E,no,oo,ro,on,Ge,ye,ue,Ue,nn=class{constructor(e,n){p(this,E);p(this,Ae);p(this,$);p(this,Ie,en());p(this,G);p(this,ne);p(this,he);p(this,Je,[]);Fe(this,"getSnapshot",()=>r(this,Ie));Fe(this,"subscribe",e=>r(this,Ae).subscribe(e));d(this,$,n),d(this,Ae,new vt(e,this))}sync(e){if(!e){this.reset();return}switch(e.state){case"connected":if(r(this,G)===e.connection)return;a(this,E,ye).call(this),d(this,G,e.connection),a(this,E,Ue).call(this,en()),a(this,E,no).call(this,e.connection);return;case"connecting":case"reconnecting":this.reset();return;case"not-embedded":d(this,G,void 0),a(this,E,ye).call(this),a(this,E,Ue).call(this,to());return;case"rejected":d(this,G,void 0),a(this,E,ye).call(this),a(this,E,ue).call(this,Yt(e.error));return;case"closed":d(this,G,void 0),a(this,E,ye).call(this),a(this,E,ue).call(this,Yo);return;default:return e}}fail(e){d(this,G,void 0),a(this,E,ye).call(this),a(this,E,ue).call(this,e)}reset(){d(this,G,void 0),a(this,E,ye).call(this),a(this,E,Ue).call(this,en())}};Ae=new WeakMap,$=new WeakMap,Ie=new WeakMap,G=new WeakMap,ne=new WeakMap,he=new WeakMap,Je=new WeakMap,E=new WeakSet,no=function(e){let n=new AbortController;d(this,ne,n);let o;try{o=e.claim(r(this,$),{signal:n.signal})}catch(i){y("a claim could not be requested",{side:"app",identifier:r(this,$).identifier,current:a(this,E,Ge).call(this,e,n),cause:S(i)}),a(this,E,Ge).call(this,e,n)&&(d(this,ne,void 0),a(this,E,ue).call(this,qt));return}o.then(i=>{if(!a(this,E,Ge).call(this,e,n)){i.ok&&i.value.release();return}if(d(this,ne,void 0),!i.ok){if(i.error.code==="PEER_LACKS_MODULE"){x("the Datadog host does not offer this module",{side:"app",identifier:r(this,$).identifier,version:r(this,$).version}),a(this,E,Ue).call(this,to());return}if(i.error.code==="ABORTED"){a(this,E,ue).call(this,qt);return}a(this,E,ue).call(this,Qt(i.error));return}a(this,E,oo).call(this,e,i.value)},i=>{y("a claim request rejected",{side:"app",identifier:r(this,$).identifier,current:a(this,E,Ge).call(this,e,n),cause:S(i)}),a(this,E,Ge).call(this,e,n)&&(d(this,ne,void 0),a(this,E,ue).call(this,qt))})},oo=function(e,n){if(!r(this,Ae).isActive||r(this,G)!==e||r(this,he)){n.release();return}d(this,he,n),r(this,Je).push(n.onInvalidated(o=>a(this,E,ro).call(this,n,o))),r(this,Je).push(n.onValuesChanged(()=>{r(this,he)===n&&a(this,E,on).call(this,n)})),a(this,E,on).call(this,n)},ro=function(e,n){if(r(this,he)!==e)return;let o=Qt(n);a(this,E,ye).call(this),a(this,E,ue).call(this,o)},on=function(e){let n=Object.entries(r(this,$).fields),o=n.map(([s])=>s),i=Object.create(null);for(let[s,c]of n){let u=e.fields[s];i[s]=c.kind==="value"?u.get():u}if(r(this,Ie).status==="ready"){let s=r(this,Ie).fields;if(o.every(c=>Object.is(s[c],i[c])))return}a(this,E,Ue).call(this,Object.freeze({status:"ready",fields:Object.freeze(i)}))},Ge=function(e,n){return r(this,Ae).isActive&&r(this,G)===e&&r(this,ne)===n&&!n.signal.aborted},ye=function(){r(this,ne)?.abort(),d(this,ne,void 0);for(let n of r(this,Je).splice(0))n();let e=r(this,he);d(this,he,void 0),e?.release()},ue=function(e){y("a Datadog App claim failed",{side:"app",identifier:r(this,$).identifier,version:r(this,$).version,code:e.code,action:e.action,reason:e.message}),a(this,E,Ue).call(this,Qo(e))},Ue=function(e){r(this,Ie)!==e&&(d(this,Ie,e),r(this,Ae).notify())};var tn=Object.freeze({state:"connecting"});function qo(t){switch(t.state){case"connecting":return{state:"connecting",error:t.error};case"connected":return{state:"connected",surfaceId:t.surfaceId};case"reconnecting":return{state:"reconnecting",lastError:t.lastError};case"rejected":return{state:"rejected",error:t.error};case"not-embedded":return{state:"not-embedded"};case"closed":return{state:"closed"};default:return t}}var Ke,Ze,Xe,Rt,rn=class{constructor(e){p(this,Xe);p(this,Ke);p(this,Ze,tn);Fe(this,"getSnapshot",()=>r(this,Ze));Fe(this,"subscribe",e=>r(this,Ke).subscribe(e));d(this,Ke,new vt(e,this))}sync(e){a(this,Xe,Rt).call(this,e?qo(e):tn)}fail(e){a(this,Xe,Rt).call(this,{state:"rejected",error:{code:"TRANSPORT_FAILED",cause:e}})}reset(){a(this,Xe,Rt).call(this,tn)}};Ke=new WeakMap,Ze=new WeakMap,Xe=new WeakSet,Rt=function(e){r(this,Ze)!==e&&(d(this,Ze,e),r(this,Ke).notify())};var lt,X,ut,fe,Ye,_e,Qe,Ve,P,io,so,ao,co,an,dn,cn,sn=class{constructor(e){this.connector=e;p(this,P);p(this,lt,new WeakMap);p(this,X,new Set);p(this,ut,{activate:e=>a(this,P,ao).call(this,e),deactivate:e=>a(this,P,co).call(this,e)});p(this,fe);p(this,Ye);p(this,_e);p(this,Qe);p(this,Ve,0)}connector;getClaim(e){let n=e,o=r(this,lt).get(n);if(o)return o;let i=new nn(r(this,ut),e);return r(this,lt).set(n,i),i}getEmbeddingMetadata(){return r(this,Qe)||d(this,Qe,new rn(r(this,ut))),r(this,Qe)}start(){d(this,Ve,r(this,Ve)+1),r(this,Ve)===1&&a(this,P,io).call(this);let e=!0;return()=>{e&&(e=!1,d(this,Ve,r(this,Ve)-1),r(this,Ve)===0&&a(this,P,so).call(this))}}};lt=new WeakMap,X=new WeakMap,ut=new WeakMap,fe=new WeakMap,Ye=new WeakMap,_e=new WeakMap,Qe=new WeakMap,Ve=new WeakMap,P=new WeakSet,io=function(){d(this,_e,void 0);for(let n of r(this,X))n.reset();let e;try{e=this.connector.connect()}catch(n){a(this,P,cn).call(this,"connect",n);return}d(this,fe,e);try{d(this,Ye,e.subscribe(()=>a(this,P,an).call(this,e))),a(this,P,an).call(this,e)}catch(n){a(this,P,dn).call(this,e),a(this,P,cn).call(this,"subscribe",n);return}},so=function(){let e=r(this,fe);e&&a(this,P,dn).call(this,e),d(this,_e,void 0);for(let n of r(this,X))n.reset()},ao=function(e){if(r(this,X).add(e),r(this,_e)){e.fail(r(this,_e));return}e.sync(r(this,fe)?.getSnapshot())},co=function(e){r(this,X).delete(e),e.reset()},an=function(e){if(r(this,fe)!==e)return;let n=e.getSnapshot();for(let o of r(this,X))o.sync(n)},dn=function(e){if(r(this,fe)!==e)return;d(this,fe,void 0);let n=r(this,Ye);d(this,Ye,void 0),n&&L("embedding connection handle unsubscribe",()=>n());for(let o of r(this,X))L("embedding claim resource reset",()=>o.reset());L("embedding connection handle close",()=>e.close())},cn=function(e,n){y("the embedding connection could not be started",{side:"app",step:e,affectedResources:r(this,X).size,cause:S(n)}),d(this,_e,eo);for(let o of r(this,X))o.fail(eo)};function lo(t){return new sn(t)}var er=lo(Qn),tr=vn(er);import{useSyncExternalStore as nr}from"react";var ln=new WeakMap;function uo(t){return t==="connecting"||t==="reconnecting"}function or(t,e){let n=ln.get(e);if(!n){let o=yn(t),i;n=new Promise(h=>{i=h}),ln.set(e,n);let s,c=!1,u=()=>{c||uo(e.getSnapshot().state)||(c=!0,s?.(),ln.delete(e),Rn(t,o),i())};s=e.subscribe(u),c?s():u()}throw n}function rr(){throw new Error("useDatadogAppEmbedding does not support server rendering: the Datadog App embedding connection only exists in the browser.")}function ir(t){throw new Error(t.state==="rejected"?`The Datadog App embedding connection was rejected: ${t.error.code}.`:"The Datadog App embedding connection closed.")}function sr(t){let e=An(),n=e.getEmbeddingMetadata(),o=nr(n.subscribe,n.getSnapshot,rr);return t?.suspense&&(uo(o.state)&&or(e,n),(o.state==="rejected"||o.state==="closed")&&ir(o)),o}export{tr as DatadogAppProvider,sr as useDatadogAppEmbedding};
|
|
7
|
+
//# sourceMappingURL=index.js.map
|