Core: createContext, mount, update
Classes
Section titled “Classes”AsyncServiceNotReadyError
Section titled “AsyncServiceNotReadyError”Defined in: src/core/errors.ts:272
Thrown when synchronous inject() targets an async provider that has not
resolved yet.
Async registrations (withAsyncProvider) never resolve synchronously. Use
injectAsync(token)(target) and await the result, or await mountAsync()(element) first for eager singletons.
The constructor accepts either a token string or a full options bag.
tokenOrOptions
Token name or AsyncServiceNotReadyErrorOptions bag.
Example
Section titled “Example”import { injectAsync } from '@sandlada/document-context'
const svc = await injectAsync('remote-config')(document.getElementById('app')!)Extends
Section titled “Extends”Constructors
Section titled “Constructors”Constructor
Section titled “Constructor”new AsyncServiceNotReadyError(
tokenOrOptions):AsyncServiceNotReadyError
Defined in: src/core/errors.ts:275
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
tokenOrOptions |
string | AsyncServiceNotReadyErrorOptions |
Returns
Section titled “Returns”Overrides
Section titled “Overrides”DocumentContextError.constructor
Properties
Section titled “Properties”| Property | Modifier | Type | Description | Inherited from |
|---|---|---|---|---|
cause? |
public |
unknown |
- | DocumentContextError.cause |
code |
readonly |
string |
- | DocumentContextError.code |
details |
readonly |
Record<string, unknown> |
- | DocumentContextError.details |
message |
public |
string |
- | DocumentContextError.message |
name |
public |
string |
- | DocumentContextError.name |
resolutionGuide? |
readonly |
string |
- | DocumentContextError.resolutionGuide |
stack? |
public |
string |
- | DocumentContextError.stack |
token |
readonly |
string |
- | - |
stackTraceLimit |
static |
number |
The Error.stackTraceLimit property specifies the number of stack frames collected by a stack trace (whether generated by new Error().stack or Error.captureStackTrace(obj)). The default value is 10 but may be set to any valid JavaScript number. Changes will affect any stack trace captured after the value has been changed. If set to a non-number value, or set to a negative number, stack traces will not capture any frames. |
DocumentContextError.stackTraceLimit |
Methods
Section titled “Methods”toString()
Section titled “toString()”toString():
string
Defined in: src/core/errors.ts:55
Returns a string representation of an object.
Returns
Section titled “Returns”string
Inherited from
Section titled “Inherited from”captureStackTrace()
Section titled “captureStackTrace()”
staticcaptureStackTrace(targetObject,constructorOpt?):void
Defined in: node_modules/@types/node/globals.d.ts:51
Creates a .stack property on targetObject, which when accessed returns
a string representing the location in the code at which
Error.captureStackTrace() was called.
const myObject = {};Error.captureStackTrace(myObject);myObject.stack; // Similar to `new Error().stack`The first line of the trace will be prefixed with
${myObject.name}: ${myObject.message}.
The optional constructorOpt argument accepts a function. If given, all frames
above constructorOpt, including constructorOpt, will be omitted from the
generated stack trace.
The constructorOpt argument is useful for hiding implementation
details of error generation from the user. For instance:
function a() { b();}
function b() { c();}
function c() { // Create an error without stack trace to avoid calculating the stack trace twice. const { stackTraceLimit } = Error; Error.stackTraceLimit = 0; const error = new Error(); Error.stackTraceLimit = stackTraceLimit;
// Capture the stack trace above function b Error.captureStackTrace(error, b); // Neither function c, nor b is included in the stack trace throw error;}
a();Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
targetObject |
object |
constructorOpt? |
Function |
Returns
Section titled “Returns”void
Inherited from
Section titled “Inherited from”DocumentContextError.captureStackTrace
isError()
Section titled “isError()”
staticisError(error):error is Error
Defined in: site/node_modules/typescript/lib/lib.esnext.error.d.ts:21
Indicates whether the argument provided is a built-in Error instance or not.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
error |
unknown |
Returns
Section titled “Returns”error is Error
Inherited from
Section titled “Inherited from”prepareStackTrace()
Section titled “prepareStackTrace()”
staticprepareStackTrace(err,stackTraces):any
Defined in: node_modules/@types/node/globals.d.ts:55
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
err |
Error |
stackTraces |
CallSite[] |
Returns
Section titled “Returns”any
https://v8.dev/docs/stack-trace-api#customizing-stack-traces
Inherited from
Section titled “Inherited from”DocumentContextError.prepareStackTrace
CircularDependencyError
Section titled “CircularDependencyError”Defined in: src/core/errors.ts:112
Thrown when a dependency cycle is detected during service resolution.
Both the synchronous (inject) and asynchronous (injectAsync) pipelines
maintain a resolution stack; re-entering a token already on the stack throws
this error with the full dependencyPath. Break the cycle with lazy
resolution (inject inside a method instead of the factory top level),
by extracting shared logic into a third service, or via event decoupling.
The constructor accepts either a bare path array or a full options bag, plus
an optional positional resolutionGuide shorthand.
dependencyPathOrOptions
Either the cycle path array or a CircularDependencyErrorOptions bag.
resolutionGuide
Positional guide override, used only with the array form.
Example
Section titled “Example”import { CircularDependencyError } from '@sandlada/document-context'
throw new CircularDependencyError(['auth', 'router', 'auth'])throw new CircularDependencyError({ dependencyPath: ['a', 'b', 'a'], details: { token: 'a' }})Extends
Section titled “Extends”Constructors
Section titled “Constructors”Constructor
Section titled “Constructor”new CircularDependencyError(
dependencyPathOrOptions,resolutionGuide?):CircularDependencyError
Defined in: src/core/errors.ts:115
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
dependencyPathOrOptions |
readonly string[] | CircularDependencyErrorOptions |
resolutionGuide? |
string |
Returns
Section titled “Returns”Overrides
Section titled “Overrides”DocumentContextError.constructor
Properties
Section titled “Properties”| Property | Modifier | Type | Description | Inherited from |
|---|---|---|---|---|
cause? |
public |
unknown |
- | DocumentContextError.cause |
code |
readonly |
string |
- | DocumentContextError.code |
dependencyPath |
readonly |
readonly string[] |
- | - |
details |
readonly |
Record<string, unknown> |
- | DocumentContextError.details |
message |
public |
string |
- | DocumentContextError.message |
name |
public |
string |
- | DocumentContextError.name |
resolutionGuide? |
readonly |
string |
- | DocumentContextError.resolutionGuide |
stack? |
public |
string |
- | DocumentContextError.stack |
stackTraceLimit |
static |
number |
The Error.stackTraceLimit property specifies the number of stack frames collected by a stack trace (whether generated by new Error().stack or Error.captureStackTrace(obj)). The default value is 10 but may be set to any valid JavaScript number. Changes will affect any stack trace captured after the value has been changed. If set to a non-number value, or set to a negative number, stack traces will not capture any frames. |
DocumentContextError.stackTraceLimit |
Methods
Section titled “Methods”toString()
Section titled “toString()”toString():
string
Defined in: src/core/errors.ts:55
Returns a string representation of an object.
Returns
Section titled “Returns”string
Inherited from
Section titled “Inherited from”captureStackTrace()
Section titled “captureStackTrace()”
staticcaptureStackTrace(targetObject,constructorOpt?):void
Defined in: node_modules/@types/node/globals.d.ts:51
Creates a .stack property on targetObject, which when accessed returns
a string representing the location in the code at which
Error.captureStackTrace() was called.
const myObject = {};Error.captureStackTrace(myObject);myObject.stack; // Similar to `new Error().stack`The first line of the trace will be prefixed with
${myObject.name}: ${myObject.message}.
The optional constructorOpt argument accepts a function. If given, all frames
above constructorOpt, including constructorOpt, will be omitted from the
generated stack trace.
The constructorOpt argument is useful for hiding implementation
details of error generation from the user. For instance:
function a() { b();}
function b() { c();}
function c() { // Create an error without stack trace to avoid calculating the stack trace twice. const { stackTraceLimit } = Error; Error.stackTraceLimit = 0; const error = new Error(); Error.stackTraceLimit = stackTraceLimit;
// Capture the stack trace above function b Error.captureStackTrace(error, b); // Neither function c, nor b is included in the stack trace throw error;}
a();Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
targetObject |
object |
constructorOpt? |
Function |
Returns
Section titled “Returns”void
Inherited from
Section titled “Inherited from”DocumentContextError.captureStackTrace
isError()
Section titled “isError()”
staticisError(error):error is Error
Defined in: site/node_modules/typescript/lib/lib.esnext.error.d.ts:21
Indicates whether the argument provided is a built-in Error instance or not.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
error |
unknown |
Returns
Section titled “Returns”error is Error
Inherited from
Section titled “Inherited from”prepareStackTrace()
Section titled “prepareStackTrace()”
staticprepareStackTrace(err,stackTraces):any
Defined in: node_modules/@types/node/globals.d.ts:55
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
err |
Error |
stackTraces |
CallSite[] |
Returns
Section titled “Returns”any
https://v8.dev/docs/stack-trace-api#customizing-stack-traces
Inherited from
Section titled “Inherited from”DocumentContextError.prepareStackTrace
DisposedSessionError
Section titled “DisposedSessionError”Defined in: src/core/errors.ts:342
Reported when an operation targets a disposed ISession.
Note the runtime contract: update() / subscribe() on a disposed session
silently no-op (returning false / an empty unsubscribe) rather than
throwing, so dangling async closures cannot crash the page. This error class
exists for explicit diagnostic paths and custom guards that choose to
surface disposal loudly.
The constructor accepts a session-key string, an options bag, or nothing.
sessionKeyOrOptions
Session key string or DisposedSessionErrorOptions bag. Optional.
Example
Section titled “Example”import { update } from '@sandlada/document-context'
const ok = update({ count: 1 })(session)if (!ok) { console.warn('session already disposed, update skipped')}Extends
Section titled “Extends”Constructors
Section titled “Constructors”Constructor
Section titled “Constructor”new DisposedSessionError(
sessionKeyOrOptions?):DisposedSessionError
Defined in: src/core/errors.ts:345
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
sessionKeyOrOptions? |
string | DisposedSessionErrorOptions |
Returns
Section titled “Returns”Overrides
Section titled “Overrides”DocumentContextError.constructor
Properties
Section titled “Properties”| Property | Modifier | Type | Description | Inherited from |
|---|---|---|---|---|
cause? |
public |
unknown |
- | DocumentContextError.cause |
code |
readonly |
string |
- | DocumentContextError.code |
details |
readonly |
Record<string, unknown> |
- | DocumentContextError.details |
message |
public |
string |
- | DocumentContextError.message |
name |
public |
string |
- | DocumentContextError.name |
resolutionGuide? |
readonly |
string |
- | DocumentContextError.resolutionGuide |
sessionKey? |
readonly |
string |
- | - |
stack? |
public |
string |
- | DocumentContextError.stack |
stackTraceLimit |
static |
number |
The Error.stackTraceLimit property specifies the number of stack frames collected by a stack trace (whether generated by new Error().stack or Error.captureStackTrace(obj)). The default value is 10 but may be set to any valid JavaScript number. Changes will affect any stack trace captured after the value has been changed. If set to a non-number value, or set to a negative number, stack traces will not capture any frames. |
DocumentContextError.stackTraceLimit |
Methods
Section titled “Methods”toString()
Section titled “toString()”toString():
string
Defined in: src/core/errors.ts:55
Returns a string representation of an object.
Returns
Section titled “Returns”string
Inherited from
Section titled “Inherited from”captureStackTrace()
Section titled “captureStackTrace()”
staticcaptureStackTrace(targetObject,constructorOpt?):void
Defined in: node_modules/@types/node/globals.d.ts:51
Creates a .stack property on targetObject, which when accessed returns
a string representing the location in the code at which
Error.captureStackTrace() was called.
const myObject = {};Error.captureStackTrace(myObject);myObject.stack; // Similar to `new Error().stack`The first line of the trace will be prefixed with
${myObject.name}: ${myObject.message}.
The optional constructorOpt argument accepts a function. If given, all frames
above constructorOpt, including constructorOpt, will be omitted from the
generated stack trace.
The constructorOpt argument is useful for hiding implementation
details of error generation from the user. For instance:
function a() { b();}
function b() { c();}
function c() { // Create an error without stack trace to avoid calculating the stack trace twice. const { stackTraceLimit } = Error; Error.stackTraceLimit = 0; const error = new Error(); Error.stackTraceLimit = stackTraceLimit;
// Capture the stack trace above function b Error.captureStackTrace(error, b); // Neither function c, nor b is included in the stack trace throw error;}
a();Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
targetObject |
object |
constructorOpt? |
Function |
Returns
Section titled “Returns”void
Inherited from
Section titled “Inherited from”DocumentContextError.captureStackTrace
isError()
Section titled “isError()”
staticisError(error):error is Error
Defined in: site/node_modules/typescript/lib/lib.esnext.error.d.ts:21
Indicates whether the argument provided is a built-in Error instance or not.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
error |
unknown |
Returns
Section titled “Returns”error is Error
Inherited from
Section titled “Inherited from”prepareStackTrace()
Section titled “prepareStackTrace()”
staticprepareStackTrace(err,stackTraces):any
Defined in: node_modules/@types/node/globals.d.ts:55
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
err |
Error |
stackTraces |
CallSite[] |
Returns
Section titled “Returns”any
https://v8.dev/docs/stack-trace-api#customizing-stack-traces
Inherited from
Section titled “Inherited from”DocumentContextError.prepareStackTrace
DocumentContextError
Section titled “DocumentContextError”Defined in: src/core/errors.ts:41
Abstract base class for every @sandlada/document-context exception.
Carries a stable code, a structured details bag, and an optional
resolutionGuide alongside the standard Error message, name, and cause.
All errors pushed to the session error stream (readErrorStream) are
instances of this class. Never thrown directly; catch one of the concrete
subclasses instead.
options
See DocumentContextErrorOptions.
Example
Section titled “Example”import { readErrorStream } from '@sandlada/document-context'
readErrorStream(session).subscribe((err) => { console.error(err.toString(), err.code, err.details)})Extends
Section titled “Extends”Error
Extended by
Section titled “Extended by”CircularDependencyErrorUnknownServiceErrorAsyncServiceNotReadyErrorDisposedSessionErrorUnconnectedNodeErrorPropertySyncSecurityErrorHydrationMismatchErrorInvalidStorageDataError
Constructors
Section titled “Constructors”Constructor
Section titled “Constructor”new DocumentContextError(
options):DocumentContextError
Defined in: src/core/errors.ts:46
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
options |
DocumentContextErrorOptions |
Returns
Section titled “Returns”Overrides
Section titled “Overrides”Error.constructor
Properties
Section titled “Properties”Methods
Section titled “Methods”toString()
Section titled “toString()”toString():
string
Defined in: src/core/errors.ts:55
Returns a string representation of an object.
Returns
Section titled “Returns”string
captureStackTrace()
Section titled “captureStackTrace()”
staticcaptureStackTrace(targetObject,constructorOpt?):void
Defined in: node_modules/@types/node/globals.d.ts:51
Creates a .stack property on targetObject, which when accessed returns
a string representing the location in the code at which
Error.captureStackTrace() was called.
const myObject = {};Error.captureStackTrace(myObject);myObject.stack; // Similar to `new Error().stack`The first line of the trace will be prefixed with
${myObject.name}: ${myObject.message}.
The optional constructorOpt argument accepts a function. If given, all frames
above constructorOpt, including constructorOpt, will be omitted from the
generated stack trace.
The constructorOpt argument is useful for hiding implementation
details of error generation from the user. For instance:
function a() { b();}
function b() { c();}
function c() { // Create an error without stack trace to avoid calculating the stack trace twice. const { stackTraceLimit } = Error; Error.stackTraceLimit = 0; const error = new Error(); Error.stackTraceLimit = stackTraceLimit;
// Capture the stack trace above function b Error.captureStackTrace(error, b); // Neither function c, nor b is included in the stack trace throw error;}
a();Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
targetObject |
object |
constructorOpt? |
Function |
Returns
Section titled “Returns”void
Inherited from
Section titled “Inherited from”Error.captureStackTrace
isError()
Section titled “isError()”
staticisError(error):error is Error
Defined in: site/node_modules/typescript/lib/lib.esnext.error.d.ts:21
Indicates whether the argument provided is a built-in Error instance or not.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
error |
unknown |
Returns
Section titled “Returns”error is Error
Inherited from
Section titled “Inherited from”Error.isError
prepareStackTrace()
Section titled “prepareStackTrace()”
staticprepareStackTrace(err,stackTraces):any
Defined in: node_modules/@types/node/globals.d.ts:55
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
err |
Error |
stackTraces |
CallSite[] |
Returns
Section titled “Returns”any
https://v8.dev/docs/stack-trace-api#customizing-stack-traces
Inherited from
Section titled “Inherited from”Error.prepareStackTrace
HydrationMismatchError
Section titled “HydrationMismatchError”Defined in: src/core/errors.ts:600
Reported when server-rendered DOM, persisted storage, and blueprint seeds disagree on a property during hydration.
This is a diagnostic carrier rather than a hard failure: the configured
hydrationStrategy (storageFirst by default) deterministically picks the
winner, and this error shape documents the loser for logging or dev
overlays. Check the strategy and verify SSR HTML matches client seeds.
The constructor accepts either (propertyKey, expectedValue, actualValue?)
positionally or a full options bag.
propertyKeyOrOptions
State key or HydrationMismatchErrorOptions bag.
expectedValue
Reference value, used only with the string form.
actualValue
Applied value, used only with the string form.
Example
Section titled “Example”import { HydrationMismatchError } from '@sandlada/document-context'
throw new HydrationMismatchError({ propertyKey: 'theme', expectedValue: 'dark', actualValue: 'light'})Extends
Section titled “Extends”Constructors
Section titled “Constructors”Constructor
Section titled “Constructor”new HydrationMismatchError(
propertyKeyOrOptions,expectedValue?,actualValue?):HydrationMismatchError
Defined in: src/core/errors.ts:605
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
propertyKeyOrOptions |
string | HydrationMismatchErrorOptions |
expectedValue? |
unknown |
actualValue? |
unknown |
Returns
Section titled “Returns”Overrides
Section titled “Overrides”DocumentContextError.constructor
Properties
Section titled “Properties”| Property | Modifier | Type | Description | Inherited from |
|---|---|---|---|---|
actualValue |
readonly |
unknown |
- | - |
cause? |
public |
unknown |
- | DocumentContextError.cause |
code |
readonly |
string |
- | DocumentContextError.code |
details |
readonly |
Record<string, unknown> |
- | DocumentContextError.details |
expectedValue |
readonly |
unknown |
- | - |
message |
public |
string |
- | DocumentContextError.message |
name |
public |
string |
- | DocumentContextError.name |
propertyKey |
readonly |
string |
- | - |
resolutionGuide? |
readonly |
string |
- | DocumentContextError.resolutionGuide |
stack? |
public |
string |
- | DocumentContextError.stack |
stackTraceLimit |
static |
number |
The Error.stackTraceLimit property specifies the number of stack frames collected by a stack trace (whether generated by new Error().stack or Error.captureStackTrace(obj)). The default value is 10 but may be set to any valid JavaScript number. Changes will affect any stack trace captured after the value has been changed. If set to a non-number value, or set to a negative number, stack traces will not capture any frames. |
DocumentContextError.stackTraceLimit |
Methods
Section titled “Methods”toString()
Section titled “toString()”toString():
string
Defined in: src/core/errors.ts:55
Returns a string representation of an object.
Returns
Section titled “Returns”string
Inherited from
Section titled “Inherited from”captureStackTrace()
Section titled “captureStackTrace()”
staticcaptureStackTrace(targetObject,constructorOpt?):void
Defined in: node_modules/@types/node/globals.d.ts:51
Creates a .stack property on targetObject, which when accessed returns
a string representing the location in the code at which
Error.captureStackTrace() was called.
const myObject = {};Error.captureStackTrace(myObject);myObject.stack; // Similar to `new Error().stack`The first line of the trace will be prefixed with
${myObject.name}: ${myObject.message}.
The optional constructorOpt argument accepts a function. If given, all frames
above constructorOpt, including constructorOpt, will be omitted from the
generated stack trace.
The constructorOpt argument is useful for hiding implementation
details of error generation from the user. For instance:
function a() { b();}
function b() { c();}
function c() { // Create an error without stack trace to avoid calculating the stack trace twice. const { stackTraceLimit } = Error; Error.stackTraceLimit = 0; const error = new Error(); Error.stackTraceLimit = stackTraceLimit;
// Capture the stack trace above function b Error.captureStackTrace(error, b); // Neither function c, nor b is included in the stack trace throw error;}
a();Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
targetObject |
object |
constructorOpt? |
Function |
Returns
Section titled “Returns”void
Inherited from
Section titled “Inherited from”DocumentContextError.captureStackTrace
isError()
Section titled “isError()”
staticisError(error):error is Error
Defined in: site/node_modules/typescript/lib/lib.esnext.error.d.ts:21
Indicates whether the argument provided is a built-in Error instance or not.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
error |
unknown |
Returns
Section titled “Returns”error is Error
Inherited from
Section titled “Inherited from”prepareStackTrace()
Section titled “prepareStackTrace()”
staticprepareStackTrace(err,stackTraces):any
Defined in: node_modules/@types/node/globals.d.ts:55
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
err |
Error |
stackTraces |
CallSite[] |
Returns
Section titled “Returns”any
https://v8.dev/docs/stack-trace-api#customizing-stack-traces
Inherited from
Section titled “Inherited from”DocumentContextError.prepareStackTrace
InvalidStorageDataError
Section titled “InvalidStorageDataError”Defined in: src/core/errors.ts:694
Reported when storage deserialization fails or persisted JSON is corrupt.
The storage pipeline never lets a bad payload crash mounting: synchronous
read failures, async adapter rejections, BroadcastChannel message parse
failures, and storage-event parse failures are all routed to the session
error stream (readErrorStream) as this error, and hydration falls back to
DOM/blueprint sources. Supply a migrate function in withStorage to
recover old schemas instead of dropping them.
The constructor accepts either (key, rawData?) positionally or a full
options bag.
keyOrOptions
Storage key or InvalidStorageDataErrorOptions.
rawData
Raw payload, used only with the string form.
Example
Section titled “Example”import { readErrorStream } from '@sandlada/document-context'
readErrorStream(session).subscribe((err) => { if (err.code === 'INVALID_STORAGE_DATA') { console.warn('dropping corrupt payload for', err.details) }})Extends
Section titled “Extends”Constructors
Section titled “Constructors”Constructor
Section titled “Constructor”new InvalidStorageDataError(
keyOrOptions,rawData?):InvalidStorageDataError
Defined in: src/core/errors.ts:698
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
keyOrOptions |
string | InvalidStorageDataErrorOptions |
rawData? |
unknown |
Returns
Section titled “Returns”Overrides
Section titled “Overrides”DocumentContextError.constructor
Properties
Section titled “Properties”| Property | Modifier | Type | Description | Inherited from |
|---|---|---|---|---|
cause? |
public |
unknown |
- | DocumentContextError.cause |
code |
readonly |
string |
- | DocumentContextError.code |
details |
readonly |
Record<string, unknown> |
- | DocumentContextError.details |
key |
readonly |
string |
- | - |
message |
public |
string |
- | DocumentContextError.message |
name |
public |
string |
- | DocumentContextError.name |
rawData |
readonly |
unknown |
- | - |
resolutionGuide? |
readonly |
string |
- | DocumentContextError.resolutionGuide |
stack? |
public |
string |
- | DocumentContextError.stack |
stackTraceLimit |
static |
number |
The Error.stackTraceLimit property specifies the number of stack frames collected by a stack trace (whether generated by new Error().stack or Error.captureStackTrace(obj)). The default value is 10 but may be set to any valid JavaScript number. Changes will affect any stack trace captured after the value has been changed. If set to a non-number value, or set to a negative number, stack traces will not capture any frames. |
DocumentContextError.stackTraceLimit |
Methods
Section titled “Methods”toString()
Section titled “toString()”toString():
string
Defined in: src/core/errors.ts:55
Returns a string representation of an object.
Returns
Section titled “Returns”string
Inherited from
Section titled “Inherited from”captureStackTrace()
Section titled “captureStackTrace()”
staticcaptureStackTrace(targetObject,constructorOpt?):void
Defined in: node_modules/@types/node/globals.d.ts:51
Creates a .stack property on targetObject, which when accessed returns
a string representing the location in the code at which
Error.captureStackTrace() was called.
const myObject = {};Error.captureStackTrace(myObject);myObject.stack; // Similar to `new Error().stack`The first line of the trace will be prefixed with
${myObject.name}: ${myObject.message}.
The optional constructorOpt argument accepts a function. If given, all frames
above constructorOpt, including constructorOpt, will be omitted from the
generated stack trace.
The constructorOpt argument is useful for hiding implementation
details of error generation from the user. For instance:
function a() { b();}
function b() { c();}
function c() { // Create an error without stack trace to avoid calculating the stack trace twice. const { stackTraceLimit } = Error; Error.stackTraceLimit = 0; const error = new Error(); Error.stackTraceLimit = stackTraceLimit;
// Capture the stack trace above function b Error.captureStackTrace(error, b); // Neither function c, nor b is included in the stack trace throw error;}
a();Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
targetObject |
object |
constructorOpt? |
Function |
Returns
Section titled “Returns”void
Inherited from
Section titled “Inherited from”DocumentContextError.captureStackTrace
isError()
Section titled “isError()”
staticisError(error):error is Error
Defined in: site/node_modules/typescript/lib/lib.esnext.error.d.ts:21
Indicates whether the argument provided is a built-in Error instance or not.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
error |
unknown |
Returns
Section titled “Returns”error is Error
Inherited from
Section titled “Inherited from”prepareStackTrace()
Section titled “prepareStackTrace()”
staticprepareStackTrace(err,stackTraces):any
Defined in: node_modules/@types/node/globals.d.ts:55
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
err |
Error |
stackTraces |
CallSite[] |
Returns
Section titled “Returns”any
https://v8.dev/docs/stack-trace-api#customizing-stack-traces
Inherited from
Section titled “Inherited from”DocumentContextError.prepareStackTrace
PropertySyncSecurityError
Section titled “PropertySyncSecurityError”Defined in: src/core/errors.ts:508
Thrown when a bridge path attempts prototype pollution or targets an XSS sink.
Matching is case-insensitive per dot-segment. Blocked tokens are
__proto__, prototype, constructor; blocked sinks are innerHTML,
outerHTML, insertAdjacentHTML, srcdoc, script, and eval. Thrown
eagerly by validatePropertyPath() from both readDomProperty() and
writeDomProperty(), so a bad mapping fails at mount rather than silently
writing somewhere dangerous.
The constructor accepts either (dangerousPath, targetNode?) positionally
or a full options bag.
dangerousPathOrOptions
Rejected path or PropertySyncSecurityErrorOptions bag.
targetNode
Host element, used only with the string form.
Example
Section titled “Example”import { withBridge } from '@sandlada/document-context'
// Throws at mount: 'innerHTML' is a forbidden sink.const bad = pipe(base, withBridge({ properties: { html: 'innerHTML' } }))Extends
Section titled “Extends”Constructors
Section titled “Constructors”Constructor
Section titled “Constructor”new PropertySyncSecurityError(
dangerousPathOrOptions,targetNode?):PropertySyncSecurityError
Defined in: src/core/errors.ts:512
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
dangerousPathOrOptions |
string | PropertySyncSecurityErrorOptions |
targetNode? |
string | HTMLElement |
Returns
Section titled “Returns”Overrides
Section titled “Overrides”DocumentContextError.constructor
Properties
Section titled “Properties”| Property | Modifier | Type | Description | Inherited from |
|---|---|---|---|---|
cause? |
public |
unknown |
- | DocumentContextError.cause |
code |
readonly |
string |
- | DocumentContextError.code |
dangerousPath |
readonly |
string |
- | - |
details |
readonly |
Record<string, unknown> |
- | DocumentContextError.details |
message |
public |
string |
- | DocumentContextError.message |
name |
public |
string |
- | DocumentContextError.name |
resolutionGuide? |
readonly |
string |
- | DocumentContextError.resolutionGuide |
stack? |
public |
string |
- | DocumentContextError.stack |
targetNode? |
readonly |
string | HTMLElement |
- | - |
stackTraceLimit |
static |
number |
The Error.stackTraceLimit property specifies the number of stack frames collected by a stack trace (whether generated by new Error().stack or Error.captureStackTrace(obj)). The default value is 10 but may be set to any valid JavaScript number. Changes will affect any stack trace captured after the value has been changed. If set to a non-number value, or set to a negative number, stack traces will not capture any frames. |
DocumentContextError.stackTraceLimit |
Methods
Section titled “Methods”toString()
Section titled “toString()”toString():
string
Defined in: src/core/errors.ts:55
Returns a string representation of an object.
Returns
Section titled “Returns”string
Inherited from
Section titled “Inherited from”captureStackTrace()
Section titled “captureStackTrace()”
staticcaptureStackTrace(targetObject,constructorOpt?):void
Defined in: node_modules/@types/node/globals.d.ts:51
Creates a .stack property on targetObject, which when accessed returns
a string representing the location in the code at which
Error.captureStackTrace() was called.
const myObject = {};Error.captureStackTrace(myObject);myObject.stack; // Similar to `new Error().stack`The first line of the trace will be prefixed with
${myObject.name}: ${myObject.message}.
The optional constructorOpt argument accepts a function. If given, all frames
above constructorOpt, including constructorOpt, will be omitted from the
generated stack trace.
The constructorOpt argument is useful for hiding implementation
details of error generation from the user. For instance:
function a() { b();}
function b() { c();}
function c() { // Create an error without stack trace to avoid calculating the stack trace twice. const { stackTraceLimit } = Error; Error.stackTraceLimit = 0; const error = new Error(); Error.stackTraceLimit = stackTraceLimit;
// Capture the stack trace above function b Error.captureStackTrace(error, b); // Neither function c, nor b is included in the stack trace throw error;}
a();Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
targetObject |
object |
constructorOpt? |
Function |
Returns
Section titled “Returns”void
Inherited from
Section titled “Inherited from”DocumentContextError.captureStackTrace
isError()
Section titled “isError()”
staticisError(error):error is Error
Defined in: site/node_modules/typescript/lib/lib.esnext.error.d.ts:21
Indicates whether the argument provided is a built-in Error instance or not.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
error |
unknown |
Returns
Section titled “Returns”error is Error
Inherited from
Section titled “Inherited from”prepareStackTrace()
Section titled “prepareStackTrace()”
staticprepareStackTrace(err,stackTraces):any
Defined in: node_modules/@types/node/globals.d.ts:55
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
err |
Error |
stackTraces |
CallSite[] |
Returns
Section titled “Returns”any
https://v8.dev/docs/stack-trace-api#customizing-stack-traces
Inherited from
Section titled “Inherited from”DocumentContextError.prepareStackTrace
UnconnectedNodeError
Section titled “UnconnectedNodeError”Defined in: src/core/errors.ts:419
Thrown when inject() is called on a detached DOM node.
Scope resolution depends on context-request event bubbling through
connected ancestors, so node.isConnected must be true. The single
exception is a token already present in the global singleton registry, which
resolves without DOM traversal. Otherwise, defer injection to
connectedCallback() or to after parent.appendChild(node).
The constructor accepts either (token, targetNode?) positionally or a
full options bag.
tokenOrOptions
Token name or UnconnectedNodeErrorOptions.
targetNode
Detached node, used only with the string form.
Example
Section titled “Example”import { inject } from '@sandlada/document-context'
class MyEl extends HTMLElement { connectedCallback() { const svc = inject('logger')(this) }}Extends
Section titled “Extends”Constructors
Section titled “Constructors”Constructor
Section titled “Constructor”new UnconnectedNodeError(
tokenOrOptions,targetNode?):UnconnectedNodeError
Defined in: src/core/errors.ts:423
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
tokenOrOptions |
string | UnconnectedNodeErrorOptions |
targetNode? |
HTMLElement | Node |
Returns
Section titled “Returns”Overrides
Section titled “Overrides”DocumentContextError.constructor
Properties
Section titled “Properties”| Property | Modifier | Type | Description | Inherited from |
|---|---|---|---|---|
cause? |
public |
unknown |
- | DocumentContextError.cause |
code |
readonly |
string |
- | DocumentContextError.code |
details |
readonly |
Record<string, unknown> |
- | DocumentContextError.details |
message |
public |
string |
- | DocumentContextError.message |
name |
public |
string |
- | DocumentContextError.name |
resolutionGuide? |
readonly |
string |
- | DocumentContextError.resolutionGuide |
stack? |
public |
string |
- | DocumentContextError.stack |
targetNode? |
readonly |
HTMLElement | Node |
- | - |
token |
readonly |
string |
- | - |
stackTraceLimit |
static |
number |
The Error.stackTraceLimit property specifies the number of stack frames collected by a stack trace (whether generated by new Error().stack or Error.captureStackTrace(obj)). The default value is 10 but may be set to any valid JavaScript number. Changes will affect any stack trace captured after the value has been changed. If set to a non-number value, or set to a negative number, stack traces will not capture any frames. |
DocumentContextError.stackTraceLimit |
Methods
Section titled “Methods”toString()
Section titled “toString()”toString():
string
Defined in: src/core/errors.ts:55
Returns a string representation of an object.
Returns
Section titled “Returns”string
Inherited from
Section titled “Inherited from”captureStackTrace()
Section titled “captureStackTrace()”
staticcaptureStackTrace(targetObject,constructorOpt?):void
Defined in: node_modules/@types/node/globals.d.ts:51
Creates a .stack property on targetObject, which when accessed returns
a string representing the location in the code at which
Error.captureStackTrace() was called.
const myObject = {};Error.captureStackTrace(myObject);myObject.stack; // Similar to `new Error().stack`The first line of the trace will be prefixed with
${myObject.name}: ${myObject.message}.
The optional constructorOpt argument accepts a function. If given, all frames
above constructorOpt, including constructorOpt, will be omitted from the
generated stack trace.
The constructorOpt argument is useful for hiding implementation
details of error generation from the user. For instance:
function a() { b();}
function b() { c();}
function c() { // Create an error without stack trace to avoid calculating the stack trace twice. const { stackTraceLimit } = Error; Error.stackTraceLimit = 0; const error = new Error(); Error.stackTraceLimit = stackTraceLimit;
// Capture the stack trace above function b Error.captureStackTrace(error, b); // Neither function c, nor b is included in the stack trace throw error;}
a();Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
targetObject |
object |
constructorOpt? |
Function |
Returns
Section titled “Returns”void
Inherited from
Section titled “Inherited from”DocumentContextError.captureStackTrace
isError()
Section titled “isError()”
staticisError(error):error is Error
Defined in: site/node_modules/typescript/lib/lib.esnext.error.d.ts:21
Indicates whether the argument provided is a built-in Error instance or not.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
error |
unknown |
Returns
Section titled “Returns”error is Error
Inherited from
Section titled “Inherited from”prepareStackTrace()
Section titled “prepareStackTrace()”
staticprepareStackTrace(err,stackTraces):any
Defined in: node_modules/@types/node/globals.d.ts:55
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
err |
Error |
stackTraces |
CallSite[] |
Returns
Section titled “Returns”any
https://v8.dev/docs/stack-trace-api#customizing-stack-traces
Inherited from
Section titled “Inherited from”DocumentContextError.prepareStackTrace
UnknownServiceError
Section titled “UnknownServiceError”Defined in: src/core/errors.ts:191
Thrown when inject() finds no provider for a token in the DOM scope chain.
Resolution walks the context-request event path up to the document root
and then consults the global singleton registry. If every step misses, this
error is thrown. Register the token with withProvider() /
withAsyncProvider() on an ancestor blueprint, or seed it via
setGlobalSingleton().
The constructor accepts either (token, targetElement?) positionally or a
full options bag.
tokenOrOptions
Token name string or UnknownServiceErrorOptions bag.
targetElement
Host element, used only with the string form.
Example
Section titled “Example”import { inject, withProvider, createContext, pipe, mount } from '@sandlada/document-context'
try { inject('auth-service')(document.getElementById('login')!)} catch (err) { console.error(String(err))}Extends
Section titled “Extends”Constructors
Section titled “Constructors”Constructor
Section titled “Constructor”new UnknownServiceError(
tokenOrOptions,targetElement?):UnknownServiceError
Defined in: src/core/errors.ts:195
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
tokenOrOptions |
string | UnknownServiceErrorOptions |
targetElement? |
string | HTMLElement |
Returns
Section titled “Returns”Overrides
Section titled “Overrides”DocumentContextError.constructor
Properties
Section titled “Properties”| Property | Modifier | Type | Description | Inherited from |
|---|---|---|---|---|
cause? |
public |
unknown |
- | DocumentContextError.cause |
code |
readonly |
string |
- | DocumentContextError.code |
details |
readonly |
Record<string, unknown> |
- | DocumentContextError.details |
message |
public |
string |
- | DocumentContextError.message |
name |
public |
string |
- | DocumentContextError.name |
resolutionGuide? |
readonly |
string |
- | DocumentContextError.resolutionGuide |
stack? |
public |
string |
- | DocumentContextError.stack |
targetElement? |
readonly |
string | HTMLElement |
- | - |
token |
readonly |
string |
- | - |
stackTraceLimit |
static |
number |
The Error.stackTraceLimit property specifies the number of stack frames collected by a stack trace (whether generated by new Error().stack or Error.captureStackTrace(obj)). The default value is 10 but may be set to any valid JavaScript number. Changes will affect any stack trace captured after the value has been changed. If set to a non-number value, or set to a negative number, stack traces will not capture any frames. |
DocumentContextError.stackTraceLimit |
Methods
Section titled “Methods”toString()
Section titled “toString()”toString():
string
Defined in: src/core/errors.ts:55
Returns a string representation of an object.
Returns
Section titled “Returns”string
Inherited from
Section titled “Inherited from”captureStackTrace()
Section titled “captureStackTrace()”
staticcaptureStackTrace(targetObject,constructorOpt?):void
Defined in: node_modules/@types/node/globals.d.ts:51
Creates a .stack property on targetObject, which when accessed returns
a string representing the location in the code at which
Error.captureStackTrace() was called.
const myObject = {};Error.captureStackTrace(myObject);myObject.stack; // Similar to `new Error().stack`The first line of the trace will be prefixed with
${myObject.name}: ${myObject.message}.
The optional constructorOpt argument accepts a function. If given, all frames
above constructorOpt, including constructorOpt, will be omitted from the
generated stack trace.
The constructorOpt argument is useful for hiding implementation
details of error generation from the user. For instance:
function a() { b();}
function b() { c();}
function c() { // Create an error without stack trace to avoid calculating the stack trace twice. const { stackTraceLimit } = Error; Error.stackTraceLimit = 0; const error = new Error(); Error.stackTraceLimit = stackTraceLimit;
// Capture the stack trace above function b Error.captureStackTrace(error, b); // Neither function c, nor b is included in the stack trace throw error;}
a();Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
targetObject |
object |
constructorOpt? |
Function |
Returns
Section titled “Returns”void
Inherited from
Section titled “Inherited from”DocumentContextError.captureStackTrace
isError()
Section titled “isError()”
staticisError(error):error is Error
Defined in: site/node_modules/typescript/lib/lib.esnext.error.d.ts:21
Indicates whether the argument provided is a built-in Error instance or not.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
error |
unknown |
Returns
Section titled “Returns”error is Error
Inherited from
Section titled “Inherited from”prepareStackTrace()
Section titled “prepareStackTrace()”
staticprepareStackTrace(err,stackTraces):any
Defined in: node_modules/@types/node/globals.d.ts:55
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
err |
Error |
stackTraces |
CallSite[] |
Returns
Section titled “Returns”any
https://v8.dev/docs/stack-trace-api#customizing-stack-traces
Inherited from
Section titled “Inherited from”DocumentContextError.prepareStackTrace
Interfaces
Section titled “Interfaces”AsyncServiceNotReadyErrorOptions
Section titled “AsyncServiceNotReadyErrorOptions”Defined in: src/core/errors.ts:242
Options bag for AsyncServiceNotReadyError.
Properties
Section titled “Properties”CircularDependencyErrorOptions
Section titled “CircularDependencyErrorOptions”Defined in: src/core/errors.ts:75
Options bag for CircularDependencyError.
Properties
Section titled “Properties”DisposedSessionErrorOptions
Section titled “DisposedSessionErrorOptions”Defined in: src/core/errors.ts:309
Options bag for DisposedSessionError.
Properties
Section titled “Properties”DocumentContextErrorOptions
Section titled “DocumentContextErrorOptions”Defined in: src/core/errors.ts:11
Options bag for constructing a DocumentContextError.
Properties
Section titled “Properties”HydrationMismatchErrorOptions
Section titled “HydrationMismatchErrorOptions”Defined in: src/core/errors.ts:561
Options bag for HydrationMismatchError.
Properties
Section titled “Properties”IAsyncStorageAdapter
Section titled “IAsyncStorageAdapter”Defined in: src/core/types.ts:276
Asynchronous key-value persistence adapter.
Same shape as IStorageAdapter but every method returns a Promise.
Reads hydrate late (applied via update() after mount); writes report
failures to the session error stream instead of throwing.
Example
Section titled “Example”const idbAdapter = { getItem: async (key: string) => (await idb.get(key)) ?? null, setItem: async (key: string, value: string) => { await idb.set(key, value) }, removeItem: async (key: string) => { await idb.del(key) }}Type Parameters
Section titled “Type Parameters”| Type Parameter | Default type |
|---|---|
S |
any |
Methods
Section titled “Methods”getItem()
Section titled “getItem()”getItem(
key):Promise<string|S|null>
Defined in: src/core/types.ts:277
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
key |
string |
Returns
Section titled “Returns”Promise<string | S | null>
removeItem()
Section titled “removeItem()”removeItem(
key):Promise<void>
Defined in: src/core/types.ts:279
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
key |
string |
Returns
Section titled “Returns”Promise<void>
setItem()
Section titled “setItem()”setItem(
key,value):Promise<void>
Defined in: src/core/types.ts:278
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
key |
string |
value |
string | S |
Returns
Section titled “Returns”Promise<void>
IBridgeOptions
Section titled “IBridgeOptions”Defined in: src/core/types.ts:202
Bidirectional state-DOM synchronization options for withBridge.
Each withBridge() call appends one IBridgeOptions entry to
blueprint.bridges and registers a mount hook that activates it. Multiple
entries accumulate; later entries do not replace earlier ones.
Example
Section titled “Example”import { withBridge } from '@sandlada/document-context'
const blueprint = pipe( createContext({ query: '' }), withBridge({ properties: { query: 'value' }, events: ['input'], batch: true }))Type Parameters
Section titled “Type Parameters”| Type Parameter | Default type |
|---|---|
S |
any |
Properties
Section titled “Properties”| Property | Modifier | Type | Description |
|---|---|---|---|
activeElementGuard? |
readonly |
boolean |
Declared focus guard flag. Currently reserved: cursor preservation for text inputs is always applied via safeWriteValueWithCursor regardless of this value. |
batch? |
readonly |
boolean |
When not false (default), state-to-DOM writes are coalesced into a single queueMicrotask flush per tick. Set to false for synchronous writes. |
conflict? |
readonly |
"lastWriteWins" | "statePrecedence" | "domPrecedence" |
Declared conflict policy for simultaneous writes. Currently reserved: the runtime applies last-write-wins ordering and does not yet branch on this value. |
events? |
readonly |
readonly string[] |
DOM event names that trigger DOM-to-state sync. Defaults to ['input', 'change']. |
properties |
readonly |
{ readonly [K in string | number | symbol]?: string | IBridgePropertyRule<S> } | Map from state key to DOM path or IBridgePropertyRule. Only listed keys are synchronized; unlisted state stays memory-only. |
IBridgePropertyRule
Section titled “IBridgePropertyRule”Defined in: src/core/types.ts:159
Binding rule mapping one state key to one DOM property path.
The shorthand form is a bare path string (for example 'dataset.count').
The object form adds direction-specific codecs plus the DOM event that
triggers DOM-to-state sync for this binding.
Example
Section titled “Example”import { withBridge, parseNumber } from '@sandlada/document-context'
const blueprint = pipe( createContext({ count: 0, theme: 'light' }), withBridge({ properties: { count: { target: 'dataset.count', parse: parseNumber }, theme: 'aria-theme' } }))Type Parameters
Section titled “Type Parameters”| Type Parameter | Default type |
|---|---|
S |
any |
Properties
Section titled “Properties”IContextBlueprint
Section titled “IContextBlueprint”Defined in: src/core/types.ts:426
Pure, immutable blueprint: the Phase 1 declaration of state shape, service providers, DOM bridges, persistence, and lifecycle hooks.
Blueprints never touch the DOM, perform no I/O, and install no listeners.
Operators (withProvider, withBridge, withStorage, withHook) return a
new blueprint with structural sharing; mount(blueprint)(element) is the
single execution boundary that turns a blueprint into a live ISession.
Example
Section titled “Example”import { createContext, pipe, withProvider } from '@sandlada/document-context'
const blueprint = pipe( createContext({ count: 0 }), withProvider('logger', () => new ConsoleLogger()))Type Parameters
Section titled “Type Parameters”| Type Parameter | Default type |
|---|---|
S extends Record<PropertyKey, any> |
Record<PropertyKey, any> |
Services |
object |
Properties
Section titled “Properties”| Property | Modifier | Type | Description |
|---|---|---|---|
bridges |
readonly |
readonly IBridgeOptions<S>[] |
Accumulated bridge option entries, applied in order at mount time. |
hooks |
readonly |
readonly ILifecycleHookRegistration<S, Services>[] |
Accumulated lifecycle hook registrations. |
initialState |
readonly |
Readonly<S> |
Seed state snapshot. Frozen in development builds. |
providers |
readonly |
ReadonlyMap<string | ServiceToken<any, string>, IServiceRegistration<any>> |
Service registrations keyed by string or ServiceToken. |
storage? |
readonly |
Readonly<IStorageOptions<S>> |
Persistence options when withStorage was applied. |
IInternalSessionState
Section titled “IInternalSessionState”Defined in: src/core/session-internal.ts:25
Mutable runtime internals for one live session, held in a WeakMap keyed by
the opaque ISession handle (never exposed publicly).
Type Parameters
Section titled “Type Parameters”| Type Parameter | Default type |
|---|---|
S extends Record<PropertyKey, any> |
Record<PropertyKey, any> |
Properties
Section titled “Properties”| Property | Type | Description |
|---|---|---|
abortController |
AbortController |
Aborted on dispose(); its signal is surfaced as session.abortSignal. |
cleanups |
() => void | Promise<void>[] |
Mount/plugin/hook cleanups executed LIFO at dispose. |
dirtyQueue |
(state) => S | Partial<S>[] |
Updaters accumulated while suspended, replayed on resuscitation. |
errorSubject |
ReplaySubject<DocumentContextError> |
ReplaySubject(20) collecting non-fatal runtime errors; observed via readErrorStream(). |
inFlightAsyncServices |
Map<string | ServiceToken<any, string>, Promise<any>> |
Coalesced in-flight async factories. |
isDisposed |
boolean |
Permanent terminal flag. |
isSuspended |
boolean |
Parked-in-TTL flag for keyed sessions. |
scopedServices |
Map<string | ServiceToken<any, string>, any> |
Cache for 'scoped' lifecycle instances. |
sessionKey? |
string |
Value of data-context-key, if present. |
stateSubject |
BehaviorSubject<S> |
BehaviorSubject holding the current immutable state; seeded from blueprint.initialState (post-hydration). |
target |
HTMLElement |
Current host element (repointed on resuscitation). |
ILifecycleHookRegistration
Section titled “ILifecycleHookRegistration”Defined in: src/core/types.ts:391
Stored lifecycle hook registration inside a blueprint.
Type Parameters
Section titled “Type Parameters”| Type Parameter | Default type |
|---|---|
S extends Record<PropertyKey, any> |
Record<PropertyKey, any> |
Services |
object |
Properties
Section titled “Properties”| Property | Modifier | Type | Description |
|---|---|---|---|
event |
readonly |
keyof ILifecycleHooks<Record<PropertyKey, any>, { }> |
Event channel the handler subscribes to. |
handler |
readonly |
Function |
Untyped handler reference; invocation is typed by the mount / dispose / observer pipelines according to event. |
ILifecycleHooks
Section titled “ILifecycleHooks”Defined in: src/core/types.ts:367
Lifecycle hook callbacks keyed by event name.
Register entries with withHook(event, handler); all five channels are
optional and may hold at most one handler shape each per call (multiple
withHook calls for the same event accumulate in FIFO mount order).
Example
Section titled “Example”import { withHook } from '@sandlada/document-context'
const blueprint = pipe( base, withHook('mount', (session) => { console.log('mounted on', session.target) return () => console.log('cleaned up') }), withHook('dispose', (session) => console.log('disposed')))Type Parameters
Section titled “Type Parameters”| Type Parameter | Default type |
|---|---|
S extends Record<PropertyKey, any> |
Record<PropertyKey, any> |
Services |
object |
Properties
Section titled “Properties”| Property | Modifier | Type | Description |
|---|---|---|---|
adopt? |
readonly |
(session, newDocument) => void |
Runs when a session migrates to a new Document (for example an iframe) via adoptSessionToDocument. Receives (session, newDocument). |
dispose? |
readonly |
(session) => void | Promise<void> |
Runs during dispose() in LIFO order, before mount cleanups. Fire-and-forget async is tolerated; rejections are routed to the session error stream. |
mount? |
readonly |
(session) => HookCleanup | Promise<HookCleanup> |
Runs after the session is cached and global mount plugins have executed. May return a cleanup pushed onto the dispose stack. |
resuscitate? |
readonly |
(session, newTarget) => void |
Runs when a suspended keyed session is reattached to a new host via resuscitateKeyedSession. Receives (session, newTarget). |
suspend? |
readonly |
(session) => void |
Runs when a keyed (data-context-key) host disconnects and enters the 50ms suspended window instead of being disposed immediately. |
InvalidStorageDataErrorOptions
Section titled “InvalidStorageDataErrorOptions”Defined in: src/core/errors.ts:657
Options bag for InvalidStorageDataError.
Properties
Section titled “Properties”IServiceRegistration
Section titled “IServiceRegistration”Defined in: src/core/types.ts:112
Immutable registration record for one service provider.
This is a pure data structure held inside IContextBlueprint.providers.
It is created by withProvider / withAsyncProvider and consumed by the
inject / injectAsync resolution pipeline. Never constructed by hand in
application code.
Type Parameters
Section titled “Type Parameters”| Type Parameter | Default type |
|---|---|
T |
unknown |
Properties
Section titled “Properties”| Property | Modifier | Type | Description |
|---|---|---|---|
factory |
readonly |
(session) => T | Promise<T> |
Instantiation function invoked lazily on first injection (or eagerly for async singletons under mountAsync). Receives the owning session so the factory can itself call inject / select. |
isAsync |
readonly |
boolean |
true when the factory returns a Promise. Async services reject synchronous inject() with AsyncServiceNotReadyError and must be resolved via injectAsync(). |
lifecycle |
readonly |
ServiceLifecycle |
Caching policy; see ServiceLifecycle. |
multi? |
readonly |
boolean |
Reserved multi-provider flag. When true, the registration participates in injectAll() accumulation instead of first-match short-circuiting. |
token |
readonly |
string | ServiceToken<T, string> |
Lookup key: either a plain string or a branded ServiceToken. String tokens collide by text; token objects collide by object identity. |
ISession
Section titled “ISession”Defined in: src/core/types.ts:469
Opaque handle to a mounted, live runtime session (Phase 2).
Obtained only from mount(blueprint)(element) or mountAsync. Carries the
host element, the originating blueprint, a disposal flag, and an
AbortSignal bound to the session lifetime. State itself is never stored on
this object; it lives in the internal BehaviorSubject keyed by WeakMap.
Example
Section titled “Example”import { mount, select, update } from '@sandlada/document-context'
const session = mount(blueprint)(document.getElementById('counter')!)const getCount = select((s) => s.count)console.log(getCount(session))
// ExplicitResourceManagement (optional){ using s = mount(blueprint)(document.getElementById('x')!)}Type Parameters
Section titled “Type Parameters”| Type Parameter | Default type |
|---|---|
S extends Record<PropertyKey, any> |
Record<PropertyKey, any> |
Services |
object |
Properties
Section titled “Properties”| Property | Modifier | Type | Description |
|---|---|---|---|
[asyncDispose] |
readonly |
() => Promise<void> |
- |
[dispose] |
readonly |
() => void |
- |
[SessionBrand] |
readonly |
true |
- |
abortSignal |
readonly |
AbortSignal |
Aborts when the session is disposed; pass to fetch or async providers for cooperative cancellation. |
blueprint |
readonly |
IContextBlueprint<S, Services> |
Originating immutable blueprint. |
isDisposed |
readonly |
boolean |
true after dispose(); subsequent update() calls silently no-op and return false. |
target |
readonly |
HTMLElement |
Host element the blueprint was mounted on. |
IStorageAdapter
Section titled “IStorageAdapter”Defined in: src/core/types.ts:254
Synchronous key-value persistence adapter.
Any object with the getItem / setItem / removeItem shape qualifies, so the
built-in localStorage / sessionStorage adapters, a custom in-memory map,
or an IndexedDB-backed synchronous facade can be supplied to withStorage.
Example
Section titled “Example”const memory = new Map<string, string>()const adapter = { getItem: (key: string) => memory.get(key) ?? null, setItem: (key: string, value: string) => { memory.set(key, String(value)) }, removeItem: (key: string) => { memory.delete(key) }}Type Parameters
Section titled “Type Parameters”| Type Parameter | Default type |
|---|---|
S |
any |
Methods
Section titled “Methods”getItem()
Section titled “getItem()”getItem(
key):string|S|null
Defined in: src/core/types.ts:255
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
key |
string |
Returns
Section titled “Returns”string | S | null
removeItem()
Section titled “removeItem()”removeItem(
key):void
Defined in: src/core/types.ts:257
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
key |
string |
Returns
Section titled “Returns”void
setItem()
Section titled “setItem()”setItem(
key,value):void
Defined in: src/core/types.ts:256
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
key |
string |
value |
string | S |
Returns
Section titled “Returns”void
IStorageOptions
Section titled “IStorageOptions”Defined in: src/core/types.ts:315
State persistence and rehydration options for withStorage.
Example
Section titled “Example”import { withStorage } from '@sandlada/document-context'
const blueprint = pipe( createContext({ count: 0 }), withStorage({ adapter: 'localStorage', key: 'counter-app', version: 2, migrate: (old, oldVersion) => ({ count: Number((old as any).count) || 0 }) }))Type Parameters
Section titled “Type Parameters”| Type Parameter | Default type |
|---|---|
S |
any |
Properties
Section titled “Properties”| Property | Modifier | Type | Description |
|---|---|---|---|
adapter |
readonly |
IStorageAdapter<S> | IAsyncStorageAdapter<S> | "localStorage" | "sessionStorage" |
'localStorage', 'sessionStorage', or a custom sync/async adapter object. String shorthands resolve to Web Storage with an in-memory fallback outside the browser. |
crossTabSync? |
readonly |
boolean |
When not false (default enabled), state changes broadcast via BroadcastChannel and incoming storage events are applied. |
hydrationStrategy? |
readonly |
HydrationStrategy |
Initial merge precedence; see HydrationStrategy. Defaults to 'storageFirst'. |
key |
readonly |
string |
Storage key (and BroadcastChannel / Web Locks namespace suffix). Unique per persisted blueprint. |
migrate? |
readonly |
(persistedState, oldVersion) => Partial<S> |
Migration invoked when the persisted __v is older than version. Receives (persistedState, oldVersion) and returns the partial state to hydrate. |
version? |
readonly |
number |
Schema version stamped into the {"__v", "data"} envelope. Defaults to 1. |
IWithAsyncProviderOptions
Section titled “IWithAsyncProviderOptions”Defined in: src/core/async-provider.ts:19
Options for withAsyncProvider.
Properties
Section titled “Properties”| Property | Modifier | Type | Description |
|---|---|---|---|
lifecycle? |
readonly |
ServiceLifecycle |
Caching policy, defaulting to 'scoped'. Resolved async values are cached the same way as sync ones ('singleton' lands in the global registry, 'scoped' on the session, 'transient' is never cached). |
multi? |
readonly |
boolean |
When true, the registration participates in injectAllAsync() accumulation. Defaults to false. |
IWithProviderOptions
Section titled “IWithProviderOptions”Defined in: src/core/providers.ts:19
Options for withProvider / withAsyncProvider.
Properties
Section titled “Properties”| Property | Modifier | Type | Description |
|---|---|---|---|
lifecycle? |
readonly |
ServiceLifecycle |
Caching policy, defaulting to 'scoped'. See ServiceLifecycle: 'singleton' shares one instance page-wide, 'scoped' caches one instance per session, 'transient' creates a fresh instance per injection. |
multi? |
readonly |
boolean |
When true, the registration participates in injectAll() accumulation. Defaults to false (first-match wins). |
PropertySyncSecurityErrorOptions
Section titled “PropertySyncSecurityErrorOptions”Defined in: src/core/errors.ts:472
Options bag for PropertySyncSecurityError.
Properties
Section titled “Properties”ServiceRegistry
Section titled “ServiceRegistry”Defined in: src/core/types.ts:502
Global service-type registry for string tokens.
Augment this interface once per application (declaration merging) so that
inject('auth-service') returns a typed value instead of unknown.
Example
Section titled “Example”declare module '@sandlada/document-context' { interface ServiceRegistry { 'auth-service': AuthService 'theme-mode': 'light' | 'dark' }}
import { inject } from '@sandlada/document-context'
const auth = inject('auth-service')(document.getElementById('login')!)ServiceToken
Section titled “ServiceToken”Defined in: src/core/types.ts:36
Branded, type-safe dependency-injection token.
A ServiceToken carries its value type T and its lookup name Name at the
type level, so inject(token) can return T without a cast. Prefer tokens
over raw strings when a service is shared across bundles or teams, because
two strings with the same text collide while two tokens with different
generic arguments do not type-check as interchangeable.
Tokens are created once with createToken and then used as the token
argument of withProvider, withAsyncProvider, inject, and injectAsync.
Example
Section titled “Example”import { createToken, withProvider, mount, inject } from '@sandlada/document-context'import type { ServiceToken } from '@sandlada/document-context'
const LoggerToken: ServiceToken<ConsoleLogger, 'logger'> = createToken<ConsoleLogger>('logger')const blueprint = pipe( createContext({ count: 0 }), withProvider(LoggerToken, () => new ConsoleLogger()))const session = mount(blueprint)(document.getElementById('app')!)const logger = inject(LoggerToken)(session)Type Parameters
Section titled “Type Parameters”| Type Parameter | Default type |
|---|---|
T |
- |
Name extends string |
string |
Properties
Section titled “Properties”UnconnectedNodeErrorOptions
Section titled “UnconnectedNodeErrorOptions”Defined in: src/core/errors.ts:383
Options bag for UnconnectedNodeError.
Properties
Section titled “Properties”UnknownServiceErrorOptions
Section titled “UnknownServiceErrorOptions”Defined in: src/core/errors.ts:154
Options bag for UnknownServiceError.
Properties
Section titled “Properties”Type Aliases
Section titled “Type Aliases”BlueprintOperator
Section titled “BlueprintOperator”BlueprintOperator<
S,InServices,OutServices> = (blueprint) =>IContextBlueprint<S,OutServices>
Defined in: src/core/pipe.ts:19
Operator that transforms one blueprint into another while preserving the
state shape S and threading the service-type accumulator
(InServices to OutServices).
Every with* operator returns this shape, so pipe can chain them with
full type inference. Operators must stay pure: clone-and-return, never
mutate the input blueprint.
Type Parameters
Section titled “Type Parameters”| Type Parameter |
|---|
S extends Record<PropertyKey, any> |
InServices |
OutServices |
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
blueprint |
IContextBlueprint<S, InServices> |
Returns
Section titled “Returns”IContextBlueprint<S, OutServices>
Example
Section titled “Example”import { withProvider } from '@sandlada/document-context'
const addLogger = withProvider('logger', () => new ConsoleLogger())HookCleanup
Section titled “HookCleanup”HookCleanup =
void| (() =>void)
Defined in: src/core/types.ts:331
Cleanup contract for lifecycle hooks.
A hook returns either nothing or a zero-argument cleanup invoked during
dispose() in LIFO order. Async cleanups are awaited only opportunistically;
prefer synchronous cleanup.
HydrationStrategy
Section titled “HydrationStrategy”HydrationStrategy =
"storageFirst"|"domFirst"|"blueprintFirst"|"merge"
Defined in: src/core/types.ts:235
Precedence policy for the initial hydration merge in resolveHydratedState.
The three sources are always blueprint initialState, live DOM properties
(extracted via bridge paths), and persisted storage data. The strategy only
controls spread order, later sources winning:
'storageFirst'(default) —{...blueprint, ...dom, ...storage}.'domFirst'—{...blueprint, ...storage, ...dom}. Note: the current implementation treats'merge'identically to'domFirst'.'blueprintFirst'—{...dom, ...storage, ...blueprint}.'merge'— currently an alias of'domFirst'.
Example
Section titled “Example”import { withStorage } from '@sandlada/document-context'
const blueprint = pipe( createContext({ count: 0 }), withStorage({ adapter: 'localStorage', key: 'counter', hydrationStrategy: 'domFirst' }))LifecycleEventName
Section titled “LifecycleEventName”LifecycleEventName = keyof
ILifecycleHooks
Defined in: src/core/types.ts:382
Valid lifecycle event names. Equal to keyof ILifecycleHooks:
'mount' | 'dispose' | 'suspend' | 'resuscitate' | 'adopt'.
MountPlugin
Section titled “MountPlugin”MountPlugin = (
session,internal) =>void| (() =>void) |Promise<void| (() =>void)>
Defined in: src/core/mount.ts:25
Runtime plugin invoked once per mount() call, after the session handle is
cached but before blueprint mount hooks run.
A plugin may return a zero-argument cleanup (synchronous or promise-like)
that is pushed onto the session dispose stack and executed LIFO at
dispose() time. The built-in bridge, storage, and DOM-responder plugins
are all registered through this mechanism.
Parameters
Section titled “Parameters”| Parameter | Type | Description |
|---|---|---|
session |
ISession<any, any> |
Freshly created live session. |
internal |
IInternalSessionState<any> |
Internal mutable state (subjects, caches, flags). |
Returns
Section titled “Returns”void | (() => void) | Promise<void | (() => void)>
An optional cleanup, or a promise of one.
ServiceLifecycle
Section titled “ServiceLifecycle”ServiceLifecycle =
"singleton"|"scoped"|"transient"
Defined in: src/core/types.ts:88
Lifetime policy for a registered service.
'singleton'— one instance per page, stored in the global singleton registry and shared across every session and DOM scope.'scoped'— one instance per mounted session, cached on the session internals and shared by every injection within that session scope.'transient'— a fresh instance on everyinject()call; never cached.
Example
Section titled “Example”import { withProvider } from '@sandlada/document-context'
const blueprint = pipe( base, withProvider('config', () => loadConfig(), { lifecycle: 'singleton' }), withProvider('form-state', () => createFormState(), { lifecycle: 'scoped' }), withProvider('id', () => crypto.randomUUID(), { lifecycle: 'transient' }))Functions
Section titled “Functions”createContext()
Section titled “createContext()”Creates a pure, immutable blueprint seed for a context container (Phase 1).
This is the entry point of the two-phase architecture. It performs zero DOM
access, zero I/O, and installs zero listeners: it only snapshots
initialState and returns an empty-provider blueprint that later operators
(withProvider, withBridge, withStorage, withHook) extend via pipe.
The single execution boundary is mount(blueprint)(element).
In development (NODE_ENV !== 'production') the snapshot is shallow-frozen
with Object.freeze({ ...initialState }) so accidental mutation throws
early; in production the reference is kept as-is for speed.
export function createContext<S extends Record<PropertyKey, any>>( initialState: S): IContextBlueprint<S, {}>;Defined in: src/core/context.ts
Example
Section titled “Example”import { createContext, pipe, withProvider, mount } from '@sandlada/document-context'
const blueprint = pipe( createContext({ count: 0, theme: 'light' as 'light' | 'dark' }), withProvider('logger', () => new ConsoleLogger()))const session = mount(blueprint)(document.getElementById('app')!)createInternalSessionState()
Section titled “createInternalSessionState()”Allocates fresh internals for a mount: seeds the state subject from the
blueprint, creates the error replay subject, abort controller, and empty
caches, and captures the data-context-key session key when present.
export function createInternalSessionState<S extends Record<PropertyKey, any>>( target: HTMLElement, blueprint: IContextBlueprint<S, any>): IInternalSessionState<S>;Defined in: src/core/session-internal.ts
createToken()
Section titled “createToken()”Creates a branded ServiceToken for type-safe dependency injection.
This is a pure factory: it allocates a fresh token object, performs no I/O,
and registers nothing. Each call returns a distinct object identity, so two
tokens created with the same name string are still different runtime keys.
Create tokens once at module scope and reuse them.
export function createToken<T, Name extends string = string>(name: Name): ServiceToken<T, Name>;Defined in: src/core/types.ts
Example
Section titled “Example”import { createToken } from '@sandlada/document-context'
const AuthToken = createToken<AuthService>('auth-service')const ThemeToken = createToken<'light' | 'dark'>('theme-mode')dispose()
Section titled “dispose()”Tears down a mounted session and releases every resource it owns.
Idempotent: disposing twice (or disposing a session with no internals) is a
safe no-op. The pipeline is: mark isDisposed and drop the element mapping
→ abortController.abort() (cancelling session.abortSignal consumers) →
run blueprint dispose hooks LIFO → run mount/plugin cleanups LIFO →
dispatch a bubbling, composed context-dispose CustomEvent with
detail: { sessionKey }. Synchronous throws and async rejections inside
hooks or cleanups are caught and routed to the session error stream as
DISPOSE_HOOK_ERROR / MOUNT_CLEANUP_ERROR instead of propagating.
After disposal, update() returns false, subscribe() returns an empty
unsubscribe, and session.isDisposed stays true permanently.
export function dispose<S extends Record<PropertyKey, any>, Services>( session: ISession<S, Services>): void;Defined in: src/core/dispose.ts
Example
Section titled “Example”import { dispose, update } from '@sandlada/document-context'
dispose(session)console.log(session.isDisposed)update({ count: 1 })(session) // false, silent no-opfindKeyedSession()
Section titled “findKeyedSession()”Looks up the live session parked under a data-context-key.
Returns the registered session even while it is suspended (that is the
resuscitation window). Callers must still check session.isDisposed,
because expired or explicitly disposed sessions stay mapped until the TTL
timer or unregisterKeyedSession() clears them.
export function findKeyedSession<S extends Record<PropertyKey, any> = Record<PropertyKey, any>>( key: string): ISession<S, any> | undefined;Defined in: src/core/resuscitation.ts
Example
Section titled “Example”import { findKeyedSession } from '@sandlada/document-context'
const existing = findKeyedSession('cart-panel')if (existing && !existing.isDisposed) { console.log('reusing suspended session')}getElementSession()
Section titled “getElementSession()”Returns the live session cached for a host element, if any.
export function getElementSession<S extends Record<PropertyKey, any> = Record<PropertyKey, any>>( element: HTMLElement): ISession<S, any> | undefined;Defined in: src/core/session-internal.ts
getInternalSession()
Section titled “getInternalSession()”Returns the internals for a session handle, or undefined when the session
was never mounted through this runtime (or its entry was collected).
export function getInternalSession<S extends Record<PropertyKey, any> = Record<PropertyKey, any>>( session: ISession<S, any>): IInternalSessionState<S> | undefined;Defined in: src/core/session-internal.ts
injectDecorator()
Section titled “injectDecorator()”Property / accessor decorator that lazily resolves a service on each access.
Supports two decorator protocols: legacy TypeScript experimental decorators
((target, propertyKey, descriptor?)) and TC39 Stage 3 decorators
(kind === 'field' | 'getter' | 'method' | 'accessor'). In both cases the
installed getter resolves inject(token)(host) per access, where host is
this.element ?? this.target ?? this, so host-backed components (custom
elements, controllers) resolve against their own DOM scope. Resolution is
lazy and uncached: every property read re-runs injection.
This is the class-body counterpart of function-style dom/inject, which
takes an explicit (elementOrSession) target instead of this.
export function injectDecorator<K extends string | ServiceToken<any>>(token: K);Defined in: src/core/decorators.ts
Example
Section titled “Example”import { injectDecorator } from '@sandlada/document-context'
class MyPanel { element!: HTMLElement @injectDecorator('logger') declare logger: ConsoleLogger}isDev()
Section titled “isDev()”Reports whether the current build is a development build.
Returns false only when globalThis.process.env.NODE_ENV is exactly
'production'; every other environment (including browsers without
process) counts as development and enables freezing and extra checks.
Never throws; sandbox failures also yield false.
export function isDev(): boolean;Defined in: src/core/session-internal.ts
mount()
Section titled “mount()”Mounts a pure blueprint onto a physical host element (Phase 2 execution boundary), activating the runtime session.
Idempotent per element: mounting the same HTMLElement twice returns the
existing non-disposed session instead of creating a second one. On a fresh
mount the pipeline is: create internal state (BehaviorSubject seeded from
blueprint.initialState) → cache session in both WeakMaps → run global
mount plugins in order → run blueprint mount hooks FIFO (promise cleanups
are attached when they settle) → dispatch a bubbling, composed
context-mount CustomEvent with detail: { session }.
Plugin and hook throws never propagate; they are routed to the session
error stream as MOUNT_PLUGIN_ERROR / MOUNT_HOOK_ERROR.
export function mount<S extends Record<PropertyKey, any>, Services>( blueprint: IContextBlueprint<S, Services>): (element: HTMLElement) => ISession<S, Services>;Defined in: src/core/mount.ts
Example
Section titled “Example”import { createContext, mount, select } from '@sandlada/document-context'
const blueprint = createContext({ count: 0 })const mountCounter = mount(blueprint)const session = mountCounter(document.getElementById('counter')!)const getCount = select((s: { count: number }) => s.count)console.log(getCount(session))mountAsync()
Section titled “mountAsync()”Asynchronous mount boundary: mounts synchronously, then yields one microtask before resolving.
This is intentionally thin: it delegates to mount(blueprint)(element) and
awaits Promise.resolve(), giving pending mount-hook microtasks and async
storage hydration callbacks a chance to run. It does not itself await async
providers to completion; resolve those explicitly with injectAsync().
Mounting the same element twice is idempotent and returns the cached
session, same as mount.
export function mountAsync<S extends Record<PropertyKey, any>, Services>( blueprint: IContextBlueprint<S, Services>): (element: HTMLElement) => Promise<ISession<S, Services>>;Defined in: src/core/mount-async.ts
Example
Section titled “Example”import { mountAsync, injectAsync } from '@sandlada/document-context'
const session = await mountAsync(blueprint)(document.getElementById('app')!)const config = await injectAsync('remote-config')(session)pipe()
Section titled “pipe()”Composes blueprint operators left-to-right into a single immutable blueprint.
Pure Phase 1 composition: no DOM access, no I/O, no listeners. Each operator
receives the blueprint returned by the previous one, so service types
accumulate (S0 through S10) with full inference. Calling pipe(source)
with no operators returns source unchanged.
Overloads cover chains of up to ten operators with precise typing; longer chains fall through to the variadic implementation signature.
export function pipe<S extends Record<PropertyKey, any>, S0>( source: IContextBlueprint<S, S0>): IContextBlueprint<S, S0>export function pipe<S extends Record<PropertyKey, any>, S0, S1>( source: IContextBlueprint<S, S0>, op1: BlueprintOperator<S, S0, S1>): IContextBlueprint<S, S1>export function pipe<S extends Record<PropertyKey, any>, S0, S1, S2>( source: IContextBlueprint<S, S0>, op1: BlueprintOperator<S, S0, S1>, op2: BlueprintOperator<S, S1, S2>): IContextBlueprint<S, S2>export function pipe<S extends Record<PropertyKey, any>, S0, S1, S2, S3>( source: IContextBlueprint<S, S0>, op1: BlueprintOperator<S, S0, S1>, op2: BlueprintOperator<S, S1, S2>, op3: BlueprintOperator<S, S2, S3>): IContextBlueprint<S, S3>export function pipe<S extends Record<PropertyKey, any>, S0, S1, S2, S3, S4>( source: IContextBlueprint<S, S0>, op1: BlueprintOperator<S, S0, S1>, op2: BlueprintOperator<S, S1, S2>, op3: BlueprintOperator<S, S2, S3>, op4: BlueprintOperator<S, S3, S4>): IContextBlueprint<S, S4>export function pipe<S extends Record<PropertyKey, any>, S0, S1, S2, S3, S4, S5>( source: IContextBlueprint<S, S0>, op1: BlueprintOperator<S, S0, S1>, op2: BlueprintOperator<S, S1, S2>, op3: BlueprintOperator<S, S2, S3>, op4: BlueprintOperator<S, S3, S4>, op5: BlueprintOperator<S, S4, S5>): IContextBlueprint<S, S5>export function pipe<S extends Record<PropertyKey, any>, S0, S1, S2, S3, S4, S5, S6>( source: IContextBlueprint<S, S0>, op1: BlueprintOperator<S, S0, S1>, op2: BlueprintOperator<S, S1, S2>, op3: BlueprintOperator<S, S2, S3>, op4: BlueprintOperator<S, S3, S4>, op5: BlueprintOperator<S, S4, S5>, op6: BlueprintOperator<S, S5, S6>): IContextBlueprint<S, S6>export function pipe<S extends Record<PropertyKey, any>, S0, S1, S2, S3, S4, S5, S6, S7>( source: IContextBlueprint<S, S0>, op1: BlueprintOperator<S, S0, S1>, op2: BlueprintOperator<S, S1, S2>, op3: BlueprintOperator<S, S2, S3>, op4: BlueprintOperator<S, S3, S4>, op5: BlueprintOperator<S, S4, S5>, op6: BlueprintOperator<S, S5, S6>, op7: BlueprintOperator<S, S6, S7>): IContextBlueprint<S, S7>export function pipe<S extends Record<PropertyKey, any>, S0, S1, S2, S3, S4, S5, S6, S7, S8>( source: IContextBlueprint<S, S0>, op1: BlueprintOperator<S, S0, S1>, op2: BlueprintOperator<S, S1, S2>, op3: BlueprintOperator<S, S2, S3>, op4: BlueprintOperator<S, S3, S4>, op5: BlueprintOperator<S, S4, S5>, op6: BlueprintOperator<S, S5, S6>, op7: BlueprintOperator<S, S6, S7>, op8: BlueprintOperator<S, S7, S8>): IContextBlueprint<S, S8>export function pipe<S extends Record<PropertyKey, any>, S0, S1, S2, S3, S4, S5, S6, S7, S8, S9>( source: IContextBlueprint<S, S0>, op1: BlueprintOperator<S, S0, S1>, op2: BlueprintOperator<S, S1, S2>, op3: BlueprintOperator<S, S2, S3>, op4: BlueprintOperator<S, S3, S4>, op5: BlueprintOperator<S, S4, S5>, op6: BlueprintOperator<S, S5, S6>, op7: BlueprintOperator<S, S6, S7>, op8: BlueprintOperator<S, S7, S8>, op9: BlueprintOperator<S, S8, S9>): IContextBlueprint<S, S9>export function pipe<S extends Record<PropertyKey, any>, S0, S1, S2, S3, S4, S5, S6, S7, S8, S9, S10>( source: IContextBlueprint<S, S0>, op1: BlueprintOperator<S, S0, S1>, op2: BlueprintOperator<S, S1, S2>, op3: BlueprintOperator<S, S2, S3>, op4: BlueprintOperator<S, S3, S4>, op5: BlueprintOperator<S, S4, S5>, op6: BlueprintOperator<S, S5, S6>, op7: BlueprintOperator<S, S6, S7>, op8: BlueprintOperator<S, S7, S8>, op9: BlueprintOperator<S, S8, S9>, op10: BlueprintOperator<S, S9, S10>): IContextBlueprint<S, S10>Defined in: src/core/pipe.ts
source
Seed blueprint, typically from createContext().
operators
BlueprintOperator functions applied in order
(op1, then op2, and so on).
Example
Section titled “Example”import { createContext, pipe, withProvider, withBridge, withStorage } from '@sandlada/document-context'
const blueprint = pipe( createContext({ count: 0 }), withProvider('logger', () => new ConsoleLogger()), withBridge({ properties: { count: 'dataset.count' } }), withStorage({ adapter: 'localStorage', key: 'counter' }))provide()
Section titled “provide()”Class decorator that tags a class as the provider for a token.
Attaches __serviceToken / __serviceOptions metadata to the constructor
without registering anything: pair it with a manual withProvider(token, (s) => new Target(s)) (or provideClass) that reads the metadata, or with
a framework integration that scans decorated classes. Does not instantiate
the class by itself.
export function provide<K extends string | ServiceToken<any>>( token: K, options?: { lifecycle?: ServiceLifecycle; multi?: boolean });Defined in: src/core/decorators.ts
Example
Section titled “Example”import { provide } from '@sandlada/document-context'
@provide('logger', { lifecycle: 'singleton' })class Logger {}provideClass()
Section titled “provideClass()”Pure Phase 1 operator that registers a class constructor as a service.
Thin wrapper over withProvider(token, (session) => new Ctor(session)).
Prefer this over hand-written factories when the service is naturally a
class. For decorator style (@provide on the class plus lazy
@inject-decorated properties), see provide and
injectDecorator.
Note: this module’s decorator alias inject (re-exported as
injectDecorator) resolves services on class instances via
this.element ?? this.target, while dom/inject’s function-style
inject(token)(elementOrSession) resolves from an explicit target. They
share a name but take different targets; the decorator form is for class
bodies, the function form for everywhere else.
export function provideClass< K extends string | ServiceToken<any>, T, S extends Record<PropertyKey, any>, ExistingServices>( token: K, ClassConstructor: Constructor<T>, options?: { lifecycle?: ServiceLifecycle; multi?: boolean }): (blueprint: IContextBlueprint<S, ExistingServices>) => IContextBlueprint<S, any>;Defined in: src/core/decorators.ts
Example
Section titled “Example”import { createContext, pipe, provideClass, mount, inject } from '@sandlada/document-context'
class Logger { constructor(private session: unknown) {} log(msg: string) { console.log(msg) }}const blueprint = pipe( createContext({ count: 0 }), provideClass('logger', Logger, { lifecycle: 'singleton' }))const session = mount(blueprint)(document.getElementById('app')!)inject('logger')(session)readErrorStream()
Section titled “readErrorStream()”Returns the non-fatal runtime error stream for a session.
The stream is a ReplaySubject<DocumentContextError>(20) held on session
internals, so late subscribers replay up to the last 20 errors. Sources
include mount plugin/hook failures, dispose cleanup failures, storage parse
failures, and bridge errors. Fatal DI throws (UnknownServiceError,
CircularDependencyError) still throw synchronously at the call site and
are not duplicated here.
Exposes only the Observable interface; the underlying subject stays
encapsulated and RxJS never leaks into the public API beyond this type.
export function readErrorStream<S extends Record<PropertyKey, any>, Services>( session: ISession<S, Services>): Observable<DocumentContextError>;Defined in: src/core/dispose.ts
Example
Section titled “Example”import { readErrorStream } from '@sandlada/document-context'
const sub = readErrorStream(session).subscribe((err) => { console.error(`[${err.code}]`, err.message, err.resolutionGuide)})registerKeyedSession()
Section titled “registerKeyedSession()”Registers a live session under a data-context-key for suspend/resuscitate.
Keyed sessions survive host detachment: instead of immediate disposal, the
observer parks them in the suspended state for a 50ms TTL during which
resuscitateKeyedSession() can reattach them to a new host with state
intact. Overwrites any previous session under the same key.
export function registerKeyedSession( key: string, session: ISession<any, any>): void;Defined in: src/core/resuscitation.ts
Example
Section titled “Example”import { registerKeyedSession } from '@sandlada/document-context'
registerKeyedSession('cart-panel', session)registerMountPlugin()
Section titled “registerMountPlugin()”Registers a global runtime plugin executed during every mount().
Plugins run in registration order on each mount. Synchronous throws are
caught and routed to the session error stream as MOUNT_PLUGIN_ERROR, so
one failing plugin never prevents the session from mounting.
export function registerMountPlugin(plugin: MountPlugin): () => void;Defined in: src/core/mount.ts
Example
Section titled “Example”import { registerMountPlugin } from '@sandlada/document-context'
const unregister = registerMountPlugin((session) => { console.log('mounted on', session.target) return () => console.log('disposed')})unregister()removeElementSession()
Section titled “removeElementSession()”Drops the element-to-session mapping (called once per dispose()).
The session handle itself stays usable for isDisposed checks; only the
reverse lookup is removed.
export function removeElementSession(element: HTMLElement): void;Defined in: src/core/session-internal.ts
resuscitateKeyedSession()
Section titled “resuscitateKeyedSession()”Reattaches a suspended keyed session to a new host element (resuscitation).
Clears the suspended flag, repoints internal target at newTarget,
re-caches the session under the new element, replays the queued dirty
updates accumulated via update() during suspension (in order, then emits
once), runs blueprint resuscitate hooks as (session, newTarget), and
dispatches a bubbling, composed context-resuscitate CustomEvent with
detail: { session, newTarget }. Hook throws are sandboxed.
Returns undefined when no session is registered under key, when the
registered session is disposed, or when its internals are gone.
export function resuscitateKeyedSession<S extends Record<PropertyKey, any> = Record<PropertyKey, any>>( key: string, newTarget: HTMLElement): ISession<S, any> | undefined;Defined in: src/core/resuscitation.ts
Example
Section titled “Example”import { resuscitateKeyedSession } from '@sandlada/document-context'
const replacement = document.querySelector('[data-context-key="cart-panel"]') as HTMLElementconst session = resuscitateKeyedSession('cart-panel', replacement)select()
Section titled “select()”Curried synchronous snapshot reader in Data-Last form select(selector)(session).
Applies the pure selector projection to the current state value. When no
internal session exists (for example a bare blueprint seed), it falls back
to session.blueprint.initialState. In development, object results that are
not already frozen are shallow-frozen before returning, so downstream
mutation throws early instead of corrupting the store.
The selector must stay pure: no DOM access, no I/O, no mutation of state.
export function select<S extends Record<PropertyKey, any>, R>( selector: (state: S) => R): <Services>(session: ISession<S, Services>) => R;Defined in: src/core/select.ts
Example
Section titled “Example”import { select } from '@sandlada/document-context'
const selectCount = select((s: { count: number }) => s.count)const count = selectCount(session)const selectDouble = select((s: { count: number }) => s.count * 2)setElementSession()
Section titled “setElementSession()”Caches a session handle under its host element (called once per mount(),
re-pointed on resuscitation).
export function setElementSession<S extends Record<PropertyKey, any> = Record<PropertyKey, any>>( element: HTMLElement, session: ISession<S, any>): void;Defined in: src/core/session-internal.ts
setInternalSession()
Section titled “setInternalSession()”Associates internals with a session handle (called once per mount()).
export function setInternalSession<S extends Record<PropertyKey, any> = Record<PropertyKey, any>>( session: ISession<S, any>, state: IInternalSessionState<S>): void;Defined in: src/core/session-internal.ts
subscribe()
Section titled “subscribe()”Subscribes a listener to reactive state changes in Data-Last form
subscribe(listener)(session).
Backed by the session BehaviorSubject, so the listener fires immediately
with the current state and again on every subsequent update(), bridge
write, storage hydration, or resuscitation flush. The returned function
unsubscribes exactly that listener; call it during dispose cleanups to
avoid leaks.
Disposed sessions yield a no-op unsubscribe without invoking the listener,
matching the update() silent-no-op contract.
export function subscribe<S extends Record<PropertyKey, any>>( listener: (state: S) => void): <Services>(session: ISession<S, Services>) => () => void;Defined in: src/core/subscribe.ts
Example
Section titled “Example”import { subscribe } from '@sandlada/document-context'
const unsubscribe = subscribe((s: { count: number }) => { console.log('count is', s.count)})(session)unsubscribe()unregisterKeyedSession()
Section titled “unregisterKeyedSession()”Removes the session parked under a data-context-key without disposing it.
Use when a keyed host is permanently retired and its suspended session should no longer be resuscitable. Safe to call for unknown keys (no-op).
export function unregisterKeyedSession(key: string): void;Defined in: src/core/resuscitation.ts
Example
Section titled “Example”import { unregisterKeyedSession } from '@sandlada/document-context'
unregisterKeyedSession('cart-panel')update()
Section titled “update()”Curried immutable state updater in Data-Last form update(updater)(session).
Accepts either a partial object (shallow-merged) or a transition function
(prevState) => partial | full. The next state is always a fresh object
({ ...current, ...partial }, frozen in development) and is emitted through
the session BehaviorSubject, waking subscribers, bridges, and storage.
Disposal and suspension contract: updates on a disposed session (or one
whose internals are gone) silently no-op and return false, so dangling
async closures cannot throw. Updates arriving while the session is suspended
(keyed host detached within its 50ms TTL) are additionally appended to the
dirty queue for replay on resuscitation, while still emitting to the live
subject.
export function update<S extends Record<PropertyKey, any>>( updater: Partial<S> | ((prevState: S) => Partial<S> | S)): <Services>(session: ISession<S, Services>) => boolean;Defined in: src/core/update.ts
Example
Section titled “Example”import { update } from '@sandlada/document-context'
const increment = update<{ count: number }>((s) => ({ count: s.count + 1 }))increment(session)update({ theme: 'dark' })(session)withAsyncProvider()
Section titled “withAsyncProvider()”Pure Phase 1 operator that registers an asynchronous service provider.
Identical to withProvider except the factory returns a Promise<T>.
In-flight promises are coalesced per token and evicted immediately on
rejection, so concurrent injectAsync() callers share one attempt and a
failure self-heals for the next retry. The service type accumulates as
Promise<T>; synchronous inject() against this token throws
AsyncServiceNotReadyError and callers must use injectAsync().
export function withAsyncProvider< K extends string | ServiceToken<any>, T, S extends Record<PropertyKey, any>, ExistingServices>( token: K, asyncFactory: (session: ISession<S, ExistingServices>) => Promise<T>, options?: IWithAsyncProviderOptions): ( blueprint: IContextBlueprint<S, ExistingServices>) => IContextBlueprint< S, ExistingServices & (K extends ServiceToken<infer R> ? Record<K['name'], Promise<R>> : K extends string ? Record<K, Promise<T>> : {})>;Defined in: src/core/async-provider.ts
Example
Section titled “Example”import { createContext, pipe, withAsyncProvider, mountAsync, injectAsync } from '@sandlada/document-context'
const blueprint = pipe( createContext({ count: 0 }), withAsyncProvider('remote-config', async () => fetch('/config.json').then((r) => r.json())))const session = await mountAsync(blueprint)(document.getElementById('app')!)const config = await injectAsync('remote-config')(session)withHook()
Section titled “withHook()”Pure Phase 1 operator that registers a lifecycle hook callback.
Appends { event, handler } to blueprint.hooks with structural sharing.
Multiple calls for the same event accumulate: mount handlers run FIFO,
dispose handlers run LIFO. Valid events are mount, dispose,
suspend, resuscitate, and adopt; the handler signature is checked
against ILifecycleHooks<S, Services>[Event].
export function withHook< Event extends LifecycleEventName, S extends Record<PropertyKey, any>, Services>( event: Event, handler: NonNullable<ILifecycleHooks<S, Services>[Event]>): (blueprint: IContextBlueprint<S, Services>) => IContextBlueprint<S, Services>;Defined in: src/core/hooks.ts
Example
Section titled “Example”import { withHook } from '@sandlada/document-context'
const blueprint = pipe( base, withHook('mount', (session) => { const timer = setInterval(() => console.log('tick'), 1000) return () => clearInterval(timer) }))withProvider()
Section titled “withProvider()”Pure Phase 1 operator that registers a synchronous service provider.
Clones the blueprint with structural sharing and adds (or replaces) the
entry in providers. The factory runs lazily on first inject() and
receives the owning session, so it may itself call inject() / select().
Recursive re-entry of the same token throws CircularDependencyError.
String tokens are typed via the ServiceRegistry augmentation; branded
ServiceToken arguments infer their value type from the token.
export function withProvider< K extends string | ServiceToken<any>, T, S extends Record<PropertyKey, any>, ExistingServices>( token: K, factory: (session: ISession<S, ExistingServices>) => T, options?: IWithProviderOptions): ( blueprint: IContextBlueprint<S, ExistingServices>) => IContextBlueprint< S, ExistingServices & (K extends ServiceToken<infer R> ? Record<K['name'], R> : K extends string ? Record<K, T> : {})>;Defined in: src/core/providers.ts
Example
Section titled “Example”import { createContext, pipe, withProvider, mount, inject } from '@sandlada/document-context'
const blueprint = pipe( createContext({ count: 0 }), withProvider('logger', () => new ConsoleLogger(), { lifecycle: 'singleton' }))const session = mount(blueprint)(document.getElementById('app')!)const logger = inject('logger')(session)