@hamak/ui-store-api 0.4.7 → 0.4.19
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/package.json +5 -2
- package/.turbo/turbo-build.log +0 -1
- package/.turbo/turbo-test.log +0 -12
- package/CHANGELOG.md +0 -41
- package/project.json +0 -24
- package/src/api/index.ts +0 -7
- package/src/api/middleware-registry.ts +0 -39
- package/src/api/reducer-registry.ts +0 -48
- package/src/api/store-manager.ts +0 -65
- package/src/fs/contracts/filesystem-facade.contract.ts +0 -67
- package/src/fs/contracts/filesystem-manager.contract.ts +0 -50
- package/src/fs/index.ts +0 -16
- package/src/index.ts +0 -9
- package/src/tokens/index.ts +0 -5
- package/src/tokens/service-tokens.test.ts +0 -88
- package/src/tokens/service-tokens.ts +0 -9
- package/src/types/extension-types.test.ts +0 -108
- package/src/types/extension-types.ts +0 -26
- package/src/types/index.ts +0 -8
- package/src/types/middleware-types.ts +0 -39
- package/src/types/reducer-types.ts +0 -27
- package/src/types/store-types.ts +0 -56
- package/tsconfig.es2015.json +0 -21
- package/tsconfig.json +0 -19
package/package.json
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hamak/ui-store-api",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.19",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "UI Store API - Redux store interfaces and contracts",
|
|
7
7
|
"main": "dist/index.js",
|
|
8
8
|
"types": "dist/index.d.ts",
|
|
9
9
|
"sideEffects": false,
|
|
10
|
+
"files": [
|
|
11
|
+
"dist"
|
|
12
|
+
],
|
|
10
13
|
"repository": {
|
|
11
14
|
"type": "git",
|
|
12
15
|
"url": "https://github.com/amah/app-framework.git",
|
|
@@ -34,7 +37,7 @@
|
|
|
34
37
|
}
|
|
35
38
|
},
|
|
36
39
|
"dependencies": {
|
|
37
|
-
"@hamak/shared-utils": "
|
|
40
|
+
"@hamak/shared-utils": "*",
|
|
38
41
|
"redux": "^5.0.1"
|
|
39
42
|
},
|
|
40
43
|
"devDependencies": {
|
package/.turbo/turbo-build.log
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
$ tsc -p tsconfig.json && tsc -p tsconfig.es2015.json
|
package/.turbo/turbo-test.log
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
$ vitest run
|
|
2
|
-
|
|
3
|
-
RUN v2.1.9 /Users/amah/Devs/projects/app-framework/packages/ui-store/ui-store-api
|
|
4
|
-
|
|
5
|
-
✓ src/types/extension-types.test.ts (7 tests) 6ms
|
|
6
|
-
✓ src/tokens/service-tokens.test.ts (8 tests) 8ms
|
|
7
|
-
|
|
8
|
-
Test Files 2 passed (2)
|
|
9
|
-
Tests 15 passed (15)
|
|
10
|
-
Start at 21:18:14
|
|
11
|
-
Duration 1.81s (transform 109ms, setup 0ms, collect 217ms, tests 14ms, environment 0ms, prepare 938ms)
|
|
12
|
-
|
package/CHANGELOG.md
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
## 0.4.0 (2025-11-10)
|
|
2
|
-
|
|
3
|
-
### 🚀 Features
|
|
4
|
-
|
|
5
|
-
- implement notification plugin with UI and backend components ([c19ffcf](https://github.com/amah/app-framework/commit/c19ffcf))
|
|
6
|
-
- add ES2015 build support and fix TypeScript config for logging packages ([be5e45e](https://github.com/amah/app-framework/commit/be5e45e))
|
|
7
|
-
- complete logging system build and add optional console interception ([f390bc6](https://github.com/amah/app-framework/commit/f390bc6))
|
|
8
|
-
- implement core pluggable logging system (Phase 1) ([2abdc1a](https://github.com/amah/app-framework/commit/2abdc1a))
|
|
9
|
-
|
|
10
|
-
### 🩹 Fixes
|
|
11
|
-
|
|
12
|
-
- add notification packages to workspaces ([97a234d](https://github.com/amah/app-framework/commit/97a234d))
|
|
13
|
-
|
|
14
|
-
### ❤️ Thank You
|
|
15
|
-
|
|
16
|
-
- Amah
|
|
17
|
-
- Claude
|
|
18
|
-
|
|
19
|
-
## 0.3.0 (2025-11-06)
|
|
20
|
-
|
|
21
|
-
### 🚀 Features
|
|
22
|
-
|
|
23
|
-
- migrate from Turbo to Nx 22 with comprehensive monorepo setup ([e63801e](https://github.com/amah/app-framework/commit/e63801e))
|
|
24
|
-
- add Nx Release for automated dependency management ([01d474f](https://github.com/amah/app-framework/commit/01d474f))
|
|
25
|
-
- migrate from Turbo to Nx 22 monorepo orchestration ([d374271](https://github.com/amah/app-framework/commit/d374271))
|
|
26
|
-
- add configurable main padding and resizable sidebar to DashboardLayout ([c1d25bf](https://github.com/amah/app-framework/commit/c1d25bf))
|
|
27
|
-
- add debug logging and version management system ([ea514fc](https://github.com/amah/app-framework/commit/ea514fc))
|
|
28
|
-
- **ui-store:** add STORE_EXTENSIONS_TOKEN for DI-based middleware/reducer registration ([e855bdd](https://github.com/amah/app-framework/commit/e855bdd))
|
|
29
|
-
- Rename package scope from @amk to @hamak and configure npm publishing ([b6040b5](https://github.com/amah/app-framework/commit/b6040b5))
|
|
30
|
-
- Add hybrid local/CI-CD development workflow with bun link ([d09f528](https://github.com/amah/app-framework/commit/d09f528))
|
|
31
|
-
- Add Turborepo for intelligent build orchestration and fix test type errors ([ba41db8](https://github.com/amah/app-framework/commit/ba41db8))
|
|
32
|
-
- Add Redux store integration with ui-store package and demo ([e5aafa8](https://github.com/amah/app-framework/commit/e5aafa8))
|
|
33
|
-
|
|
34
|
-
### 🩹 Fixes
|
|
35
|
-
|
|
36
|
-
- move git config to top-level release.git in nx.json ([1bb2187](https://github.com/amah/app-framework/commit/1bb2187))
|
|
37
|
-
|
|
38
|
-
### ❤️ Thank You
|
|
39
|
-
|
|
40
|
-
- Amah
|
|
41
|
-
- Claude
|
package/project.json
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@hamak/ui-store-api",
|
|
3
|
-
"$schema": "../../../node_modules/nx/schemas/project-schema.json",
|
|
4
|
-
"sourceRoot": "packages/ui-store/ui-store-api/src",
|
|
5
|
-
"projectType": "library",
|
|
6
|
-
"targets": {
|
|
7
|
-
"build": {
|
|
8
|
-
"executor": "nx:run-commands",
|
|
9
|
-
"outputs": ["{projectRoot}/dist"],
|
|
10
|
-
"options": {
|
|
11
|
-
"command": "tsc -p tsconfig.json && tsc -p tsconfig.es2015.json",
|
|
12
|
-
"cwd": "{projectRoot}"
|
|
13
|
-
}
|
|
14
|
-
},
|
|
15
|
-
"clean": {
|
|
16
|
-
"executor": "nx:run-commands",
|
|
17
|
-
"options": {
|
|
18
|
-
"command": "rm -rf dist",
|
|
19
|
-
"cwd": "{projectRoot}"
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
},
|
|
23
|
-
"tags": ["type:library", "scope:ui-store"]
|
|
24
|
-
}
|
package/src/api/index.ts
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Middleware Registry Interface
|
|
3
|
-
* Extension point for plugins to contribute middleware
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { Middleware } from 'redux';
|
|
7
|
-
import type { MiddlewareRegistration } from '../types';
|
|
8
|
-
|
|
9
|
-
export interface IMiddlewareRegistry {
|
|
10
|
-
/**
|
|
11
|
-
* Register a middleware
|
|
12
|
-
*/
|
|
13
|
-
register(registration: MiddlewareRegistration): void;
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Unregister a middleware by ID
|
|
17
|
-
*/
|
|
18
|
-
unregister(id: string): void;
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Get all middleware in priority order
|
|
22
|
-
*/
|
|
23
|
-
getAll(): Middleware[];
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Check if middleware is registered
|
|
27
|
-
*/
|
|
28
|
-
has(id: string): boolean;
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Get middleware registration info
|
|
32
|
-
*/
|
|
33
|
-
getInfo(id: string): MiddlewareRegistration | undefined;
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Get all registrations with metadata
|
|
37
|
-
*/
|
|
38
|
-
getAllRegistrations(): MiddlewareRegistration[];
|
|
39
|
-
}
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Reducer Registry Interface
|
|
3
|
-
* Allows dynamic reducer registration and hot replacement
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { Reducer } from 'redux';
|
|
7
|
-
import type { ReducerMap, ReducerRegistration } from '../types';
|
|
8
|
-
|
|
9
|
-
export interface IReducerRegistry {
|
|
10
|
-
/**
|
|
11
|
-
* Register a reducer for a state slice key
|
|
12
|
-
* @param key - State slice key
|
|
13
|
-
* @param reducer - Reducer function
|
|
14
|
-
* @param replace - Whether to replace existing reducer (default: false)
|
|
15
|
-
*/
|
|
16
|
-
register(key: string, reducer: Reducer, replace?: boolean): void;
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Unregister a reducer
|
|
20
|
-
* @param key - State slice key
|
|
21
|
-
*/
|
|
22
|
-
unregister(key: string): void;
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Get all registered reducers
|
|
26
|
-
*/
|
|
27
|
-
getAll(): ReducerMap;
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Get combined root reducer
|
|
31
|
-
*/
|
|
32
|
-
getCombinedReducer(): Reducer;
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Check if reducer is registered
|
|
36
|
-
*/
|
|
37
|
-
has(key: string): boolean;
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Get reducer registration info
|
|
41
|
-
*/
|
|
42
|
-
getInfo(key: string): ReducerRegistration | undefined;
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Get all registrations with metadata
|
|
46
|
-
*/
|
|
47
|
-
getAllRegistrations(): ReducerRegistration[];
|
|
48
|
-
}
|
package/src/api/store-manager.ts
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Store Manager Interface
|
|
3
|
-
* Main orchestrator for Redux store management
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { Store, Reducer, Action } from 'redux';
|
|
7
|
-
import type { StoreConfig, RootState, AppAction } from '../types';
|
|
8
|
-
import type { IMiddlewareRegistry } from './middleware-registry';
|
|
9
|
-
import type { IReducerRegistry } from './reducer-registry';
|
|
10
|
-
|
|
11
|
-
export interface IStoreManager {
|
|
12
|
-
/**
|
|
13
|
-
* Get the Redux store instance
|
|
14
|
-
* @throws Error if store is not initialized
|
|
15
|
-
*/
|
|
16
|
-
getStore(): Store<RootState, AppAction>;
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Check if store is initialized
|
|
20
|
-
*/
|
|
21
|
-
isInitialized(): boolean;
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Initialize the store
|
|
25
|
-
* Should be called after all plugins have registered middleware/reducers
|
|
26
|
-
* @internal - Called by plugin framework during activation
|
|
27
|
-
*/
|
|
28
|
-
initialize(config?: StoreConfig): Store<RootState, AppAction>;
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Get middleware registry (for plugin contributions)
|
|
32
|
-
*/
|
|
33
|
-
getMiddlewareRegistry(): IMiddlewareRegistry;
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Get reducer registry (for dynamic reducers)
|
|
37
|
-
*/
|
|
38
|
-
getReducerRegistry(): IReducerRegistry;
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Dispatch an action
|
|
42
|
-
*/
|
|
43
|
-
dispatch<A extends Action>(action: A): A;
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Get current state
|
|
47
|
-
*/
|
|
48
|
-
getState<S = RootState>(): S;
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Subscribe to state changes
|
|
52
|
-
* @returns Unsubscribe function
|
|
53
|
-
*/
|
|
54
|
-
subscribe(listener: () => void): () => void;
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Replace the root reducer (for hot module replacement)
|
|
58
|
-
*/
|
|
59
|
-
replaceReducer(nextReducer: Reducer<RootState, AppAction>): void;
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Destroy the store and clean up resources
|
|
63
|
-
*/
|
|
64
|
-
destroy(): void;
|
|
65
|
-
}
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import { FileSystemNode, DirectoryNode, FileNode, Path } from '@hamak/shared-utils';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* High-level facade for filesystem operations
|
|
5
|
-
* Provides a convenient API over the filesystem manager
|
|
6
|
-
*/
|
|
7
|
-
export interface IFileSystemFacade {
|
|
8
|
-
/**
|
|
9
|
-
* Get the root directory node
|
|
10
|
-
*/
|
|
11
|
-
getRoot(): DirectoryNode;
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Resolve a file or directory at the given path
|
|
15
|
-
*/
|
|
16
|
-
resolve(path: Path): FileSystemNode | undefined;
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Resolve a file at the given path
|
|
20
|
-
*/
|
|
21
|
-
resolveFile<T = any>(path: Path): FileNode<T> | undefined;
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Resolve a directory at the given path
|
|
25
|
-
*/
|
|
26
|
-
resolveDirectory(path: Path): DirectoryNode | undefined;
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Create or update a file at the given path
|
|
30
|
-
*/
|
|
31
|
-
setFile<T = any>(
|
|
32
|
-
path: Path,
|
|
33
|
-
content: T,
|
|
34
|
-
schema?: string,
|
|
35
|
-
params?: { override?: boolean; contentIsPresent?: boolean }
|
|
36
|
-
): void;
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Update file content at the given path
|
|
40
|
-
*/
|
|
41
|
-
updateFileContent<T = any>(path: Path, content: T): void;
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Create a directory at the given path
|
|
45
|
-
*/
|
|
46
|
-
mkdir(path: Path, params?: { override?: boolean }): void;
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Remove a file or directory at the given path
|
|
50
|
-
*/
|
|
51
|
-
remove(path: Path): void;
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Check if a path exists
|
|
55
|
-
*/
|
|
56
|
-
exists(path: Path): boolean;
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Check if a path is a file
|
|
60
|
-
*/
|
|
61
|
-
isFile(path: Path): boolean;
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Check if a path is a directory
|
|
65
|
-
*/
|
|
66
|
-
isDirectory(path: Path): boolean;
|
|
67
|
-
}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { FileSystemNode, DirectoryNode, FileNode, FileSystemState, Path } from '@hamak/shared-utils';
|
|
2
|
-
import { Action } from 'redux';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Redux selector function type
|
|
6
|
-
*/
|
|
7
|
-
export type Selector<S, R> = (state: S) => R;
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Actions for filesystem operations
|
|
11
|
-
*/
|
|
12
|
-
export interface FileSystemNodeAction extends Action {
|
|
13
|
-
command: any // Will be typed more specifically in implementation
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Parameters for filesystem node actions
|
|
18
|
-
*/
|
|
19
|
-
export interface FileSystemNodeActionParams {
|
|
20
|
-
override?: boolean
|
|
21
|
-
contentIsPresent?: boolean
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Filesystem manager interface - manages Redux state for virtual filesystem
|
|
26
|
-
*/
|
|
27
|
-
export interface IFileSystemManager {
|
|
28
|
-
/**
|
|
29
|
-
* Get the slice name for this filesystem
|
|
30
|
-
*/
|
|
31
|
-
readonly sliceName: string;
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Get initial filesystem state
|
|
35
|
-
*/
|
|
36
|
-
getInitialState(): FileSystemState;
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Get the reducer function for filesystem operations
|
|
40
|
-
*/
|
|
41
|
-
getReducer(): (state: FileSystemState, action: Action) => FileSystemState;
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Create a selector for a specific path in the filesystem
|
|
45
|
-
*/
|
|
46
|
-
createSelector<S>(
|
|
47
|
-
fileSystemSelector: Selector<S, FileSystemState | undefined>,
|
|
48
|
-
path: string | string[]
|
|
49
|
-
): Selector<S, FileSystemNode | undefined>;
|
|
50
|
-
}
|
package/src/fs/index.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
// Re-export filesystem types from shared-utils
|
|
2
|
-
export type {
|
|
3
|
-
FileSystemNode,
|
|
4
|
-
DirectoryNode,
|
|
5
|
-
FileNode,
|
|
6
|
-
FileSystemNodeBase,
|
|
7
|
-
FileSystemNodeState,
|
|
8
|
-
FileMemoState,
|
|
9
|
-
FileSystemState,
|
|
10
|
-
FileContentSchema
|
|
11
|
-
} from '@hamak/shared-utils';
|
|
12
|
-
export { fileSystemNodeInitialState } from '@hamak/shared-utils';
|
|
13
|
-
|
|
14
|
-
// Filesystem contracts
|
|
15
|
-
export * from './contracts/filesystem-manager.contract';
|
|
16
|
-
export * from './contracts/filesystem-facade.contract';
|
package/src/index.ts
DELETED
package/src/tokens/index.ts
DELETED
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Service Tokens Tests
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { describe, test, expect } from 'vitest';
|
|
6
|
-
import {
|
|
7
|
-
STORE_MANAGER_TOKEN,
|
|
8
|
-
MIDDLEWARE_REGISTRY_TOKEN,
|
|
9
|
-
REDUCER_REGISTRY_TOKEN,
|
|
10
|
-
STORE_EXTENSIONS_TOKEN,
|
|
11
|
-
} from './service-tokens';
|
|
12
|
-
|
|
13
|
-
describe('Service Tokens', () => {
|
|
14
|
-
describe('Token Definitions', () => {
|
|
15
|
-
test('STORE_MANAGER_TOKEN should be defined as symbol', () => {
|
|
16
|
-
expect(typeof STORE_MANAGER_TOKEN).toBe('symbol');
|
|
17
|
-
expect(STORE_MANAGER_TOKEN.toString()).toBe('Symbol(StoreManager)');
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
test('MIDDLEWARE_REGISTRY_TOKEN should be defined as symbol', () => {
|
|
21
|
-
expect(typeof MIDDLEWARE_REGISTRY_TOKEN).toBe('symbol');
|
|
22
|
-
expect(MIDDLEWARE_REGISTRY_TOKEN.toString()).toBe('Symbol(MiddlewareRegistry)');
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
test('REDUCER_REGISTRY_TOKEN should be defined as symbol', () => {
|
|
26
|
-
expect(typeof REDUCER_REGISTRY_TOKEN).toBe('symbol');
|
|
27
|
-
expect(REDUCER_REGISTRY_TOKEN.toString()).toBe('Symbol(ReducerRegistry)');
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
test('STORE_EXTENSIONS_TOKEN should be defined as symbol', () => {
|
|
31
|
-
expect(typeof STORE_EXTENSIONS_TOKEN).toBe('symbol');
|
|
32
|
-
expect(STORE_EXTENSIONS_TOKEN.toString()).toBe('Symbol(StoreExtensions)');
|
|
33
|
-
});
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
describe('Token Uniqueness', () => {
|
|
37
|
-
test('each token should be unique', () => {
|
|
38
|
-
const tokens = [
|
|
39
|
-
STORE_MANAGER_TOKEN,
|
|
40
|
-
MIDDLEWARE_REGISTRY_TOKEN,
|
|
41
|
-
REDUCER_REGISTRY_TOKEN,
|
|
42
|
-
STORE_EXTENSIONS_TOKEN,
|
|
43
|
-
];
|
|
44
|
-
|
|
45
|
-
const uniqueTokens = new Set(tokens);
|
|
46
|
-
expect(uniqueTokens.size).toBe(tokens.length);
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
test('tokens should not equal each other', () => {
|
|
50
|
-
expect(STORE_MANAGER_TOKEN).not.toBe(MIDDLEWARE_REGISTRY_TOKEN);
|
|
51
|
-
expect(STORE_MANAGER_TOKEN).not.toBe(REDUCER_REGISTRY_TOKEN);
|
|
52
|
-
expect(STORE_MANAGER_TOKEN).not.toBe(STORE_EXTENSIONS_TOKEN);
|
|
53
|
-
expect(MIDDLEWARE_REGISTRY_TOKEN).not.toBe(REDUCER_REGISTRY_TOKEN);
|
|
54
|
-
expect(MIDDLEWARE_REGISTRY_TOKEN).not.toBe(STORE_EXTENSIONS_TOKEN);
|
|
55
|
-
expect(REDUCER_REGISTRY_TOKEN).not.toBe(STORE_EXTENSIONS_TOKEN);
|
|
56
|
-
});
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
describe('Token Usage', () => {
|
|
60
|
-
test('tokens should be usable as Map keys', () => {
|
|
61
|
-
const map = new Map();
|
|
62
|
-
map.set(STORE_MANAGER_TOKEN, 'store manager');
|
|
63
|
-
map.set(MIDDLEWARE_REGISTRY_TOKEN, 'middleware registry');
|
|
64
|
-
map.set(REDUCER_REGISTRY_TOKEN, 'reducer registry');
|
|
65
|
-
map.set(STORE_EXTENSIONS_TOKEN, 'store extensions');
|
|
66
|
-
|
|
67
|
-
expect(map.get(STORE_MANAGER_TOKEN)).toBe('store manager');
|
|
68
|
-
expect(map.get(MIDDLEWARE_REGISTRY_TOKEN)).toBe('middleware registry');
|
|
69
|
-
expect(map.get(REDUCER_REGISTRY_TOKEN)).toBe('reducer registry');
|
|
70
|
-
expect(map.get(STORE_EXTENSIONS_TOKEN)).toBe('store extensions');
|
|
71
|
-
expect(map.size).toBe(4);
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
test('tokens should be usable as object keys', () => {
|
|
75
|
-
const obj = {
|
|
76
|
-
[STORE_MANAGER_TOKEN]: 'store manager',
|
|
77
|
-
[MIDDLEWARE_REGISTRY_TOKEN]: 'middleware registry',
|
|
78
|
-
[REDUCER_REGISTRY_TOKEN]: 'reducer registry',
|
|
79
|
-
[STORE_EXTENSIONS_TOKEN]: 'store extensions',
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
expect(obj[STORE_MANAGER_TOKEN]).toBe('store manager');
|
|
83
|
-
expect(obj[MIDDLEWARE_REGISTRY_TOKEN]).toBe('middleware registry');
|
|
84
|
-
expect(obj[REDUCER_REGISTRY_TOKEN]).toBe('reducer registry');
|
|
85
|
-
expect(obj[STORE_EXTENSIONS_TOKEN]).toBe('store extensions');
|
|
86
|
-
});
|
|
87
|
-
});
|
|
88
|
-
});
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Dependency Injection Tokens
|
|
3
|
-
* Used for service resolution in the microkernel
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
export const STORE_MANAGER_TOKEN = Symbol('StoreManager');
|
|
7
|
-
export const MIDDLEWARE_REGISTRY_TOKEN = Symbol('MiddlewareRegistry');
|
|
8
|
-
export const REDUCER_REGISTRY_TOKEN = Symbol('ReducerRegistry');
|
|
9
|
-
export const STORE_EXTENSIONS_TOKEN = Symbol('StoreExtensions');
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Extension Types Tests
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { describe, test, expect } from 'vitest';
|
|
6
|
-
import type {
|
|
7
|
-
StoreMiddlewareExtension,
|
|
8
|
-
StorePluginExtensions,
|
|
9
|
-
StoreExtensionsRegistry,
|
|
10
|
-
} from './extension-types';
|
|
11
|
-
import type { Middleware } from 'redux';
|
|
12
|
-
|
|
13
|
-
describe('Extension Types', () => {
|
|
14
|
-
describe('StorePluginExtensions', () => {
|
|
15
|
-
test('should accept middleware array', () => {
|
|
16
|
-
const middleware: Middleware = () => (next) => (action) => next(action);
|
|
17
|
-
const extensions: StorePluginExtensions = {
|
|
18
|
-
middleware: [
|
|
19
|
-
{
|
|
20
|
-
id: 'test',
|
|
21
|
-
middleware,
|
|
22
|
-
},
|
|
23
|
-
],
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
expect(extensions.middleware).toBeDefined();
|
|
27
|
-
expect(extensions.middleware?.length).toBe(1);
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
test('should accept reducers record', () => {
|
|
31
|
-
const reducer = (state = {}) => state;
|
|
32
|
-
const extensions: StorePluginExtensions = {
|
|
33
|
-
reducers: {
|
|
34
|
-
testReducer: reducer,
|
|
35
|
-
},
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
expect(extensions.reducers).toBeDefined();
|
|
39
|
-
expect(extensions.reducers?.testReducer).toBe(reducer);
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
test('should accept both middleware and reducers', () => {
|
|
43
|
-
const middleware: Middleware = () => (next) => (action) => next(action);
|
|
44
|
-
const reducer = (state = {}) => state;
|
|
45
|
-
const extensions: StorePluginExtensions = {
|
|
46
|
-
middleware: [{ id: 'test', middleware }],
|
|
47
|
-
reducers: { testReducer: reducer },
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
expect(extensions.middleware).toBeDefined();
|
|
51
|
-
expect(extensions.reducers).toBeDefined();
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
test('should accept empty object', () => {
|
|
55
|
-
const extensions: StorePluginExtensions = {};
|
|
56
|
-
|
|
57
|
-
expect(extensions).toBeDefined();
|
|
58
|
-
expect(extensions.middleware).toBeUndefined();
|
|
59
|
-
expect(extensions.reducers).toBeUndefined();
|
|
60
|
-
});
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
describe('StoreExtensionsRegistry', () => {
|
|
64
|
-
test('should define register method signature', () => {
|
|
65
|
-
const mockRegistry: StoreExtensionsRegistry = {
|
|
66
|
-
register: (source: string, extensions: StorePluginExtensions) => {
|
|
67
|
-
expect(source).toBeDefined();
|
|
68
|
-
expect(extensions).toBeDefined();
|
|
69
|
-
},
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
mockRegistry.register('test-source', {});
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
test('should accept source and extensions', () => {
|
|
76
|
-
const middleware: Middleware = () => (next) => (action) => next(action);
|
|
77
|
-
const reducer = (state = {}) => state;
|
|
78
|
-
|
|
79
|
-
const mockRegistry: StoreExtensionsRegistry = {
|
|
80
|
-
register: (source: string, extensions: StorePluginExtensions) => {
|
|
81
|
-
expect(source).toBe('test-plugin');
|
|
82
|
-
expect(extensions.middleware?.length).toBe(1);
|
|
83
|
-
expect(extensions.reducers?.testReducer).toBe(reducer);
|
|
84
|
-
},
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
mockRegistry.register('test-plugin', {
|
|
88
|
-
middleware: [{ id: 'test', middleware }],
|
|
89
|
-
reducers: { testReducer: reducer },
|
|
90
|
-
});
|
|
91
|
-
});
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
describe('StoreMiddlewareExtension', () => {
|
|
95
|
-
test('should match MiddlewareRegistration structure', () => {
|
|
96
|
-
const middleware: Middleware = () => (next) => (action) => next(action);
|
|
97
|
-
const extension: StoreMiddlewareExtension = {
|
|
98
|
-
id: 'test-middleware',
|
|
99
|
-
middleware,
|
|
100
|
-
priority: 100,
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
expect(extension.id).toBe('test-middleware');
|
|
104
|
-
expect(extension.middleware).toBe(middleware);
|
|
105
|
-
expect(extension.priority).toBe(100);
|
|
106
|
-
});
|
|
107
|
-
});
|
|
108
|
-
});
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Store extension types
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import type { Reducer } from 'redux';
|
|
6
|
-
import type { MiddlewareRegistration } from './middleware-types';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Middleware contribution matches registry entries
|
|
10
|
-
*/
|
|
11
|
-
export type StoreMiddlewareExtension = MiddlewareRegistration;
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Extension payload that mirrors store plugin config
|
|
15
|
-
*/
|
|
16
|
-
export interface StorePluginExtensions {
|
|
17
|
-
middleware?: StoreMiddlewareExtension[];
|
|
18
|
-
reducers?: Record<string, Reducer>;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Registry exposed via STORE_EXTENSIONS_TOKEN
|
|
23
|
-
*/
|
|
24
|
-
export interface StoreExtensionsRegistry {
|
|
25
|
-
register(source: string, extensions: StorePluginExtensions): void;
|
|
26
|
-
}
|
package/src/types/index.ts
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Middleware Type Definitions
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import type { Middleware } from 'redux';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Middleware registration with metadata
|
|
9
|
-
*/
|
|
10
|
-
export interface MiddlewareRegistration {
|
|
11
|
-
/** Unique identifier for this middleware */
|
|
12
|
-
id: string;
|
|
13
|
-
|
|
14
|
-
/** The Redux middleware function */
|
|
15
|
-
middleware: Middleware;
|
|
16
|
-
|
|
17
|
-
/** Execution priority (higher = runs earlier). Default: 0 */
|
|
18
|
-
priority?: number;
|
|
19
|
-
|
|
20
|
-
/** Plugin that registered this middleware */
|
|
21
|
-
plugin?: string;
|
|
22
|
-
|
|
23
|
-
/** Optional description for debugging */
|
|
24
|
-
description?: string;
|
|
25
|
-
|
|
26
|
-
/** Whether this middleware can be disabled */
|
|
27
|
-
optional?: boolean;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Middleware configuration
|
|
32
|
-
*/
|
|
33
|
-
export interface MiddlewareConfig {
|
|
34
|
-
/** Middleware IDs to disable */
|
|
35
|
-
disabled?: string[];
|
|
36
|
-
|
|
37
|
-
/** Override priorities for specific middleware */
|
|
38
|
-
priorities?: Record<string, number>;
|
|
39
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Reducer Type Definitions
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import type { Reducer } from 'redux';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Reducer registration metadata
|
|
9
|
-
*/
|
|
10
|
-
export interface ReducerRegistration {
|
|
11
|
-
/** State slice key */
|
|
12
|
-
key: string;
|
|
13
|
-
|
|
14
|
-
/** The reducer function */
|
|
15
|
-
reducer: Reducer;
|
|
16
|
-
|
|
17
|
-
/** Plugin that registered this reducer */
|
|
18
|
-
plugin?: string;
|
|
19
|
-
|
|
20
|
-
/** Timestamp of registration */
|
|
21
|
-
registeredAt: Date;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Reducer map type
|
|
26
|
-
*/
|
|
27
|
-
export type ReducerMap = Record<string, Reducer>;
|
package/src/types/store-types.ts
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Store Type Definitions
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import type { Store, Reducer, Action, StoreEnhancer } from 'redux';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Store configuration
|
|
9
|
-
*/
|
|
10
|
-
export interface StoreConfig {
|
|
11
|
-
/** Enable Redux DevTools integration */
|
|
12
|
-
devTools?: boolean;
|
|
13
|
-
|
|
14
|
-
/** Initial/preloaded state */
|
|
15
|
-
preloadedState?: any;
|
|
16
|
-
|
|
17
|
-
/** Additional store enhancers */
|
|
18
|
-
enhancers?: StoreEnhancer[];
|
|
19
|
-
|
|
20
|
-
/** Persistence configuration */
|
|
21
|
-
persistence?: {
|
|
22
|
-
/** Enable state persistence */
|
|
23
|
-
enabled: boolean;
|
|
24
|
-
/** Storage key prefix */
|
|
25
|
-
key?: string;
|
|
26
|
-
/** Storage type */
|
|
27
|
-
storage?: 'localStorage' | 'sessionStorage' | 'indexedDB';
|
|
28
|
-
/** Keys to persist (whitelist) */
|
|
29
|
-
whitelist?: string[];
|
|
30
|
-
/** Keys to ignore (blacklist) */
|
|
31
|
-
blacklist?: string[];
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Root state shape (can be extended by applications)
|
|
37
|
-
*/
|
|
38
|
-
export interface RootState {
|
|
39
|
-
[key: string]: any;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Standard action shape following FSA (Flux Standard Action)
|
|
44
|
-
*/
|
|
45
|
-
export interface AppAction<T = any> extends Action<string> {
|
|
46
|
-
type: string;
|
|
47
|
-
payload?: T;
|
|
48
|
-
error?: boolean;
|
|
49
|
-
meta?: any;
|
|
50
|
-
[key: string]: any;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Store instance type
|
|
55
|
-
*/
|
|
56
|
-
export type AppStore = Store<RootState, AppAction>;
|
package/tsconfig.es2015.json
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2015",
|
|
4
|
-
"module": "CommonJS",
|
|
5
|
-
"lib": ["ES2015"],
|
|
6
|
-
"skipLibCheck": true,
|
|
7
|
-
"moduleResolution": "node",
|
|
8
|
-
"resolveJsonModule": true,
|
|
9
|
-
"strict": true,
|
|
10
|
-
"outDir": "./dist/es2015",
|
|
11
|
-
"rootDir": "./src",
|
|
12
|
-
"declaration": false,
|
|
13
|
-
"declarationMap": false,
|
|
14
|
-
"sourceMap": false,
|
|
15
|
-
"downlevelIteration": true,
|
|
16
|
-
"esModuleInterop": true,
|
|
17
|
-
"allowSyntheticDefaultImports": true
|
|
18
|
-
},
|
|
19
|
-
"include": ["src/**/*"],
|
|
20
|
-
"exclude": ["node_modules", "dist", "**/*.test.ts"]
|
|
21
|
-
}
|
package/tsconfig.json
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2020",
|
|
4
|
-
"module": "ESNext",
|
|
5
|
-
"lib": ["ES2020"],
|
|
6
|
-
"skipLibCheck": true,
|
|
7
|
-
"moduleResolution": "bundler",
|
|
8
|
-
"resolveJsonModule": true,
|
|
9
|
-
"isolatedModules": true,
|
|
10
|
-
"strict": true,
|
|
11
|
-
"outDir": "./dist",
|
|
12
|
-
"rootDir": "./src",
|
|
13
|
-
"declaration": true,
|
|
14
|
-
"declarationMap": true,
|
|
15
|
-
"allowImportingTsExtensions": false
|
|
16
|
-
},
|
|
17
|
-
"include": ["src/**/*"],
|
|
18
|
-
"exclude": ["node_modules", "dist", "**/*.test.ts"]
|
|
19
|
-
}
|