@tstdl/base 0.93.138 → 0.93.140
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +166 -0
- package/ai/genkit/multi-region.plugin.js +5 -3
- package/ai/genkit/tests/multi-region.test.d.ts +1 -0
- package/ai/genkit/tests/multi-region.test.js +5 -2
- package/ai/parser/parser.js +2 -2
- package/ai/prompts/build.js +1 -0
- package/ai/prompts/instructions-formatter.d.ts +15 -2
- package/ai/prompts/instructions-formatter.js +36 -31
- package/ai/prompts/prompt-builder.js +5 -5
- package/ai/prompts/steering.d.ts +3 -2
- package/ai/prompts/steering.js +3 -1
- package/ai/tests/instructions-formatter.test.js +1 -0
- package/api/README.md +403 -0
- package/api/client/client.js +7 -13
- package/api/client/tests/api-client.test.js +10 -10
- package/api/default-error-handlers.js +1 -1
- package/api/response.d.ts +2 -2
- package/api/response.js +22 -33
- package/api/server/api-controller.d.ts +1 -1
- package/api/server/api-controller.js +3 -3
- package/api/server/api-request-token.provider.d.ts +1 -0
- package/api/server/api-request-token.provider.js +1 -0
- package/api/server/middlewares/allowed-methods.middleware.js +2 -1
- package/api/server/middlewares/content-type.middleware.js +2 -1
- package/api/types.d.ts +3 -2
- package/application/README.md +240 -0
- package/application/application.js +2 -2
- package/audit/README.md +267 -0
- package/authentication/README.md +288 -0
- package/authentication/client/authentication.service.d.ts +12 -11
- package/authentication/client/authentication.service.js +21 -21
- package/authentication/client/http-client.middleware.js +2 -2
- package/authentication/tests/authentication.client-error-handling.test.js +2 -1
- package/authentication/tests/authentication.client-service-refresh.test.js +5 -3
- package/browser/README.md +401 -0
- package/cancellation/README.md +156 -0
- package/cancellation/tests/coverage.test.d.ts +1 -0
- package/cancellation/tests/coverage.test.js +49 -0
- package/cancellation/tests/leak.test.d.ts +1 -0
- package/cancellation/tests/leak.test.js +35 -0
- package/cancellation/tests/token.test.d.ts +1 -0
- package/cancellation/tests/token.test.js +136 -0
- package/cancellation/token.d.ts +53 -177
- package/cancellation/token.js +132 -201
- package/context/README.md +174 -0
- package/cookie/README.md +161 -0
- package/css/README.md +157 -0
- package/data-structures/README.md +320 -0
- package/decorators/README.md +140 -0
- package/distributed-loop/README.md +231 -0
- package/distributed-loop/distributed-loop.js +1 -1
- package/document-management/README.md +403 -0
- package/document-management/server/services/document-management.service.js +9 -7
- package/document-management/tests/document-management-core.test.js +2 -7
- package/document-management/tests/document-management.api.test.js +6 -7
- package/document-management/tests/document-statistics.service.test.js +11 -12
- package/document-management/tests/document.service.test.js +3 -3
- package/document-management/tests/enum-helpers.test.js +2 -3
- package/dom/README.md +213 -0
- package/enumerable/README.md +259 -0
- package/enumeration/README.md +121 -0
- package/errors/README.md +267 -0
- package/file/README.md +191 -0
- package/formats/README.md +210 -0
- package/function/README.md +144 -0
- package/http/README.md +318 -0
- package/http/client/adapters/undici.adapter.js +1 -1
- package/http/client/http-client-request.d.ts +6 -5
- package/http/client/http-client-request.js +8 -9
- package/http/server/node/node-http-server.js +1 -2
- package/image-service/README.md +137 -0
- package/injector/README.md +491 -0
- package/injector/injector.d.ts +1 -0
- package/injector/injector.js +17 -5
- package/injector/tests/leak.test.d.ts +1 -0
- package/injector/tests/leak.test.js +45 -0
- package/intl/README.md +113 -0
- package/json-path/README.md +182 -0
- package/jsx/README.md +154 -0
- package/key-value-store/README.md +191 -0
- package/lock/README.md +249 -0
- package/lock/web/web-lock.js +119 -47
- package/logger/README.md +287 -0
- package/mail/README.md +256 -0
- package/memory/README.md +144 -0
- package/message-bus/README.md +244 -0
- package/message-bus/message-bus-base.js +1 -1
- package/module/README.md +182 -0
- package/module/module.d.ts +1 -1
- package/module/module.js +77 -17
- package/module/modules/web-server.module.js +1 -1
- package/notification/tests/notification-type.service.test.js +24 -15
- package/object-storage/README.md +300 -0
- package/openid-connect/README.md +274 -0
- package/orm/README.md +423 -0
- package/package.json +8 -6
- package/password/README.md +164 -0
- package/pdf/README.md +246 -0
- package/polyfills.js +1 -0
- package/pool/README.md +198 -0
- package/process/README.md +237 -0
- package/promise/README.md +252 -0
- package/promise/cancelable-promise.js +1 -1
- package/random/README.md +193 -0
- package/reflection/README.md +305 -0
- package/rpc/README.md +386 -0
- package/rxjs-utils/README.md +262 -0
- package/schema/README.md +342 -0
- package/serializer/README.md +342 -0
- package/signals/implementation/README.md +134 -0
- package/sse/README.md +278 -0
- package/task-queue/README.md +300 -0
- package/task-queue/postgres/task-queue.d.ts +2 -1
- package/task-queue/postgres/task-queue.js +32 -2
- package/task-queue/task-context.js +1 -1
- package/task-queue/task-queue.d.ts +17 -0
- package/task-queue/task-queue.js +103 -44
- package/task-queue/tests/complex.test.js +4 -4
- package/task-queue/tests/dependencies.test.js +4 -2
- package/task-queue/tests/queue.test.js +111 -0
- package/task-queue/tests/worker.test.js +21 -13
- package/templates/README.md +287 -0
- package/testing/README.md +157 -0
- package/text/README.md +346 -0
- package/threading/README.md +238 -0
- package/types/README.md +311 -0
- package/utils/README.md +322 -0
- package/utils/async-iterable-helpers/observable-iterable.d.ts +1 -1
- package/utils/async-iterable-helpers/observable-iterable.js +4 -8
- package/utils/async-iterable-helpers/take-until.js +4 -4
- package/utils/backoff.js +89 -30
- package/utils/retry-with-backoff.js +1 -1
- package/utils/timer.d.ts +1 -1
- package/utils/timer.js +5 -7
- package/utils/timing.d.ts +1 -1
- package/utils/timing.js +2 -4
- package/utils/z-base32.d.ts +1 -0
- package/utils/z-base32.js +1 -0
package/cookie/README.md
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# @tstdl/base/cookie
|
|
2
|
+
|
|
3
|
+
A lightweight, type-safe utility module for handling HTTP cookies. It provides functions to parse `Cookie` header strings into usable maps and to format `Set-Cookie` header strings with support for modern attributes like `SameSite`, `Partitioned`, and `Priority`.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [✨ Features](#-features)
|
|
8
|
+
- [Core Concepts](#core-concepts)
|
|
9
|
+
- [🚀 Basic Usage](#-basic-usage)
|
|
10
|
+
- [Parsing Cookies](#parsing-cookies)
|
|
11
|
+
- [Formatting Set-Cookie](#formatting-set-cookie)
|
|
12
|
+
- [🔧 Advanced Topics](#-advanced-topics)
|
|
13
|
+
- [Modern Cookie Attributes](#modern-cookie-attributes)
|
|
14
|
+
- [Expiration and Max-Age](#expiration-and-max-age)
|
|
15
|
+
- [Deleting Cookies](#deleting-cookies)
|
|
16
|
+
- [📚 API](#-api)
|
|
17
|
+
|
|
18
|
+
## ✨ Features
|
|
19
|
+
|
|
20
|
+
- **Robust Parsing**: Converts raw `Cookie` header strings into a standard JavaScript `Map`. Supports quoted values and automatic decoding.
|
|
21
|
+
- **Comprehensive Formatting**: Generates `Set-Cookie` strings supporting standard and modern attributes.
|
|
22
|
+
- **Automatic Encoding**: Handles URL encoding and decoding of cookie values automatically.
|
|
23
|
+
- **Modern Standards**: Supports `Partitioned` (CHIPS), `Priority`, and `SameSite` attributes.
|
|
24
|
+
- **Type Safety**: Fully typed options for compile-time safety.
|
|
25
|
+
|
|
26
|
+
## Core Concepts
|
|
27
|
+
|
|
28
|
+
HTTP Cookies are small pieces of data stored on the user's device. They are exchanged between the client and server via HTTP headers.
|
|
29
|
+
|
|
30
|
+
1. **Parsing (`Cookie` Header)**: When a browser sends a request, it includes cookies in a single string (e.g., `name=value; name2=value2`). This module parses that string into a key-value map for easy access.
|
|
31
|
+
2. **Formatting (`Set-Cookie` Header)**: To store a cookie on the client, the server sends a `Set-Cookie` header. This string includes the name, value, and various directives (attributes) that control the cookie's scope, security, and lifetime.
|
|
32
|
+
|
|
33
|
+
## 🚀 Basic Usage
|
|
34
|
+
|
|
35
|
+
### Parsing Cookies
|
|
36
|
+
|
|
37
|
+
Use `parseCookieString` to convert a raw cookie header string (typically found in `req.headers.cookie`) into a `Map`.
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
import { parseCookieString } from '@tstdl/base/cookie';
|
|
41
|
+
|
|
42
|
+
// Simulating a raw header string received from a browser
|
|
43
|
+
const rawCookieHeader = 'session_id=abc-123; theme=dark; user_preferences="%7B%22notifications%22%3Atrue%7D"';
|
|
44
|
+
|
|
45
|
+
const cookies = parseCookieString(rawCookieHeader);
|
|
46
|
+
|
|
47
|
+
// Access values
|
|
48
|
+
const sessionId = cookies.get('session_id'); // 'abc-123'
|
|
49
|
+
const theme = cookies.get('theme'); // 'dark'
|
|
50
|
+
|
|
51
|
+
// Values are automatically URL-decoded and quotes are stripped
|
|
52
|
+
const userPrefs = cookies.get('user_preferences'); // '{"notifications":true}'
|
|
53
|
+
|
|
54
|
+
if (cookies.has('session_id')) {
|
|
55
|
+
console.log('Session active:', sessionId);
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Formatting Set-Cookie
|
|
60
|
+
|
|
61
|
+
Use `formatSetCookie` to generate the string value for a `Set-Cookie` HTTP response header.
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
import { formatSetCookie } from '@tstdl/base/cookie';
|
|
65
|
+
|
|
66
|
+
// Create a secure, HTTP-only session cookie
|
|
67
|
+
const setCookieHeader = formatSetCookie('session_id', 'xyz-secret-token', {
|
|
68
|
+
path: '/',
|
|
69
|
+
httpOnly: true,
|
|
70
|
+
secure: true,
|
|
71
|
+
sameSite: 'strict',
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
console.log(setCookieHeader);
|
|
75
|
+
// Output: session_id=xyz-secret-token; Path=/; HttpOnly; SameSite=Strict; Secure
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## 🔧 Advanced Topics
|
|
79
|
+
|
|
80
|
+
### Modern Cookie Attributes
|
|
81
|
+
|
|
82
|
+
The module supports modern attributes required for specific browser behaviors, such as `Partitioned` (for CHIPS) and `Priority`.
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
import { formatSetCookie } from '@tstdl/base/cookie';
|
|
86
|
+
|
|
87
|
+
const crossSiteCookie = formatSetCookie('widget_session', '123', {
|
|
88
|
+
path: '/',
|
|
89
|
+
secure: true,
|
|
90
|
+
// Required for cookies sent in cross-site contexts (e.g., iframes)
|
|
91
|
+
sameSite: 'none',
|
|
92
|
+
// Cookies Having Independent Partitioned State (CHIPS)
|
|
93
|
+
partitioned: true,
|
|
94
|
+
// Hint to the browser about the cookie's importance
|
|
95
|
+
priority: 'high',
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
console.log(crossSiteCookie);
|
|
99
|
+
// Output: widget_session=123; Path=/; SameSite=None; Priority=High; Secure; Partitioned
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Expiration and Max-Age
|
|
103
|
+
|
|
104
|
+
You can define the lifetime of a cookie using either `expires` (absolute date) or `maxAge` (relative seconds).
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
import { formatSetCookie } from '@tstdl/base/cookie';
|
|
108
|
+
|
|
109
|
+
// Using Max-Age (in seconds)
|
|
110
|
+
const oneHourCookie = formatSetCookie('temp_data', 'foo', {
|
|
111
|
+
maxAge: 3600, // 1 hour
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// Using Expires (Date object or timestamp in milliseconds)
|
|
115
|
+
const nextWeek = new Date();
|
|
116
|
+
nextWeek.setDate(nextWeek.getDate() + 7);
|
|
117
|
+
|
|
118
|
+
const persistentCookie = formatSetCookie('permanent_data', 'bar', {
|
|
119
|
+
expires: nextWeek,
|
|
120
|
+
});
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Deleting Cookies
|
|
124
|
+
|
|
125
|
+
To delete a cookie, you should set its expiration to the past or its `maxAge` to 0.
|
|
126
|
+
|
|
127
|
+
```ts
|
|
128
|
+
import { formatSetCookie } from '@tstdl/base/cookie';
|
|
129
|
+
|
|
130
|
+
// Option 1: Set maxAge to 0
|
|
131
|
+
const deleteCookie1 = formatSetCookie('session_id', '', {
|
|
132
|
+
maxAge: 0,
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
// Option 2: Set expires to a date in the past
|
|
136
|
+
const deleteCookie2 = formatSetCookie('session_id', '', {
|
|
137
|
+
expires: new Date(0),
|
|
138
|
+
});
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## 📚 API
|
|
142
|
+
|
|
143
|
+
| Name | Type | Description |
|
|
144
|
+
| :------------------ | :-------------------------------------------------------------------- | :------------------------------------------------------------------------------------- |
|
|
145
|
+
| `formatSetCookie` | `(name: string, value: string, options?: SetCookieOptions) => string` | Formats a cookie name, value, and options into a `Set-Cookie` header string. |
|
|
146
|
+
| `parseCookieString` | `(cookieString: string) => Map<string, string>` | Parses a `Cookie` header string into a Map of key-value pairs. Values are URL-decoded. |
|
|
147
|
+
| `SetCookieOptions` | `Type` | Configuration object for cookie attributes. |
|
|
148
|
+
|
|
149
|
+
### SetCookieOptions
|
|
150
|
+
|
|
151
|
+
| Property | Type | Description |
|
|
152
|
+
| :------------ | :---------------------------- | :---------------------------------------------------------------------------------------------- |
|
|
153
|
+
| `domain` | `string` | Specifies the domain for which the cookie is valid. |
|
|
154
|
+
| `expires` | `Date \| number` | Date or timestamp (in milliseconds) when the cookie expires. |
|
|
155
|
+
| `httpOnly` | `boolean` | If true, the cookie is inaccessible to the JavaScript `Document.cookie` API. |
|
|
156
|
+
| `maxAge` | `number` | Number of seconds until the cookie expires. |
|
|
157
|
+
| `partitioned` | `boolean` | If true, sets the `Partitioned` attribute (CHIPS). Requires `secure` to be true. |
|
|
158
|
+
| `path` | `string` | Specifies the path for which the cookie is valid. |
|
|
159
|
+
| `sameSite` | `'strict' \| 'lax' \| 'none'` | Controls whether the cookie is sent with cross-site requests. |
|
|
160
|
+
| `priority` | `'low' \| 'medium' \| 'high'` | Hints at the priority of the cookie for browser retention. |
|
|
161
|
+
| `secure` | `boolean` | If true, the cookie is only sent to the server when a request is made with the `https:` scheme. |
|
package/css/README.md
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# CSS
|
|
2
|
+
|
|
3
|
+
A utility module for programmatically managing CSS variables (custom properties) using the modern Constructable Stylesheets API. It provides a type-safe, disposable interface for dynamic theming and runtime style manipulation without the overhead of managing `<style>` tags or inline styles.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [✨ Features](#-features)
|
|
8
|
+
- [Core Concepts](#core-concepts)
|
|
9
|
+
- [🚀 Basic Usage](#-basic-usage)
|
|
10
|
+
- [🔧 Advanced Topics](#-advanced-topics)
|
|
11
|
+
- [Scoped Selectors](#scoped-selectors)
|
|
12
|
+
- [Namespacing with Prefixes](#namespacing-with-prefixes)
|
|
13
|
+
- [Batch Operations & Cleanup](#batch-operations--cleanup)
|
|
14
|
+
- [Lifecycle Management (Disposal)](#lifecycle-management-disposal)
|
|
15
|
+
- [📚 API](#-api)
|
|
16
|
+
|
|
17
|
+
## ✨ Features
|
|
18
|
+
|
|
19
|
+
- **Constructable Stylesheets**: Leverages `document.adoptedStyleSheets` for performant style application.
|
|
20
|
+
- **Scoped Variables**: Apply variables globally (`:root`) or target specific CSS selectors.
|
|
21
|
+
- **Automatic Prefixing**: Automatically handles the `--` syntax for custom properties.
|
|
22
|
+
- **Batch Updates**: Set multiple variables simultaneously.
|
|
23
|
+
- **Disposable**: Implements the `Disposable` interface for automatic cleanup of stylesheets.
|
|
24
|
+
- **Type Safe**: Written in TypeScript for robust development.
|
|
25
|
+
|
|
26
|
+
## Core Concepts
|
|
27
|
+
|
|
28
|
+
This module abstracts the **CSS Object Model (CSSOM)** to simplify the management of CSS Custom Properties.
|
|
29
|
+
|
|
30
|
+
Instead of appending `<style>` elements to the DOM or manipulating the `style` attribute of individual elements, this module creates a `CSSStyleSheet` in memory and adopts it into the document. This approach is generally more performant for global or shared styles (like themes) and keeps the DOM clean.
|
|
31
|
+
|
|
32
|
+
The `CssVariables` class manages a single CSS rule within a dedicated stylesheet. You can define the **selector** (where the variables apply) and an optional **prefix** (to namespace your variables).
|
|
33
|
+
|
|
34
|
+
## 🚀 Basic Usage
|
|
35
|
+
|
|
36
|
+
The most common use case is setting global theme variables on the `:root` selector.
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
import { cssVariables } from '@tstdl/base/css';
|
|
40
|
+
|
|
41
|
+
// Create a manager for :root variables
|
|
42
|
+
const theme = cssVariables();
|
|
43
|
+
|
|
44
|
+
// Set a variable (automatically adds '--' if missing)
|
|
45
|
+
theme.set('primary-color', '#3498db');
|
|
46
|
+
theme.set('font-size', '16px');
|
|
47
|
+
|
|
48
|
+
// Read a value
|
|
49
|
+
const color = theme.get('primary-color');
|
|
50
|
+
console.log(color); // " #3498db" (note: browser may add whitespace)
|
|
51
|
+
|
|
52
|
+
// The styles are now active in the document
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## 🔧 Advanced Topics
|
|
56
|
+
|
|
57
|
+
### Scoped Selectors
|
|
58
|
+
|
|
59
|
+
You can restrict the CSS variables to a specific selector, such as a class name or an ID. This is useful for component-specific theming.
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
import { cssVariables } from '@tstdl/base/css';
|
|
63
|
+
|
|
64
|
+
// Apply variables only to elements with the class .dark-mode-container
|
|
65
|
+
const darkTheme = cssVariables('.dark-mode-container');
|
|
66
|
+
|
|
67
|
+
darkTheme.set('background', '#000000');
|
|
68
|
+
darkTheme.set('text', '#ffffff');
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Namespacing with Prefixes
|
|
72
|
+
|
|
73
|
+
To avoid collisions or group related variables, you can provide a prefix. The module handles the double hyphen syntax automatically.
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
import { cssVariables } from '@tstdl/base/css';
|
|
77
|
+
|
|
78
|
+
// Variables will be prefixed with '--my-app-'
|
|
79
|
+
const appSettings = cssVariables(':root', 'my-app-');
|
|
80
|
+
|
|
81
|
+
// Sets '--my-app-spacing'
|
|
82
|
+
appSettings.set('spacing', '1rem');
|
|
83
|
+
|
|
84
|
+
// Sets '--my-app-header-height'
|
|
85
|
+
appSettings.set('header-height', '64px');
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Batch Operations & Cleanup
|
|
89
|
+
|
|
90
|
+
Use `setMany` to apply multiple variables at once using an object or an array of entries. You can also delete specific variables or clear the entire rule.
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
import { cssVariables } from '@tstdl/base/css';
|
|
94
|
+
|
|
95
|
+
const theme = cssVariables();
|
|
96
|
+
|
|
97
|
+
// Batch update
|
|
98
|
+
theme.setMany({
|
|
99
|
+
'color-primary': 'blue',
|
|
100
|
+
'color-secondary': 'green',
|
|
101
|
+
'border-radius': '4px',
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// Delete a single variable
|
|
105
|
+
theme.delete('color-secondary');
|
|
106
|
+
|
|
107
|
+
// Clear all variables in this manager
|
|
108
|
+
theme.clear();
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Lifecycle Management (Disposal)
|
|
112
|
+
|
|
113
|
+
The `CssVariables` class implements the `Disposable` interface (`Symbol.dispose`). When the object is disposed, the underlying stylesheet is removed from `document.adoptedStyleSheets`, effectively reverting the changes.
|
|
114
|
+
|
|
115
|
+
This is particularly useful with the TypeScript `using` keyword (or manual `dispose` calls) for temporary styles.
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
import { cssVariables } from '@tstdl/base/css';
|
|
119
|
+
|
|
120
|
+
function applyTemporaryTheme() {
|
|
121
|
+
// 'using' ensures the stylesheet is removed when the scope exits
|
|
122
|
+
using tempTheme = cssVariables();
|
|
123
|
+
|
|
124
|
+
tempTheme.set('overlay-color', 'rgba(0,0,0,0.5)');
|
|
125
|
+
|
|
126
|
+
// ... perform operations with the theme active ...
|
|
127
|
+
} // tempTheme is disposed here, removing the CSS variables from the document
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## 📚 API
|
|
131
|
+
|
|
132
|
+
### Functions
|
|
133
|
+
|
|
134
|
+
| Function | Description |
|
|
135
|
+
| :--------------------------------- | :------------------------------------------------------------------------------------------------------- |
|
|
136
|
+
| `cssVariables(selector?, prefix?)` | Factory function to create a new `CssVariables` instance. Defaults to `:root` selector and empty prefix. |
|
|
137
|
+
|
|
138
|
+
### Classes
|
|
139
|
+
|
|
140
|
+
#### `CssVariables`
|
|
141
|
+
|
|
142
|
+
Implements `Disposable`.
|
|
143
|
+
|
|
144
|
+
| Method | Signature | Description |
|
|
145
|
+
| :----------------- | :------------------------------------------------------------------------------------ | :-------------------------------------------------------------------------------- |
|
|
146
|
+
| `constructor` | `(selector: string \| null, prefix?: string)` | Creates a new stylesheet adopted by the document. `selector` defaults to `:root`. |
|
|
147
|
+
| `set` | `(name: string, value: string): void` | Sets a CSS variable. Automatically handles the `--` prefix. |
|
|
148
|
+
| `setMany` | `(variables: Record<string, string> \| readonly (readonly [string, string])[]): void` | Sets multiple variables at once. |
|
|
149
|
+
| `get` | `(name: string): string \| null` | Retrieves the value of a CSS variable. Returns `null` if not set. |
|
|
150
|
+
| `delete` | `(name: string): void` | Removes a CSS variable from the rule. |
|
|
151
|
+
| `clear` | `(): void` | Clears all properties from the rule. |
|
|
152
|
+
| `[Symbol.dispose]` | `(): void` | Removes the stylesheet from the document. |
|
|
153
|
+
|
|
154
|
+
| Property | Type | Description |
|
|
155
|
+
| :--------- | :------- | :------------------------------------------ |
|
|
156
|
+
| `selector` | `string` | The CSS selector targeted by this instance. |
|
|
157
|
+
| `prefix` | `string` | The prefix applied to variable names. |
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
# @tstdl/base/data-structures
|
|
2
|
+
|
|
3
|
+
A comprehensive library of advanced, observable, and strongly-typed data structures for TypeScript, providing powerful alternatives to native collections with reactive capabilities.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [✨ Features](#-features)
|
|
8
|
+
- [Core Concepts](#core-concepts)
|
|
9
|
+
- [Collection Hierarchy](#collection-hierarchy)
|
|
10
|
+
- [Observability](#observability)
|
|
11
|
+
- [🚀 Basic Usage](#-basic-usage)
|
|
12
|
+
- [ArrayList](#arraylist)
|
|
13
|
+
- [MapDictionary](#mapdictionary)
|
|
14
|
+
- [SetCollection](#setcollection)
|
|
15
|
+
- [🔧 Advanced Topics](#-advanced-topics)
|
|
16
|
+
- [CircularBuffer](#circularbuffer)
|
|
17
|
+
- [SortedArrayList](#sortedarraylist)
|
|
18
|
+
- [Multi-Key Collections](#multi-key-collections)
|
|
19
|
+
- [Weak Reference Maps](#weak-reference-maps)
|
|
20
|
+
- [ContextDataMap](#contextdatamap)
|
|
21
|
+
- [Native Adapters](#native-adapters)
|
|
22
|
+
- [📚 API](#-api)
|
|
23
|
+
|
|
24
|
+
## ✨ Features
|
|
25
|
+
|
|
26
|
+
- **Observable State**: Track changes, size, and emptiness via RxJS Observables (`size$`, `change$`) and Signals (`$size`, `$observe`).
|
|
27
|
+
- **Rich Collection Set**: Includes Lists (Array, Sorted, Linked), Dictionaries, Sets, Circular Buffers, and LRU Caches.
|
|
28
|
+
- **Specialized Maps**: Advanced implementations like `MultiKeyMap` (nested keys), `IterableWeakMap` (iterable weak keys), and `WeakRefMap` (weak values).
|
|
29
|
+
- **Native Compatibility**: Seamlessly adapt custom structures to standard `Map` and `Set` interfaces using `asMap()` and `asSet()`.
|
|
30
|
+
- **Type Safety**: Built with rigorous TypeScript generics to ensure type safety across all operations.
|
|
31
|
+
|
|
32
|
+
## Core Concepts
|
|
33
|
+
|
|
34
|
+
### Collection Hierarchy
|
|
35
|
+
|
|
36
|
+
The module is built on a robust hierarchy of abstract base classes:
|
|
37
|
+
|
|
38
|
+
- **`Collection<T>`**: The root of the hierarchy. Provides observability (`size$`, `change$`, `$size`, `$observe`) and standard methods like `add`, `clear`, and `items()`.
|
|
39
|
+
- **`List<T>`**: Extends `Collection` for ordered, indexed data. Adds `at(index)`, `indexOf(item)`, `removeAt(index)`, and `set(index, item)`.
|
|
40
|
+
- **`Dictionary<K, V>`**: Extends `Collection` for key-value pairs. Adds `get(key)`, `set(key, value)`, `has(key)`, and `delete(key)`.
|
|
41
|
+
- **`DistinctCollection<T>`**: Extends `Collection` for unique values (Sets). Adds `has(value)` and `delete(value)`.
|
|
42
|
+
|
|
43
|
+
### Observability
|
|
44
|
+
|
|
45
|
+
All data structures in this library are reactive. You can subscribe to changes or use signals for efficient UI updates or side effects.
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
import { ArrayList } from '@tstdl/base/data-structures';
|
|
49
|
+
|
|
50
|
+
const list = new ArrayList<string>();
|
|
51
|
+
|
|
52
|
+
// RxJS Observable
|
|
53
|
+
list.size$.subscribe((size) => console.log(`Size: ${size}`));
|
|
54
|
+
|
|
55
|
+
// Signal (if using a signal-compatible environment)
|
|
56
|
+
console.log(list.$isEmpty());
|
|
57
|
+
|
|
58
|
+
list.add('Hello'); // Triggers updates
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## 🚀 Basic Usage
|
|
62
|
+
|
|
63
|
+
### ArrayList
|
|
64
|
+
|
|
65
|
+
A general-purpose, resizeable array implementation of `List`.
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
import { ArrayList } from '@tstdl/base/data-structures';
|
|
69
|
+
|
|
70
|
+
const list = new ArrayList<string>(['alpha', 'beta']);
|
|
71
|
+
|
|
72
|
+
list.add('gamma');
|
|
73
|
+
list.prepend('omega');
|
|
74
|
+
|
|
75
|
+
console.log(list.at(0)); // 'omega'
|
|
76
|
+
console.log(list.toArray()); // ['omega', 'alpha', 'beta', 'gamma']
|
|
77
|
+
|
|
78
|
+
list.remove('alpha');
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### MapDictionary
|
|
82
|
+
|
|
83
|
+
A `Dictionary` backed by the native `Map`, offering O(1) access times.
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
import { MapDictionary } from '@tstdl/base/data-structures';
|
|
87
|
+
|
|
88
|
+
const dict = new MapDictionary<number, string>();
|
|
89
|
+
|
|
90
|
+
dict.set(1, 'One');
|
|
91
|
+
dict.set(2, 'Two');
|
|
92
|
+
|
|
93
|
+
if (dict.has(1)) {
|
|
94
|
+
console.log(dict.get(1)); // 'One'
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
for (const [key, value] of dict) {
|
|
98
|
+
console.log(`${key}: ${value}`);
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### SetCollection
|
|
103
|
+
|
|
104
|
+
A `DistinctCollection` backed by the native `Set`, ensuring unique values.
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
import { SetCollection } from '@tstdl/base/data-structures';
|
|
108
|
+
|
|
109
|
+
const set = new SetCollection<number>();
|
|
110
|
+
|
|
111
|
+
set.add(1);
|
|
112
|
+
set.add(1); // Duplicate ignored
|
|
113
|
+
set.add(2);
|
|
114
|
+
|
|
115
|
+
console.log(set.size); // 2
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## 🔧 Advanced Topics
|
|
119
|
+
|
|
120
|
+
### CircularBuffer
|
|
121
|
+
|
|
122
|
+
A fixed-size buffer that overwrites the oldest elements when full. Useful for logs, history, or streaming data. It exposes specific observables for overflow events.
|
|
123
|
+
|
|
124
|
+
```typescript
|
|
125
|
+
import { CircularBuffer } from '@tstdl/base/data-structures';
|
|
126
|
+
|
|
127
|
+
const buffer = new CircularBuffer<string>(3);
|
|
128
|
+
|
|
129
|
+
// React to overflows
|
|
130
|
+
buffer.overflow$.subscribe((dropped) => {
|
|
131
|
+
console.warn(`Buffer full! Dropped: ${dropped}`);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
buffer.add('A');
|
|
135
|
+
buffer.add('B');
|
|
136
|
+
buffer.add('C');
|
|
137
|
+
buffer.add('D'); // Triggers overflow$, 'A' is dropped
|
|
138
|
+
|
|
139
|
+
console.log(buffer.toArray()); // ['B', 'C', 'D']
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### LinkedList
|
|
143
|
+
|
|
144
|
+
A doubly linked list that provides O(1) insertions and removals when holding a reference to a node.
|
|
145
|
+
|
|
146
|
+
```typescript
|
|
147
|
+
import { LinkedList } from '@tstdl/base/data-structures';
|
|
148
|
+
|
|
149
|
+
const list = new LinkedList<string>();
|
|
150
|
+
|
|
151
|
+
const nodeA = list.add('A');
|
|
152
|
+
const nodeB = list.add('B');
|
|
153
|
+
|
|
154
|
+
// O(1) insertion at specific position
|
|
155
|
+
list.addAfterNode(nodeA, 'new item');
|
|
156
|
+
|
|
157
|
+
// Access nodes directly
|
|
158
|
+
console.log(list.firstNode?.item); // 'A'
|
|
159
|
+
console.log(nodeB.previous?.item); // 'new item'
|
|
160
|
+
|
|
161
|
+
console.log(list.toArray()); // ['A', 'new item', 'B']
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### SortedArrayList
|
|
165
|
+
|
|
166
|
+
A list that maintains its elements in sorted order using a comparator. Binary search is used for insertions and lookups.
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
import { SortedArrayList } from '@tstdl/base/data-structures';
|
|
170
|
+
|
|
171
|
+
const scores = new SortedArrayList<number>([], (a, b) => a - b);
|
|
172
|
+
|
|
173
|
+
scores.add(10);
|
|
174
|
+
scores.add(5);
|
|
175
|
+
scores.add(20);
|
|
176
|
+
|
|
177
|
+
console.log(scores.toArray()); // [5, 10, 20]
|
|
178
|
+
|
|
179
|
+
// Fast lookup using binary search
|
|
180
|
+
const index = scores.fastIndexOf(10); // 1
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Multi-Key Collections
|
|
184
|
+
|
|
185
|
+
`MultiKeyMap` and `MultiKeySet` allow using arrays of values as keys. This is useful for coordinate systems, composite keys, or hierarchical data.
|
|
186
|
+
|
|
187
|
+
#### MultiKeyMap
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
import { MultiKeyMap } from '@tstdl/base/data-structures';
|
|
191
|
+
|
|
192
|
+
const grid = new MultiKeyMap<[number, number], string>();
|
|
193
|
+
|
|
194
|
+
grid.set([0, 0], 'Origin');
|
|
195
|
+
grid.set([10, 5], 'Target');
|
|
196
|
+
|
|
197
|
+
console.log(grid.get([0, 0])); // 'Origin'
|
|
198
|
+
console.log(grid.has([1, 1])); // false
|
|
199
|
+
|
|
200
|
+
// Flat access API (alternative syntax)
|
|
201
|
+
grid.setFlat(2, 2, 'Waypoint');
|
|
202
|
+
console.log(grid.getFlat(2, 2)); // 'Waypoint'
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
#### MultiKeySet
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
import { MultiKeySet } from '@tstdl/base/data-structures';
|
|
209
|
+
|
|
210
|
+
const matrix = new MultiKeySet<[number, number, number]>();
|
|
211
|
+
|
|
212
|
+
matrix.add([1, 2, 3]);
|
|
213
|
+
matrix.add([1, 2, 3]); // Duplicate ignored
|
|
214
|
+
|
|
215
|
+
console.log(matrix.size); // 1
|
|
216
|
+
console.log(matrix.has([1, 2, 3])); // true
|
|
217
|
+
|
|
218
|
+
// Flat access
|
|
219
|
+
matrix.addFlat(4, 5, 6);
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Cache
|
|
223
|
+
|
|
224
|
+
A simple LRU (Least Recently Used) cache with configurable capacity. It automatically evicts the least recently accessed items when the limit is reached.
|
|
225
|
+
|
|
226
|
+
```typescript
|
|
227
|
+
import { Cache } from '@tstdl/base/data-structures';
|
|
228
|
+
|
|
229
|
+
const cache = new Cache<string, object>(100); // Capacity: 100 items
|
|
230
|
+
|
|
231
|
+
cache.set('user:1', { name: 'Alice' });
|
|
232
|
+
|
|
233
|
+
// Accessing an item marks it as recently used
|
|
234
|
+
const user = cache.get('user:1');
|
|
235
|
+
|
|
236
|
+
// Adjusting capacity at runtime evicts items if necessary
|
|
237
|
+
cache.capacity = 50;
|
|
238
|
+
|
|
239
|
+
cache.delete('user:1');
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### Weak Reference Maps
|
|
243
|
+
|
|
244
|
+
- **`IterableWeakMap`**: A `WeakMap` that allows iteration. It uses `WeakRef` and `FinalizationRegistry` to track keys and clean up internal references when keys are garbage collected.
|
|
245
|
+
- **`WeakRefMap`**: A map where _values_ are held weakly. Useful for caching large objects that can be reconstructed if memory is tight.
|
|
246
|
+
|
|
247
|
+
```typescript
|
|
248
|
+
import { IterableWeakMap } from '@tstdl/base/data-structures';
|
|
249
|
+
|
|
250
|
+
let key: object | null = { id: 1 };
|
|
251
|
+
const map = new IterableWeakMap<object, string>();
|
|
252
|
+
|
|
253
|
+
map.set(key, 'Metadata');
|
|
254
|
+
|
|
255
|
+
// Unlike native WeakMap, we can iterate
|
|
256
|
+
for (const [k, v] of map) {
|
|
257
|
+
console.log(v); // 'Metadata'
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
key = null; // Key is now eligible for GC. Map will eventually be empty.
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### ContextDataMap
|
|
264
|
+
|
|
265
|
+
A utility map for storing arbitrary context data, often used in request processing or dependency injection scopes. Supports merging data.
|
|
266
|
+
|
|
267
|
+
```typescript
|
|
268
|
+
import { ContextDataMap } from '@tstdl/base/data-structures';
|
|
269
|
+
|
|
270
|
+
const context = new ContextDataMap();
|
|
271
|
+
|
|
272
|
+
context.set('user', { id: 1, name: 'Alice' });
|
|
273
|
+
context.set('config', { theme: 'dark' });
|
|
274
|
+
|
|
275
|
+
// Merge data into existing key
|
|
276
|
+
context.set('config', { lang: 'en' }, true);
|
|
277
|
+
|
|
278
|
+
console.log(context.get('config')); // { theme: 'dark', lang: 'en' }
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### Native Adapters
|
|
282
|
+
|
|
283
|
+
If you need to pass a `Dictionary` to a function expecting a `Map`, or a `DistinctCollection` to a function expecting a `Set`, use the adapter methods. These create lightweight wrappers without copying data.
|
|
284
|
+
|
|
285
|
+
```typescript
|
|
286
|
+
import { MapDictionary } from '@tstdl/base/data-structures';
|
|
287
|
+
|
|
288
|
+
const dict = new MapDictionary<string, number>();
|
|
289
|
+
const nativeMap: Map<string, number> = dict.asMap();
|
|
290
|
+
|
|
291
|
+
nativeMap.set('foo', 123); // Updates the underlying Dictionary
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
## 📚 API
|
|
295
|
+
|
|
296
|
+
| Class | Type | Description |
|
|
297
|
+
| :---------------------- | :----------------- | :---------------------------------------------------------- |
|
|
298
|
+
| `ArrayList<T>` | List | Dynamic array implementation backed by native Array. |
|
|
299
|
+
| `SortedArrayList<T>` | List | Auto-sorted list using a comparator and binary search. |
|
|
300
|
+
| `LinkedList<T>` | List | Doubly linked list implementation. |
|
|
301
|
+
| `CircularBuffer<T>` | Collection | Fixed-size buffer that overwrites oldest items on overflow. |
|
|
302
|
+
| `MapDictionary<K, V>` | Dictionary | Key-value collection backed by native `Map`. |
|
|
303
|
+
| `ArrayDictionary<K, V>` | Dictionary | Key-value collection backed by parallel arrays. |
|
|
304
|
+
| `MultiKeyMap<K[], V>` | Dictionary | Map using arrays as composite keys. |
|
|
305
|
+
| `IterableWeakMap<K, V>` | Dictionary | `WeakMap` that supports iteration and size tracking. |
|
|
306
|
+
| `WeakRefMap<K, V>` | Dictionary | Map where values are held via `WeakRef`. |
|
|
307
|
+
| `SetCollection<T>` | DistinctCollection | Unique value collection backed by native `Set`. |
|
|
308
|
+
| `MultiKeySet<T[]>` | DistinctCollection | Set using arrays as unique composite values. |
|
|
309
|
+
| `Cache<K, V>` | Class | Simple LRU (Least Recently Used) cache. |
|
|
310
|
+
| `ContextDataMap` | Class | Map for storing and merging arbitrary context data. |
|
|
311
|
+
| `IndexOutOfBoundsError` | Error | Thrown when accessing invalid list indices. |
|
|
312
|
+
|
|
313
|
+
### Abstract Base Classes
|
|
314
|
+
|
|
315
|
+
| Class | Description |
|
|
316
|
+
| :---------------------- | :---------------------------------------------------------- |
|
|
317
|
+
| `Collection<T>` | Base class for all data structures. Provides observability. |
|
|
318
|
+
| `List<T>` | Base for ordered, indexed collections. |
|
|
319
|
+
| `Dictionary<K, V>` | Base for key-value collections. |
|
|
320
|
+
| `DistinctCollection<T>` | Base for unique value collections (Sets). |
|