vintasend-api 1.0.0-alpha6 → 1.0.0-alpha7

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
@@ -38,6 +38,19 @@ npm install vintasend-api vintasend
38
38
  Install the same release line for both: the API is released together with
39
39
  `vintasend`, and its version matches.
40
40
 
41
+ The standalone server also needs `@hono/node-server`. It is an optional peer
42
+ dependency, so a host that mounts `createApp` in its own server does not install
43
+ a Node HTTP server it never starts:
44
+
45
+ ```bash
46
+ npm install @hono/node-server # only to run the vintasend-api command
47
+ ```
48
+
49
+ `vintasend-api` holds `createApp`, the authenticators, `ApiError` and the wire
50
+ types, and loads in a browser. `vintasend-api/server` holds what the standalone
51
+ command is built from: `loadServerConfig` and the service-module loader. It is
52
+ Node only.
53
+
41
54
  ## Architecture
42
55
 
43
56
  ```
@@ -146,11 +159,14 @@ either package: both recognise an error by its name and code, not by its class.
146
159
  Throw `ApiError.unauthorized` for a caller with no valid credential and
147
160
  `ApiError.forbidden` for one you know and refuse: a 401 would tell a signed-in
148
161
  user to sign in again. For one shared secret, pass
149
- `authenticate: apiKeyAuthenticator(key)`, which compares in constant time.
162
+ `authenticate: apiKeyAuthenticator(key)`, which compares in constant time. To
163
+ check a token yourself, such as the caller's own identity-provider token, read it
164
+ with `bearerToken(c.req.header('authorization'))`, which is `null` when the
165
+ request carries none.
150
166
 
151
167
  The app uses Web APIs only — no Node built-ins — so it runs wherever `fetch`
152
- does. The standalone server and the module-path service loader are the Node-only
153
- parts, and `createApp` loads neither.
168
+ does. The standalone server and the module-path service loader on `./server` are
169
+ the Node-only parts, and the package entry loads neither.
154
170
 
155
171
  An unexpected error is reported to the client as a generic 500 with an
156
172
  `X-Request-Id` header. By default it is logged as one line — the error's name,
@@ -9,82 +9,53 @@ export declare const DEFAULT_PAGE_SIZE = 20;
9
9
  export declare const MIN_PAGE_SIZE = 1;
10
10
  export declare const MAX_PAGE_SIZE = 100;
11
11
  export declare const paginationQuerySchema: z.ZodObject<{
12
- page: z.ZodDefault<z.ZodNumber>;
13
- pageSize: z.ZodDefault<z.ZodNumber>;
14
- }, "strip", z.ZodTypeAny, {
15
- page: number;
16
- pageSize: number;
17
- }, {
18
- page?: number | undefined;
19
- pageSize?: number | undefined;
20
- }>;
12
+ page: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
13
+ pageSize: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
14
+ }, z.core.$strip>;
21
15
  export declare const notificationListQuerySchema: z.ZodObject<{
22
- page: z.ZodDefault<z.ZodNumber>;
23
- pageSize: z.ZodDefault<z.ZodNumber>;
24
- } & {
25
- status: z.ZodOptional<z.ZodEnum<["PENDING_SEND", "SENT", "FAILED", "READ", "CANCELLED"]>>;
26
- notificationType: z.ZodOptional<z.ZodEnum<["EMAIL", "SMS", "PUSH", "IN_APP"]>>;
16
+ page: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
17
+ pageSize: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
18
+ status: z.ZodOptional<z.ZodEnum<{
19
+ PENDING_SEND: "PENDING_SEND";
20
+ SENT: "SENT";
21
+ FAILED: "FAILED";
22
+ READ: "READ";
23
+ CANCELLED: "CANCELLED";
24
+ }>>;
25
+ notificationType: z.ZodOptional<z.ZodEnum<{
26
+ EMAIL: "EMAIL";
27
+ SMS: "SMS";
28
+ PUSH: "PUSH";
29
+ IN_APP: "IN_APP";
30
+ }>>;
27
31
  adapterUsed: z.ZodOptional<z.ZodString>;
28
32
  userId: z.ZodOptional<z.ZodString>;
29
33
  bodyTemplate: z.ZodOptional<z.ZodString>;
30
34
  subjectTemplate: z.ZodOptional<z.ZodString>;
31
35
  contextName: z.ZodOptional<z.ZodString>;
32
36
  tenant: z.ZodOptional<z.ZodString>;
33
- requestedTemplateVersion: z.ZodOptional<z.ZodNumber>;
34
- usedTemplateVersion: z.ZodOptional<z.ZodNumber>;
35
- createdAtFrom: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>;
36
- createdAtTo: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>;
37
- sentAtFrom: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>;
38
- sentAtTo: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>;
39
- orderByField: z.ZodOptional<z.ZodEnum<["sendAfter", "sentAt", "readAt", "createdAt", "updatedAt"]>>;
40
- orderByDirection: z.ZodOptional<z.ZodEnum<["asc", "desc"]>>;
41
- }, "strip", z.ZodTypeAny, {
42
- page: number;
43
- pageSize: number;
44
- status?: "PENDING_SEND" | "SENT" | "FAILED" | "READ" | "CANCELLED" | undefined;
45
- notificationType?: "EMAIL" | "SMS" | "PUSH" | "IN_APP" | undefined;
46
- adapterUsed?: string | undefined;
47
- userId?: string | undefined;
48
- bodyTemplate?: string | undefined;
49
- subjectTemplate?: string | undefined;
50
- contextName?: string | undefined;
51
- tenant?: string | undefined;
52
- requestedTemplateVersion?: number | undefined;
53
- usedTemplateVersion?: number | undefined;
54
- createdAtFrom?: string | undefined;
55
- createdAtTo?: string | undefined;
56
- sentAtFrom?: string | undefined;
57
- sentAtTo?: string | undefined;
58
- orderByField?: "sendAfter" | "sentAt" | "readAt" | "createdAt" | "updatedAt" | undefined;
59
- orderByDirection?: "asc" | "desc" | undefined;
60
- }, {
61
- page?: number | undefined;
62
- pageSize?: number | undefined;
63
- status?: "PENDING_SEND" | "SENT" | "FAILED" | "READ" | "CANCELLED" | undefined;
64
- notificationType?: "EMAIL" | "SMS" | "PUSH" | "IN_APP" | undefined;
65
- adapterUsed?: string | undefined;
66
- userId?: string | undefined;
67
- bodyTemplate?: string | undefined;
68
- subjectTemplate?: string | undefined;
69
- contextName?: string | undefined;
70
- tenant?: string | undefined;
71
- requestedTemplateVersion?: number | undefined;
72
- usedTemplateVersion?: number | undefined;
73
- createdAtFrom?: string | undefined;
74
- createdAtTo?: string | undefined;
75
- sentAtFrom?: string | undefined;
76
- sentAtTo?: string | undefined;
77
- orderByField?: "sendAfter" | "sentAt" | "readAt" | "createdAt" | "updatedAt" | undefined;
78
- orderByDirection?: "asc" | "desc" | undefined;
79
- }>;
37
+ requestedTemplateVersion: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
38
+ usedTemplateVersion: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
39
+ createdAtFrom: z.ZodOptional<z.ZodString>;
40
+ createdAtTo: z.ZodOptional<z.ZodString>;
41
+ sentAtFrom: z.ZodOptional<z.ZodString>;
42
+ sentAtTo: z.ZodOptional<z.ZodString>;
43
+ orderByField: z.ZodOptional<z.ZodEnum<{
44
+ sendAfter: "sendAfter";
45
+ sentAt: "sentAt";
46
+ readAt: "readAt";
47
+ createdAt: "createdAt";
48
+ updatedAt: "updatedAt";
49
+ }>>;
50
+ orderByDirection: z.ZodOptional<z.ZodEnum<{
51
+ asc: "asc";
52
+ desc: "desc";
53
+ }>>;
54
+ }, z.core.$strip>;
80
55
  /** Body of `POST /notifications/{id}/resend`. Optional: an omitted body regenerates the context. */
81
56
  export declare const resendBodySchema: z.ZodObject<{
82
57
  useStoredContext: z.ZodDefault<z.ZodBoolean>;
83
- }, "strip", z.ZodTypeAny, {
84
- useStoredContext: boolean;
85
- }, {
86
- useStoredContext?: boolean | undefined;
87
- }>;
58
+ }, z.core.$strip>;
88
59
  export type NotificationListQueryInput = z.infer<typeof notificationListQuerySchema>;
89
60
  export type PaginationQueryInput = z.infer<typeof paginationQuerySchema>;
90
61
  export type ResendBodyInput = z.infer<typeof resendBodySchema>;
package/dist/exports.d.ts CHANGED
@@ -1,14 +1,15 @@
1
1
  /**
2
2
  * Public entrypoint for mounting the API inside a host's own server, and for sharing the wire
3
3
  * contract with TypeScript clients.
4
+ *
5
+ * It imports no Node built-in, so it loads wherever `fetch` does, a browser included. The
6
+ * standalone server's pieces are on `./server`.
4
7
  */
5
8
  export { API_BASE_PATH, type AppDependencies, createApp } from './app.js';
6
- export { loadServerConfig, type ServerConfig } from './config.js';
7
9
  export * from './contract/types.js';
8
10
  export { ApiError, invalidRequest } from './errors.js';
9
- export { type Authenticated, type Authenticator, apiKeyAuthenticator, authenticated, } from './middleware/authenticate.js';
11
+ export { type Authenticated, type Authenticator, apiKeyAuthenticator, authenticated, bearerToken, } from './middleware/authenticate.js';
10
12
  export { logUnhandledError, REQUEST_ID_HEADER, type UnhandledErrorHandler, } from './middleware/error-handler.js';
11
13
  export { createGitHubTemplateClientFromEnv, GitHubTemplateClient, } from './services/github-template-client.js';
12
14
  export type { TemplateSourceClient } from './services/notification-preview.js';
13
15
  export { asNotificationServicePort, type NotificationServicePort, } from './services/notification-service-port.js';
14
- export { createServiceProvider, loadNotificationService } from './services/service-loader.js';
package/dist/exports.js CHANGED
@@ -1,14 +1,15 @@
1
1
  /**
2
2
  * Public entrypoint for mounting the API inside a host's own server, and for sharing the wire
3
3
  * contract with TypeScript clients.
4
+ *
5
+ * It imports no Node built-in, so it loads wherever `fetch` does, a browser included. The
6
+ * standalone server's pieces are on `./server`.
4
7
  */
5
8
  export { API_BASE_PATH, createApp } from './app.js';
6
- export { loadServerConfig } from './config.js';
7
9
  export * from './contract/types.js';
8
10
  export { ApiError, invalidRequest } from './errors.js';
9
- export { apiKeyAuthenticator, authenticated, } from './middleware/authenticate.js';
11
+ export { apiKeyAuthenticator, authenticated, bearerToken, } from './middleware/authenticate.js';
10
12
  export { logUnhandledError, REQUEST_ID_HEADER, } from './middleware/error-handler.js';
11
13
  export { createGitHubTemplateClientFromEnv, GitHubTemplateClient, } from './services/github-template-client.js';
12
14
  export { asNotificationServicePort, } from './services/notification-service-port.js';
13
- export { createServiceProvider, loadNotificationService } from './services/service-loader.js';
14
15
  //# sourceMappingURL=exports.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"exports.js","sourceRoot":"","sources":["../src/exports.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,aAAa,EAAwB,SAAS,EAAE,MAAM,UAAU,CAAC;AAC1E,OAAO,EAAE,gBAAgB,EAAqB,MAAM,aAAa,CAAC;AAClE,cAAc,qBAAqB,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAGL,mBAAmB,EACnB,aAAa,GACd,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,iBAAiB,EACjB,iBAAiB,GAElB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,iCAAiC,EACjC,oBAAoB,GACrB,MAAM,sCAAsC,CAAC;AAE9C,OAAO,EACL,yBAAyB,GAE1B,MAAM,yCAAyC,CAAC;AACjD,OAAO,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC"}
1
+ {"version":3,"file":"exports.js","sourceRoot":"","sources":["../src/exports.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,aAAa,EAAwB,SAAS,EAAE,MAAM,UAAU,CAAC;AAC1E,cAAc,qBAAqB,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAGL,mBAAmB,EACnB,aAAa,EACb,WAAW,GACZ,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,iBAAiB,EACjB,iBAAiB,GAElB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,iCAAiC,EACjC,oBAAoB,GACrB,MAAM,sCAAsC,CAAC;AAE9C,OAAO,EACL,yBAAyB,GAE1B,MAAM,yCAAyC,CAAC"}
package/dist/index.js CHANGED
@@ -5,14 +5,29 @@
5
5
  * Installed as the package's `vintasend-api` command, for running the API on its own. A host that
6
6
  * already has a server mounts `createApp` instead and never loads this file.
7
7
  */
8
- import { serve } from '@hono/node-server';
9
8
  import { createApp } from './app.js';
10
- import { loadServerConfig } from './config.js';
11
9
  import { apiKeyAuthenticator } from './middleware/authenticate.js';
10
+ import { createServiceProvider, loadServerConfig } from './server.js';
12
11
  import { createGitHubTemplateClientFromEnv } from './services/github-template-client.js';
13
- import { createServiceProvider } from './services/service-loader.js';
12
+ /**
13
+ * `@hono/node-server`, which only this command uses. It is an optional peer dependency, so a host
14
+ * that mounts `createApp` in its own server does not install it.
15
+ */
16
+ async function loadNodeServer() {
17
+ try {
18
+ return await import('@hono/node-server');
19
+ }
20
+ catch (error) {
21
+ const { code, message } = error;
22
+ if (code === 'ERR_MODULE_NOT_FOUND' && message?.includes("'@hono/node-server'")) {
23
+ throw new Error('The standalone server needs @hono/node-server: npm install @hono/node-server');
24
+ }
25
+ throw error;
26
+ }
27
+ }
14
28
  async function main() {
15
29
  const config = loadServerConfig();
30
+ const { serve } = await loadNodeServer();
16
31
  const getService = createServiceProvider(config.serviceModule);
17
32
  const app = createApp({
18
33
  authenticate: apiKeyAuthenticator(config.apiKey),
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;GAKG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAE1C,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,iCAAiC,EAAE,MAAM,sCAAsC,CAAC;AACzF,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAErE,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,gBAAgB,EAAE,CAAC;IAClC,MAAM,UAAU,GAAG,qBAAqB,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;IAE/D,MAAM,GAAG,GAAG,SAAS,CAAC;QACpB,YAAY,EAAE,mBAAmB,CAAC,MAAM,CAAC,MAAM,CAAC;QAChD,UAAU;QACV,iBAAiB,EAAE,GAAG,EAAE,CAAC,iCAAiC,EAAE;QAC5D,iBAAiB,EAAE,MAAM,CAAC,iBAAiB;QAC3C,WAAW,EAAE,MAAM,CAAC,WAAW;KAChC,CAAC,CAAC;IAEH,4EAA4E;IAC5E,MAAM,UAAU,EAAE,CAAC;IAEnB,KAAK,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,EAAE;QAC7E,OAAO,CAAC,IAAI,CAAC,uCAAuC,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IAClF,CAAC,CAAC,CAAC;AACL,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,iCAAiC,EAAE,KAAK,CAAC,CAAC;IACxD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACtE,OAAO,EAAE,iCAAiC,EAAE,MAAM,sCAAsC,CAAC;AAEzF;;;GAGG;AACH,KAAK,UAAU,cAAc;IAC3B,IAAI,CAAC;QACH,OAAO,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC;IAC3C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,KAA4C,CAAC;QACvE,IAAI,IAAI,KAAK,sBAAsB,IAAI,OAAO,EAAE,QAAQ,CAAC,qBAAqB,CAAC,EAAE,CAAC;YAChF,MAAM,IAAI,KAAK,CACb,8EAA8E,CAC/E,CAAC;QACJ,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,gBAAgB,EAAE,CAAC;IAClC,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,cAAc,EAAE,CAAC;IACzC,MAAM,UAAU,GAAG,qBAAqB,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;IAE/D,MAAM,GAAG,GAAG,SAAS,CAAC;QACpB,YAAY,EAAE,mBAAmB,CAAC,MAAM,CAAC,MAAM,CAAC;QAChD,UAAU;QACV,iBAAiB,EAAE,GAAG,EAAE,CAAC,iCAAiC,EAAE;QAC5D,iBAAiB,EAAE,MAAM,CAAC,iBAAiB;QAC3C,WAAW,EAAE,MAAM,CAAC,WAAW;KAChC,CAAC,CAAC;IAEH,4EAA4E;IAC5E,MAAM,UAAU,EAAE,CAAC;IAEnB,KAAK,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,EAAE;QAC7E,OAAO,CAAC,IAAI,CAAC,uCAAuC,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IAClF,CAAC,CAAC,CAAC;AACL,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,iCAAiC,EAAE,KAAK,CAAC,CAAC;IACxD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -27,6 +27,14 @@ export type Authenticator = (c: Context) => Authenticated | Promise<Authenticate
27
27
  export declare function authenticateWith(authenticate: Authenticator): MiddlewareHandler;
28
28
  /** What the authenticator learned about this request's caller. */
29
29
  export declare function authenticated(c: Context): Authenticated;
30
+ /**
31
+ * The token in an `Authorization: Bearer <token>` header, or `null` when there is none.
32
+ *
33
+ * The scheme is matched in any case, as RFC 9110 has it. For a host writing its own
34
+ * `Authenticator` around a token it verifies itself, such as the caller's own identity-provider
35
+ * token.
36
+ */
37
+ export declare function bearerToken(header: string | undefined): string | null;
30
38
  /**
31
39
  * The shared-secret authenticator: every request must carry `Authorization: Bearer <apiKey>`.
32
40
  * It says nothing about who is calling.
@@ -45,12 +45,16 @@ async function safeEquals(a, b) {
45
45
  });
46
46
  return difference === 0;
47
47
  }
48
- function extractToken(header) {
49
- if (!header) {
50
- return undefined;
51
- }
52
- const match = header.match(/^Bearer\s+(.+)$/i);
53
- return match?.[1]?.trim();
48
+ /**
49
+ * The token in an `Authorization: Bearer <token>` header, or `null` when there is none.
50
+ *
51
+ * The scheme is matched in any case, as RFC 9110 has it. For a host writing its own
52
+ * `Authenticator` around a token it verifies itself, such as the caller's own identity-provider
53
+ * token.
54
+ */
55
+ export function bearerToken(header) {
56
+ const token = header?.match(/^Bearer\s+(.+)$/i)?.[1]?.trim();
57
+ return token ? token : null;
54
58
  }
55
59
  /**
56
60
  * The shared-secret authenticator: every request must carry `Authorization: Bearer <apiKey>`.
@@ -58,7 +62,7 @@ function extractToken(header) {
58
62
  */
59
63
  export function apiKeyAuthenticator(apiKey) {
60
64
  return async (c) => {
61
- const token = extractToken(c.req.header('authorization'));
65
+ const token = bearerToken(c.req.header('authorization'));
62
66
  if (!token || !(await safeEquals(token, apiKey))) {
63
67
  throw ApiError.unauthorized('A valid API key is required.');
64
68
  }
@@ -1 +1 @@
1
- {"version":3,"file":"authenticate.js","sourceRoot":"","sources":["../../src/middleware/authenticate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAcxC,MAAM,aAAa,GAAG,kDAAkD,CAAC;AAEzE,gGAAgG;AAChG,MAAM,UAAU,gBAAgB,CAAC,YAA2B;IAC1D,OAAO,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE;QACvB,CAAC,CAAC,GAAG,CAAC,aAAa,EAAE,MAAM,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5C,MAAM,IAAI,EAAE,CAAC;IACf,CAAC,CAAC;AACJ,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,aAAa,CAAC,CAAU;IACtC,OAAQ,CAAC,CAAC,GAAG,CAAC,aAAa,CAA+B,IAAI,EAAE,CAAC;AACnE,CAAC;AAED,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;AAElC,KAAK,UAAU,MAAM,CAAC,KAAa;IACjC,OAAO,IAAI,UAAU,CAAC,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACtF,CAAC;AAED;;;;;;;GAOG;AACH,KAAK,UAAU,UAAU,CAAC,CAAS,EAAE,CAAS;IAC5C,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAChE,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QAC3B,UAAU,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IACH,OAAO,UAAU,KAAK,CAAC,CAAC;AAC1B,CAAC;AAED,SAAS,YAAY,CAAC,MAA0B;IAC9C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;IAC/C,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;AAC5B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAc;IAChD,OAAO,KAAK,EAAE,CAAC,EAAE,EAAE;QACjB,MAAM,KAAK,GAAG,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC;QAE1D,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,MAAM,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;YACjD,MAAM,QAAQ,CAAC,YAAY,CAAC,8BAA8B,CAAC,CAAC;QAC9D,CAAC;QAED,OAAO,EAAE,CAAC;IACZ,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"authenticate.js","sourceRoot":"","sources":["../../src/middleware/authenticate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAcxC,MAAM,aAAa,GAAG,kDAAkD,CAAC;AAEzE,gGAAgG;AAChG,MAAM,UAAU,gBAAgB,CAAC,YAA2B;IAC1D,OAAO,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE;QACvB,CAAC,CAAC,GAAG,CAAC,aAAa,EAAE,MAAM,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5C,MAAM,IAAI,EAAE,CAAC;IACf,CAAC,CAAC;AACJ,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,aAAa,CAAC,CAAU;IACtC,OAAQ,CAAC,CAAC,GAAG,CAAC,aAAa,CAA+B,IAAI,EAAE,CAAC;AACnE,CAAC;AAED,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;AAElC,KAAK,UAAU,MAAM,CAAC,KAAa;IACjC,OAAO,IAAI,UAAU,CAAC,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACtF,CAAC;AAED;;;;;;;GAOG;AACH,KAAK,UAAU,UAAU,CAAC,CAAS,EAAE,CAAS;IAC5C,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAChE,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QAC3B,UAAU,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IACH,OAAO,UAAU,KAAK,CAAC,CAAC;AAC1B,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,MAA0B;IACpD,MAAM,KAAK,GAAG,MAAM,EAAE,KAAK,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;IAC7D,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AAC9B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAc;IAChD,OAAO,KAAK,EAAE,CAAC,EAAE,EAAE;QACjB,MAAM,KAAK,GAAG,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC;QAEzD,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,MAAM,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;YACjD,MAAM,QAAQ,CAAC,YAAY,CAAC,8BAA8B,CAAC,CAAC;QAC9D,CAAC;QAED,OAAO,EAAE,CAAC;IACZ,CAAC,CAAC;AACJ,CAAC"}
@@ -9,6 +9,6 @@ import type { ZodType } from 'zod';
9
9
  * refused when it is not.
10
10
  */
11
11
  export declare function validate<Target extends 'query' | 'json' | 'param', Schema extends ZodType>(target: Target, schema: Schema): import("hono").MiddlewareHandler<import("hono").Env, string, {
12
- in: (undefined extends import("zod").input<Schema> ? true : false) extends true ? { [K in Target]?: (import("zod").input<Schema> extends infer T ? T extends import("zod").input<Schema> ? T extends import("hono").ValidationTargets[K] ? T : { [K2 in keyof T]?: import("hono").ValidationTargets[K][K2] | undefined; } : never : never) | undefined; } : { [K_1 in Target]: import("zod").input<Schema> extends infer T ? T extends import("zod").input<Schema> ? T extends import("hono").ValidationTargets[K_1] ? T : { [K2_1 in keyof T]: import("hono").ValidationTargets[K_1][K2_1]; } : never : never; };
13
- out: { [K_2 in Target]: import("zod").output<Schema>; };
14
- }>;
12
+ in: (undefined extends (Schema extends import("zod/v3").ZodType<any, import("zod/v3").ZodTypeDef, any> ? import("zod/v3").input<Schema> : Schema extends import("zod/v4/core").$ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>> ? import("zod/v4/core").input<Schema> : never) ? true : false) extends true ? { [K in Target]?: ([Schema extends import("zod/v3").ZodType<any, import("zod/v3").ZodTypeDef, any> ? import("zod/v3").input<Schema> : Schema extends import("zod/v4/core").$ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>> ? import("zod/v4/core").input<Schema> : never] extends [import("hono").ValidationTargets[K]] ? import("hono").ValidationTargets[K] & (Schema extends import("zod/v3").ZodType<any, import("zod/v3").ZodTypeDef, any> ? import("zod/v3").input<Schema> : Schema extends import("zod/v4/core").$ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>> ? import("zod/v4/core").input<Schema> : never) : import("hono/validator").InferInput<Schema extends import("zod/v3").ZodType<any, import("zod/v3").ZodTypeDef, any> ? import("zod/v3").input<Schema> : Schema extends import("zod/v4/core").$ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>> ? import("zod/v4/core").input<Schema> : never, K, import("hono/types").ParsedFormValue>) | undefined; } : { [K_1 in Target]: [Schema extends import("zod/v3").ZodType<any, import("zod/v3").ZodTypeDef, any> ? import("zod/v3").input<Schema> : Schema extends import("zod/v4/core").$ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>> ? import("zod/v4/core").input<Schema> : never] extends [import("hono").ValidationTargets[K_1]] ? import("hono").ValidationTargets[K_1] & (Schema extends import("zod/v3").ZodType<any, import("zod/v3").ZodTypeDef, any> ? import("zod/v3").input<Schema> : Schema extends import("zod/v4/core").$ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>> ? import("zod/v4/core").input<Schema> : never) : import("hono/validator").InferInput<Schema extends import("zod/v3").ZodType<any, import("zod/v3").ZodTypeDef, any> ? import("zod/v3").input<Schema> : Schema extends import("zod/v4/core").$ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>> ? import("zod/v4/core").input<Schema> : never, K_1, import("hono/types").ParsedFormValue>; };
13
+ out: { [K_2 in Target]: Schema extends import("zod/v3").ZodType<any, import("zod/v3").ZodTypeDef, any> ? import("zod/v3").output<Schema> : Schema extends import("zod/v4/core").$ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>> ? import("zod").infer<Schema> : never; };
14
+ }, never>;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * What the standalone server is built from: its environment configuration and the loader for the
3
+ * service module it names.
4
+ *
5
+ * Node only, and of no use to a host that mounts `createApp` itself, so it is not on the package
6
+ * entry: that one loads in a browser.
7
+ */
8
+ export { loadServerConfig, type ServerConfig } from './config.js';
9
+ export { createServiceProvider, loadNotificationService, type VintaSendServiceFactory, } from './services/service-loader.js';
package/dist/server.js ADDED
@@ -0,0 +1,10 @@
1
+ /**
2
+ * What the standalone server is built from: its environment configuration and the loader for the
3
+ * service module it names.
4
+ *
5
+ * Node only, and of no use to a host that mounts `createApp` itself, so it is not on the package
6
+ * entry: that one loads in a browser.
7
+ */
8
+ export { loadServerConfig } from './config.js';
9
+ export { createServiceProvider, loadNotificationService, } from './services/service-loader.js';
10
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,gBAAgB,EAAqB,MAAM,aAAa,CAAC;AAClE,OAAO,EACL,qBAAqB,EACrB,uBAAuB,GAExB,MAAM,8BAA8B,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vintasend-api",
3
- "version": "1.0.0-alpha6",
3
+ "version": "1.0.0-alpha7",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/vintasoftware/vintasend-ts-api.git"
@@ -16,6 +16,10 @@
16
16
  "types": "./dist/exports.d.ts",
17
17
  "import": "./dist/exports.js"
18
18
  },
19
+ "./server": {
20
+ "types": "./dist/server.d.ts",
21
+ "import": "./dist/server.js"
22
+ },
19
23
  "./openapi.yaml": "./openapi.yaml",
20
24
  "./package.json": "./package.json"
21
25
  },
@@ -28,6 +32,7 @@
28
32
  "README.md",
29
33
  "LICENSE"
30
34
  ],
35
+ "sideEffects": false,
31
36
  "scripts": {
32
37
  "dev": "tsx watch src/index.ts",
33
38
  "build": "tsc",
@@ -39,20 +44,27 @@
39
44
  "format": "biome check --write ."
40
45
  },
41
46
  "dependencies": {
42
- "@hono/node-server": "^1.14.0",
43
- "@hono/zod-validator": "^0.4.3",
44
- "hono": "^4.7.0",
45
- "zod": "^3.24.2"
47
+ "@hono/zod-validator": "^0.9.1",
48
+ "hono": "^4.11.2",
49
+ "zod": "^4.6.5"
46
50
  },
47
51
  "peerDependencies": {
48
- "vintasend": "^1.0.0-alpha6"
52
+ "@hono/node-server": "^1.14.0",
53
+ "vintasend": "^1.0.0-alpha7"
54
+ },
55
+ "peerDependenciesMeta": {
56
+ "@hono/node-server": {
57
+ "optional": true
58
+ }
49
59
  },
50
60
  "devDependencies": {
51
61
  "@biomejs/biome": "^2.5.10",
62
+ "@hono/node-server": "^1.14.0",
52
63
  "@types/node": "^25.0.8",
64
+ "esbuild": "^0.28.2",
53
65
  "tsx": "^4.19.3",
54
66
  "typescript": "^5.9.3",
55
- "vintasend": "1.0.0-alpha6",
67
+ "vintasend": "1.0.0-alpha7",
56
68
  "vitest": "^4.0.18"
57
69
  },
58
70
  "engines": {