alepha 0.7.7 → 0.8.1

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.
Files changed (55) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +7 -34
  3. package/batch.cjs +8 -0
  4. package/batch.d.ts +147 -0
  5. package/batch.js +1 -0
  6. package/cache/redis.d.ts +13 -18
  7. package/cache.d.ts +183 -119
  8. package/command.cjs +8 -0
  9. package/command.d.ts +152 -0
  10. package/command.js +1 -0
  11. package/core.d.ts +846 -838
  12. package/datetime.d.ts +78 -78
  13. package/file.cjs +8 -0
  14. package/file.d.ts +46 -0
  15. package/file.js +1 -0
  16. package/lock/redis.d.ts +10 -12
  17. package/lock.d.ts +73 -80
  18. package/package.json +86 -34
  19. package/postgres.d.ts +348 -170
  20. package/queue/redis.d.ts +13 -13
  21. package/queue.d.ts +107 -18
  22. package/react/auth.d.ts +22 -16
  23. package/react/head.d.ts +10 -4
  24. package/react.d.ts +206 -49
  25. package/redis.d.ts +23 -27
  26. package/retry.d.ts +75 -54
  27. package/router.cjs +8 -0
  28. package/router.d.ts +45 -0
  29. package/router.js +1 -0
  30. package/scheduler.d.ts +15 -16
  31. package/security.d.ts +229 -40
  32. package/server/cache.d.ts +7 -8
  33. package/server/compress.cjs +8 -0
  34. package/server/compress.d.ts +26 -0
  35. package/server/compress.js +1 -0
  36. package/server/cookies.d.ts +249 -18
  37. package/server/cors.d.ts +7 -3
  38. package/server/health.d.ts +21 -24
  39. package/server/helmet.cjs +8 -0
  40. package/server/helmet.d.ts +70 -0
  41. package/server/helmet.js +1 -0
  42. package/server/links.d.ts +87 -93
  43. package/server/metrics.cjs +8 -0
  44. package/server/metrics.d.ts +35 -0
  45. package/server/metrics.js +1 -0
  46. package/server/multipart.cjs +8 -0
  47. package/server/multipart.d.ts +46 -0
  48. package/server/multipart.js +1 -0
  49. package/server/proxy.d.ts +11 -11
  50. package/server/static.d.ts +70 -55
  51. package/server/swagger.d.ts +55 -54
  52. package/server.d.ts +273 -123
  53. package/topic/redis.d.ts +22 -23
  54. package/topic.d.ts +26 -19
  55. package/vite.d.ts +59 -36
package/cache.d.ts CHANGED
@@ -1,43 +1,41 @@
1
- import * as _alepha_core0 from "@alepha/core";
2
- import * as _alepha_core5 from "@alepha/core";
3
- import { Alepha, KIND, Module, OPTIONS, Static } from "@alepha/core";
4
- import { DateTimeProvider, DurationLike, Timeout } from "@alepha/datetime";
5
- import * as _sinclair_typebox1 from "@sinclair/typebox";
1
+ import { Alepha, HookDescriptor, KIND, Logger, Module, OPTIONS, Static, TBoolean, TNumber, TObject, TOptional, TString } from "alepha";
2
+ import { DateTimeProvider, DurationLike, Timeout } from "alepha/datetime";
6
3
 
7
4
  //#region src/providers/CacheProvider.d.ts
5
+
8
6
  /**
9
- * Cache provider interface.
10
- *
11
- * All methods are asynchronous and return promises.
12
- * Values are stored as Uint8Array.
13
- */
7
+ * Cache provider interface.
8
+ *
9
+ * All methods are asynchronous and return promises.
10
+ * Values are stored as Uint8Array.
11
+ */
14
12
  declare abstract class CacheProvider {
15
13
  /**
16
- * Get the value of a key.
17
- *
18
- * @param name Cache name, used to group keys. Should be Redis-like "some:group:name" format.
19
- * @param key The key of the value to get.
20
- *
21
- * @return The value of the key, or undefined if the key does not exist.
22
- */
14
+ * Get the value of a key.
15
+ *
16
+ * @param name Cache name, used to group keys. Should be Redis-like "some:group:name" format.
17
+ * @param key The key of the value to get.
18
+ *
19
+ * @return The value of the key, or undefined if the key does not exist.
20
+ */
23
21
  abstract get(name: string, key: string): Promise<Uint8Array | undefined>;
24
22
  /**
25
- * Set the string value of a key.
26
- *
27
- * @param name Cache name, used to group keys. Should be Redis-like "some:group:name" format.
28
- * @param key The key of the value to set.
29
- * @param value The value to set.
30
- * @param ttl The time-to-live of the key, in milliseconds.
31
- *
32
- * @return The value of the key.
33
- */
23
+ * Set the string value of a key.
24
+ *
25
+ * @param name Cache name, used to group keys. Should be Redis-like "some:group:name" format.
26
+ * @param key The key of the value to set.
27
+ * @param value The value to set.
28
+ * @param ttl The time-to-live of the key, in milliseconds.
29
+ *
30
+ * @return The value of the key.
31
+ */
34
32
  abstract set(name: string, key: string, value: Uint8Array, ttl?: number): Promise<Uint8Array>;
35
33
  /**
36
- * Remove the specified keys.
37
- *
38
- * @param name Cache name, used to group keys. Should be Redis-like "some:group:name" format.
39
- * @param keys The keys to delete.
40
- */
34
+ * Remove the specified keys.
35
+ *
36
+ * @param name Cache name, used to group keys. Should be Redis-like "some:group:name" format.
37
+ * @param keys The keys to delete.
38
+ */
41
39
  abstract del(name: string, ...keys: string[]): Promise<void>;
42
40
  abstract has(name: string, key: string): Promise<boolean>;
43
41
  abstract keys(name: string): Promise<string[]>;
@@ -46,76 +44,77 @@ declare abstract class CacheProvider {
46
44
  //#region src/descriptors/$cache.d.ts
47
45
  declare const KEY = "CACHE";
48
46
  /**
49
- * Cache Descriptor
50
- */
47
+ * Cache Descriptor
48
+ */
51
49
  declare const $cache: {
52
50
  <TReturn = string, TParameter extends any[] = any[]>(options?: CacheDescriptorOptions<TReturn, TParameter>): CacheDescriptor<TReturn, TParameter>;
53
51
  [KIND]: string;
54
52
  };
53
+ // ---------------------------------------------------------------------------------------------------------------------
55
54
  interface CacheDescriptorOptions<TReturn, TParameter extends any[] = any[]> {
56
55
  /**
57
- * The cache name. This is useful for invalidating multiple caches at once.
58
- *
59
- * Store key as `cache:$name:$key`.
60
- *
61
- * @default ClassName:methodName
62
- */
56
+ * The cache name. This is useful for invalidating multiple caches at once.
57
+ *
58
+ * Store key as `cache:$name:$key`.
59
+ *
60
+ * @default ClassName:methodName
61
+ */
63
62
  name?: string;
64
63
  /**
65
- * Function which returns cached data.
66
- * @param args Arguments for handler.
67
- */
64
+ * Function which returns cached data.
65
+ * @param args Arguments for handler.
66
+ */
68
67
  handler?: (...args: TParameter) => TReturn;
69
68
  /**
70
- * The key generator for the cache.
71
- * If not provided, the arguments will be json.stringify().
72
- */
69
+ * The key generator for the cache.
70
+ * If not provided, the arguments will be json.stringify().
71
+ */
73
72
  key?: (...args: TParameter) => string;
74
73
  /**
75
- * The store provider for the cache.
76
- * If not provided, the default store provider will be used.
77
- */
74
+ * The store provider for the cache.
75
+ * If not provided, the default store provider will be used.
76
+ */
78
77
  provider?: CacheProvider | (() => CacheProvider) | "memory";
79
78
  /**
80
- * The time-to-live for the cache in seconds.
81
- * Set 0 to skip expiration.
82
- *
83
- * @default 300 (5 minutes).
84
- */
79
+ * The time-to-live for the cache in seconds.
80
+ * Set 0 to skip expiration.
81
+ *
82
+ * @default 300 (5 minutes).
83
+ */
85
84
  ttl?: DurationLike;
86
85
  /**
87
- * If the cache is disabled.
88
- */
86
+ * If the cache is disabled.
87
+ */
89
88
  disabled?: boolean;
90
89
  }
91
90
  interface CacheDescriptor<TReturn = any, TParameter extends any[] = any[]> {
92
91
  [KIND]: typeof KEY;
93
92
  [OPTIONS]: CacheDescriptorOptions<TReturn, TParameter>;
94
93
  /**
95
- * Cache handler.
96
- */
94
+ * Cache handler.
95
+ */
97
96
  (...args: TParameter): Promise<TReturn>;
98
97
  /**
99
- * Cache key generator.
100
- */
98
+ * Cache key generator.
99
+ */
101
100
  key: (...args: TParameter) => string;
102
101
  /**
103
- * Invalidate cache by keys.
104
- */
102
+ * Invalidate cache by keys.
103
+ */
105
104
  invalidate: (...keys: string[]) => Promise<void>;
106
105
  /**
107
- * Set cache with key, value and ttl.
108
- *
109
- * @param key
110
- * @param value
111
- * @param ttl
112
- */
106
+ * Set cache with key, value and ttl.
107
+ *
108
+ * @param key
109
+ * @param value
110
+ * @param ttl
111
+ */
113
112
  set: (key: string, value: TReturn, ttl?: DurationLike) => Promise<void>;
114
113
  /**
115
- * Get cache by key.
116
- *
117
- * @param key
118
- */
114
+ * Get cache by key.
115
+ *
116
+ * @param key
117
+ */
119
118
  get: (key: string) => Promise<TReturn | undefined>;
120
119
  }
121
120
  //#endregion
@@ -128,7 +127,7 @@ type CacheValue = {
128
127
  };
129
128
  declare class MemoryCacheProvider implements CacheProvider {
130
129
  protected readonly dateTimeProvider: DateTimeProvider;
131
- protected readonly log: _alepha_core0.Logger;
130
+ protected readonly log: Logger;
132
131
  protected store: Record<CacheName, Record<CacheKey, CacheValue>>;
133
132
  get(name: string, key: string): Promise<Uint8Array | undefined>;
134
133
  set(name: string, key: string, value: Uint8Array, ttl?: number): Promise<Uint8Array>;
@@ -138,10 +137,10 @@ declare class MemoryCacheProvider implements CacheProvider {
138
137
  }
139
138
  //#endregion
140
139
  //#region src/providers/CacheDescriptorProvider.d.ts
141
- declare const envSchema: _alepha_core5.TObject<{
142
- CACHE_DEFAULT_TTL: _sinclair_typebox1.TNumber;
143
- CACHE_PREFIX: _sinclair_typebox1.TOptional<_sinclair_typebox1.TString>;
144
- CACHE_ENABLED: _sinclair_typebox1.TBoolean;
140
+ declare const envSchema: TObject<{
141
+ CACHE_DEFAULT_TTL: TNumber;
142
+ CACHE_PREFIX: TOptional<TString>;
143
+ CACHE_ENABLED: TBoolean;
145
144
  }>;
146
145
  declare module "alepha" {
147
146
  interface Env extends Partial<Static<typeof envSchema>> {}
@@ -151,57 +150,53 @@ declare class CacheDescriptorProvider {
151
150
  protected readonly cacheProvider: CacheProvider;
152
151
  protected readonly memoryCacheProvider: MemoryCacheProvider;
153
152
  protected readonly dateTimeProvider: DateTimeProvider;
154
- protected readonly env: {
155
- CACHE_PREFIX?: string | undefined;
156
- CACHE_DEFAULT_TTL: number;
157
- CACHE_ENABLED: boolean;
158
- };
153
+ protected readonly env: Static<typeof envSchema>;
159
154
  protected readonly caches: Cache[];
160
- protected readonly configure: _alepha_core5.HookDescriptor<"configure">;
161
- register(cache: Cache): Cache<any, any[]>;
155
+ protected encoder: TextEncoder;
156
+ protected decoder: TextDecoder;
157
+ protected codes: {
158
+ BINARY: number;
159
+ JSON: number;
160
+ STRING: number;
161
+ };
162
+ protected readonly configure: HookDescriptor<"configure">;
163
+ register(cache: Cache): Cache;
162
164
  processDescriptors(): void;
163
165
  getCaches(): Cache[];
164
166
  /**
165
- * Clear all cache entries.
166
- */
167
+ * Clear all cache entries.
168
+ */
167
169
  clear(): Promise<void>;
168
170
  /**
169
- * Get the store provider for the given cache options.
170
- *
171
- * @param options
172
- */
171
+ * Get the store provider for the given cache options.
172
+ *
173
+ * @param options
174
+ */
173
175
  provider(options: Pick<CacheDescriptorOptions<any[], any>, "provider">): CacheProvider;
174
176
  /**
175
- * Get the cache key for the given state and arguments.
176
- */
177
+ * Get the cache key for the given state and arguments.
178
+ */
177
179
  key(cache: Cache, ...args: any[]): string;
178
180
  /**
179
- * Invalidate the cache for the given state and arguments.
180
- */
181
+ * Invalidate the cache for the given state and arguments.
182
+ */
181
183
  invalidate(cache: Cache, ...keys: string[]): Promise<void>;
182
184
  /**
183
- * Run the cache handler with the given state and arguments.
184
- * You must run on a $cache with a handler defined.
185
- */
185
+ * Run the cache handler with the given state and arguments.
186
+ * You must run on a $cache with a handler defined.
187
+ */
186
188
  run<TReturn, TParameter extends any[]>(cache: Cache<TReturn, TParameter>, ...args: TParameter): Promise<TReturn>;
187
189
  get<TReturn>(cache: Cache<TReturn>, key: string): Promise<TReturn | undefined>;
188
190
  /**
189
- * Manually set a value in the cache.
190
- * It's used by .run() method, but you will need it when you don't have cache handler defined.
191
- *
192
- * @param cache Cache object with all configuration and options (even TTL).
193
- * @param key Cache key, build with .key() method or manually.
194
- * @param value Value to store in cache.
195
- * @param ttl Override cache.ttl option.
196
- */
191
+ * Manually set a value in the cache.
192
+ * It's used by .run() method, but you will need it when you don't have cache handler defined.
193
+ *
194
+ * @param cache Cache object with all configuration and options (even TTL).
195
+ * @param key Cache key, build with .key() method or manually.
196
+ * @param value Value to store in cache.
197
+ * @param ttl Override cache.ttl option.
198
+ */
197
199
  set<TReturn>(cache: Cache<TReturn>, key: string, value: TReturn, ttl?: DurationLike): Promise<void>;
198
- protected encoder: TextEncoder;
199
- protected decoder: TextDecoder;
200
- protected codes: {
201
- BINARY: number;
202
- JSON: number;
203
- STRING: number;
204
- };
205
200
  protected serialize<TReturn>(value: TReturn): Uint8Array;
206
201
  protected deserialize<TReturn>(uint8Array: Uint8Array): Promise<TReturn>;
207
202
  }
@@ -211,15 +206,84 @@ interface Cache<TReturn = any, TParameter extends any[] = any[]> {
211
206
  }
212
207
  //#endregion
213
208
  //#region src/index.d.ts
209
+ // ---------------------------------------------------------------------------------------------------------------------
214
210
  /**
215
- * Alepha Cache Module
216
- *
217
- * This module provides a caching mechanism for Alepha applications.
218
- *
219
- * @see {@link $cache}
220
- * @see {@link CacheProvider}
221
- * @module alepha.cache
222
- */
211
+ * Provides high-performance caching capabilities for Alepha applications with configurable TTL and multiple storage backends.
212
+ *
213
+ * The cache module enables declarative caching through the `$cache` descriptor, allowing you to cache method results,
214
+ * API responses, or computed values with automatic invalidation and type safety. It supports both in-memory and
215
+ * persistent storage backends for different performance and durability requirements.
216
+ *
217
+ * **Key Features:**
218
+ * - Declarative caching with `$cache` descriptor on class properties
219
+ * - Configurable TTL (time-to-live) with duration literals
220
+ * - Custom key generation and automatic serialization
221
+ * - Multiple storage backends (memory, Redis, etc.)
222
+ * - Cache invalidation and manual cache operations
223
+ * - Type-safe operations with full TypeScript support
224
+ *
225
+ * **Basic Usage:**
226
+ * ```ts
227
+ * import { Alepha, run } from "alepha";
228
+ * import { AlephaCache, $cache } from "alepha/cache";
229
+ *
230
+ * class UserService {
231
+ * getUserData = $cache({
232
+ * key: (userId: string) => `user:${userId}`,
233
+ * ttl: [1, "hour"],
234
+ * handler: async (userId: string) => {
235
+ * // This will be cached for 1 hour
236
+ * return await fetchUserFromDatabase(userId);
237
+ * },
238
+ * });
239
+ *
240
+ * getUserProfile = $cache({
241
+ * provider: "memory",
242
+ * ttl: [5, "minutes"],
243
+ * handler: async (userId: string) => {
244
+ * return await buildUserProfile(userId);
245
+ * },
246
+ * });
247
+ * }
248
+ *
249
+ * const alepha = Alepha.create()
250
+ * .with(AlephaCache)
251
+ * .with(UserService);
252
+ *
253
+ * run(alepha);
254
+ * ```
255
+ *
256
+ * **Cache Operations:**
257
+ * ```ts
258
+ * class ProductService {
259
+ * productCache = $cache({
260
+ * handler: async (productId: string) => {
261
+ * return await getProduct(productId);
262
+ * },
263
+ * });
264
+ *
265
+ * async getProduct(id: string) {
266
+ * // Get from cache or compute
267
+ * return await this.productCache(id);
268
+ * }
269
+ *
270
+ * async updateProduct(id: string, data: any) {
271
+ * await updateProductInDb(id, data);
272
+ * // Invalidate cache
273
+ * await this.productCache.invalidate(this.productCache.key(id));
274
+ * }
275
+ *
276
+ * async warmUpCache(id: string, data: any) {
277
+ * // Manually set cache
278
+ * await this.productCache.set(this.productCache.key(id), data, [30, "minutes"]);
279
+ * }
280
+ * }
281
+ * ```
282
+ *
283
+ * @see {@link $cache}
284
+ * @see {@link CacheProvider}
285
+ * @module alepha.cache
286
+ */
223
287
  declare class AlephaCache implements Module {
224
288
  readonly name = "alepha.cache";
225
289
  readonly $services: (alepha: Alepha) => Alepha;
package/command.cjs ADDED
@@ -0,0 +1,8 @@
1
+ 'use strict';
2
+ var m = require('@alepha/command');
3
+ Object.keys(m).forEach(function (k) {
4
+ if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
5
+ enumerable: true,
6
+ get: function () { return m[k]; }
7
+ });
8
+ });
package/command.d.ts ADDED
@@ -0,0 +1,152 @@
1
+ import { Alepha, AlephaError, Async, HookDescriptor, KIND, Logger, Module, OPTIONS, Static, TObject, TProperties, TSchema, TString } from "alepha";
2
+ import * as fs from "node:fs/promises";
3
+ import { glob } from "node:fs/promises";
4
+
5
+ //#region src/helpers/Runner.d.ts
6
+ type Task = {
7
+ name: string;
8
+ handler: () => any;
9
+ };
10
+ interface Timer {
11
+ name: string;
12
+ duration: string;
13
+ }
14
+ interface RunnerMethod {
15
+ (cmd: string | Array<string | Task>, fn?: () => any): Promise<string>;
16
+ rm: (glob: string | string[]) => Promise<string>;
17
+ }
18
+ declare class Runner {
19
+ protected readonly log: Logger;
20
+ protected readonly timers: Timer[];
21
+ protected readonly startTime: number;
22
+ readonly run: RunnerMethod;
23
+ constructor(log: Logger);
24
+ protected exec(cmd: string): Promise<string>;
25
+ /**
26
+ * Executes one or more tasks.
27
+ *
28
+ * @param task - A single task or an array of tasks to run in parallel.
29
+ */
30
+ protected execute(task: Task | Task[]): Promise<string>;
31
+ /**
32
+ * Prints a summary of all executed tasks and their durations.
33
+ */
34
+ summary(): void;
35
+ protected executeTask(task: Task): Promise<string>;
36
+ protected renderTable(data: string[][]): void;
37
+ }
38
+ //#endregion
39
+ //#region src/descriptors/$command.d.ts
40
+ declare const KEY = "COMMAND";
41
+ /**
42
+ * Declares a CLI command.
43
+ *
44
+ * This descriptor allows you to define a command, its flags, and its handler
45
+ * within your Alepha application structure.
46
+ */
47
+ declare const $command: {
48
+ <T extends TObject>(options: CommandDescriptorOptions<T>): CommandDescriptor<T>;
49
+ [KIND]: string;
50
+ };
51
+ interface CommandDescriptorOptions<T extends TObject> {
52
+ /**
53
+ * The handler function to execute when the command is matched.
54
+ */
55
+ handler: (args: {
56
+ flags: Static<T>;
57
+ run: RunnerMethod;
58
+ glob: typeof glob;
59
+ fs: typeof fs;
60
+ }) => Async<void>;
61
+ /**
62
+ * The name of the command. If omitted, the property key is used.
63
+ *
64
+ * An empty string "" denotes the root command.
65
+ */
66
+ name?: string;
67
+ /**
68
+ * A short description of the command, shown in the help message.
69
+ */
70
+ description?: string;
71
+ /**
72
+ * An array of alternative names for the command.
73
+ */
74
+ aliases?: string[];
75
+ /**
76
+ * A TypeBox object schema defining the flags for the command.
77
+ */
78
+ flags?: T;
79
+ }
80
+ interface CommandDescriptor<T extends TObject> {
81
+ [KIND]: typeof KEY;
82
+ [OPTIONS]: CommandDescriptorOptions<T>;
83
+ /**
84
+ * Executes the command. This is a placeholder and will be replaced by the provider.
85
+ */
86
+ (flags: Static<T>): Promise<void>;
87
+ }
88
+ //#endregion
89
+ //#region src/errors/CommandError.d.ts
90
+ declare class CommandError extends AlephaError {}
91
+ //#endregion
92
+ //#region src/providers/CommandDescriptorProvider.d.ts
93
+ interface Command {
94
+ key: string;
95
+ name: string;
96
+ description?: string;
97
+ aliases: string[];
98
+ flags: TObject<TProperties>;
99
+ handler: (flags: any) => Promise<void>;
100
+ }
101
+ declare const envSchema: TObject<{
102
+ CLI_NAME: TString;
103
+ CLI_DESCRIPTION: TString;
104
+ }>;
105
+ declare module "alepha" {
106
+ interface Env extends Partial<Static<typeof envSchema>> {}
107
+ }
108
+ declare class CommandDescriptorProvider {
109
+ protected readonly env: Static<typeof envSchema>;
110
+ protected readonly alepha: Alepha;
111
+ protected readonly log: Logger;
112
+ protected commands: Command[];
113
+ options: {
114
+ name: string;
115
+ description: string;
116
+ argv: string[];
117
+ };
118
+ protected readonly globalFlags: Record<string, {
119
+ aliases: string[];
120
+ description: string;
121
+ schema: TSchema;
122
+ }>;
123
+ protected readonly onConfigure: HookDescriptor<"configure">;
124
+ protected readonly onReady: HookDescriptor<"ready">;
125
+ private findCommand;
126
+ protected parseCommandFlags(argv: string[], schema: TObject): Record<string, any>;
127
+ protected parseFlags(argv: string[], flagDefs: {
128
+ key: string;
129
+ aliases: string[];
130
+ schema: TSchema;
131
+ }[]): Record<string, any>;
132
+ private printHelp;
133
+ private getMaxCmdLength;
134
+ private getMaxFlagLength;
135
+ }
136
+ //#endregion
137
+ //#region src/index.d.ts
138
+ // ---------------------------------------------------------------------------------------------------------------------
139
+ /**
140
+ *This module provides a powerful way to build command-line interfaces
141
+ * directly within your Alepha application, using declarative descriptors.
142
+ *
143
+ * @see {@link $command}
144
+ * @module alepha.command
145
+ */
146
+ declare class AlephaCommand implements Module {
147
+ readonly name = "alepha.command";
148
+ readonly $services: (alepha: Alepha) => Alepha;
149
+ }
150
+ //#endregion
151
+ export { $command, AlephaCommand, CommandDescriptor, CommandDescriptorOptions, CommandDescriptorProvider, CommandError, Runner, RunnerMethod, Task };
152
+ //# sourceMappingURL=index.d.ts.map
package/command.js ADDED
@@ -0,0 +1 @@
1
+ export * from '@alepha/command'