alepha 0.7.4 → 0.7.5

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/README.md CHANGED
@@ -1,21 +1,44 @@
1
1
  <div align="center">
2
2
 
3
- <img src="./assets/logo.png" alt="Logo" style="width: 256px"/>
4
-
5
- <h1>Alepha</h1>
6
-
3
+ <h1 >
4
+ <img
5
+ src="https://raw.githubusercontent.com/feunard/alepha/main/assets/logo.png"
6
+ width="128"
7
+ height="128"
8
+ alt="Logo"
9
+ valign="middle"
10
+ />
11
+ Alepha
12
+ </h1>
7
13
  <p style="max-width: 512px">
8
14
  🚧
9
15
  </p>
10
-
16
+ <a href="https://www.npmjs.com/package/alepha"><img src="https://img.shields.io/npm/v/alepha.svg" alt="npm"/></a>
17
+ <a href="https://www.npmjs.com/package/alepha"><img src="https://img.shields.io/npm/l/alepha.svg" alt="npm"/></a>
18
+ <a href="https://codecov.io/gh/feunard/alepha"><img src="https://codecov.io/gh/feunard/alepha/graph/badge.svg?token=ZDLWI514CP" alt="npm"/></a>
19
+ <a href="https://www.npmjs.com/package/alepha"><img src="https://img.shields.io/npm/dt/alepha.svg" alt="npm"/></a>
20
+ <a href="https://github.com/feunard/alepha"><img src="https://img.shields.io/github/stars/feunard/alepha.svg?style=social" alt="GitHub stars"/></a>
11
21
  </div>
12
22
 
13
- [![npm](https://img.shields.io/npm/v/alepha.svg)](https://www.npmjs.com/package/alepha)
14
- [![license](https://img.shields.io/npm/l/alepha.svg)](https://www.npmjs.com/package/alepha)
15
- [![downloads](https://img.shields.io/npm/dt/alepha.svg)](https://www.npmjs.com/package/alepha)
16
-
17
23
  ## Installation
18
24
 
19
25
  ```bash
20
26
  npm install alepha
21
27
  ```
28
+
29
+ ## Usage
30
+
31
+ Minimalist http server with a single endpoint.
32
+
33
+ ```ts
34
+ import { run } from "alepha";
35
+ import { $action } from "alepha/server";
36
+
37
+ class App {
38
+ hello = $action({
39
+ handler: () => "Hello world!",
40
+ })
41
+ }
42
+
43
+ run(App);
44
+ ```
package/cache/redis.d.ts CHANGED
@@ -81,8 +81,8 @@ declare class RedisCacheProvider implements CacheProvider {
81
81
  REDIS_CACHE_PREFIX?: string | undefined;
82
82
  };
83
83
  protected readonly alepha: Alepha;
84
- get(name: string, key: string): Promise<Buffer | undefined>;
85
- set(name: string, key: string, value: Buffer | string, ttl?: number): Promise<Buffer>;
84
+ get(name: string, key: string): Promise<Uint8Array | undefined>;
85
+ set(name: string, key: string, value: Uint8Array | string, ttl?: number): Promise<Uint8Array>;
86
86
  del(name: string, ...keys: string[]): Promise<void>;
87
87
  has(name: string, key: string): Promise<boolean>;
88
88
  keys(name: string): Promise<string[]>;
@@ -97,9 +97,9 @@ declare class RedisCacheProvider implements CacheProvider {
97
97
  * @see {@link RedisCacheProvider}
98
98
  * @module alepha.cache.redis
99
99
  */
100
- declare class AlephaRedisCache implements Module {
100
+ declare class AlephaCacheRedis implements Module {
101
101
  readonly name = "alepha.cache.redis";
102
102
  readonly $services: (alepha: Alepha) => Alepha;
103
103
  }
104
104
 
105
- export { AlephaRedisCache, RedisCacheProvider };
105
+ export { AlephaCacheRedis, RedisCacheProvider };
package/cache.d.ts CHANGED
@@ -6,7 +6,7 @@ import { DurationLike, DateTimeProvider, Timeout } from '@alepha/datetime';
6
6
  * Cache provider interface.
7
7
  *
8
8
  * All methods are asynchronous and return promises.
9
- * Values are stored as Buffer.
9
+ * Values are stored as Uint8Array.
10
10
  */
11
11
  declare abstract class CacheProvider {
12
12
  /**
@@ -17,7 +17,7 @@ declare abstract class CacheProvider {
17
17
  *
18
18
  * @return The value of the key, or undefined if the key does not exist.
19
19
  */
20
- abstract get(name: string, key: string): Promise<Buffer | undefined>;
20
+ abstract get(name: string, key: string): Promise<Uint8Array | undefined>;
21
21
  /**
22
22
  * Set the string value of a key.
23
23
  *
@@ -28,7 +28,7 @@ declare abstract class CacheProvider {
28
28
  *
29
29
  * @return The value of the key.
30
30
  */
31
- abstract set(name: string, key: string, value: Buffer, ttl?: number): Promise<Buffer>;
31
+ abstract set(name: string, key: string, value: Uint8Array, ttl?: number): Promise<Uint8Array>;
32
32
  /**
33
33
  * Remove the specified keys.
34
34
  *
@@ -201,15 +201,15 @@ interface TSchema extends TKind, SchemaOptions {
201
201
  type CacheName = string;
202
202
  type CacheKey = string;
203
203
  type CacheValue = {
204
- data?: Buffer;
204
+ data?: Uint8Array;
205
205
  timeout?: Timeout;
206
206
  };
207
207
  declare class MemoryCacheProvider implements CacheProvider {
208
208
  protected readonly dateTimeProvider: DateTimeProvider;
209
209
  protected readonly log: _alepha_core.Logger;
210
210
  protected store: Record<CacheName, Record<CacheKey, CacheValue>>;
211
- get(name: string, key: string): Promise<Buffer | undefined>;
212
- set(name: string, key: string, value: Buffer, ttl?: number): Promise<Buffer>;
211
+ get(name: string, key: string): Promise<Uint8Array | undefined>;
212
+ set(name: string, key: string, value: Uint8Array, ttl?: number): Promise<Uint8Array>;
213
213
  del(name: string, ...keys: string[]): Promise<void>;
214
214
  has(name: string, key: string): Promise<boolean>;
215
215
  keys(name: string): Promise<string[]>;
@@ -273,8 +273,15 @@ declare class CacheDescriptorProvider {
273
273
  * @param ttl Override cache.ttl option.
274
274
  */
275
275
  set<TReturn>(cache: Cache<TReturn>, key: string, value: TReturn, ttl?: DurationLike): Promise<void>;
276
- protected serialize<TReturn>(value: TReturn): Buffer;
277
- protected deserialize<TReturn>(buffer: Buffer): TReturn;
276
+ protected encoder: TextEncoder;
277
+ protected decoder: TextDecoder;
278
+ protected codes: {
279
+ BINARY: number;
280
+ JSON: number;
281
+ STRING: number;
282
+ };
283
+ protected serialize<TReturn>(value: TReturn): Uint8Array;
284
+ protected deserialize<TReturn>(uint8Array: Uint8Array): Promise<TReturn>;
278
285
  }
279
286
  interface Cache<TReturn = any, TParameter extends any[] = any[]> {
280
287
  name: string;
package/core.d.ts CHANGED
@@ -530,8 +530,12 @@ interface Hooks {
530
530
  */
531
531
  declare class Alepha {
532
532
  /**
533
- * Syntactic sugar for creating a new instance of the container.
534
- * Equivalent to `Alepha.create()`.
533
+ * Creates a new instance of the Alepha container with some helpers:
534
+ *
535
+ * - merges `process.env` with the provided state.env when available.
536
+ * - populates the test hooks for Vitest or Jest environments when available.
537
+ *
538
+ * If you are not interested about these helpers, you can use the constructor directly.
535
539
  */
536
540
  static create(state?: Partial<State>): Alepha;
537
541
  /**
package/datetime.d.ts CHANGED
@@ -94,12 +94,18 @@ declare class DateTimeProvider {
94
94
  tick(): Promise<void>;
95
95
  /**
96
96
  * Wait for a certain duration.
97
+ *
98
+ * You can clear the timeout by using the `AbortSignal` API.
99
+ * Aborted signal will resolve the promise immediately, it does not reject it.
97
100
  */
98
- wait(duration: DurationLike, signal?: AbortSignal): Promise<void>;
101
+ wait(duration: DurationLike, options?: {
102
+ signal?: AbortSignal;
103
+ now?: number;
104
+ }): Promise<void>;
99
105
  /**
100
106
  * Run a callback after a certain duration.
101
107
  */
102
- timeout(callback: () => void, duration: DurationLike): Timeout;
108
+ timeout(callback: () => void, duration: DurationLike, now?: number): Timeout;
103
109
  /**
104
110
  * Create an interval.
105
111
  *
@@ -113,7 +119,7 @@ declare class DateTimeProvider {
113
119
  /**
114
120
  * Add time to the current date.
115
121
  */
116
- travel(duration: DurationLike): Promise<void>;
122
+ travel(duration: DurationLike, unit?: ManipulateType): Promise<void>;
117
123
  /**
118
124
  * Stop the time.
119
125
  */
package/lock/redis.cjs CHANGED
@@ -33,7 +33,7 @@ class RedisLockProvider {
33
33
  await this.redisProvider.del(keys);
34
34
  }
35
35
  }
36
- class AlephaLock {
36
+ class AlephaLockRedis {
37
37
  name = "alepha.lock.redis";
38
38
  $services = (alepha) => alepha.with({
39
39
  provide: lock.LockTopicProvider,
@@ -43,8 +43,8 @@ class AlephaLock {
43
43
  provide: lock.LockProvider,
44
44
  use: RedisLockProvider,
45
45
  optional: true
46
- }).with(AlephaLock);
46
+ }).with(lock.AlephaLock);
47
47
  }
48
48
 
49
- exports.AlephaLock = AlephaLock;
49
+ exports.AlephaLockRedis = AlephaLockRedis;
50
50
  exports.RedisLockProvider = RedisLockProvider;
package/lock/redis.d.ts CHANGED
@@ -18,9 +18,9 @@ declare class RedisLockProvider implements LockProvider {
18
18
  * @see {@link RedisLockProvider}
19
19
  * @module alepha.lock.redis
20
20
  */
21
- declare class AlephaLock {
21
+ declare class AlephaLockRedis {
22
22
  readonly name = "alepha.lock.redis";
23
23
  readonly $services: (alepha: Alepha) => Alepha;
24
24
  }
25
25
 
26
- export { AlephaLock, RedisLockProvider };
26
+ export { AlephaLockRedis, RedisLockProvider };
package/lock/redis.js CHANGED
@@ -1,4 +1,4 @@
1
- import { LockTopicProvider, LockProvider } from '@alepha/lock';
1
+ import { LockTopicProvider, LockProvider, AlephaLock } from '@alepha/lock';
2
2
  import { RedisTopicProvider } from '@alepha/topic-redis';
3
3
  import { $logger, $inject } from '@alepha/core';
4
4
  import { RedisProvider } from '@alepha/redis';
@@ -31,7 +31,7 @@ class RedisLockProvider {
31
31
  await this.redisProvider.del(keys);
32
32
  }
33
33
  }
34
- class AlephaLock {
34
+ class AlephaLockRedis {
35
35
  name = "alepha.lock.redis";
36
36
  $services = (alepha) => alepha.with({
37
37
  provide: LockTopicProvider,
@@ -44,4 +44,4 @@ class AlephaLock {
44
44
  }).with(AlephaLock);
45
45
  }
46
46
 
47
- export { AlephaLock, RedisLockProvider };
47
+ export { AlephaLockRedis, RedisLockProvider };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "alepha",
3
- "version": "0.7.4",
3
+ "version": "0.7.5",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "TypeScript framework for building full-stack apps with strict conventions, and React-based SPA or SSR without filesystem-based routing.",
@@ -12,28 +12,28 @@
12
12
  "main": "./core.js",
13
13
  "types": "./core.d.ts",
14
14
  "dependencies": {
15
- "@alepha/cache": "0.7.4",
16
- "@alepha/cache-redis": "0.7.4",
17
- "@alepha/core": "0.7.4",
18
- "@alepha/datetime": "0.7.4",
19
- "@alepha/lock": "0.7.4",
20
- "@alepha/postgres": "0.7.4",
21
- "@alepha/queue": "0.7.4",
22
- "@alepha/react": "0.7.4",
23
- "@alepha/react-auth": "0.7.4",
24
- "@alepha/redis": "0.7.4",
25
- "@alepha/retry": "0.7.4",
26
- "@alepha/scheduler": "0.7.4",
27
- "@alepha/security": "0.7.4",
28
- "@alepha/server": "0.7.4",
29
- "@alepha/server-cache": "0.7.4",
30
- "@alepha/server-cookies": "0.7.4",
31
- "@alepha/server-static": "0.7.4",
32
- "@alepha/server-swagger": "0.7.4",
33
- "@alepha/testing": "0.7.4",
34
- "@alepha/topic": "0.7.4",
35
- "@alepha/topic-redis": "0.7.4",
36
- "@alepha/vite": "0.7.4",
15
+ "@alepha/cache": "0.7.5",
16
+ "@alepha/cache-redis": "0.7.5",
17
+ "@alepha/core": "0.7.5",
18
+ "@alepha/datetime": "0.7.5",
19
+ "@alepha/lock": "0.7.5",
20
+ "@alepha/postgres": "0.7.5",
21
+ "@alepha/queue": "0.7.5",
22
+ "@alepha/react": "0.7.5",
23
+ "@alepha/react-auth": "0.7.5",
24
+ "@alepha/redis": "0.7.5",
25
+ "@alepha/retry": "0.7.5",
26
+ "@alepha/scheduler": "0.7.5",
27
+ "@alepha/security": "0.7.5",
28
+ "@alepha/server": "0.7.5",
29
+ "@alepha/server-cache": "0.7.5",
30
+ "@alepha/server-cookies": "0.7.5",
31
+ "@alepha/server-static": "0.7.5",
32
+ "@alepha/server-swagger": "0.7.5",
33
+ "@alepha/testing": "0.7.5",
34
+ "@alepha/topic": "0.7.5",
35
+ "@alepha/topic-redis": "0.7.5",
36
+ "@alepha/vite": "0.7.5",
37
37
  "@types/react": "^19.1.8",
38
38
  "react": "^19.1.0"
39
39
  },
@@ -47,7 +47,6 @@
47
47
  },
48
48
  "files": [
49
49
  "src",
50
- "assets",
51
50
  "**/*.js",
52
51
  "**/*.cjs",
53
52
  "**/*.d.ts",
package/postgres.d.ts CHANGED
@@ -7,7 +7,7 @@ import * as drizzle_orm_pg_core from 'drizzle-orm/pg-core';
7
7
  import { PgSequenceOptions, AnyPgTable, AnyPgColumn, UpdateDeleteAction, PgTableWithColumns, PgColumnBuilderBase, PgTableExtraConfigValue, PgDatabase, TableConfig as TableConfig$1, PgColumn, PgTransaction, PgTransactionConfig, LockStrength, LockConfig, PgInsertValue, PgSelectJoinFn } from 'drizzle-orm/pg-core';
8
8
  export * from 'drizzle-orm/pg-core';
9
9
  import * as _sinclair_typebox from '@sinclair/typebox';
10
- import { TObject, TSchema, ObjectOptions, Kind, TProperties, Evaluate, TReadonly, TOptional, Static, TAdditionalProperties, OptionalKind, TArray, TIntersect, TRecord, TBoolean, TInteger, TOptionalWithFlag, IntegerOptions, NumberOptions, StringOptions } from '@sinclair/typebox';
10
+ import { TObject, TSchema, ObjectOptions, Kind, TProperties, Evaluate, TReadonly, TOptional, Static, TAdditionalProperties, OptionalKind, TArray, TPick, TIntersect, TRecord, TBoolean, TInteger, TOptionalWithFlag, IntegerOptions, NumberOptions, StringOptions } from '@sinclair/typebox';
11
11
  import { BuildExtraConfigColumns } from 'drizzle-orm/column-builder';
12
12
  import * as _alepha_lock from '@alepha/lock';
13
13
  import { MigrationConfig } from 'drizzle-orm/migrator';
@@ -680,15 +680,19 @@ type PgQueryWhere<T extends object> = {
680
680
  exists?: SQLWrapper;
681
681
  };
682
682
 
683
- interface PgQuery<T extends TObject> {
683
+ interface PgQuery<T extends TObject, Select extends (keyof Static<T>)[] = []> {
684
+ columns?: Select;
685
+ distinct?: boolean;
684
686
  where?: PgQueryWhereWithMany<T> | SQLWrapper;
685
687
  limit?: number;
686
688
  offset?: number;
687
689
  sort?: {
688
690
  [key in keyof Static<T>]?: "asc" | "desc";
689
691
  };
692
+ groupBy?: (keyof Static<T>)[];
690
693
  relations?: PgQueryWithMap<T>;
691
694
  }
695
+ type PgQueryResult<T extends TObject, Select extends (keyof Static<T>)[]> = TPick<T, Select>;
692
696
  type PgQueryWhereWithMany<T extends TObject> = PgQueryWhere<Static<RemoveManyRelations<T>>> & ExtractManyRelations<T>;
693
697
  type ExtractManyRelations<T extends TObject> = {
694
698
  [K in keyof T["properties"] as T["properties"][K] extends {
@@ -879,7 +883,7 @@ declare class Repository<TTable extends PgTableWithColumns<TableConfig$1>, TTabl
879
883
  * @param opts The statement options.
880
884
  * @returns The found entities.
881
885
  */
882
- find(query?: PgQuery<TTableSchema>, opts?: StatementOptions): Promise<Static<TTableSchema>[]>;
886
+ find<Select extends (keyof Static<TTableSchema>)[]>(query?: PgQuery<TTableSchema, Select>, opts?: StatementOptions): Promise<Static<PgQueryResult<TTableSchema, Select>>[]>;
883
887
  /**
884
888
  * Find a single entity.
885
889
  *
@@ -4358,13 +4362,7 @@ declare const envSchema: _alepha_core.TObject<{
4358
4362
  PG_DATABASE: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
4359
4363
  PG_PASSWORD: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
4360
4364
  PG_PORT: _sinclair_typebox.TOptional<_sinclair_typebox.TNumber>;
4361
- /**
4362
- *
4363
- */
4364
- DATABASE_URL: _sinclair_typebox.TString;
4365
- /**
4366
- *
4367
- */
4365
+ DATABASE_URL: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
4368
4366
  DATABASE_MIGRATIONS_FOLDER: _sinclair_typebox.TString;
4369
4367
  /**
4370
4368
  * The schema to use.
@@ -4404,10 +4402,10 @@ declare class NodePostgresProvider implements PostgresProvider {
4404
4402
  PG_DATABASE?: string | undefined;
4405
4403
  PG_PASSWORD?: string | undefined;
4406
4404
  PG_PORT?: number | undefined;
4405
+ DATABASE_URL?: string | undefined;
4407
4406
  POSTGRES_SCHEMA?: string | undefined;
4408
4407
  POSTGRES_SYNCHRONIZE?: boolean | undefined;
4409
4408
  POSTGRES_PUSH_SCHEMA?: boolean | undefined;
4410
- DATABASE_URL: string;
4411
4409
  DATABASE_MIGRATIONS_FOLDER: string;
4412
4410
  POSTGRES_REJECT_UNAUTHORIZED: boolean;
4413
4411
  };
@@ -4590,4 +4588,4 @@ declare class AlephaPostgres implements Module {
4590
4588
  readonly $services: (alepha: Alepha) => Alepha;
4591
4589
  }
4592
4590
 
4593
- export { $entity, $repository, $sequence, $transaction, AlephaPostgres, type BaseEntity, type BaseEntityKeys, DrizzleKitProvider, type Entity, type EntityDescriptorOptions, EntityNotFoundError, type ExtractManyRelations, type FilterOperators, type FromSchema, NodePostgresProvider, type NodePostgresProviderState, type NullToUndefined, type NullifyIfOptional, PG_CREATED_AT, PG_DEFAULT, PG_IDENTITY, PG_MANY, PG_ONE, PG_PRIMARY_KEY, PG_REF, PG_SCHEMA, PG_SERIAL, PG_UPDATED_AT, PG_VERSION, type Page, type PageQuery, type PgAttrField, type PgDefault, type PgIdentityOptions, type PgMany, type PgManyOptions, type PgPrimaryKey, type PgQuery, type PgQueryWhere, type PgQueryWhereWithMany, type PgQueryWith, type PgQueryWithMap, type PgRef, type PgRefOptions, type PgSymbolKeys, type PgSymbols, type PgTableConfig, type PgTableWithColumnsAndSchema, PostgresProvider, PostgresTypeProvider, type RemoveManyRelations, Repository, type RepositoryDescriptorOptions, RepositoryDescriptorProvider, type SQLLike, type SequenceDescriptor, type SequenceDescriptorOptions, type StatementOptions, type TEntity, type TInsertObject, type TPage, type TransactionContext, type TransactionDescriptorOptions, entityKeys, entitySchema, nullToUndefined, pageQuerySchema, pageSchema, pg, pgTableSchema, schema, schemaToColumns };
4591
+ export { $entity, $repository, $sequence, $transaction, AlephaPostgres, type BaseEntity, type BaseEntityKeys, DrizzleKitProvider, type Entity, type EntityDescriptorOptions, EntityNotFoundError, type ExtractManyRelations, type FilterOperators, type FromSchema, NodePostgresProvider, type NodePostgresProviderState, type NullToUndefined, type NullifyIfOptional, PG_CREATED_AT, PG_DEFAULT, PG_IDENTITY, PG_MANY, PG_ONE, PG_PRIMARY_KEY, PG_REF, PG_SCHEMA, PG_SERIAL, PG_UPDATED_AT, PG_VERSION, type Page, type PageQuery, type PgAttrField, type PgDefault, type PgIdentityOptions, type PgMany, type PgManyOptions, type PgPrimaryKey, type PgQuery, type PgQueryResult, type PgQueryWhere, type PgQueryWhereWithMany, type PgQueryWith, type PgQueryWithMap, type PgRef, type PgRefOptions, type PgSymbolKeys, type PgSymbols, type PgTableConfig, type PgTableWithColumnsAndSchema, PostgresProvider, PostgresTypeProvider, type RemoveManyRelations, Repository, type RepositoryDescriptorOptions, RepositoryDescriptorProvider, type SQLLike, type SequenceDescriptor, type SequenceDescriptorOptions, type StatementOptions, type TEntity, type TInsertObject, type TPage, type TransactionContext, type TransactionDescriptorOptions, entityKeys, entitySchema, nullToUndefined, pageQuerySchema, pageSchema, pg, pgTableSchema, schema, schemaToColumns };
package/react/auth.d.ts CHANGED
@@ -142,6 +142,7 @@ interface AuthDescriptorOptions {
142
142
  clientSecret?: string;
143
143
  redirectUri?: string;
144
144
  useIdToken?: boolean;
145
+ logoutUri?: string;
145
146
  };
146
147
  }
147
148
  interface AuthDescriptor {
@@ -236,6 +237,7 @@ declare class ReactAuthProvider {
236
237
  redirectUri: string;
237
238
  fallback?: () => Async<AccessToken>;
238
239
  useIdToken?: boolean;
240
+ logoutUri?: string;
239
241
  }>;
240
242
  /**
241
243
  *
@@ -261,6 +263,7 @@ interface AuthProvider {
261
263
  };
262
264
  fallback?: () => Async<AccessToken>;
263
265
  useIdToken?: boolean;
266
+ logoutUri?: string;
264
267
  }
265
268
  interface ReactUser {
266
269
  id: string;
package/react.d.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  import * as _alepha_core from '@alepha/core';
2
2
  import { TSchema as TSchema$1, KIND, OPTIONS, Static, Async, Alepha, Service, TObject, Module } from '@alepha/core';
3
- import { ServerRoute, ServerRequest, ApiLinksResponse, HttpClient, ClientScope, HttpVirtualClient, ServerRouterProvider, ServerTimingProvider, ServerHandler } from '@alepha/server';
3
+ import { ServerRequest, ApiLinksResponse, HttpClient, ClientScope, HttpVirtualClient, ServerRouterProvider, ServerTimingProvider, ServerHandler } from '@alepha/server';
4
4
  import * as React from 'react';
5
5
  import React__default, { PropsWithChildren, ReactNode, FC, ErrorInfo, AnchorHTMLAttributes } from 'react';
6
+ import { ServerRouteCache } from '@alepha/server-cache';
6
7
  import { Root } from 'react-dom/client';
7
8
  import { RouterProvider, Route } from '@alepha/router';
8
9
  import * as react_jsx_runtime from 'react/jsx-runtime';
@@ -101,7 +102,7 @@ interface PageConfigSchema {
101
102
  }
102
103
  type TPropsDefault = any;
103
104
  type TPropsParentDefault = {};
104
- interface PageDescriptorOptions<TConfig extends PageConfigSchema = PageConfigSchema, TProps extends object = TPropsDefault, TPropsParent extends object = TPropsParentDefault> extends Pick<ServerRoute, "cache"> {
105
+ interface PageDescriptorOptions<TConfig extends PageConfigSchema = PageConfigSchema, TProps extends object = TPropsDefault, TPropsParent extends object = TPropsParentDefault> {
105
106
  /**
106
107
  * Name your page.
107
108
  *
@@ -181,6 +182,7 @@ interface PageDescriptorOptions<TConfig extends PageConfigSchema = PageConfigSch
181
182
  */
182
183
  client?: boolean | ClientOnlyProps;
183
184
  afterHandler?: (request: ServerRequest) => any;
185
+ cache?: ServerRouteCache;
184
186
  }
185
187
  interface PageDescriptor<TConfig extends PageConfigSchema = PageConfigSchema, TProps extends object = TPropsDefault, TPropsParent extends object = TPropsParentDefault> {
186
188
  [KIND]: typeof KEY;
@@ -436,6 +438,51 @@ interface ReactHydrationState {
436
438
  links?: ApiLinksResponse;
437
439
  }
438
440
 
441
+ /**
442
+ * Props for the ErrorBoundary component.
443
+ */
444
+ interface ErrorBoundaryProps {
445
+ /**
446
+ * Fallback React node to render when an error is caught.
447
+ * If not provided, a default error message will be shown.
448
+ */
449
+ fallback: (error: Error) => ReactNode;
450
+ /**
451
+ * Optional callback that receives the error and error info.
452
+ * Use this to log errors to a monitoring service.
453
+ */
454
+ onError?: (error: Error, info: ErrorInfo) => void;
455
+ }
456
+ /**
457
+ * State of the ErrorBoundary component.
458
+ */
459
+ interface ErrorBoundaryState {
460
+ error?: Error;
461
+ }
462
+ /**
463
+ * A reusable error boundary for catching rendering errors
464
+ * in any part of the React component tree.
465
+ */
466
+ declare class ErrorBoundary extends React__default.Component<PropsWithChildren<ErrorBoundaryProps>, ErrorBoundaryState> {
467
+ constructor(props: ErrorBoundaryProps);
468
+ /**
469
+ * Update state so the next render shows the fallback UI.
470
+ */
471
+ static getDerivedStateFromError(error: Error): ErrorBoundaryState;
472
+ /**
473
+ * Lifecycle method called when an error is caught.
474
+ * You can log the error or perform side effects here.
475
+ */
476
+ componentDidCatch(error: Error, info: ErrorInfo): void;
477
+ render(): ReactNode;
478
+ }
479
+
480
+ interface LinkProps extends AnchorHTMLAttributes<HTMLAnchorElement> {
481
+ to: string | PageDescriptor;
482
+ children?: React__default.ReactNode;
483
+ }
484
+ declare const Link: (props: LinkProps) => react_jsx_runtime.JSX.Element | null;
485
+
439
486
  interface NestedViewProps {
440
487
  children?: ReactNode;
441
488
  }
@@ -462,6 +509,19 @@ interface NestedViewProps {
462
509
  */
463
510
  declare const NestedView: (props: NestedViewProps) => react_jsx_runtime.JSX.Element;
464
511
 
512
+ interface RouterContextValue {
513
+ alepha: Alepha;
514
+ state: RouterState;
515
+ context: PageReactContext;
516
+ }
517
+ declare const RouterContext: React.Context<RouterContextValue | undefined>;
518
+
519
+ interface RouterLayerContextValue {
520
+ index: number;
521
+ path: string;
522
+ }
523
+ declare const RouterLayerContext: React.Context<RouterLayerContextValue | undefined>;
524
+
465
525
  declare class RouterHookApi {
466
526
  private readonly pages;
467
527
  private readonly state;
@@ -523,64 +583,6 @@ declare class RedirectionError extends Error {
523
583
  constructor(page: HrefLike);
524
584
  }
525
585
 
526
- /**
527
- * Props for the ErrorBoundary component.
528
- */
529
- interface ErrorBoundaryProps {
530
- /**
531
- * Fallback React node to render when an error is caught.
532
- * If not provided, a default error message will be shown.
533
- */
534
- fallback: (error: Error) => ReactNode;
535
- /**
536
- * Optional callback that receives the error and error info.
537
- * Use this to log errors to a monitoring service.
538
- */
539
- onError?: (error: Error, info: ErrorInfo) => void;
540
- }
541
- /**
542
- * State of the ErrorBoundary component.
543
- */
544
- interface ErrorBoundaryState {
545
- error?: Error;
546
- }
547
- /**
548
- * A reusable error boundary for catching rendering errors
549
- * in any part of the React component tree.
550
- */
551
- declare class ErrorBoundary extends React__default.Component<PropsWithChildren<ErrorBoundaryProps>, ErrorBoundaryState> {
552
- constructor(props: ErrorBoundaryProps);
553
- /**
554
- * Update state so the next render shows the fallback UI.
555
- */
556
- static getDerivedStateFromError(error: Error): ErrorBoundaryState;
557
- /**
558
- * Lifecycle method called when an error is caught.
559
- * You can log the error or perform side effects here.
560
- */
561
- componentDidCatch(error: Error, info: ErrorInfo): void;
562
- render(): ReactNode;
563
- }
564
-
565
- interface LinkProps extends AnchorHTMLAttributes<HTMLAnchorElement> {
566
- to: string | PageDescriptor;
567
- children?: React__default.ReactNode;
568
- }
569
- declare const Link: (props: LinkProps) => react_jsx_runtime.JSX.Element | null;
570
-
571
- interface RouterContextValue {
572
- alepha: Alepha;
573
- state: RouterState;
574
- context: PageReactContext;
575
- }
576
- declare const RouterContext: React.Context<RouterContextValue | undefined>;
577
-
578
- interface RouterLayerContextValue {
579
- index: number;
580
- path: string;
581
- }
582
- declare const RouterLayerContext: React.Context<RouterLayerContextValue | undefined>;
583
-
584
586
  declare const useActive: (path: HrefLike) => UseActiveHook;
585
587
  interface UseActiveHook {
586
588
  isActive: boolean;
package/scheduler.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import * as _alepha_core from '@alepha/core';
2
- import { Async, KIND, OPTIONS, Static, Alepha } from '@alepha/core';
3
- import { DurationLike, DateTimeProvider, Interval } from '@alepha/datetime';
2
+ import { Async, KIND, OPTIONS, Alepha, Static } from '@alepha/core';
3
+ import { DateTime, DurationLike, DateTimeProvider, Interval } from '@alepha/datetime';
4
4
  import * as _alepha_lock from '@alepha/lock';
5
- import { ScheduledTask } from 'node-cron';
5
+ import { Cron } from 'cron-schedule';
6
6
 
7
7
  declare const KEY = "SCHEDULER";
8
8
  /**
@@ -17,7 +17,7 @@ type SchedulerDescriptorOptions = {
17
17
  /**
18
18
  * Function to run on schedule.
19
19
  */
20
- handler: () => Async<void>;
20
+ handler: (args: SchedulerHandlerArguments) => Async<void>;
21
21
  /**
22
22
  * Name of the scheduler. Defaults to the function name.
23
23
  */
@@ -36,7 +36,9 @@ type SchedulerDescriptorOptions = {
36
36
  interval?: DurationLike;
37
37
  /**
38
38
  * If true, the scheduler will be locked and only one instance will run at a time.
39
- * Defaults to true.
39
+ * You probably need to import {@link AlephaLockRedis} for distributed locking.
40
+ *
41
+ * @default true
40
42
  */
41
43
  lock?: boolean;
42
44
  };
@@ -45,6 +47,9 @@ interface SchedulerDescriptor {
45
47
  [OPTIONS]: SchedulerDescriptorOptions;
46
48
  (): Promise<void>;
47
49
  }
50
+ interface SchedulerHandlerArguments {
51
+ now: DateTime;
52
+ }
48
53
 
49
54
  /** Symbol key applied to readonly types */
50
55
  declare const ReadonlyKind: unique symbol;
@@ -110,6 +115,28 @@ interface TSchema extends TKind, SchemaOptions {
110
115
  static: unknown;
111
116
  }
112
117
 
118
+ interface CronJob {
119
+ handler: (context: {
120
+ now: DateTime;
121
+ }) => Promise<void>;
122
+ cron: Cron;
123
+ loop: boolean;
124
+ running?: boolean;
125
+ onError?: (error: Error) => void;
126
+ abort: AbortController;
127
+ }
128
+ declare class CronProvider {
129
+ protected readonly dt: DateTimeProvider;
130
+ protected readonly alepha: Alepha;
131
+ protected readonly log: _alepha_core.Logger;
132
+ start(cron: CronJob): void;
133
+ stop(cron: CronJob): void;
134
+ create(expression: string, handler: (context: {
135
+ now: DateTime;
136
+ }) => Promise<void>): CronJob;
137
+ run(task: CronJob, now?: undefined): void;
138
+ }
139
+
113
140
  declare const envSchema: _alepha_core.TObject<{
114
141
  SCHEDULER_PREFIX: TOptional<TString>;
115
142
  }>;
@@ -124,10 +151,12 @@ declare class SchedulerDescriptorProvider {
124
151
  };
125
152
  protected readonly alepha: Alepha;
126
153
  protected readonly dateTimeProvider: DateTimeProvider;
154
+ protected readonly cronProvider: CronProvider;
127
155
  protected readonly schedulers: Scheduler[];
128
156
  protected readonly configure: _alepha_core.HookDescriptor<"configure">;
129
157
  protected readonly start: _alepha_core.HookDescriptor<"start">;
130
158
  protected readonly stop: _alepha_core.HookDescriptor<"stop">;
159
+ protected createContextId(): string;
131
160
  /**
132
161
  * Get the schedulers.
133
162
  */
@@ -147,11 +176,12 @@ declare class SchedulerDescriptorProvider {
147
176
  * @protected
148
177
  */
149
178
  protected createScheduler(options: SchedulerDescriptorOptions, instance: any, key: string): Scheduler;
179
+ protected createHandler(name: string, options: SchedulerDescriptorOptions): (args: SchedulerHandlerArguments) => Promise<void>;
150
180
  trigger(name: string): Promise<void>;
151
181
  protected runLock: _alepha_lock.LockDescriptor<(options: SchedulerDescriptorOptions & {
152
182
  name: string;
183
+ args: SchedulerHandlerArguments;
153
184
  }) => Promise<void>>;
154
- protected run(options: SchedulerDescriptorOptions): Promise<void>;
155
185
  /**
156
186
  * Prefix the scheduler key.
157
187
  */
@@ -166,8 +196,8 @@ declare class SchedulerDescriptorProvider {
166
196
  interface Scheduler {
167
197
  name: string;
168
198
  options: SchedulerDescriptorOptions;
169
- trigger: () => Promise<void>;
170
- cron?: ScheduledTask;
199
+ trigger: (args: SchedulerHandlerArguments) => Promise<void>;
200
+ cron?: CronJob;
171
201
  interval?: Interval;
172
202
  }
173
203
 
@@ -184,4 +214,4 @@ declare class AlephaScheduler {
184
214
  readonly $services: (alepha: Alepha) => Alepha;
185
215
  }
186
216
 
187
- export { $scheduler, AlephaScheduler, type Scheduler, type SchedulerDescriptor, type SchedulerDescriptorOptions, SchedulerDescriptorProvider, isScheduler };
217
+ export { $scheduler, AlephaScheduler, type Scheduler, type SchedulerDescriptor, type SchedulerDescriptorOptions, SchedulerDescriptorProvider, type SchedulerHandlerArguments, isScheduler };
package/server/cache.d.ts CHANGED
@@ -6,7 +6,7 @@ import { ServerHandler, ServerRequestConfig } from '@alepha/server';
6
6
 
7
7
  declare module "alepha/server" {
8
8
  interface ServerRoute {
9
- cache?: ServiceRouteCache;
9
+ cache?: ServerRouteCache;
10
10
  }
11
11
  interface ActionDescriptor {
12
12
  invalidate: () => Promise<void>;
@@ -27,7 +27,7 @@ declare class ServerCacheProvider {
27
27
  protected getCacheByRoute(route: RouteLike): RouteCache | undefined;
28
28
  protected createCacheKey(args: ServerRequestConfig): string;
29
29
  }
30
- type ServiceRouteCache = boolean | DurationLike | Omit<CacheDescriptorOptions<any>, "handler" | "key">;
30
+ type ServerRouteCache = boolean | DurationLike | Omit<CacheDescriptorOptions<any>, "handler" | "key">;
31
31
  type RouteCache = Cache<{
32
32
  contentType?: string;
33
33
  body: string;
@@ -43,9 +43,40 @@ type RouteLike = {
43
43
  handler?: ServerHandler;
44
44
  };
45
45
 
46
+ /**
47
+ * # Alepha Server Cache Module
48
+ *
49
+ * @description
50
+ * Plugin for Alepha Server that provides server-side caching capabilities.
51
+ * It uses the Alepha Cache module to cache responses from server actions ($action).
52
+ * It also provides a ETag-based cache invalidation mechanism.
53
+ *
54
+ * @example
55
+ * ```ts
56
+ * import { Alepha } from "@alepha/core";
57
+ * import { $action } from "@alepha/server";
58
+ * import { AlephaServerCache } from "alepha/server/cache";
59
+ *
60
+ * class ApiServer {
61
+ * hello = $action({
62
+ * cache: true,
63
+ * handler: () => "Hello, World!",
64
+ * });
65
+ * }
66
+ *
67
+ * const alepha = Alepha.create()
68
+ * .with(AlephaServerCache)
69
+ * .with(ApiServer);
70
+ *
71
+ * run(alepha);
72
+ * ```
73
+ *
74
+ * @see {@link ServerCacheProvider}
75
+ * @module alepha.server.cache
76
+ */
46
77
  declare class AlephaServerCache implements Module {
47
78
  readonly name = "alepha.server.cache";
48
79
  readonly $services: (alepha: Alepha) => Alepha;
49
80
  }
50
81
 
51
- export { AlephaServerCache, ServerCacheProvider, type ServiceRouteCache };
82
+ export { AlephaServerCache, ServerCacheProvider, type ServerRouteCache };
@@ -100,6 +100,16 @@ declare class ServerSwaggerProvider {
100
100
  protected configureSwaggerUi(prefix: string, options: SwaggerDescriptorOptions): Promise<void>;
101
101
  }
102
102
 
103
+ /**
104
+ * Alepha Server Swagger Module
105
+ *
106
+ * Plugin for Alepha Server that provides Swagger documentation capabilities.
107
+ * It generates OpenAPI v3 documentation for the server's endpoints ($action).
108
+ * It also provides a Swagger UI for interactive API documentation.
109
+ *
110
+ * @see {@link ServerSwaggerProvider}
111
+ * @module alepha.server.swagger
112
+ */
103
113
  declare class AlephaServerSwagger implements Module {
104
114
  readonly name = "alepha.server.swagger";
105
115
  readonly $services: (alepha: Alepha) => Alepha;
package/vite.d.ts CHANGED
@@ -59,11 +59,11 @@ interface ViteAlephaBuildVercelOptions {
59
59
  */
60
60
  clientDir?: string;
61
61
  }
62
- declare function viteAlephaBuildVercel(opts?: ViteAlephaBuildVercelOptions): {
62
+ declare function viteAlephaBuildVercel(opts?: ViteAlephaBuildVercelOptions): Promise<{
63
63
  name: string;
64
64
  apply: string;
65
65
  writeBundle(): void;
66
- };
66
+ }>;
67
67
 
68
68
  interface ViteCompressOptions {
69
69
  /**
package/assets/logo.png DELETED
Binary file