@arcote.tech/arc 0.1.12 → 0.3.0
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/dist/adapters/auth-adapter.d.ts +47 -0
- package/dist/adapters/command-wire.d.ts +28 -0
- package/dist/adapters/event-publisher.d.ts +106 -0
- package/dist/adapters/event-wire.d.ts +79 -0
- package/dist/adapters/index.d.ts +18 -0
- package/dist/adapters/wire.d.ts +20 -0
- package/dist/context/context.d.ts +49 -52
- package/dist/context/index.d.ts +1 -10
- package/dist/context-element/command/command-context.d.ts +71 -0
- package/dist/context-element/command/command-data.d.ts +33 -0
- package/dist/context-element/command/command-handler.d.ts +6 -0
- package/dist/context-element/command/command.d.ts +198 -0
- package/dist/context-element/command/index.d.ts +6 -0
- package/dist/context-element/context-element.d.ts +75 -0
- package/dist/context-element/event/event-data.d.ts +35 -0
- package/dist/context-element/event/event.d.ts +158 -0
- package/dist/context-element/event/index.d.ts +5 -0
- package/dist/context-element/event/instance.d.ts +26 -0
- package/dist/context-element/index.d.ts +10 -0
- package/dist/context-element/view/index.d.ts +5 -0
- package/dist/context-element/view/view-context.d.ts +51 -0
- package/dist/context-element/view/view-data.d.ts +40 -0
- package/dist/context-element/view/view.d.ts +194 -0
- package/dist/data-storage/data-storage-forked.d.ts +1 -1
- package/dist/data-storage/data-storage-master.d.ts +7 -10
- package/dist/data-storage/data-storage-observable.d.ts +61 -0
- package/dist/data-storage/data-storage.abstract.d.ts +1 -1
- package/dist/{db/interface.d.ts → data-storage/database-adapter.d.ts} +8 -3
- package/dist/{database → data-storage}/database-store.d.ts +45 -0
- package/dist/data-storage/{types.d.ts → find-options.d.ts} +1 -1
- package/dist/data-storage/index.d.ts +6 -2
- package/dist/{db/postgresAdapter.d.ts → data-storage/postgresql-adapter.d.ts} +7 -33
- package/dist/data-storage/query-result-resolver.d.ts +18 -0
- package/dist/data-storage/query-result-resolver.test.d.ts +2 -0
- package/dist/{db/sqliteAdapter.d.ts → data-storage/sqlite-adapter.d.ts} +5 -31
- package/dist/data-storage/store-state-fork.d.ts +1 -1
- package/dist/data-storage/store-state-master.d.ts +6 -2
- package/dist/data-storage/store-state.abstract.d.ts +1 -1
- package/dist/elements/abstract.d.ts +1 -1
- package/dist/elements/any.d.ts +1 -1
- package/dist/elements/array.d.ts +5 -5
- package/dist/elements/blob.d.ts +1 -1
- package/dist/elements/boolean.d.ts +1 -1
- package/dist/elements/branded.d.ts +5 -5
- package/dist/elements/date.d.ts +1 -1
- package/dist/elements/default.d.ts +5 -5
- package/dist/elements/file.d.ts +1 -1
- package/dist/elements/id.d.ts +3 -3
- package/dist/elements/index.d.ts +1 -0
- package/dist/elements/number.d.ts +1 -1
- package/dist/elements/object.d.ts +11 -10
- package/dist/elements/optional.d.ts +5 -5
- package/dist/elements/or.d.ts +5 -5
- package/dist/elements/record.d.ts +3 -3
- package/dist/elements/string-enum.d.ts +1 -1
- package/dist/elements/string.d.ts +1 -1
- package/dist/index.d.ts +8 -7
- package/dist/index.js +2373 -3439
- package/dist/model/index.d.ts +2 -0
- package/dist/model/live-query/index.d.ts +2 -0
- package/dist/model/live-query/live-query.d.ts +31 -0
- package/dist/model/live-query/query-cache.d.ts +60 -0
- package/dist/model/model-adapters.d.ts +13 -0
- package/dist/model/model.d.ts +19 -78
- package/dist/model/mutation-executor/index.d.ts +2 -0
- package/dist/model/mutation-executor/mutation-executor.d.ts +29 -0
- package/dist/token/index.d.ts +41 -0
- package/dist/token/secured-data-storage.d.ts +125 -0
- package/dist/token/token-cache.d.ts +100 -0
- package/dist/token/token-data.d.ts +38 -0
- package/dist/token/token-instance.d.ts +71 -0
- package/dist/token/token.d.ts +127 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/types/add-question-marks.d.ts +9 -0
- package/dist/utils/types/first-argument.d.ts +5 -0
- package/dist/utils/types/get-type.d.ts +13 -0
- package/dist/utils/types/index.d.ts +6 -0
- package/dist/utils/types/merge.d.ts +7 -0
- package/dist/utils/types/object-util.d.ts +6 -0
- package/dist/utils/types/simplify.d.ts +7 -0
- package/package.json +10 -6
- package/dist/command/command-definition.d.ts +0 -5
- package/dist/command/command.d.ts +0 -45
- package/dist/command/index.d.ts +0 -2
- package/dist/context/commands.d.ts +0 -12
- package/dist/context/element.d.ts +0 -80
- package/dist/context/event.d.ts +0 -45
- package/dist/context/query-builder-context.d.ts +0 -15
- package/dist/context/query-builders.d.ts +0 -17
- package/dist/context/query-cache.d.ts +0 -9
- package/dist/context/query.d.ts +0 -12
- package/dist/context/reactive-query.d.ts +0 -23
- package/dist/context/serializable-query.d.ts +0 -11
- package/dist/context/translator.d.ts +0 -4
- package/dist/database/database-mappers.d.ts +0 -39
- package/dist/database/index.d.ts +0 -3
- package/dist/db/index.d.ts +0 -4
- package/dist/listener/index.d.ts +0 -2
- package/dist/listener/listener.d.ts +0 -23
- package/dist/model/EventPublisher.d.ts +0 -12
- package/dist/model/event-publisher.d.ts +0 -12
- package/dist/query/query-definition.d.ts +0 -8
- package/dist/route/index.d.ts +0 -2
- package/dist/route/route.d.ts +0 -35
- package/dist/rtc/client.d.ts +0 -3
- package/dist/rtc/index.d.ts +0 -4
- package/dist/rtc/messages.d.ts +0 -20
- package/dist/rtc/rtc.d.ts +0 -11
- package/dist/server/query-handler.d.ts +0 -43
- package/dist/state/index.d.ts +0 -2
- package/dist/state/query-builder.d.ts +0 -2
- package/dist/state/query.d.ts +0 -2
- package/dist/state/state.d.ts +0 -2
- package/dist/strategies/cache-strategy.d.ts +0 -20
- package/dist/strategies/datastorage-strategy.d.ts +0 -15
- package/dist/strategies/index.d.ts +0 -7
- package/dist/strategies/leader-strategy.d.ts +0 -16
- package/dist/strategies/model-strategy.d.ts +0 -9
- package/dist/strategies/query-strategy.d.ts +0 -20
- package/dist/telemetry/context.d.ts +0 -65
- package/dist/telemetry/index.d.ts +0 -47
- package/dist/telemetry/interfaces.d.ts +0 -84
- package/dist/telemetry/logger.d.ts +0 -67
- package/dist/telemetry/no-op.d.ts +0 -54
- package/dist/telemetry/tracer.d.ts +0 -85
- package/dist/tests/context/context.test.d.ts +0 -2
- package/dist/tests/pipe.d.ts +0 -2
- package/dist/tests/query/advance-query.test.d.ts +0 -2
- package/dist/tests/query/collection-all.test.d.ts +0 -2
- package/dist/tests/utils/expect-not-false.d.ts +0 -2
- package/dist/tests/utils/sqlite-adapter.d.ts +0 -3
- package/dist/tests/utils/test-model.d.ts +0 -25
- package/dist/tests/validations/array.test.d.ts +0 -2
- package/dist/tests/validations/date.test.d.ts +0 -2
- package/dist/tests/validations/number.test.d.ts +0 -2
- package/dist/tests/validations/object.test.d.ts +0 -2
- package/dist/tests/validations/record.test.d.ts +0 -2
- package/dist/tests/validations/string-enum.test.d.ts +0 -2
- package/dist/tests/validations/string.test.d.ts +0 -2
- package/dist/utils.d.ts +0 -56
- package/dist/view/index.d.ts +0 -6
- package/dist/view/queries/abstract-view-query.d.ts +0 -19
- package/dist/view/queries/find-one.d.ts +0 -13
- package/dist/view/queries/find.d.ts +0 -21
- package/dist/view/queries/index.d.ts +0 -3
- package/dist/view/query-builders/find-one.d.ts +0 -14
- package/dist/view/query-builders/find.d.ts +0 -14
- package/dist/view/query-builders/index.d.ts +0 -2
- package/dist/view/query-builders/new-query-builder.d.ts +0 -2
- package/dist/view/record.d.ts +0 -4
- package/dist/view/static-view.d.ts +0 -43
- package/dist/view/view.d.ts +0 -68
- /package/dist/{database → data-storage}/schema-extraction.d.ts +0 -0
- /package/dist/{data-storage → utils}/deep-merge.d.ts +0 -0
package/dist/model/index.d.ts
CHANGED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { ArcContextAny } from "../../context/context";
|
|
2
|
+
import type { Simplify } from "../../utils";
|
|
3
|
+
import type { Model } from "../model";
|
|
4
|
+
export type QueryContext<C extends ArcContextAny> = Simplify<{
|
|
5
|
+
[Element in C["elements"][number] as Element["queryContext"] extends (...args: any[]) => infer Return ? Element["name"] : never]: Element["queryContext"] extends (...args: any[]) => infer Return ? Return : never;
|
|
6
|
+
}>;
|
|
7
|
+
/**
|
|
8
|
+
* Live Query Result
|
|
9
|
+
*/
|
|
10
|
+
export type LiveQueryResult<T> = {
|
|
11
|
+
result: T;
|
|
12
|
+
unsubscribe: () => void;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Live Query
|
|
16
|
+
*
|
|
17
|
+
* Creates a live query that watches views and calls a callback when data changes.
|
|
18
|
+
* Uses view's queryContext directly (applies protectBy restrictions).
|
|
19
|
+
* Uses dataStorage.observeQueries() for reactivity.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* const { result, unsubscribe } = liveQuery(
|
|
24
|
+
* model,
|
|
25
|
+
* (q) => q.tasks.find({ projectId: "123" }),
|
|
26
|
+
* (data) => console.log("Tasks updated:", data)
|
|
27
|
+
* );
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export declare function liveQuery<C extends ArcContextAny, TResult>(model: Model<C>, queryFn: (q: QueryContext<C>) => Promise<TResult>, callback: (data: TResult) => void): LiveQueryResult<TResult>;
|
|
31
|
+
//# sourceMappingURL=live-query.d.ts.map
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { FindOptions, QueryListenerCallback } from "../../data-storage";
|
|
2
|
+
/**
|
|
3
|
+
* Cache for query results with change resolution
|
|
4
|
+
* Stores results per store + serialized options
|
|
5
|
+
*/
|
|
6
|
+
export declare class QueryCache {
|
|
7
|
+
private cache;
|
|
8
|
+
private onChangeCallback;
|
|
9
|
+
/**
|
|
10
|
+
* Set callback to be called when any cached result changes
|
|
11
|
+
*/
|
|
12
|
+
onChange(callback: () => void): void;
|
|
13
|
+
/**
|
|
14
|
+
* Get cache key from options
|
|
15
|
+
*/
|
|
16
|
+
private getOptionsKey;
|
|
17
|
+
/**
|
|
18
|
+
* Get or create store cache
|
|
19
|
+
*/
|
|
20
|
+
private getStoreCache;
|
|
21
|
+
/**
|
|
22
|
+
* Check if we have a cached result for this store + options
|
|
23
|
+
*/
|
|
24
|
+
has(storeName: string, options: FindOptions<any>): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Get cached result for store + options
|
|
27
|
+
*/
|
|
28
|
+
get<Item extends {
|
|
29
|
+
_id: string;
|
|
30
|
+
}>(storeName: string, options: FindOptions<Item>): Item[] | undefined;
|
|
31
|
+
/**
|
|
32
|
+
* Get or create listener for store + options
|
|
33
|
+
* Returns existing listener if already cached, or creates new one
|
|
34
|
+
*/
|
|
35
|
+
getOrCreateListener<Item extends {
|
|
36
|
+
_id: string;
|
|
37
|
+
}>(storeName: string, options: FindOptions<Item>): QueryListenerCallback<Item>;
|
|
38
|
+
/**
|
|
39
|
+
* Update cached result after fetch
|
|
40
|
+
*/
|
|
41
|
+
updateResult<Item extends {
|
|
42
|
+
_id: string;
|
|
43
|
+
}>(storeName: string, options: FindOptions<Item>, result: Item[]): void;
|
|
44
|
+
/**
|
|
45
|
+
* Apply change events to cached result
|
|
46
|
+
*/
|
|
47
|
+
private applyChanges;
|
|
48
|
+
/**
|
|
49
|
+
* Get all listeners for unsubscribing
|
|
50
|
+
*/
|
|
51
|
+
getAllListeners(): Array<{
|
|
52
|
+
storeName: string;
|
|
53
|
+
listener: QueryListenerCallback<any>;
|
|
54
|
+
}>;
|
|
55
|
+
/**
|
|
56
|
+
* Clear all cached data
|
|
57
|
+
*/
|
|
58
|
+
clear(): void;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=query-cache.d.ts.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { AuthAdapter } from "../adapters/auth-adapter";
|
|
2
|
+
import type { CommandWire } from "../adapters/command-wire";
|
|
3
|
+
import type { EventPublisher } from "../adapters/event-publisher";
|
|
4
|
+
import type { EventWire } from "../adapters/event-wire";
|
|
5
|
+
import type { DataStorage } from "../data-storage";
|
|
6
|
+
export type ModelAdapters = {
|
|
7
|
+
dataStorage?: DataStorage;
|
|
8
|
+
commandWire?: CommandWire;
|
|
9
|
+
eventPublisher?: EventPublisher;
|
|
10
|
+
eventWire?: EventWire;
|
|
11
|
+
authAdapter?: AuthAdapter;
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=model-adapters.d.ts.map
|
package/dist/model/model.d.ts
CHANGED
|
@@ -1,80 +1,21 @@
|
|
|
1
|
-
import
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
export declare class Model<C extends ArcContextAny> extends ModelBase<C> {
|
|
21
|
-
private readonly context;
|
|
22
|
-
private readonly dataStorage?;
|
|
23
|
-
private readonly catchErrorCallback?;
|
|
24
|
-
private queryCache;
|
|
25
|
-
constructor(context: C, dataStorage?: DataStorage | undefined, catchErrorCallback?: ((error: any) => void) | undefined);
|
|
26
|
-
query<Q extends IArcQueryBuilder>(queryBuilderFn: UnaryFunction<ReturnType<C["queryBuilder"]>, Q>, authContext: AuthContext): Promise<ReturnType<Q["toQuery"]>["lastResult"]>;
|
|
27
|
-
subscribe<Q extends IArcQueryBuilder>(queryBuilderFn: UnaryFunction<ReturnType<C["queryBuilder"]>, Q>, callback: (result: ReturnType<Q["toQuery"]>["lastResult"]) => void, authContext: AuthContext): {
|
|
28
|
-
result: ReturnType<Q["toQuery"]>["lastResult"];
|
|
29
|
-
unsubscribe: () => void;
|
|
30
|
-
};
|
|
31
|
-
commands(authContext: AuthContext): ArcContextElementMethodReturnType<C["elements"], "commandClient">;
|
|
32
|
-
routes(authContext: AuthContext): any;
|
|
33
|
-
get $debug(): {};
|
|
34
|
-
}
|
|
35
|
-
export declare class RemoteModelClient<C extends ArcContextAny> extends ModelBase<C> {
|
|
36
|
-
private readonly context;
|
|
37
|
-
private readonly apiBaseUrl;
|
|
38
|
-
private readonly client;
|
|
39
|
-
private readonly catchErrorCallback;
|
|
40
|
-
private queryCache;
|
|
41
|
-
private inFlightRequests;
|
|
42
|
-
constructor(context: C, apiBaseUrl: string, client: string, catchErrorCallback: (error: any) => void);
|
|
43
|
-
/**
|
|
44
|
-
* Generate a cache key from query details
|
|
45
|
-
*/
|
|
46
|
-
private generateCacheKey;
|
|
47
|
-
/**
|
|
48
|
-
* Execute the actual HTTP query request
|
|
49
|
-
*/
|
|
50
|
-
private executeQuery;
|
|
51
|
-
/**
|
|
52
|
-
* Check if a schema contains blob or file elements
|
|
53
|
-
*/
|
|
54
|
-
private schemaContainsBlobOrFile;
|
|
55
|
-
/**
|
|
56
|
-
* Recursively check object shape for blob/file elements
|
|
57
|
-
*/
|
|
58
|
-
private checkShapeForBlobOrFile;
|
|
59
|
-
/**
|
|
60
|
-
* Check if an element is a blob or file element
|
|
61
|
-
*/
|
|
62
|
-
private isBlobOrFileElement;
|
|
63
|
-
/**
|
|
64
|
-
* Convert an object to FormData, handling nested objects and blobs
|
|
65
|
-
*/
|
|
66
|
-
private objectToFormData;
|
|
67
|
-
/**
|
|
68
|
-
* Get authorization headers for API requests
|
|
69
|
-
*/
|
|
70
|
-
private getAuthHeaders;
|
|
71
|
-
query<Q extends IArcQueryBuilder>(queryBuilderFn: UnaryFunction<ReturnType<C["queryBuilder"]>, Q>, authContext: AuthContext): Promise<ReturnType<Q["toQuery"]>["lastResult"]>;
|
|
72
|
-
subscribe<Q extends IArcQueryBuilder>(queryBuilderFn: UnaryFunction<ReturnType<C["queryBuilder"]>, Q>, callback: (result: ReturnType<Q["toQuery"]>["lastResult"]) => void, authContext: AuthContext): {
|
|
73
|
-
result: ReturnType<Q["toQuery"]>["lastResult"];
|
|
74
|
-
unsubscribe: () => void;
|
|
75
|
-
};
|
|
76
|
-
commands(authContext: AuthContext): ArcContextElementMethodReturnType<C["elements"], "commandClient">;
|
|
77
|
-
routes(authContext: AuthContext): any;
|
|
1
|
+
import type { ArcEnvironment } from "../context-element/context-element";
|
|
2
|
+
import type { ArcContextAny } from "../context/context";
|
|
3
|
+
import type { ModelAdapters } from "./model-adapters";
|
|
4
|
+
export declare class Model<Context extends ArcContextAny> {
|
|
5
|
+
readonly context: Context;
|
|
6
|
+
private adapters;
|
|
7
|
+
private environment;
|
|
8
|
+
private initialized;
|
|
9
|
+
constructor(context: Context, options: {
|
|
10
|
+
adapters: ModelAdapters;
|
|
11
|
+
environment: ArcEnvironment;
|
|
12
|
+
});
|
|
13
|
+
/**
|
|
14
|
+
* Initialize all context elements
|
|
15
|
+
* Should be called after model creation
|
|
16
|
+
*/
|
|
17
|
+
init(): Promise<void>;
|
|
18
|
+
getAdapters(): ModelAdapters;
|
|
19
|
+
getEnvironment(): ArcEnvironment;
|
|
78
20
|
}
|
|
79
|
-
export {};
|
|
80
21
|
//# sourceMappingURL=model.d.ts.map
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { ArcContextAny } from "../../context/context";
|
|
2
|
+
import type { Simplify } from "../../utils";
|
|
3
|
+
import type { Model } from "../model";
|
|
4
|
+
/**
|
|
5
|
+
* Mutation Executor Type
|
|
6
|
+
*
|
|
7
|
+
* Extracts all elements that have a mutateContext method and creates
|
|
8
|
+
* a typed object with methods for executing mutations (commands).
|
|
9
|
+
*/
|
|
10
|
+
export type MutationExecutor<C extends ArcContextAny> = Simplify<{
|
|
11
|
+
[Element in C["elements"][number] as Element["mutateContext"] extends (...args: any[]) => infer Return ? Element["name"] : never]: Element["mutateContext"] extends (...args: any[]) => infer Return ? Return : never;
|
|
12
|
+
}>;
|
|
13
|
+
/**
|
|
14
|
+
* Mutation Executor
|
|
15
|
+
*
|
|
16
|
+
* Creates a typed proxy object with methods for each command in the context.
|
|
17
|
+
* Each method executes the command with proper context and handles event emission.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* const model = new Model(myContext);
|
|
22
|
+
* const mutations = mutationExecutor(model);
|
|
23
|
+
*
|
|
24
|
+
* // Type-safe command execution
|
|
25
|
+
* await mutations.createTask({ title: "New task" });
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export declare function mutationExecutor<C extends ArcContextAny>(model: Model<C>): MutationExecutor<C>;
|
|
29
|
+
//# sourceMappingURL=mutation-executor.d.ts.map
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token - Security context abstraction for Arc Framework
|
|
3
|
+
*
|
|
4
|
+
* Tokens provide a unified way to handle authentication and authorization
|
|
5
|
+
* across all layers of the application:
|
|
6
|
+
*
|
|
7
|
+
* - React hooks (useCommands with token)
|
|
8
|
+
* - Commands (protectBy)
|
|
9
|
+
* - Views/Events (protectBy) - Protection rules defined here
|
|
10
|
+
* - DataStorage (secure)
|
|
11
|
+
* - Wire (JWT)
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* // Define a token
|
|
16
|
+
* const userToken = token("user", { userId: string() })
|
|
17
|
+
* .secret(process.env.USER_SECRET)
|
|
18
|
+
* .withRules({
|
|
19
|
+
* 'task:create': async () => true,
|
|
20
|
+
* });
|
|
21
|
+
*
|
|
22
|
+
* // Define protection on view (not on token!)
|
|
23
|
+
* const tasks = view("tasks", taskId, taskSchema)
|
|
24
|
+
* .protectBy(userToken, (params) => ({
|
|
25
|
+
* read: { userId: params.userId },
|
|
26
|
+
* write: { userId: params.userId },
|
|
27
|
+
* }));
|
|
28
|
+
*
|
|
29
|
+
* // Create instance and use
|
|
30
|
+
* const instance = userToken.create({ userId: "user_123" });
|
|
31
|
+
* const jwt = instance.getJWT();
|
|
32
|
+
* const canCreate = await instance.canI('task:create');
|
|
33
|
+
* const securedStorage = secureDataStorage(dataStorage, instance, context);
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export { secureDataStorage, SecuredDataStorage, SecuredStoreState, } from "./secured-data-storage";
|
|
37
|
+
export { ArcToken, token, type ArcTokenAny } from "./token";
|
|
38
|
+
export { TokenCache, type TokenCacheOptions } from "./token-cache";
|
|
39
|
+
export type { ArcTokenData, TokenParams, TokenRule, TokenRuleContext, TokenRules, } from "./token-data";
|
|
40
|
+
export { TokenInstance, type TokenInstanceAny } from "./token-instance";
|
|
41
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SecuredDataStorage - DataStorage wrapper with token-based security
|
|
3
|
+
*
|
|
4
|
+
* Wraps a DataStorage instance and automatically applies token-based
|
|
5
|
+
* WHERE conditions to all queries. Protection rules are defined on
|
|
6
|
+
* views/events via .protectBy(), not on the token itself.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* // View defines its own protection
|
|
11
|
+
* const tasks = view("tasks", taskId, taskSchema)
|
|
12
|
+
* .protectBy(userToken, (params) => ({
|
|
13
|
+
* read: { userId: params.userId },
|
|
14
|
+
* write: { userId: params.userId },
|
|
15
|
+
* }));
|
|
16
|
+
*
|
|
17
|
+
* // SecuredDataStorage uses view's protection
|
|
18
|
+
* const securedStorage = new SecuredDataStorage(dataStorage, tokenInstance, context);
|
|
19
|
+
* const myTasks = await securedStorage.getStore("tasks").find({});
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
import type { ArcContextAny } from "../context/context";
|
|
23
|
+
import type { DataStorage } from "../data-storage/data-storage.abstract";
|
|
24
|
+
import type { FindOptions } from "../data-storage/find-options";
|
|
25
|
+
import type { StoreState } from "../data-storage/store-state.abstract";
|
|
26
|
+
import type { TokenInstanceAny } from "./token-instance";
|
|
27
|
+
/**
|
|
28
|
+
* Secured store state wrapper
|
|
29
|
+
* Applies token conditions to all queries based on view's protectBy config
|
|
30
|
+
*/
|
|
31
|
+
export declare class SecuredStoreState<Item extends {
|
|
32
|
+
_id: string;
|
|
33
|
+
}> {
|
|
34
|
+
private readonly store;
|
|
35
|
+
private readonly tokenInstance;
|
|
36
|
+
private readonly storeName;
|
|
37
|
+
private readonly context?;
|
|
38
|
+
private readonly protection;
|
|
39
|
+
constructor(store: StoreState<Item>, tokenInstance: TokenInstanceAny, storeName: string, context?: ArcContextAny | undefined);
|
|
40
|
+
/**
|
|
41
|
+
* Get protection config from view's protectBy
|
|
42
|
+
*/
|
|
43
|
+
private getProtectionFromContext;
|
|
44
|
+
/**
|
|
45
|
+
* Find items with token-based filtering
|
|
46
|
+
*/
|
|
47
|
+
find(options?: FindOptions<Item>): Promise<Item[]>;
|
|
48
|
+
/**
|
|
49
|
+
* Set item with token-based write check
|
|
50
|
+
*/
|
|
51
|
+
set(item: Item): Promise<void>;
|
|
52
|
+
/**
|
|
53
|
+
* Remove item with token-based write check
|
|
54
|
+
*/
|
|
55
|
+
remove(id: string): Promise<void>;
|
|
56
|
+
/**
|
|
57
|
+
* Modify item with token-based write check
|
|
58
|
+
*/
|
|
59
|
+
modify(id: string, data: Partial<Item>): Promise<{
|
|
60
|
+
from: Item | null;
|
|
61
|
+
to: Item | null;
|
|
62
|
+
}>;
|
|
63
|
+
/**
|
|
64
|
+
* Apply changes with token-based write check
|
|
65
|
+
*/
|
|
66
|
+
applyChanges(changes: any[]): Promise<void>;
|
|
67
|
+
/**
|
|
68
|
+
* Fork the store (returns unsecured fork)
|
|
69
|
+
*/
|
|
70
|
+
fork(): import("..").ForkedStoreState<Item>;
|
|
71
|
+
/**
|
|
72
|
+
* Apply token condition to find options
|
|
73
|
+
*/
|
|
74
|
+
private applyTokenCondition;
|
|
75
|
+
/**
|
|
76
|
+
* Check if write is allowed
|
|
77
|
+
*/
|
|
78
|
+
private canWrite;
|
|
79
|
+
/**
|
|
80
|
+
* Get write condition
|
|
81
|
+
*/
|
|
82
|
+
private getWriteCondition;
|
|
83
|
+
/**
|
|
84
|
+
* Check if item matches a condition (simple implementation)
|
|
85
|
+
*/
|
|
86
|
+
private itemMatchesCondition;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* SecuredDataStorage - DataStorage wrapper with token-based security
|
|
90
|
+
*/
|
|
91
|
+
export declare class SecuredDataStorage {
|
|
92
|
+
private readonly dataStorage;
|
|
93
|
+
private readonly tokenInstance;
|
|
94
|
+
private readonly context?;
|
|
95
|
+
private readonly storeCache;
|
|
96
|
+
constructor(dataStorage: DataStorage, tokenInstance: TokenInstanceAny, context?: ArcContextAny | undefined);
|
|
97
|
+
/**
|
|
98
|
+
* Get a secured store by name
|
|
99
|
+
*/
|
|
100
|
+
getStore<Item extends {
|
|
101
|
+
_id: string;
|
|
102
|
+
}>(storeName: string): SecuredStoreState<Item>;
|
|
103
|
+
/**
|
|
104
|
+
* Get the underlying unsecured DataStorage
|
|
105
|
+
* Use with caution!
|
|
106
|
+
*/
|
|
107
|
+
getUnsecuredStorage(): DataStorage;
|
|
108
|
+
/**
|
|
109
|
+
* Get the token instance used for security
|
|
110
|
+
*/
|
|
111
|
+
getTokenInstance(): TokenInstanceAny;
|
|
112
|
+
/**
|
|
113
|
+
* Fork the data storage (returns unsecured fork)
|
|
114
|
+
*/
|
|
115
|
+
fork(): import("..").ForkedDataStorage;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Create a SecuredDataStorage from DataStorage and token instance
|
|
119
|
+
*
|
|
120
|
+
* @param dataStorage - The DataStorage to secure
|
|
121
|
+
* @param tokenInstance - Token instance for security context
|
|
122
|
+
* @param context - Optional context to get view protections from
|
|
123
|
+
*/
|
|
124
|
+
export declare function secureDataStorage(dataStorage: DataStorage, tokenInstance: TokenInstanceAny, context?: ArcContextAny): SecuredDataStorage;
|
|
125
|
+
//# sourceMappingURL=secured-data-storage.d.ts.map
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TokenCache - Server-side caching for resolved tokens
|
|
3
|
+
*
|
|
4
|
+
* Caches token instances and permission results to avoid
|
|
5
|
+
* repeated database queries for the same token.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* const cache = new TokenCache({ ttl: 60000 }); // 1 minute TTL
|
|
10
|
+
*
|
|
11
|
+
* // Get or create cached instance
|
|
12
|
+
* const instance = await cache.getOrCreate(jwt, () => token.parseJWT(jwt));
|
|
13
|
+
*
|
|
14
|
+
* // Cache permission results
|
|
15
|
+
* const canEdit = await cache.getPermission(instance, 'form:edit', () =>
|
|
16
|
+
* instance.canI('form:edit')
|
|
17
|
+
* );
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
import type { TokenInstanceAny } from "./token-instance";
|
|
21
|
+
export interface TokenCacheOptions {
|
|
22
|
+
/**
|
|
23
|
+
* Time-to-live in milliseconds
|
|
24
|
+
* Default: 5 minutes
|
|
25
|
+
*/
|
|
26
|
+
ttl?: number;
|
|
27
|
+
/**
|
|
28
|
+
* Maximum number of cached entries
|
|
29
|
+
* Default: 1000
|
|
30
|
+
*/
|
|
31
|
+
maxSize?: number;
|
|
32
|
+
}
|
|
33
|
+
export declare class TokenCache {
|
|
34
|
+
private readonly instanceCache;
|
|
35
|
+
private readonly permissionCache;
|
|
36
|
+
private readonly ttl;
|
|
37
|
+
private readonly maxSize;
|
|
38
|
+
constructor(options?: TokenCacheOptions);
|
|
39
|
+
/**
|
|
40
|
+
* Get cached token instance or create new one
|
|
41
|
+
*
|
|
42
|
+
* @param jwt - JWT string as cache key
|
|
43
|
+
* @param factory - Function to create instance if not cached
|
|
44
|
+
*/
|
|
45
|
+
getOrCreate<T extends TokenInstanceAny>(jwt: string, factory: () => T | null | Promise<T | null>): Promise<T | null>;
|
|
46
|
+
/**
|
|
47
|
+
* Get cached permission result or compute it
|
|
48
|
+
*
|
|
49
|
+
* @param instance - Token instance
|
|
50
|
+
* @param permission - Permission name
|
|
51
|
+
* @param factory - Function to compute permission if not cached
|
|
52
|
+
*/
|
|
53
|
+
getPermission(instance: TokenInstanceAny, permission: string, factory: () => Promise<boolean>): Promise<boolean>;
|
|
54
|
+
/**
|
|
55
|
+
* Cache a token instance
|
|
56
|
+
*/
|
|
57
|
+
private setInstance;
|
|
58
|
+
/**
|
|
59
|
+
* Cache a permission result
|
|
60
|
+
*/
|
|
61
|
+
private setPermission;
|
|
62
|
+
/**
|
|
63
|
+
* Generate cache key for permission
|
|
64
|
+
*/
|
|
65
|
+
private getPermissionKey;
|
|
66
|
+
/**
|
|
67
|
+
* Ensure cache doesn't exceed max size
|
|
68
|
+
*/
|
|
69
|
+
private ensureCapacity;
|
|
70
|
+
/**
|
|
71
|
+
* Invalidate all cached data for a specific token instance
|
|
72
|
+
*
|
|
73
|
+
* @param instance - Token instance to invalidate
|
|
74
|
+
*/
|
|
75
|
+
invalidateInstance(instance: TokenInstanceAny): void;
|
|
76
|
+
/**
|
|
77
|
+
* Invalidate a specific JWT
|
|
78
|
+
*
|
|
79
|
+
* @param jwt - JWT string to invalidate
|
|
80
|
+
*/
|
|
81
|
+
invalidateJWT(jwt: string): void;
|
|
82
|
+
/**
|
|
83
|
+
* Clear all cached data
|
|
84
|
+
*/
|
|
85
|
+
clear(): void;
|
|
86
|
+
/**
|
|
87
|
+
* Remove expired entries
|
|
88
|
+
*/
|
|
89
|
+
cleanup(): void;
|
|
90
|
+
/**
|
|
91
|
+
* Get cache statistics
|
|
92
|
+
*/
|
|
93
|
+
getStats(): {
|
|
94
|
+
instanceCount: number;
|
|
95
|
+
permissionCount: number;
|
|
96
|
+
maxSize: number;
|
|
97
|
+
ttl: number;
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=token-cache.d.ts.map
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token Data Types
|
|
3
|
+
*
|
|
4
|
+
* Type definitions for the Token security abstraction
|
|
5
|
+
*/
|
|
6
|
+
import type { ArcContextElement } from "../context-element/context-element";
|
|
7
|
+
import type { ArcObject, ArcRawShape } from "../elements/object";
|
|
8
|
+
/**
|
|
9
|
+
* Token parameters schema - defines what data the token carries
|
|
10
|
+
*/
|
|
11
|
+
export type TokenParams = Record<string, any>;
|
|
12
|
+
/**
|
|
13
|
+
* Context provided to rule functions
|
|
14
|
+
* Contains query elements for checking permissions
|
|
15
|
+
*/
|
|
16
|
+
export type TokenRuleContext<QueryElements extends ArcContextElement<any>[]> = {
|
|
17
|
+
[K in QueryElements[number] as K["name"]]: K["queryContext"] extends (...args: any) => infer R ? R : never;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Rule function signature
|
|
21
|
+
* Async function that checks if permission is granted
|
|
22
|
+
*/
|
|
23
|
+
export type TokenRule<Params extends TokenParams, QueryElements extends ArcContextElement<any>[]> = (ctx: TokenRuleContext<QueryElements>, params: Params) => Promise<boolean>;
|
|
24
|
+
/**
|
|
25
|
+
* Rules map - permission name to rule function
|
|
26
|
+
*/
|
|
27
|
+
export type TokenRules<Params extends TokenParams, QueryElements extends ArcContextElement<any>[]> = Record<string, TokenRule<Params, QueryElements>>;
|
|
28
|
+
/**
|
|
29
|
+
* Token data structure - internal configuration
|
|
30
|
+
*/
|
|
31
|
+
export type ArcTokenData<Name extends string = string, ParamsShape extends ArcRawShape = ArcRawShape, QueryElements extends ArcContextElement<any>[] = ArcContextElement<any>[], Rules extends TokenRules<any, QueryElements> = TokenRules<any, QueryElements>> = {
|
|
32
|
+
name: Name;
|
|
33
|
+
paramsSchema: ArcObject<ParamsShape>;
|
|
34
|
+
secret?: string;
|
|
35
|
+
queryElements: QueryElements;
|
|
36
|
+
rules: Rules;
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=token-data.d.ts.map
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TokenInstance - A concrete instance of a token with actual parameter values
|
|
3
|
+
*
|
|
4
|
+
* Created from:
|
|
5
|
+
* - token.create({ userId: "123" })
|
|
6
|
+
* - token.parseJWT(jwtString)
|
|
7
|
+
*
|
|
8
|
+
* Used for:
|
|
9
|
+
* - Permission checks: instance.canI('form:edit')
|
|
10
|
+
* - JWT generation: instance.getJWT()
|
|
11
|
+
*/
|
|
12
|
+
import type { ModelAdapters } from "../model/model-adapters";
|
|
13
|
+
import type { TokenParams } from "./token-data";
|
|
14
|
+
/**
|
|
15
|
+
* Interface for token definition (avoids circular import)
|
|
16
|
+
*/
|
|
17
|
+
export interface ITokenDefinition {
|
|
18
|
+
name: string;
|
|
19
|
+
checkPermission(permission: string, params: any, adapters?: ModelAdapters): Promise<boolean>;
|
|
20
|
+
generateJWT(params: any, expiresIn?: number): string;
|
|
21
|
+
}
|
|
22
|
+
export declare class TokenInstance<Params extends TokenParams, RuleNames extends string = string> {
|
|
23
|
+
private readonly token;
|
|
24
|
+
readonly params: Params;
|
|
25
|
+
private readonly adapters?;
|
|
26
|
+
constructor(token: ITokenDefinition, params: Params, adapters?: ModelAdapters | undefined);
|
|
27
|
+
/**
|
|
28
|
+
* Check if this token instance has a specific permission
|
|
29
|
+
*
|
|
30
|
+
* @param permission - Permission name (e.g., 'form:edit')
|
|
31
|
+
* @returns Promise<boolean> - Whether permission is granted
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```typescript
|
|
35
|
+
* if (await tokenInstance.canI('form:edit')) {
|
|
36
|
+
* // User can edit form
|
|
37
|
+
* }
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
canI(permission: RuleNames): Promise<boolean>;
|
|
41
|
+
/**
|
|
42
|
+
* Generate JWT string from this token instance
|
|
43
|
+
*
|
|
44
|
+
* @returns JWT string containing token name and params
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```typescript
|
|
48
|
+
* const jwt = tokenInstance.getJWT();
|
|
49
|
+
* // Use in Authorization header
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
getJWT(): string;
|
|
53
|
+
/**
|
|
54
|
+
* Get the token definition this instance was created from
|
|
55
|
+
*/
|
|
56
|
+
getTokenDefinition(): ITokenDefinition;
|
|
57
|
+
/**
|
|
58
|
+
* Get token name
|
|
59
|
+
*/
|
|
60
|
+
get name(): string;
|
|
61
|
+
/**
|
|
62
|
+
* Create a new instance with updated adapters
|
|
63
|
+
* Used when adapters become available later
|
|
64
|
+
*/
|
|
65
|
+
withAdapters(adapters: ModelAdapters): TokenInstance<Params, RuleNames>;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Type helper for any token instance
|
|
69
|
+
*/
|
|
70
|
+
export type TokenInstanceAny = TokenInstance<any, any>;
|
|
71
|
+
//# sourceMappingURL=token-instance.d.ts.map
|