@fjell/registry 4.4.13 → 4.4.16
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/API.md +62 -0
- package/GETTING_STARTED.md +69 -0
- package/docs/docs.config.ts +41 -56
- package/docs/package.json +6 -5
- package/docs/public/GETTING_STARTED.md +69 -0
- package/docs/public/api.md +37 -502
- package/docs/public/examples-README.md +19 -0
- package/docs/src/types.d.ts +37 -3
- package/package.json +8 -3
package/API.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# API Reference
|
|
2
|
+
|
|
3
|
+
Complete Registry API documentation and method reference.
|
|
4
|
+
|
|
5
|
+
## Core Registry Interface
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
interface Registry {
|
|
9
|
+
readonly type: string; // Mandatory type identifier
|
|
10
|
+
createInstance: <...>(...) => Instance<...>;
|
|
11
|
+
get: (...) => Instance | null;
|
|
12
|
+
getCoordinates: () => Coordinate[]; // Discover all registered coordinates
|
|
13
|
+
instanceTree: InstanceTree;
|
|
14
|
+
}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Primary Methods
|
|
18
|
+
|
|
19
|
+
### `createRegistry(type: string): Registry`
|
|
20
|
+
Creates a new registry with the specified type identifier.
|
|
21
|
+
|
|
22
|
+
### `registry.createInstance(kta, scopes, factory)`
|
|
23
|
+
Registers a new service instance with the given key type array and scopes.
|
|
24
|
+
|
|
25
|
+
### `registry.get(kta, options)`
|
|
26
|
+
Retrieves a service instance by key type array and scope options.
|
|
27
|
+
|
|
28
|
+
### `registry.getCoordinates(): Coordinate[]`
|
|
29
|
+
Returns all registered coordinates for service discovery and introspection.
|
|
30
|
+
|
|
31
|
+
## RegistryHub Interface
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
interface RegistryHub {
|
|
35
|
+
registerRegistry: (registry: Registry) => void;
|
|
36
|
+
get: (registryType: string, kta: string[], options?: GetOptions) => Instance | null;
|
|
37
|
+
getRegistries: () => Registry[];
|
|
38
|
+
getAllCoordinates: () => Array<{coordinate: Coordinate, registryType: string}>;
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Coordinate System
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
interface Coordinate {
|
|
46
|
+
kta: string[]; // Key Type Array - hierarchical identifiers
|
|
47
|
+
scopes: string[]; // Context qualifiers
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Complete Documentation
|
|
52
|
+
|
|
53
|
+
For comprehensive API documentation with detailed examples, implementation patterns, and advanced usage scenarios, see the **Foundation** section which contains the complete Registry documentation including:
|
|
54
|
+
|
|
55
|
+
- Interface definitions and type signatures
|
|
56
|
+
- Detailed method documentation with examples
|
|
57
|
+
- Registry and RegistryHub patterns
|
|
58
|
+
- Coordinate system explanation
|
|
59
|
+
- Service discovery and introspection
|
|
60
|
+
- Error handling and best practices
|
|
61
|
+
|
|
62
|
+
The Foundation section serves as the authoritative API reference with full context and examples.
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Getting Started
|
|
2
|
+
|
|
3
|
+
Quick start guide to using Fjell Registry in your applications.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @fjell/registry
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Basic Usage
|
|
12
|
+
|
|
13
|
+
The simplest way to get started with Registry:
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { createRegistry, createInstance } from '@fjell/registry'
|
|
17
|
+
|
|
18
|
+
// Create a registry with a type identifier
|
|
19
|
+
const registry = createRegistry('services')
|
|
20
|
+
|
|
21
|
+
// Register a simple service
|
|
22
|
+
registry.createInstance(['logger'], [], (coordinate, context) => {
|
|
23
|
+
const service = new LoggerService()
|
|
24
|
+
const instance = createInstance(context.registry, coordinate)
|
|
25
|
+
|
|
26
|
+
// Attach service methods to the instance
|
|
27
|
+
(instance as any).log = service.log.bind(service)
|
|
28
|
+
return instance
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
// Retrieve and use the service
|
|
32
|
+
const logger = registry.get(['logger'], [])
|
|
33
|
+
logger?.log('Hello from Registry!')
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Core Concepts Quick Reference
|
|
37
|
+
|
|
38
|
+
- **Registry**: Central service container with a mandatory type identifier
|
|
39
|
+
- **Coordinate**: Unique identifier using key types + scopes
|
|
40
|
+
- **Instance**: Registered service with coordinate and registry reference
|
|
41
|
+
- **Scopes**: Context qualifiers like environment or implementation type
|
|
42
|
+
|
|
43
|
+
## Next Steps
|
|
44
|
+
|
|
45
|
+
- Check out the **Examples** section for complete working examples
|
|
46
|
+
- Read the **Foundation** section for deep understanding of concepts
|
|
47
|
+
- Explore the **API Reference** for complete method documentation
|
|
48
|
+
|
|
49
|
+
## Common Patterns
|
|
50
|
+
|
|
51
|
+
### Single Registry (Simple Apps)
|
|
52
|
+
```typescript
|
|
53
|
+
const registry = createRegistry('app')
|
|
54
|
+
// Register all your services here
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Multiple Registries (Enterprise)
|
|
58
|
+
```typescript
|
|
59
|
+
const servicesRegistry = createRegistry('services')
|
|
60
|
+
const dataRegistry = createRegistry('data')
|
|
61
|
+
const cacheRegistry = createRegistry('cache')
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Scoped Services
|
|
65
|
+
```typescript
|
|
66
|
+
// Different implementations for different environments
|
|
67
|
+
registry.createInstance(['database'], ['postgresql'], ...)
|
|
68
|
+
registry.createInstance(['database'], ['firestore'], ...)
|
|
69
|
+
```
|
package/docs/docs.config.ts
CHANGED
|
@@ -4,7 +4,13 @@ interface DocsConfig {
|
|
|
4
4
|
port: number;
|
|
5
5
|
branding: {
|
|
6
6
|
theme: string;
|
|
7
|
+
tagline: string;
|
|
8
|
+
logo?: string;
|
|
7
9
|
backgroundImage?: string;
|
|
10
|
+
primaryColor?: string;
|
|
11
|
+
accentColor?: string;
|
|
12
|
+
github?: string;
|
|
13
|
+
npm?: string;
|
|
8
14
|
};
|
|
9
15
|
sections: Array<{
|
|
10
16
|
id: string;
|
|
@@ -12,6 +18,10 @@ interface DocsConfig {
|
|
|
12
18
|
subtitle: string;
|
|
13
19
|
file: string;
|
|
14
20
|
}>;
|
|
21
|
+
filesToCopy: Array<{
|
|
22
|
+
source: string;
|
|
23
|
+
destination: string;
|
|
24
|
+
}>;
|
|
15
25
|
plugins?: any[];
|
|
16
26
|
version: {
|
|
17
27
|
source: string;
|
|
@@ -22,88 +32,63 @@ interface DocsConfig {
|
|
|
22
32
|
}
|
|
23
33
|
|
|
24
34
|
const config: DocsConfig = {
|
|
25
|
-
projectName: '
|
|
26
|
-
basePath: '/
|
|
27
|
-
port:
|
|
35
|
+
projectName: 'Fjell Registry',
|
|
36
|
+
basePath: '/registry/',
|
|
37
|
+
port: 3001,
|
|
28
38
|
branding: {
|
|
29
|
-
theme: '
|
|
30
|
-
|
|
39
|
+
theme: 'registry',
|
|
40
|
+
tagline: 'Common Registry for Fjell',
|
|
41
|
+
backgroundImage: '/pano.png',
|
|
42
|
+
github: 'https://github.com/getfjell/registry',
|
|
43
|
+
npm: 'https://www.npmjs.com/package/@fjell/registry'
|
|
31
44
|
},
|
|
32
45
|
sections: [
|
|
33
46
|
{
|
|
34
47
|
id: 'overview',
|
|
35
48
|
title: 'Foundation',
|
|
36
49
|
subtitle: 'Core concepts & philosophy',
|
|
37
|
-
file: ''
|
|
50
|
+
file: '/registry/README.md'
|
|
38
51
|
},
|
|
39
52
|
{
|
|
40
53
|
id: 'getting-started',
|
|
41
54
|
title: 'Getting Started',
|
|
42
|
-
subtitle: 'Your first
|
|
43
|
-
file: ''
|
|
55
|
+
subtitle: 'Your first registry operations',
|
|
56
|
+
file: '/registry/GETTING_STARTED.md'
|
|
44
57
|
},
|
|
45
58
|
{
|
|
46
59
|
id: 'api-reference',
|
|
47
60
|
title: 'API Reference',
|
|
48
61
|
subtitle: 'Complete method documentation',
|
|
49
|
-
file: ''
|
|
62
|
+
file: '/registry/API.md'
|
|
50
63
|
},
|
|
51
64
|
{
|
|
52
65
|
id: 'examples',
|
|
53
66
|
title: 'Examples',
|
|
54
67
|
subtitle: 'Code examples & usage patterns',
|
|
55
|
-
file: '/
|
|
68
|
+
file: '/registry/examples-README.md'
|
|
56
69
|
}
|
|
57
70
|
],
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
customContent: {
|
|
63
|
-
'overview': () => {
|
|
64
|
-
return `# Foundation
|
|
65
|
-
|
|
66
|
-
Core concepts and philosophy behind Fjell HTTP API.
|
|
67
|
-
|
|
68
|
-
This library provides a simple and powerful HTTP client for making API requests with comprehensive error handling and response parsing.`;
|
|
71
|
+
filesToCopy: [
|
|
72
|
+
{
|
|
73
|
+
source: '../README.md',
|
|
74
|
+
destination: 'public/README.md'
|
|
69
75
|
},
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
Your first HTTP API calls with Fjell.
|
|
74
|
-
|
|
75
|
-
## Installation
|
|
76
|
-
|
|
77
|
-
\`\`\`bash
|
|
78
|
-
npm install @fjell/http-api
|
|
79
|
-
\`\`\`
|
|
80
|
-
|
|
81
|
-
## Basic Usage
|
|
82
|
-
|
|
83
|
-
\`\`\`typescript
|
|
84
|
-
import { HttpClient } from '@fjell/http-api'
|
|
85
|
-
|
|
86
|
-
const client = new HttpClient({
|
|
87
|
-
baseURL: 'https://api.example.com'
|
|
88
|
-
})
|
|
89
|
-
|
|
90
|
-
const response = await client.get('/users')
|
|
91
|
-
\`\`\``;
|
|
76
|
+
{
|
|
77
|
+
source: '../examples/README.md',
|
|
78
|
+
destination: 'public/examples-README.md'
|
|
92
79
|
},
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
### GET Requests
|
|
101
|
-
### POST Requests
|
|
102
|
-
### PUT Requests
|
|
103
|
-
### DELETE Requests
|
|
104
|
-
|
|
105
|
-
Complete documentation coming soon...`;
|
|
80
|
+
{
|
|
81
|
+
source: '../GETTING_STARTED.md',
|
|
82
|
+
destination: 'public/GETTING_STARTED.md'
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
source: '../API.md',
|
|
86
|
+
destination: 'public/API.md'
|
|
106
87
|
}
|
|
88
|
+
],
|
|
89
|
+
plugins: [],
|
|
90
|
+
version: {
|
|
91
|
+
source: 'package.json'
|
|
107
92
|
}
|
|
108
93
|
}
|
|
109
94
|
|
package/docs/package.json
CHANGED
|
@@ -4,14 +4,15 @@
|
|
|
4
4
|
"version": "0.0.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"
|
|
8
|
-
"
|
|
7
|
+
"copy-docs": "node node_modules/@fjell/docs-template/scripts/copy-docs.js",
|
|
8
|
+
"dev": "npm run copy-docs && vite",
|
|
9
|
+
"build": "npm run copy-docs && tsc && vite build",
|
|
9
10
|
"preview": "vite preview",
|
|
10
11
|
"test": "vitest run --coverage",
|
|
11
12
|
"test:watch": "vitest --watch"
|
|
12
13
|
},
|
|
13
14
|
"dependencies": {
|
|
14
|
-
"@fjell/docs-template": "^1.0.
|
|
15
|
+
"@fjell/docs-template": "^1.0.5",
|
|
15
16
|
"react": "^19.1.0",
|
|
16
17
|
"react-dom": "^19.1.0"
|
|
17
18
|
},
|
|
@@ -22,12 +23,12 @@
|
|
|
22
23
|
"@types/react": "^19.1.8",
|
|
23
24
|
"@types/react-dom": "^19.1.6",
|
|
24
25
|
"@types/react-syntax-highlighter": "^15.5.13",
|
|
25
|
-
"@vitejs/plugin-react": "^4.
|
|
26
|
+
"@vitejs/plugin-react": "^4.7.0",
|
|
26
27
|
"@vitest/coverage-v8": "^3.2.4",
|
|
27
28
|
"@vitest/ui": "^3.2.4",
|
|
28
29
|
"jsdom": "^26.1.0",
|
|
29
30
|
"typescript": "^5.8.3",
|
|
30
|
-
"vite": "^7.0.
|
|
31
|
+
"vite": "^7.0.5",
|
|
31
32
|
"vitest": "^3.2.4"
|
|
32
33
|
}
|
|
33
34
|
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Getting Started
|
|
2
|
+
|
|
3
|
+
Quick start guide to using Fjell Registry in your applications.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @fjell/registry
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Basic Usage
|
|
12
|
+
|
|
13
|
+
The simplest way to get started with Registry:
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { createRegistry, createInstance } from '@fjell/registry'
|
|
17
|
+
|
|
18
|
+
// Create a registry with a type identifier
|
|
19
|
+
const registry = createRegistry('services')
|
|
20
|
+
|
|
21
|
+
// Register a simple service
|
|
22
|
+
registry.createInstance(['logger'], [], (coordinate, context) => {
|
|
23
|
+
const service = new LoggerService()
|
|
24
|
+
const instance = createInstance(context.registry, coordinate)
|
|
25
|
+
|
|
26
|
+
// Attach service methods to the instance
|
|
27
|
+
(instance as any).log = service.log.bind(service)
|
|
28
|
+
return instance
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
// Retrieve and use the service
|
|
32
|
+
const logger = registry.get(['logger'], [])
|
|
33
|
+
logger?.log('Hello from Registry!')
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Core Concepts Quick Reference
|
|
37
|
+
|
|
38
|
+
- **Registry**: Central service container with a mandatory type identifier
|
|
39
|
+
- **Coordinate**: Unique identifier using key types + scopes
|
|
40
|
+
- **Instance**: Registered service with coordinate and registry reference
|
|
41
|
+
- **Scopes**: Context qualifiers like environment or implementation type
|
|
42
|
+
|
|
43
|
+
## Next Steps
|
|
44
|
+
|
|
45
|
+
- Check out the **Examples** section for complete working examples
|
|
46
|
+
- Read the **Foundation** section for deep understanding of concepts
|
|
47
|
+
- Explore the **API Reference** for complete method documentation
|
|
48
|
+
|
|
49
|
+
## Common Patterns
|
|
50
|
+
|
|
51
|
+
### Single Registry (Simple Apps)
|
|
52
|
+
```typescript
|
|
53
|
+
const registry = createRegistry('app')
|
|
54
|
+
// Register all your services here
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Multiple Registries (Enterprise)
|
|
58
|
+
```typescript
|
|
59
|
+
const servicesRegistry = createRegistry('services')
|
|
60
|
+
const dataRegistry = createRegistry('data')
|
|
61
|
+
const cacheRegistry = createRegistry('cache')
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Scoped Services
|
|
65
|
+
```typescript
|
|
66
|
+
// Different implementations for different environments
|
|
67
|
+
registry.createInstance(['database'], ['postgresql'], ...)
|
|
68
|
+
registry.createInstance(['database'], ['firestore'], ...)
|
|
69
|
+
```
|
package/docs/public/api.md
CHANGED
|
@@ -1,527 +1,62 @@
|
|
|
1
|
-
#
|
|
1
|
+
# API Reference
|
|
2
2
|
|
|
3
|
-
Complete API documentation
|
|
3
|
+
Complete Registry API documentation and method reference.
|
|
4
4
|
|
|
5
|
-
##
|
|
6
|
-
|
|
7
|
-
Fjell Core provides essential item management, key utilities, and service coordination for the entire Fjell ecosystem. This reference covers all public APIs, interfaces, and utilities.
|
|
8
|
-
|
|
9
|
-
## Core Modules
|
|
10
|
-
|
|
11
|
-
### IFactory - Item Factory
|
|
12
|
-
|
|
13
|
-
The IFactory provides type-safe item creation with validation and configuration support.
|
|
14
|
-
|
|
15
|
-
#### Methods
|
|
16
|
-
|
|
17
|
-
##### `create<T>(type: string, data: Partial<T>): T`
|
|
18
|
-
|
|
19
|
-
Creates a new item of the specified type with type safety.
|
|
20
|
-
|
|
21
|
-
**Parameters:**
|
|
22
|
-
- `type` - String identifier for the item type
|
|
23
|
-
- `data` - Partial item data to initialize the item
|
|
24
|
-
|
|
25
|
-
**Returns:** Fully constructed item of type T
|
|
26
|
-
|
|
27
|
-
**Example:**
|
|
28
|
-
```typescript
|
|
29
|
-
import { IFactory } from '@fjell/core'
|
|
30
|
-
|
|
31
|
-
interface User {
|
|
32
|
-
id: string
|
|
33
|
-
name: string
|
|
34
|
-
email: string
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const user = IFactory.create<User>('user', {
|
|
38
|
-
id: 'user-123',
|
|
39
|
-
name: 'John Doe',
|
|
40
|
-
email: 'john@example.com'
|
|
41
|
-
})
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
##### `createWithDefaults<T>(type: string, data: Partial<T>, defaults: Partial<T>): T`
|
|
45
|
-
|
|
46
|
-
Creates an item with default values applied when properties are missing.
|
|
47
|
-
|
|
48
|
-
**Parameters:**
|
|
49
|
-
- `type` - String identifier for the item type
|
|
50
|
-
- `data` - Partial item data
|
|
51
|
-
- `defaults` - Default values to apply for missing properties
|
|
52
|
-
|
|
53
|
-
**Returns:** Constructed item with defaults applied
|
|
54
|
-
|
|
55
|
-
---
|
|
56
|
-
|
|
57
|
-
### KUtils - Key Utilities
|
|
58
|
-
|
|
59
|
-
Utilities for hierarchical key generation, parsing, and manipulation.
|
|
60
|
-
|
|
61
|
-
#### Methods
|
|
62
|
-
|
|
63
|
-
##### `generateKey(components: string[]): string`
|
|
64
|
-
|
|
65
|
-
Generates a hierarchical key from an array of components.
|
|
66
|
-
|
|
67
|
-
**Parameters:**
|
|
68
|
-
- `components` - Array of string components to join
|
|
69
|
-
|
|
70
|
-
**Returns:** Generated key string with proper separators
|
|
71
|
-
|
|
72
|
-
**Example:**
|
|
73
|
-
```typescript
|
|
74
|
-
import { KUtils } from '@fjell/core'
|
|
75
|
-
|
|
76
|
-
const userKey = KUtils.generateKey(['users', 'user-123'])
|
|
77
|
-
// Returns: "users:user-123"
|
|
78
|
-
|
|
79
|
-
const profileKey = KUtils.generateKey(['users', 'user-123', 'profile'])
|
|
80
|
-
// Returns: "users:user-123:profile"
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
##### `parseKey(key: string): string[]`
|
|
84
|
-
|
|
85
|
-
Parses a hierarchical key back into its component parts.
|
|
86
|
-
|
|
87
|
-
**Parameters:**
|
|
88
|
-
- `key` - Key string to parse
|
|
89
|
-
|
|
90
|
-
**Returns:** Array of key components
|
|
91
|
-
|
|
92
|
-
**Example:**
|
|
93
|
-
```typescript
|
|
94
|
-
const components = KUtils.parseKey('users:user-123:profile')
|
|
95
|
-
// Returns: ['users', 'user-123', 'profile']
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
##### `isValidKey(key: string): boolean`
|
|
99
|
-
|
|
100
|
-
Validates whether a key is properly formatted according to Fjell standards.
|
|
101
|
-
|
|
102
|
-
**Parameters:**
|
|
103
|
-
- `key` - Key string to validate
|
|
104
|
-
|
|
105
|
-
**Returns:** Boolean indicating if the key is valid
|
|
106
|
-
|
|
107
|
-
##### `getParentKey(key: string): string | null`
|
|
108
|
-
|
|
109
|
-
Gets the parent key by removing the last component.
|
|
110
|
-
|
|
111
|
-
**Parameters:**
|
|
112
|
-
- `key` - Child key
|
|
113
|
-
|
|
114
|
-
**Returns:** Parent key string or null if no parent exists
|
|
115
|
-
|
|
116
|
-
**Example:**
|
|
117
|
-
```typescript
|
|
118
|
-
const parentKey = KUtils.getParentKey('users:user-123:profile')
|
|
119
|
-
// Returns: "users:user-123"
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
---
|
|
123
|
-
|
|
124
|
-
### AItemService - Abstract Service Base
|
|
125
|
-
|
|
126
|
-
Abstract base class for building domain-specific services with common patterns.
|
|
127
|
-
|
|
128
|
-
#### Properties
|
|
129
|
-
|
|
130
|
-
##### `logger: Logger`
|
|
131
|
-
Logger instance for the service (when logging is configured).
|
|
132
|
-
|
|
133
|
-
#### Methods
|
|
134
|
-
|
|
135
|
-
##### `validate<T>(item: T): Promise<void>`
|
|
136
|
-
|
|
137
|
-
Validates an item according to service-specific rules. Override in subclasses.
|
|
138
|
-
|
|
139
|
-
**Parameters:**
|
|
140
|
-
- `item` - Item to validate
|
|
141
|
-
|
|
142
|
-
**Throws:** ValidationError if validation fails
|
|
143
|
-
|
|
144
|
-
##### `save<T>(item: T): Promise<T>`
|
|
145
|
-
|
|
146
|
-
Saves an item to the underlying storage. Override in subclasses.
|
|
147
|
-
|
|
148
|
-
**Parameters:**
|
|
149
|
-
- `item` - Item to save
|
|
150
|
-
|
|
151
|
-
**Returns:** Promise resolving to the saved item
|
|
152
|
-
|
|
153
|
-
##### `findById<T>(id: string): Promise<T | null>`
|
|
154
|
-
|
|
155
|
-
Finds an item by its identifier. Override in subclasses.
|
|
156
|
-
|
|
157
|
-
**Parameters:**
|
|
158
|
-
- `id` - Item identifier
|
|
159
|
-
|
|
160
|
-
**Returns:** Promise resolving to the found item or null
|
|
161
|
-
|
|
162
|
-
##### `delete(id: string): Promise<void>`
|
|
163
|
-
|
|
164
|
-
Deletes an item by its identifier. Override in subclasses.
|
|
165
|
-
|
|
166
|
-
**Parameters:**
|
|
167
|
-
- `id` - Item identifier to delete
|
|
168
|
-
|
|
169
|
-
**Example:**
|
|
170
|
-
```typescript
|
|
171
|
-
import { AItemService, IFactory } from '@fjell/core'
|
|
172
|
-
|
|
173
|
-
class UserService extends AItemService {
|
|
174
|
-
private users = new Map<string, User>()
|
|
175
|
-
|
|
176
|
-
async save<User>(user: User): Promise<User> {
|
|
177
|
-
// Custom save logic
|
|
178
|
-
this.users.set(user.id, user)
|
|
179
|
-
return user
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
async findById(id: string): Promise<User | null> {
|
|
183
|
-
return this.users.get(id) || null
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
async validate(user: User): Promise<void> {
|
|
187
|
-
if (!user.email?.includes('@')) {
|
|
188
|
-
throw new Error('Valid email required')
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
---
|
|
195
|
-
|
|
196
|
-
### IQFactory - Query Factory
|
|
197
|
-
|
|
198
|
-
Factory for building complex queries for data retrieval.
|
|
199
|
-
|
|
200
|
-
#### Methods
|
|
201
|
-
|
|
202
|
-
##### `create(type: string): QueryBuilder`
|
|
203
|
-
|
|
204
|
-
Creates a new query builder for the specified entity type.
|
|
205
|
-
|
|
206
|
-
**Parameters:**
|
|
207
|
-
- `type` - Entity type to query
|
|
208
|
-
|
|
209
|
-
**Returns:** QueryBuilder instance for method chaining
|
|
210
|
-
|
|
211
|
-
**Example:**
|
|
212
|
-
```typescript
|
|
213
|
-
import { IQFactory } from '@fjell/core'
|
|
214
|
-
|
|
215
|
-
const query = IQFactory.create('user')
|
|
216
|
-
.where('status', 'active')
|
|
217
|
-
.where('age', '>', 18)
|
|
218
|
-
.orderBy('createdAt', 'desc')
|
|
219
|
-
.limit(10)
|
|
220
|
-
```
|
|
221
|
-
|
|
222
|
-
---
|
|
223
|
-
|
|
224
|
-
### QueryBuilder
|
|
225
|
-
|
|
226
|
-
Fluent interface for constructing queries with filters, sorting, and pagination.
|
|
227
|
-
|
|
228
|
-
#### Methods
|
|
229
|
-
|
|
230
|
-
##### `where(field: string, value: any): QueryBuilder`
|
|
231
|
-
##### `where(field: string, operator: string, value: any): QueryBuilder`
|
|
232
|
-
|
|
233
|
-
Adds a where condition to the query.
|
|
234
|
-
|
|
235
|
-
**Parameters:**
|
|
236
|
-
- `field` - Field name to filter on
|
|
237
|
-
- `operator` - Comparison operator ('=', '>', '<', '>=', '<=', '!=', 'like', 'in')
|
|
238
|
-
- `value` - Value to compare against
|
|
239
|
-
|
|
240
|
-
**Returns:** QueryBuilder for method chaining
|
|
241
|
-
|
|
242
|
-
##### `orderBy(field: string, direction?: 'asc' | 'desc'): QueryBuilder`
|
|
243
|
-
|
|
244
|
-
Adds ordering to the query results.
|
|
245
|
-
|
|
246
|
-
**Parameters:**
|
|
247
|
-
- `field` - Field to order by
|
|
248
|
-
- `direction` - Sort direction (default: 'asc')
|
|
249
|
-
|
|
250
|
-
**Returns:** QueryBuilder for method chaining
|
|
251
|
-
|
|
252
|
-
##### `limit(count: number): QueryBuilder`
|
|
253
|
-
|
|
254
|
-
Limits the number of results returned.
|
|
255
|
-
|
|
256
|
-
**Parameters:**
|
|
257
|
-
- `count` - Maximum number of results
|
|
258
|
-
|
|
259
|
-
**Returns:** QueryBuilder for method chaining
|
|
260
|
-
|
|
261
|
-
##### `offset(count: number): QueryBuilder`
|
|
262
|
-
|
|
263
|
-
Sets the number of results to skip (for pagination).
|
|
264
|
-
|
|
265
|
-
**Parameters:**
|
|
266
|
-
- `count` - Number of results to skip
|
|
267
|
-
|
|
268
|
-
**Returns:** QueryBuilder for method chaining
|
|
269
|
-
|
|
270
|
-
---
|
|
271
|
-
|
|
272
|
-
### IQUtils - Query Utilities
|
|
273
|
-
|
|
274
|
-
Utilities for executing and manipulating queries.
|
|
275
|
-
|
|
276
|
-
#### Methods
|
|
277
|
-
|
|
278
|
-
##### `execute<T>(query: QueryBuilder): Promise<T[]>`
|
|
279
|
-
|
|
280
|
-
Executes a query and returns the matching results.
|
|
281
|
-
|
|
282
|
-
**Parameters:**
|
|
283
|
-
- `query` - Query to execute
|
|
284
|
-
|
|
285
|
-
**Returns:** Promise resolving to array of matching items
|
|
286
|
-
|
|
287
|
-
##### `count(query: QueryBuilder): Promise<number>`
|
|
288
|
-
|
|
289
|
-
Counts the number of results that would be returned by a query.
|
|
290
|
-
|
|
291
|
-
**Parameters:**
|
|
292
|
-
- `query` - Query to count
|
|
293
|
-
|
|
294
|
-
**Returns:** Promise resolving to the count
|
|
295
|
-
|
|
296
|
-
##### `exists(query: QueryBuilder): Promise<boolean>`
|
|
297
|
-
|
|
298
|
-
Checks if any results exist for the given query.
|
|
299
|
-
|
|
300
|
-
**Parameters:**
|
|
301
|
-
- `query` - Query to check
|
|
302
|
-
|
|
303
|
-
**Returns:** Promise resolving to boolean indicating existence
|
|
304
|
-
|
|
305
|
-
---
|
|
306
|
-
|
|
307
|
-
## Core Interfaces
|
|
308
|
-
|
|
309
|
-
### Item
|
|
310
|
-
|
|
311
|
-
Base interface that all items should extend.
|
|
312
|
-
|
|
313
|
-
```typescript
|
|
314
|
-
interface Item {
|
|
315
|
-
id: string
|
|
316
|
-
type?: string
|
|
317
|
-
createdAt?: string
|
|
318
|
-
updatedAt?: string
|
|
319
|
-
}
|
|
320
|
-
```
|
|
321
|
-
|
|
322
|
-
### ServiceConfig
|
|
323
|
-
|
|
324
|
-
Configuration options for services.
|
|
325
|
-
|
|
326
|
-
```typescript
|
|
327
|
-
interface ServiceConfig {
|
|
328
|
-
name: string
|
|
329
|
-
version?: string
|
|
330
|
-
logger?: Logger
|
|
331
|
-
enableMetrics?: boolean
|
|
332
|
-
timeout?: number
|
|
333
|
-
}
|
|
334
|
-
```
|
|
335
|
-
|
|
336
|
-
### ValidationResult
|
|
337
|
-
|
|
338
|
-
Result of item validation operations.
|
|
339
|
-
|
|
340
|
-
```typescript
|
|
341
|
-
interface ValidationResult {
|
|
342
|
-
isValid: boolean
|
|
343
|
-
errors: ValidationError[]
|
|
344
|
-
warnings?: ValidationWarning[]
|
|
345
|
-
}
|
|
346
|
-
```
|
|
347
|
-
|
|
348
|
-
### WhereCondition
|
|
349
|
-
|
|
350
|
-
Represents a query filter condition.
|
|
5
|
+
## Core Registry Interface
|
|
351
6
|
|
|
352
7
|
```typescript
|
|
353
|
-
interface
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
8
|
+
interface Registry {
|
|
9
|
+
readonly type: string; // Mandatory type identifier
|
|
10
|
+
createInstance: <...>(...) => Instance<...>;
|
|
11
|
+
get: (...) => Instance | null;
|
|
12
|
+
getCoordinates: () => Coordinate[]; // Discover all registered coordinates
|
|
13
|
+
instanceTree: InstanceTree;
|
|
357
14
|
}
|
|
358
15
|
```
|
|
359
16
|
|
|
360
|
-
|
|
17
|
+
## Primary Methods
|
|
361
18
|
|
|
362
|
-
|
|
19
|
+
### `createRegistry(type: string): Registry`
|
|
20
|
+
Creates a new registry with the specified type identifier.
|
|
363
21
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
field: string
|
|
367
|
-
direction: 'asc' | 'desc'
|
|
368
|
-
}
|
|
369
|
-
```
|
|
370
|
-
|
|
371
|
-
---
|
|
22
|
+
### `registry.createInstance(kta, scopes, factory)`
|
|
23
|
+
Registers a new service instance with the given key type array and scopes.
|
|
372
24
|
|
|
373
|
-
|
|
25
|
+
### `registry.get(kta, options)`
|
|
26
|
+
Retrieves a service instance by key type array and scope options.
|
|
374
27
|
|
|
375
|
-
###
|
|
28
|
+
### `registry.getCoordinates(): Coordinate[]`
|
|
29
|
+
Returns all registered coordinates for service discovery and introspection.
|
|
376
30
|
|
|
377
|
-
|
|
31
|
+
## RegistryHub Interface
|
|
378
32
|
|
|
379
33
|
```typescript
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
34
|
+
interface RegistryHub {
|
|
35
|
+
registerRegistry: (registry: Registry) => void;
|
|
36
|
+
get: (registryType: string, kta: string[], options?: GetOptions) => Instance | null;
|
|
37
|
+
getRegistries: () => Registry[];
|
|
38
|
+
getAllCoordinates: () => Array<{coordinate: Coordinate, registryType: string}>;
|
|
383
39
|
}
|
|
384
40
|
```
|
|
385
41
|
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
Thrown when a requested item cannot be found.
|
|
389
|
-
|
|
390
|
-
```typescript
|
|
391
|
-
class CoreNotFoundError extends Error {
|
|
392
|
-
id: string
|
|
393
|
-
itemType?: string
|
|
394
|
-
}
|
|
395
|
-
```
|
|
396
|
-
|
|
397
|
-
### CoreOperationError
|
|
398
|
-
|
|
399
|
-
Thrown when a core operation fails.
|
|
42
|
+
## Coordinate System
|
|
400
43
|
|
|
401
44
|
```typescript
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
45
|
+
interface Coordinate {
|
|
46
|
+
kta: string[]; // Key Type Array - hierarchical identifiers
|
|
47
|
+
scopes: string[]; // Context qualifiers
|
|
405
48
|
}
|
|
406
49
|
```
|
|
407
50
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
## Usage Patterns
|
|
411
|
-
|
|
412
|
-
### Repository Pattern
|
|
413
|
-
|
|
414
|
-
```typescript
|
|
415
|
-
import { AItemService, IFactory, KUtils } from '@fjell/core'
|
|
416
|
-
|
|
417
|
-
class UserRepository extends AItemService {
|
|
418
|
-
private storage = new Map<string, User>()
|
|
419
|
-
|
|
420
|
-
async create(userData: Partial<User>): Promise<User> {
|
|
421
|
-
const user = IFactory.create<User>('user', {
|
|
422
|
-
id: this.generateId(),
|
|
423
|
-
createdAt: new Date().toISOString(),
|
|
424
|
-
...userData
|
|
425
|
-
})
|
|
426
|
-
|
|
427
|
-
await this.validate(user)
|
|
428
|
-
return this.save(user)
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
async save(user: User): Promise<User> {
|
|
432
|
-
const key = KUtils.generateKey(['users', user.id])
|
|
433
|
-
this.storage.set(key, user)
|
|
434
|
-
return user
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
async findById(id: string): Promise<User | null> {
|
|
438
|
-
const key = KUtils.generateKey(['users', id])
|
|
439
|
-
return this.storage.get(key) || null
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
private generateId(): string {
|
|
443
|
-
return `user-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
```
|
|
51
|
+
## Complete Documentation
|
|
447
52
|
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
```typescript
|
|
451
|
-
import { IQFactory, IQUtils } from '@fjell/core'
|
|
452
|
-
|
|
453
|
-
// Find active adult users, ordered by creation date
|
|
454
|
-
const activeAdults = await IQUtils.execute(
|
|
455
|
-
IQFactory.create('user')
|
|
456
|
-
.where('status', 'active')
|
|
457
|
-
.where('age', '>=', 18)
|
|
458
|
-
.orderBy('createdAt', 'desc')
|
|
459
|
-
.limit(50)
|
|
460
|
-
)
|
|
461
|
-
|
|
462
|
-
// Check if any admin users exist
|
|
463
|
-
const hasAdmins = await IQUtils.exists(
|
|
464
|
-
IQFactory.create('user')
|
|
465
|
-
.where('role', 'admin')
|
|
466
|
-
)
|
|
467
|
-
|
|
468
|
-
// Count users by status
|
|
469
|
-
const activeCount = await IQUtils.count(
|
|
470
|
-
IQFactory.create('user')
|
|
471
|
-
.where('status', 'active')
|
|
472
|
-
)
|
|
473
|
-
```
|
|
474
|
-
|
|
475
|
-
### Service Composition
|
|
476
|
-
|
|
477
|
-
```typescript
|
|
478
|
-
class UserManagementService extends AItemService {
|
|
479
|
-
constructor(
|
|
480
|
-
private userRepo: UserRepository,
|
|
481
|
-
private emailService: EmailService,
|
|
482
|
-
private auditService: AuditService
|
|
483
|
-
) {
|
|
484
|
-
super()
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
async registerUser(userData: Partial<User>): Promise<User> {
|
|
488
|
-
// Create user
|
|
489
|
-
const user = await this.userRepo.create(userData)
|
|
490
|
-
|
|
491
|
-
// Send welcome email
|
|
492
|
-
await this.emailService.sendWelcome(user.email)
|
|
493
|
-
|
|
494
|
-
// Log the registration
|
|
495
|
-
await this.auditService.log('user_registered', {
|
|
496
|
-
userId: user.id,
|
|
497
|
-
email: user.email
|
|
498
|
-
})
|
|
499
|
-
|
|
500
|
-
return user
|
|
501
|
-
}
|
|
502
|
-
}
|
|
503
|
-
```
|
|
504
|
-
|
|
505
|
-
---
|
|
506
|
-
|
|
507
|
-
## Testing Utilities
|
|
508
|
-
|
|
509
|
-
Fjell Core provides testing utilities to help with unit and integration tests.
|
|
510
|
-
|
|
511
|
-
### TestUtils
|
|
512
|
-
|
|
513
|
-
```typescript
|
|
514
|
-
import { TestUtils } from '@fjell/core/testing'
|
|
515
|
-
|
|
516
|
-
// Create mock instances for testing
|
|
517
|
-
const mockFactory = TestUtils.createMockFactory()
|
|
518
|
-
const mockService = TestUtils.createMockService()
|
|
519
|
-
|
|
520
|
-
// Test helpers
|
|
521
|
-
expect(TestUtils.isValidKey('users:123')).toBe(true)
|
|
522
|
-
expect(TestUtils.getKeyComponents('users:123:profile')).toEqual(['users', '123', 'profile'])
|
|
523
|
-
```
|
|
53
|
+
For comprehensive API documentation with detailed examples, implementation patterns, and advanced usage scenarios, see the **Foundation** section which contains the complete Registry documentation including:
|
|
524
54
|
|
|
525
|
-
|
|
55
|
+
- Interface definitions and type signatures
|
|
56
|
+
- Detailed method documentation with examples
|
|
57
|
+
- Registry and RegistryHub patterns
|
|
58
|
+
- Coordinate system explanation
|
|
59
|
+
- Service discovery and introspection
|
|
60
|
+
- Error handling and best practices
|
|
526
61
|
|
|
527
|
-
|
|
62
|
+
The Foundation section serves as the authoritative API reference with full context and examples.
|
|
@@ -33,6 +33,18 @@ Shows how each key path maps to different implementations via scopes using the r
|
|
|
33
33
|
|
|
34
34
|
Perfect for enterprise applications that need clean separation of concerns and organized service architecture.
|
|
35
35
|
|
|
36
|
+
### 4. `registry-statistics-example.ts` 📊 **Usage Analytics**
|
|
37
|
+
**Track and monitor registry usage patterns with scope-aware analytics!** Demonstrates advanced statistics tracking:
|
|
38
|
+
- **Scope-Aware Tracking**: Separate statistics for each kta + scopes combination
|
|
39
|
+
- **Total Call Monitoring**: Track overall `get()` method usage
|
|
40
|
+
- **Detailed Coordinate Records**: Individual tracking for each service/scope pair
|
|
41
|
+
- **Environment Analysis**: Aggregate statistics by environment (prod/dev)
|
|
42
|
+
- **Most/Least Used Services**: Identify usage patterns and bottlenecks
|
|
43
|
+
- **Immutable Statistics**: Safe access to tracking data without affecting internal state
|
|
44
|
+
- **Normalized Scope Handling**: Consistent tracking regardless of scope order
|
|
45
|
+
|
|
46
|
+
Perfect for monitoring, optimization, understanding service usage patterns, and analyzing environment-specific behavior in production applications.
|
|
47
|
+
|
|
36
48
|
## Key Concepts Demonstrated
|
|
37
49
|
|
|
38
50
|
### Simple Usage (simple-example.ts)
|
|
@@ -162,9 +174,16 @@ npx tsx examples/coordinates-example.ts
|
|
|
162
174
|
# Run the RegistryHub cross-registry coordinate discovery example
|
|
163
175
|
npx tsx examples/registry-hub-coordinates-example.ts
|
|
164
176
|
|
|
177
|
+
# Run the registry statistics tracking example
|
|
178
|
+
npx tsx examples/registry-statistics-example.ts
|
|
179
|
+
|
|
165
180
|
# Or in Node.js
|
|
166
181
|
node -r esbuild-register examples/simple-example.ts
|
|
182
|
+
node -r esbuild-register examples/multi-level-keys.ts
|
|
167
183
|
node -r esbuild-register examples/registry-hub-types.ts
|
|
184
|
+
node -r esbuild-register examples/coordinates-example.ts
|
|
185
|
+
node -r esbuild-register examples/registry-hub-coordinates-example.ts
|
|
186
|
+
node -r esbuild-register examples/registry-statistics-example.ts
|
|
168
187
|
```
|
|
169
188
|
|
|
170
189
|
## Integration with Real Fjell Registry
|
package/docs/src/types.d.ts
CHANGED
|
@@ -1,9 +1,43 @@
|
|
|
1
|
+
// Types are provided by the @fjell/docs-template package
|
|
2
|
+
|
|
1
3
|
declare module '@fjell/docs-template' {
|
|
2
|
-
export
|
|
3
|
-
|
|
4
|
+
export interface DocsConfig {
|
|
5
|
+
projectName: string;
|
|
6
|
+
basePath: string;
|
|
7
|
+
port: number;
|
|
8
|
+
branding: {
|
|
9
|
+
theme: string;
|
|
10
|
+
tagline: string;
|
|
11
|
+
logo?: string;
|
|
12
|
+
backgroundImage?: string;
|
|
13
|
+
primaryColor?: string;
|
|
14
|
+
accentColor?: string;
|
|
15
|
+
github?: string;
|
|
16
|
+
npm?: string;
|
|
17
|
+
};
|
|
18
|
+
sections: Array<{
|
|
19
|
+
id: string;
|
|
20
|
+
title: string;
|
|
21
|
+
subtitle: string;
|
|
22
|
+
file: string;
|
|
23
|
+
}>;
|
|
24
|
+
plugins?: any[];
|
|
25
|
+
version: {
|
|
26
|
+
source: string;
|
|
27
|
+
};
|
|
28
|
+
customContent?: {
|
|
29
|
+
[key: string]: (content: string) => string;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface DocsAppProps {
|
|
34
|
+
config: DocsConfig;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const DocsApp: React.ComponentType<DocsAppProps>;
|
|
4
38
|
}
|
|
5
39
|
|
|
6
|
-
declare module '../docs.config.
|
|
40
|
+
declare module '../docs.config.ts' {
|
|
7
41
|
import type { DocsConfig } from '@fjell/docs-template'
|
|
8
42
|
const config: DocsConfig
|
|
9
43
|
export default config
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fjell/registry",
|
|
3
|
-
"version": "4.4.
|
|
3
|
+
"version": "4.4.16",
|
|
4
4
|
"keywords": [
|
|
5
5
|
"registry",
|
|
6
6
|
"fjell"
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"type": "module",
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"@fjell/core": "^4.4.13",
|
|
25
|
-
"@fjell/logging": "^4.4.
|
|
25
|
+
"@fjell/logging": "^4.4.14",
|
|
26
26
|
"deepmerge": "^4.3.1"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
"@types/node": "^24.1.0",
|
|
36
36
|
"@typescript-eslint/eslint-plugin": "^8.38.0",
|
|
37
37
|
"@typescript-eslint/parser": "^8.38.0",
|
|
38
|
+
"@vitejs/plugin-react": "^4.7.0",
|
|
38
39
|
"@vitest/coverage-v8": "^3.2.4",
|
|
39
40
|
"concurrently": "^9.2.0",
|
|
40
41
|
"eslint": "^9.31.0",
|
|
@@ -59,6 +60,10 @@
|
|
|
59
60
|
"clean": "rimraf dist",
|
|
60
61
|
"test": "pnpm run lint && vitest run --coverage",
|
|
61
62
|
"test:memory:optimized": "pnpm run lint && NODE_OPTIONS=\"--max-old-space-size=8192 --max-semi-space-size=1024\" vitest run tests/memory.test.ts",
|
|
62
|
-
"test:timing:optimized": "pnpm run lint && NODE_OPTIONS=\"--max-old-space-size=8192 --max-semi-space-size=1024\" vitest run tests/timing.test.ts"
|
|
63
|
+
"test:timing:optimized": "pnpm run lint && NODE_OPTIONS=\"--max-old-space-size=8192 --max-semi-space-size=1024\" vitest run tests/timing.test.ts",
|
|
64
|
+
"docs:dev": "cd docs && pnpm run dev",
|
|
65
|
+
"docs:build": "cd docs && pnpm run build",
|
|
66
|
+
"docs:preview": "cd docs && pnpm run preview",
|
|
67
|
+
"docs:test": "cd docs && pnpm run test"
|
|
63
68
|
}
|
|
64
69
|
}
|