@arcote.tech/arc 0.4.10 → 0.5.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/context-element/aggregate/aggregate-data.d.ts +12 -32
- package/dist/context-element/aggregate/aggregate-element.d.ts +58 -31
- package/dist/context-element/command/command-context.d.ts +7 -25
- package/dist/context-element/command/command-data.d.ts +4 -13
- package/dist/context-element/command/command.d.ts +11 -121
- package/dist/context-element/command/index.d.ts +1 -1
- package/dist/context-element/element-context.d.ts +25 -15
- package/dist/context-element/function/arc-function-data.d.ts +70 -0
- package/dist/context-element/function/arc-function.d.ts +119 -0
- package/dist/context-element/function/index.d.ts +3 -0
- package/dist/context-element/index.d.ts +1 -0
- package/dist/context-element/listener/listener.d.ts +12 -93
- package/dist/context-element/route/route.d.ts +7 -68
- package/dist/elements/object.d.ts +4 -4
- package/dist/index.js +291 -216
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/merge-unsafe.d.ts +6 -0
- package/package.json +1 -1
|
@@ -6,22 +6,17 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import type { ArcIdAny } from "../../elements/id";
|
|
8
8
|
import type { ArcObjectAny } from "../../elements/object";
|
|
9
|
-
import type { ArcEventAny } from "../event/event";
|
|
10
9
|
import type { Simplify } from "../../utils";
|
|
10
|
+
import type { ArcEventAny } from "../event/event";
|
|
11
11
|
import type { ArcEventInstance } from "../event/instance";
|
|
12
12
|
import type { ArcViewHandlerContext } from "../view/view-context";
|
|
13
13
|
import type { ViewProtection } from "../view/view-data";
|
|
14
14
|
/**
|
|
15
15
|
* Handler for an aggregate event — same signature as ArcView handler.
|
|
16
|
-
* Receives ctx with set/modify/remove and the event instance.
|
|
17
16
|
*/
|
|
18
17
|
export type AggregateEventHandler<Id extends ArcIdAny, Schema extends ArcObjectAny, Event extends ArcEventAny> = (ctx: ArcViewHandlerContext<Id, Schema>, event: ArcEventInstance<Event>) => Promise<void>;
|
|
19
18
|
/**
|
|
20
19
|
* Entry in the aggregate's event registry.
|
|
21
|
-
* Pairs an ArcEvent instance with its view handler.
|
|
22
|
-
*
|
|
23
|
-
* - isInline: true if event was created via .event() or .publicEvent() (inline definition)
|
|
24
|
-
* - isPublic: true if event was created via .publicEvent() (accessible via getEvent())
|
|
25
20
|
*/
|
|
26
21
|
export interface AggregateEventEntry<Event extends ArcEventAny = ArcEventAny, Id extends ArcIdAny = ArcIdAny, Schema extends ArcObjectAny = ArcObjectAny, IsPublic extends boolean = boolean> {
|
|
27
22
|
readonly event: Event;
|
|
@@ -29,34 +24,19 @@ export interface AggregateEventEntry<Event extends ArcEventAny = ArcEventAny, Id
|
|
|
29
24
|
readonly isInline: boolean;
|
|
30
25
|
readonly isPublic: IsPublic;
|
|
31
26
|
}
|
|
32
|
-
/**
|
|
33
|
-
* Context passed to mutateMethod handlers.
|
|
34
|
-
* Provides emit per registered event + $auth from adapters.
|
|
35
|
-
*/
|
|
36
|
-
export type AggregateMutateContext<Events extends AggregateEventEntry[]> = {
|
|
37
|
-
[E in Events[number] as E["event"]["name"]]: {
|
|
38
|
-
emit: (payload: any) => Promise<void>;
|
|
39
|
-
};
|
|
40
|
-
} & {
|
|
41
|
-
$auth: {
|
|
42
|
-
params: any;
|
|
43
|
-
tokenName: string;
|
|
44
|
-
};
|
|
45
|
-
};
|
|
46
27
|
/**
|
|
47
28
|
* Entry in the aggregate's mutateMethod registry.
|
|
48
|
-
*
|
|
29
|
+
* Stores the ArcFunction for runtime infrastructure + fields for type extraction.
|
|
49
30
|
*/
|
|
50
31
|
export interface AggregateMutateMethodEntry {
|
|
51
32
|
readonly name: string;
|
|
52
|
-
readonly params: ArcObjectAny;
|
|
53
|
-
readonly handler:
|
|
33
|
+
readonly params: ArcObjectAny | null;
|
|
34
|
+
readonly handler: Function | false | null;
|
|
54
35
|
readonly result?: any;
|
|
55
36
|
readonly cronExpression?: string;
|
|
56
37
|
}
|
|
57
38
|
/**
|
|
58
39
|
* Cron method entry extracted at build time.
|
|
59
|
-
* Used by CronScheduler to discover and register cron jobs.
|
|
60
40
|
*/
|
|
61
41
|
export interface AggregateCronMethodEntry {
|
|
62
42
|
readonly aggregateName: string;
|
|
@@ -65,17 +45,15 @@ export interface AggregateCronMethodEntry {
|
|
|
65
45
|
}
|
|
66
46
|
/**
|
|
67
47
|
* Entry in the aggregate's clientQuery registry.
|
|
68
|
-
* Defines a named query exposed via queryContext/useQuery.
|
|
69
48
|
*/
|
|
70
49
|
export interface AggregateQueryMethodEntry {
|
|
71
50
|
readonly name: string;
|
|
72
|
-
readonly handler:
|
|
51
|
+
readonly handler: Function | false | null;
|
|
73
52
|
}
|
|
74
53
|
/**
|
|
75
|
-
*
|
|
76
|
-
*
|
|
54
|
+
* Resolve mutateMethod return type from entry fields.
|
|
55
|
+
* explicit result > handler return > Promise<any>
|
|
77
56
|
*/
|
|
78
|
-
/** Resolve mutateMethod return type: explicit result > handler return > Promise<any> */
|
|
79
57
|
type MutateReturn<M> = M extends {
|
|
80
58
|
result: infer R;
|
|
81
59
|
} ? [R] extends [never] ? M extends {
|
|
@@ -83,6 +61,10 @@ type MutateReturn<M> = M extends {
|
|
|
83
61
|
} ? Promise<HR> : Promise<any> : Promise<R> : M extends {
|
|
84
62
|
handlerReturn: infer HR;
|
|
85
63
|
} ? Promise<HR> : Promise<any>;
|
|
64
|
+
/**
|
|
65
|
+
* Maps MutateMethods tuple → { methodName: (params) => Promise<ReturnType> }
|
|
66
|
+
* Used as return type of mutateContext().
|
|
67
|
+
*/
|
|
86
68
|
export type AggregateMutateMethodContext<MutateMethods extends AggregateMutateMethodEntry[]> = {
|
|
87
69
|
[M in MutateMethods[number] as M["name"]]: M["params"] extends {
|
|
88
70
|
deserialize: (...a: any) => infer P;
|
|
@@ -90,15 +72,13 @@ export type AggregateMutateMethodContext<MutateMethods extends AggregateMutateMe
|
|
|
90
72
|
};
|
|
91
73
|
/**
|
|
92
74
|
* Maps QueryMethods tuple → { methodName: consumer API }
|
|
93
|
-
* Extracts
|
|
94
|
-
* Uses rest args pattern so handlers without params produce no-arg consumer methods.
|
|
75
|
+
* Extracts args and return type directly from handler (same as pre-refactor).
|
|
95
76
|
*/
|
|
96
77
|
export type AggregateQueryContext<QueryMethods extends AggregateQueryMethodEntry[]> = {
|
|
97
78
|
[M in QueryMethods[number] as M["name"]]: M["handler"] extends (ctx: any, ...args: infer Args) => Promise<infer R> ? (...args: Args) => Promise<Simplify<R>> : never;
|
|
98
79
|
};
|
|
99
80
|
/**
|
|
100
81
|
* Static configuration stored on the aggregate constructor.
|
|
101
|
-
* Read by aggregateContextElement() to build the ArcContextElement.
|
|
102
82
|
*/
|
|
103
83
|
export interface AggregateStaticConfig {
|
|
104
84
|
readonly __aggregateName: string;
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* ArcAggregateElement — unified aggregate builder + context element.
|
|
3
3
|
*
|
|
4
|
-
* aggregate() returns this directly. No .build()
|
|
4
|
+
* aggregate() returns this directly. No .build() needed.
|
|
5
5
|
* Each builder method returns a new immutable instance.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* - getHandlers() / getElements() → for eventPublisher registration
|
|
11
|
-
* - databaseStoreSchema() → table schema
|
|
7
|
+
* mutateMethod/clientQuery use the ArcFunction callback pattern:
|
|
8
|
+
* .mutateMethod('create', fn => fn.withParams({...}).handle(...))
|
|
9
|
+
* .clientQuery('getAll', fn => fn.handle(async ctx => ctx.$query.find({})))
|
|
12
10
|
*/
|
|
13
11
|
import type { DatabaseStoreSchema } from "../../data-storage/database-store";
|
|
14
12
|
import type { ArcIdAny } from "../../elements/id";
|
|
@@ -20,6 +18,8 @@ import type { ArcTokenAny } from "../../token/token";
|
|
|
20
18
|
import { ArcContextElement } from "../context-element";
|
|
21
19
|
import { ArcEvent, type ArcEventAny } from "../event/event";
|
|
22
20
|
import type { ArcEventInstance } from "../event/instance";
|
|
21
|
+
import { ArcFunction, type DefaultFunctionData } from "../function/arc-function";
|
|
22
|
+
import type { ArcFunctionData } from "../function/arc-function-data";
|
|
23
23
|
import type { ArcViewHandlerContext, ArcViewItem } from "../view/view-context";
|
|
24
24
|
import type { ViewProtection, ViewProtectionFn } from "../view/view-data";
|
|
25
25
|
import { AggregateBase } from "./aggregate-base";
|
|
@@ -42,7 +42,11 @@ type AggregatePrivateQuery<Id extends ArcIdAny, Schema extends ArcObjectAny> = {
|
|
|
42
42
|
(where?: any): Promise<AggregateRow<Id, Schema> | undefined>;
|
|
43
43
|
};
|
|
44
44
|
};
|
|
45
|
-
|
|
45
|
+
/**
|
|
46
|
+
* ExtraCtx for mutateMethod handlers.
|
|
47
|
+
* Event emitters + $query + $auth — injected by aggregate.
|
|
48
|
+
*/
|
|
49
|
+
type MutateMethodExtraCtx<Id extends ArcIdAny, Schema extends ArcObjectAny, Events extends AggregateEventEntry[]> = {
|
|
46
50
|
[E in Events[number] as E["event"]["name"]]: {
|
|
47
51
|
emit: (payload: E["event"]["payload"] extends {
|
|
48
52
|
deserialize: (...a: any) => any;
|
|
@@ -55,7 +59,10 @@ type MutateMethodContext<Id extends ArcIdAny, Schema extends ArcObjectAny, Event
|
|
|
55
59
|
};
|
|
56
60
|
$query: AggregatePrivateQuery<Id, Schema>;
|
|
57
61
|
};
|
|
58
|
-
|
|
62
|
+
/**
|
|
63
|
+
* ExtraCtx for clientQuery handlers.
|
|
64
|
+
*/
|
|
65
|
+
type ClientQueryExtraCtx<Id extends ArcIdAny, Schema extends ArcObjectAny, Events extends AggregateEventEntry[]> = {
|
|
59
66
|
$query: AggregatePrivateQuery<Id, Schema>;
|
|
60
67
|
$auth: {
|
|
61
68
|
params: any;
|
|
@@ -91,10 +98,8 @@ export type AggregateConstructor<Id extends ArcIdAny = ArcIdAny, Schema extends
|
|
|
91
98
|
getEvent<EventName extends PublicEventNames<Events>>(name: EventName): GetPublicEvent<Events, EventName>;
|
|
92
99
|
};
|
|
93
100
|
export type AggregateConstructorAny = AggregateConstructor<any, any, any>;
|
|
94
|
-
/** Extract the full row type from an aggregate element. */
|
|
95
101
|
export type AggregateData<El extends ArcAggregateElement<any, any, any, any, any>> = AggregateRow<El extends ArcAggregateElement<infer _N, infer I, any, any, any> ? I : never, El extends ArcAggregateElement<infer _N, any, infer S, any, any> ? S : never>;
|
|
96
102
|
export declare class ArcAggregateElement<Name extends string = string, Id extends ArcIdAny = ArcIdAny, Schema extends ArcObjectAny = ArcObjectAny, Events extends AggregateEventEntry[] = AggregateEventEntry[], MutateMethods extends AggregateMutateMethodEntry[] = AggregateMutateMethodEntry[], QueryMethods extends AggregateQueryMethodEntry[] = AggregateQueryMethodEntry[]> extends ArcContextElement<Name> {
|
|
97
|
-
/** Expose schema for eventPublisher view registration (duck typing) */
|
|
98
103
|
readonly schema: Schema;
|
|
99
104
|
private readonly _id_factory;
|
|
100
105
|
private readonly _events;
|
|
@@ -119,53 +124,75 @@ export declare class ArcAggregateElement<Name extends string = string, Id extend
|
|
|
119
124
|
...Events,
|
|
120
125
|
AggregateEventEntry<E, ArcIdAny, ArcObjectAny, false>
|
|
121
126
|
], MutateMethods, QueryMethods>;
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
127
|
+
/**
|
|
128
|
+
* Define a mutation method using ArcFunction callback pattern.
|
|
129
|
+
*
|
|
130
|
+
* The callback receives an ArcFunction pre-configured with ExtraCtx
|
|
131
|
+
* containing event emitters, $query, and $auth.
|
|
132
|
+
*
|
|
133
|
+
* @example
|
|
134
|
+
* ```typescript
|
|
135
|
+
* .mutateMethod('create', fn => fn
|
|
136
|
+
* .withParams({ title: string() })
|
|
137
|
+
* .withResult({ id: string() })
|
|
138
|
+
* .handle(async (ctx, params) => {
|
|
139
|
+
* const id = taskId.generate();
|
|
140
|
+
* await ctx.created.emit({ title: params.title });
|
|
141
|
+
* return { id };
|
|
142
|
+
* })
|
|
143
|
+
* )
|
|
144
|
+
* ```
|
|
145
|
+
*/
|
|
146
|
+
mutateMethod<const MethodName extends string, ReturnFn extends ArcFunction<ArcFunctionData, MutateMethodExtraCtx<Id, Schema, Events>>>(methodName: MethodName, configure: (fn: ArcFunction<DefaultFunctionData, MutateMethodExtraCtx<Id, Schema, Events>>) => ReturnFn): ArcAggregateElement<Name, Id, Schema, Events, [
|
|
126
147
|
...MutateMethods,
|
|
127
148
|
{
|
|
128
149
|
name: MethodName;
|
|
129
|
-
params:
|
|
130
|
-
handler:
|
|
131
|
-
handlerReturn: HR;
|
|
132
|
-
result:
|
|
150
|
+
params: ReturnFn["data"]["params"];
|
|
151
|
+
handler: ReturnFn["data"]["handler"];
|
|
152
|
+
handlerReturn: ReturnFn["data"]["handler"] extends (...args: any[]) => Promise<infer HR> ? HR : void;
|
|
153
|
+
result: ReturnFn["data"]["result"] extends ArcObjectAny ? $type<ReturnFn["data"]["result"]> : never;
|
|
133
154
|
}
|
|
134
155
|
], QueryMethods>;
|
|
135
156
|
cron(expression: string): ArcAggregateElement<Name, Id, Schema, Events, MutateMethods, QueryMethods>;
|
|
136
|
-
|
|
157
|
+
/**
|
|
158
|
+
* Define a client query method using ArcFunction callback pattern.
|
|
159
|
+
*
|
|
160
|
+
* The callback receives an ArcFunction pre-configured with ExtraCtx
|
|
161
|
+
* containing $query, $auth, and Aggregate constructor.
|
|
162
|
+
*
|
|
163
|
+
* @example
|
|
164
|
+
* ```typescript
|
|
165
|
+
* .clientQuery('getAll', fn => fn
|
|
166
|
+
* .handle(async (ctx) => ctx.$query.find({}))
|
|
167
|
+
* )
|
|
168
|
+
* .clientQuery('getById', fn => fn
|
|
169
|
+
* .withParams({ id: taskId })
|
|
170
|
+
* .handle(async (ctx, { id }) => ctx.$query.findOne({ _id: id }))
|
|
171
|
+
* )
|
|
172
|
+
* ```
|
|
173
|
+
*/
|
|
174
|
+
clientQuery<const MethodName extends string, ReturnFn extends ArcFunction<ArcFunctionData, ClientQueryExtraCtx<Id, Schema, Events>>>(methodName: MethodName, configure: (fn: ArcFunction<DefaultFunctionData, ClientQueryExtraCtx<Id, Schema, Events>>) => ReturnFn): ArcAggregateElement<Name, Id, Schema, Events, MutateMethods, [
|
|
137
175
|
...QueryMethods,
|
|
138
176
|
{
|
|
139
177
|
name: MethodName;
|
|
140
|
-
handler:
|
|
178
|
+
handler: ReturnFn["data"]["handler"];
|
|
141
179
|
}
|
|
142
180
|
]>;
|
|
143
|
-
/**
|
|
144
|
-
* Declare seed data inserted after table creation.
|
|
145
|
-
* Rows with `_id` use it as-is; rows without get auto-generated IDs.
|
|
146
|
-
*/
|
|
147
181
|
seedWith(data: Array<$type<Schema> & {
|
|
148
182
|
_id?: $type<Id>;
|
|
149
183
|
}>, options?: {
|
|
150
184
|
version?: number;
|
|
151
185
|
}): ArcAggregateElement<Name, Id, Schema, Events, MutateMethods, QueryMethods>;
|
|
152
|
-
/**
|
|
153
|
-
* Return a copy with seed data attached.
|
|
154
|
-
* Use with context.replace() to add seeds to framework-provided aggregates.
|
|
155
|
-
*/
|
|
156
186
|
withSeeds(data: Array<$type<Schema> & {
|
|
157
187
|
_id?: $type<Id>;
|
|
158
188
|
}>, options?: {
|
|
159
189
|
version?: number;
|
|
160
190
|
}): ArcAggregateElement<Name, Id, Schema, Events, MutateMethods, QueryMethods>;
|
|
161
|
-
/** The internal AggregateConstructor class. Use in clientQuery to extend with business methods. */
|
|
162
191
|
get Aggregate(): AggregateConstructor<Id, Schema, Events>;
|
|
163
192
|
private buildConstructor;
|
|
164
193
|
getHandlers(): Record<string, (ctx: any, event: any) => Promise<void>>;
|
|
165
194
|
getElements(): ArcEventAny[];
|
|
166
|
-
/** Public event accessor (same as old static getEvent) */
|
|
167
195
|
getEvent<EventName extends PublicEventNames<Events>>(eventName: EventName): GetPublicEvent<Events, EventName>;
|
|
168
|
-
/** Cron methods for CronScheduler discovery */
|
|
169
196
|
get cronMethods(): AggregateCronMethodEntry[];
|
|
170
197
|
queryContext(adapters: ModelAdapters): AggregateQueryContext<QueryMethods>;
|
|
171
198
|
private buildPrivateQuery;
|
|
@@ -1,34 +1,16 @@
|
|
|
1
|
-
import type { ArcToken, ArcTokenAny } from "../../token/token";
|
|
2
|
-
import type { $type } from "../../utils/types/get-type";
|
|
3
1
|
import type { ArcContextElement } from "../context-element";
|
|
4
2
|
import type { ElementContext } from "../element-context";
|
|
5
|
-
import type {
|
|
6
|
-
/**
|
|
7
|
-
* Extract token params type from a token
|
|
8
|
-
*/
|
|
9
|
-
type TokenParams<T extends ArcTokenAny> = T extends {
|
|
10
|
-
paramsSchema: infer P extends {
|
|
11
|
-
deserialize: (...args: any) => any;
|
|
12
|
-
};
|
|
13
|
-
} ? $type<P> : Record<string, any>;
|
|
14
|
-
/**
|
|
15
|
-
* Auth context type for protected commands
|
|
16
|
-
* Provides access to token params from the authenticated user
|
|
17
|
-
*/
|
|
18
|
-
export type AuthContext<T extends ArcTokenAny> = {
|
|
19
|
-
params: TokenParams<T>;
|
|
20
|
-
tokenName: T extends ArcToken<infer Name, any, any, any> ? Name : string;
|
|
21
|
-
};
|
|
3
|
+
import type { FnAuthContext, FnProtection } from "../function/arc-function-data";
|
|
22
4
|
/**
|
|
23
5
|
* Extract union of all token types from protections array
|
|
24
6
|
*/
|
|
25
|
-
type ProtectionTokens<Protections extends
|
|
7
|
+
type ProtectionTokens<Protections extends FnProtection[]> = Protections[number]["token"];
|
|
26
8
|
/**
|
|
27
|
-
* Command context provided to command handlers
|
|
28
|
-
* Extends shared ElementContext with
|
|
9
|
+
* Command context provided to command handlers.
|
|
10
|
+
* Extends shared ElementContext with $auth from protectedBy().
|
|
29
11
|
*/
|
|
30
|
-
export type ArcCommandContext<QueryElements extends ArcContextElement<any>[], MutationElements extends ArcContextElement<any>[], Protections extends
|
|
31
|
-
$auth:
|
|
12
|
+
export type ArcCommandContext<QueryElements extends ArcContextElement<any>[], MutationElements extends ArcContextElement<any>[], Protections extends FnProtection[] = []> = ElementContext<QueryElements, MutationElements> & (Protections extends [] ? object : {
|
|
13
|
+
$auth: FnAuthContext<ProtectionTokens<Protections>>;
|
|
32
14
|
});
|
|
33
15
|
/**
|
|
34
16
|
* Helper type to extract command context from command data
|
|
@@ -36,7 +18,7 @@ export type ArcCommandContext<QueryElements extends ArcContextElement<any>[], Mu
|
|
|
36
18
|
export type ArcCommandContextFromData<Data> = Data extends {
|
|
37
19
|
queryElements: infer Q extends ArcContextElement<any>[];
|
|
38
20
|
mutationElements: infer M extends ArcContextElement<any>[];
|
|
39
|
-
protections?: infer P extends
|
|
21
|
+
protections?: infer P extends FnProtection[];
|
|
40
22
|
} ? ArcCommandContext<Q, M, P extends undefined ? [] : P> : never;
|
|
41
23
|
export {};
|
|
42
24
|
//# sourceMappingURL=command-context.d.ts.map
|
|
@@ -1,23 +1,14 @@
|
|
|
1
1
|
import type { ArcObjectAny } from "../../elements/object";
|
|
2
|
-
import type { ArcTokenAny } from "../../token/token";
|
|
3
|
-
import type { TokenInstanceAny } from "../../token/token-instance";
|
|
4
2
|
import type { ArcContextElement } from "../context-element";
|
|
3
|
+
import type { FnProtection, FnProtectionCheck } from "../function/arc-function-data";
|
|
5
4
|
import type { ArcCommandHandler } from "./command-handler";
|
|
6
5
|
/**
|
|
7
|
-
* Protection
|
|
8
|
-
* Receives token instance and returns whether access is allowed
|
|
6
|
+
* Protection types — aliases for unified FnProtection
|
|
9
7
|
*/
|
|
10
|
-
export type
|
|
11
|
-
|
|
12
|
-
* Protection configuration for a command
|
|
13
|
-
*/
|
|
14
|
-
export type CommandProtection = {
|
|
15
|
-
token: ArcTokenAny;
|
|
16
|
-
check: CommandProtectionCheck<any>;
|
|
17
|
-
};
|
|
8
|
+
export type CommandProtection = FnProtection;
|
|
9
|
+
export type CommandProtectionCheck<T> = FnProtectionCheck<any>;
|
|
18
10
|
/**
|
|
19
11
|
* Command data configuration
|
|
20
|
-
* Contains all generic types and non-generic configuration in one object
|
|
21
12
|
*/
|
|
22
13
|
export type ArcCommandData = {
|
|
23
14
|
name: string;
|
|
@@ -6,160 +6,68 @@ import type { TokenInstanceAny } from "../../token/token-instance";
|
|
|
6
6
|
import type { Merge } from "../../utils";
|
|
7
7
|
import type { $type } from "../../utils/types/get-type";
|
|
8
8
|
import { ArcContextElement } from "../context-element";
|
|
9
|
+
import { ArcFunction } from "../function/arc-function";
|
|
10
|
+
import type { FnProtection, FnProtectionCheck } from "../function/arc-function-data";
|
|
9
11
|
import type { ArcCommandContextFromData } from "./command-context";
|
|
10
|
-
import type { ArcCommandData
|
|
12
|
+
import type { ArcCommandData } from "./command-data";
|
|
11
13
|
import type { ArcCommandHandler } from "./command-handler";
|
|
12
14
|
/**
|
|
13
15
|
* Arc Command - Business action that modifies state
|
|
14
16
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* - Accept typed parameters
|
|
18
|
-
* - Return typed results
|
|
19
|
-
* - Query state through query elements (views)
|
|
20
|
-
* - Mutate state through mutation elements (events, other commands)
|
|
21
|
-
*
|
|
22
|
-
* Commands follow the factory pattern from the Arc guide:
|
|
23
|
-
* - All configuration in a single Data object
|
|
24
|
-
* - Type-safe throughout
|
|
25
|
-
* - Immutable with clone-on-modify
|
|
26
|
-
* - Separate query and mutation concerns
|
|
17
|
+
* Uses ArcFunction internally (#fn) for unified params, result, protection,
|
|
18
|
+
* and context dependency management.
|
|
27
19
|
*
|
|
28
20
|
* @example
|
|
29
21
|
* ```typescript
|
|
30
22
|
* const registerCmd = command("register")
|
|
31
|
-
* .public()
|
|
32
23
|
* .query([usersView])
|
|
33
24
|
* .mutate([userRegisteredEvent])
|
|
34
25
|
* .withParams({ email: string(), password: string() })
|
|
35
26
|
* .withResult({ success: boolean() })
|
|
27
|
+
* .protectBy(adminToken, t => t.canI('register'))
|
|
36
28
|
* .handle(async (ctx, params) => {
|
|
37
|
-
* // Business logic here
|
|
38
29
|
* return { success: true };
|
|
39
30
|
* });
|
|
40
31
|
* ```
|
|
41
32
|
*/
|
|
42
33
|
export declare class ArcCommand<const Data extends ArcCommandData> extends ArcContextElement<Data["name"]> {
|
|
34
|
+
#private;
|
|
43
35
|
private readonly data;
|
|
44
|
-
constructor(data: Data);
|
|
45
|
-
/**
|
|
46
|
-
* Set command description for documentation and tooling
|
|
47
|
-
*/
|
|
36
|
+
constructor(data: Data, fn?: ArcFunction<any>);
|
|
48
37
|
description<const Desc extends string>(description: Desc): ArcCommand<Merge<Data, {
|
|
49
38
|
description: Desc;
|
|
50
39
|
}>>;
|
|
51
|
-
/**
|
|
52
|
-
* Check if command is public (no protections = public)
|
|
53
|
-
* Commands without protectBy() are considered public
|
|
54
|
-
*/
|
|
55
40
|
get isPublic(): boolean;
|
|
56
|
-
/**
|
|
57
|
-
* Add query elements (views) that this command needs to read from
|
|
58
|
-
* Query elements provide read-only access to state
|
|
59
|
-
*
|
|
60
|
-
* @param elements - Array of view elements to query
|
|
61
|
-
*/
|
|
62
41
|
query<const Elements extends ArcContextElement<any>[]>(elements: Elements): ArcCommand<Merge<Data, {
|
|
63
42
|
queryElements: Elements;
|
|
64
43
|
}>>;
|
|
65
|
-
/**
|
|
66
|
-
* Add mutation elements (events, commands) that this command needs to modify state
|
|
67
|
-
* Mutation elements provide write access to state
|
|
68
|
-
*
|
|
69
|
-
* @param elements - Array of event/command elements to mutate with
|
|
70
|
-
*/
|
|
71
44
|
mutate<const Elements extends ArcContextElement<any>[]>(elements: Elements): ArcCommand<Merge<Data, {
|
|
72
45
|
mutationElements: Elements;
|
|
73
46
|
}>>;
|
|
74
|
-
/**
|
|
75
|
-
* Define command parameters schema
|
|
76
|
-
*
|
|
77
|
-
* @param schema - Object schema or raw shape defining parameter structure
|
|
78
|
-
*/
|
|
79
47
|
withParams<NewParams extends ArcRawShape>(schema: NewParams | ArcObject<NewParams>): ArcCommand<Merge<Data, {
|
|
80
48
|
params: ArcObject<NewParams>;
|
|
81
49
|
}>>;
|
|
82
|
-
/**
|
|
83
|
-
* Define command result schemas
|
|
84
|
-
* Commands can return multiple result types (success, error variants)
|
|
85
|
-
*
|
|
86
|
-
* @param schemas - Array of object schemas for possible results
|
|
87
|
-
*/
|
|
88
50
|
withResult<NewResults extends ArcRawShape[]>(...schemas: NewResults): ArcCommand<Merge<Data, {
|
|
89
51
|
results: { [K in keyof NewResults]: ArcObject<NewResults[K]>; };
|
|
90
52
|
}>>;
|
|
91
|
-
/**
|
|
92
|
-
* Set command handler function
|
|
93
|
-
* The handler contains the business logic for this command
|
|
94
|
-
*
|
|
95
|
-
* @param handler - Function that executes command logic, or false to disable
|
|
96
|
-
*/
|
|
97
53
|
handle<Handler extends ArcCommandHandler<ArcCommandContextFromData<Data>, Data["params"] extends ArcObjectAny ? $type<Data["params"]> : null, $type<Data["results"][number]>> | false>(handler: Handler): ArcCommand<Merge<Data, {
|
|
98
54
|
handler: Handler;
|
|
99
55
|
}>>;
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
* Multiple protections can be added (all must pass)
|
|
103
|
-
*
|
|
104
|
-
* @param token - Token definition to protect with
|
|
105
|
-
* @param check - Function to check if access is allowed
|
|
106
|
-
*
|
|
107
|
-
* @example
|
|
108
|
-
* ```typescript
|
|
109
|
-
* command("editForm")
|
|
110
|
-
* .protectBy(moderatorToken, (token) => token.canI('form:edit'))
|
|
111
|
-
* .handle(async (ctx, params) => { ... });
|
|
112
|
-
* ```
|
|
113
|
-
*/
|
|
114
|
-
protectBy<T extends ArcTokenAny>(token: T, check: CommandProtectionCheck<T>): ArcCommand<Merge<Data, {
|
|
115
|
-
protections: [...Data["protections"] extends infer P extends CommandProtection[] ? P : [], {
|
|
56
|
+
protectBy<T extends ArcTokenAny>(token: T, check: FnProtectionCheck<T>): ArcCommand<Merge<Data, {
|
|
57
|
+
protections: [...Data["protections"] extends infer P extends FnProtection[] ? P : [], {
|
|
116
58
|
token: T;
|
|
117
59
|
check: typeof check;
|
|
118
60
|
}];
|
|
119
61
|
}>>;
|
|
120
|
-
/**
|
|
121
|
-
* Check if command has protections
|
|
122
|
-
*/
|
|
123
62
|
get hasProtections(): boolean;
|
|
124
|
-
|
|
125
|
-
* Get all protection configurations
|
|
126
|
-
*/
|
|
127
|
-
get protections(): CommandProtection[];
|
|
128
|
-
/**
|
|
129
|
-
* Verify all protections pass for given token instances
|
|
130
|
-
*
|
|
131
|
-
* @param tokens - Array of token instances to verify
|
|
132
|
-
* @returns true if all protections pass
|
|
133
|
-
*/
|
|
63
|
+
get protections(): FnProtection[];
|
|
134
64
|
verifyProtections(tokens: TokenInstanceAny[]): Promise<boolean>;
|
|
135
|
-
/**
|
|
136
|
-
* Initialize command in the given environment
|
|
137
|
-
* On server: registers command handler for remote execution
|
|
138
|
-
*/
|
|
139
65
|
init(environment: import("../context-element").ArcEnvironment, adapters: ModelAdapters): Promise<void>;
|
|
140
|
-
/**
|
|
141
|
-
* Generate mutation context for this command
|
|
142
|
-
* Provides execute functionality to run the command
|
|
143
|
-
*
|
|
144
|
-
* @param adapters - Available adapters (storage, commandWire, eventPublisher)
|
|
145
|
-
* @returns Context object with execute method
|
|
146
|
-
*/
|
|
147
66
|
mutateContext(adapters: ModelAdapters): ((params: Data["params"] extends ArcObjectAny ? $type<Data["params"]> : null) => Promise<$type<Data["results"][number]>>) & {
|
|
148
67
|
params: Data["params"];
|
|
149
68
|
};
|
|
150
|
-
/**
|
|
151
|
-
* Execute command locally with handler
|
|
152
|
-
* Collects events and publishes them via eventPublisher
|
|
153
|
-
*/
|
|
154
69
|
private executeLocally;
|
|
155
|
-
/**
|
|
156
|
-
* Build command context with access to query and mutation elements
|
|
157
|
-
*/
|
|
158
70
|
private buildCommandContext;
|
|
159
|
-
/**
|
|
160
|
-
* Convert command to JSON Schema format
|
|
161
|
-
* Used for OpenAPI documentation and validation
|
|
162
|
-
*/
|
|
163
71
|
toJsonSchema(): {
|
|
164
72
|
type: string;
|
|
165
73
|
name: string;
|
|
@@ -168,21 +76,6 @@ export declare class ArcCommand<const Data extends ArcCommandData> extends ArcCo
|
|
|
168
76
|
strict: boolean;
|
|
169
77
|
};
|
|
170
78
|
}
|
|
171
|
-
/**
|
|
172
|
-
* Create a new command with the given name
|
|
173
|
-
*
|
|
174
|
-
* @param name - Unique command name
|
|
175
|
-
* @returns New command instance ready for configuration
|
|
176
|
-
*
|
|
177
|
-
* @example
|
|
178
|
-
* ```typescript
|
|
179
|
-
* const myCommand = command("myCommand")
|
|
180
|
-
* .withParams({ input: string() })
|
|
181
|
-
* .handle(async (ctx, params) => {
|
|
182
|
-
* // logic here
|
|
183
|
-
* });
|
|
184
|
-
* ```
|
|
185
|
-
*/
|
|
186
79
|
export declare function command<const Name extends string>(name: Name): ArcCommand<{
|
|
187
80
|
readonly name: Name;
|
|
188
81
|
readonly params: null;
|
|
@@ -191,8 +84,5 @@ export declare function command<const Name extends string>(name: Name): ArcComma
|
|
|
191
84
|
readonly mutationElements: [];
|
|
192
85
|
readonly protections: [];
|
|
193
86
|
}>;
|
|
194
|
-
/**
|
|
195
|
-
* Type alias for any command (used in collections)
|
|
196
|
-
*/
|
|
197
87
|
export type ArcCommandAny = ArcCommand<any>;
|
|
198
88
|
//# sourceMappingURL=command.d.ts.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { ArcCommand, command, type ArcCommandAny } from "./command";
|
|
2
|
-
export type { ArcCommandContext, ArcCommandContextFromData,
|
|
2
|
+
export type { ArcCommandContext, ArcCommandContextFromData, } from "./command-context";
|
|
3
3
|
export type { ArcCommandData, CommandProtection, CommandProtectionCheck, } from "./command-data";
|
|
4
4
|
export type { ArcCommandHandler } from "./command-handler";
|
|
5
5
|
export type { ArcObjectAny, ArcRawShape } from "../../elements/object";
|
|
@@ -2,37 +2,47 @@ import type { ModelAdapters } from "../model/model-adapters";
|
|
|
2
2
|
import type { ArcContextElement } from "./context-element";
|
|
3
3
|
/**
|
|
4
4
|
* Query context — maps element names to their queryContext return types.
|
|
5
|
-
* Uses key remapping to filter only elements that have queryContext.
|
|
6
5
|
*/
|
|
7
6
|
type QueryContext<Elements extends ArcContextElement<any>[]> = {
|
|
8
7
|
[K in Elements[number] as K["queryContext"] extends (...args: any) => any ? K["name"] : never]: K["queryContext"] extends (...args: any) => infer R ? R : never;
|
|
9
8
|
};
|
|
10
9
|
/**
|
|
11
10
|
* Mutation context — maps element names to their mutateContext return types.
|
|
12
|
-
* Uses key remapping to filter only elements that have mutateContext.
|
|
13
11
|
*/
|
|
14
12
|
type MutationContext<Elements extends ArcContextElement<any>[]> = {
|
|
15
13
|
[K in Elements[number] as K["mutateContext"] extends (...args: any) => any ? K["name"] : never]: K["mutateContext"] extends (...args: any) => infer R ? R : never;
|
|
16
14
|
};
|
|
17
15
|
/**
|
|
18
|
-
*
|
|
19
|
-
* handler that needs typed access to query/mutation elements.
|
|
16
|
+
* Callable accessor — both a function (for references) and an object (for named access).
|
|
20
17
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* // By name (declared in .query()/.mutate()):
|
|
21
|
+
* ctx.query.myMessages.getByConversation({ conversationId })
|
|
22
|
+
*
|
|
23
|
+
* // By reference (factories, dynamic elements):
|
|
24
|
+
* ctx.query(messageElement).getByConversation({ conversationId })
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
type QueryAccessor<Elements extends ArcContextElement<any>[]> = ((element: ArcContextElement<any>) => any) & QueryContext<Elements>;
|
|
28
|
+
type MutateAccessor<Elements extends ArcContextElement<any>[]> = ((element: ArcContextElement<any>) => any) & MutationContext<Elements>;
|
|
29
|
+
/**
|
|
30
|
+
* Unified element context — shared between routes, commands, listeners.
|
|
31
|
+
*
|
|
32
|
+
* Elements are accessible by name (ctx.query.myView) or
|
|
33
|
+
* by reference (ctx.query(element)).
|
|
23
34
|
*/
|
|
24
|
-
export type ElementContext<QueryElements extends ArcContextElement<any>[], MutationElements extends ArcContextElement<any>[]> =
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
} ? R : never;
|
|
35
|
+
export type ElementContext<QueryElements extends ArcContextElement<any>[], MutationElements extends ArcContextElement<any>[]> = {
|
|
36
|
+
query: QueryAccessor<QueryElements>;
|
|
37
|
+
mutate: MutateAccessor<MutationElements>;
|
|
38
|
+
$auth?: {
|
|
39
|
+
params: any;
|
|
40
|
+
tokenName: string;
|
|
41
|
+
};
|
|
32
42
|
};
|
|
33
43
|
/**
|
|
34
44
|
* Build element context at runtime.
|
|
35
|
-
* Shared implementation for routes, commands,
|
|
45
|
+
* Shared implementation for routes, commands, listeners.
|
|
36
46
|
*/
|
|
37
47
|
export declare function buildElementContext(queryElements: ArcContextElement<any>[], mutationElements: ArcContextElement<any>[], adapters: ModelAdapters): any;
|
|
38
48
|
export {};
|