Type of the items.
Type of the items.
Resolves the payload into the items; receives the signal of the read as second argument.
Extensions by key, run in the order of the keys and
exposed under their key; a key set to undefined is skipped.
Protected_Bus used to register handlers and to raise the events.
Protected Readonly_The pipeline: every extension given, in the order of the keys.
Protected Readonly_true from the first read() until the latest one settles: a read
superseded by a newer one does not reset it.
Items of the latest completed read; a superseded read never sets them.
Aborts the running read (its read() rejects with AbortedException
and it raises no event afterwards), removes every handler and disposes
every extension.
Registers a handler for an event.
Name of the event to listen to.
Event to subscribe to.
Callback invoked every time event is raised.
a subscription; dispose it to remove this single handler.
Runs the read cycle and updates items. Rejects with the error of
the reader or of an extension, after raising the error event.
A read() requested while another is running supersedes it: the
superseded read() rejects with the AbortedException of ts-core at
once, raises no error event and leaves items untouched; the new one
runs. A consumer awaiting read() ignores the supersession with
isAbortedException; a consumer that only listens to items and
error has nothing to handle. Note that a read() requested from a
handler raised during the cycle (e.g. the page event of a pagination
going back to a valid page) supersedes the running read as well.
Data source driven only by its extensions: it knows nothing about filters, pagination and so on, it just runs the read cycle described in IDataSourceExtension over its pipeline of extensions: the build phase (
buildPayloadof each extension, in the order of the keys), then the read phase (readItemsof each extension as an onion around the reader, the first key outermost).Extensions by key. The extensions are given as a record (DataSourceExtensionsDefinition) and exposed under the same keys as readonly own properties, set only when given:
"sorting" in sourceisfalsefor a source without sorting. The pipeline runs them in the order of the keys of the record, the order they are written in (JavaScript lists integer-like keys first: name the extensions). The order is yours and it matters: writefilteringbeforepagination, so the count reader receives the filters; in the read phase the first key wraps the others, so it transforms the items last. A key that is already a member of the source (items,read, …) is refused.The class cannot type its members from a generic record, so it exposes no keyed property in its type. Build a source with createDataSource, which returns the IDataSource typed with every key of the record.
Inheritance. The class is exported to be extended, not to be built with
new: a subclass knows its extensions, so it types the keys itself, onedeclare readonlyper key given tosuper.declarematters: it emits nothing, where a plain field declaration would, underuseDefineForClassFields(the default from theES2022target on), redefine the property toundefinedaftersuperhas set it. The compiler does not check the declarations against the record, the subclass keeps them in line. A subclass reaches the pipeline (_extensions), the reader (_reader) and the_eventBus; a method or an accessor it adds is refused as a key like the members of the class.The latest read wins. The read cycle runs in one
AbortableDelegateof ts-core: aread()requested while another is running aborts it, so the supersededread()rejects withAbortedExceptionat once, its signal is aborted (the reader and the hooks receive it, e.g. forfetch) and the cycle stops at the nextawaitwithout touchingitemsnor raisingitemsorerror: the remainingbuildPayloadhooks are not invoked, and every layer of the read phase,nextincluded, rejects withAbortedExceptioninstead of running.itemsand theitemsevent therefore always come from the latest read, whatever the order the readers resolve in, and isReading staystrueuntil the latest read settles.dispose()aborts the running read the same way.Example
Example
Example