@keimelion/sdk 0.0.0-stage → 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Keimelion
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,198 @@
1
- # Temporary Holding Version
1
+ # @keimelion/sdk
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Official TypeScript SDK for the [Keimelion](https://keimelion.com) API.
4
+
5
+ It is the **single source of truth for the API contract**: request and response Zod schemas,
6
+ enums, error codes and a typed `fetch`-based HTTP client. The API itself imports its contract
7
+ schemas from this package, and every consumer (frontend, Chrome extension, back-office)
8
+ installs it from npm.
9
+
10
+ | Subpath | Content |
11
+ | ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
12
+ | `@keimelion/sdk/schemas` | Zod request / response schemas + their `XInput` / `XParsed` types, shared primitives (pagination, password, username, slug, url, currency, sort), error envelope, refine messages |
13
+ | `@keimelion/sdk/enums` | `ErrorCode`, `HttpStatus`, `HttpMethod`, `HttpHeader` and every domain enum (`UserRoles`, `ItemStatuses`, `SupportedCurrencies`…) |
14
+ | `@keimelion/sdk/client` | `createClient`, `ApiError`, `HttpClient` |
15
+
16
+ Admin endpoints will live under `client.admin.*` in the same client (no separate subpath).
17
+
18
+ Runs in browsers, Node.js ≥ 20 and MV3 service workers: the sources never import Node-only
19
+ modules, an ORM, an HTTP framework or a DB driver (enforced by ESLint in CI).
20
+
21
+ ## Install
22
+
23
+ ```bash
24
+ npm install @keimelion/sdk zod
25
+ ```
26
+
27
+ `zod` (`^4.5.0`) is a **peer dependency**: it is never bundled, your app provides it.
28
+ The package is public on npmjs — no registry token, `.npmrc` or build secret is needed.
29
+
30
+ ## Usage
31
+
32
+ ```ts
33
+ import { ApiError, createClient } from '@keimelion/sdk/client'
34
+ import { ErrorCode } from '@keimelion/sdk/enums'
35
+
36
+ const client = createClient({
37
+ baseUrl: 'https://api.keimelion.com',
38
+ getToken: async () => (await storage.get('accessToken')) ?? null,
39
+ // fetch: customFetch, // optional, defaults to globalThis.fetch
40
+ // timeoutMs: 10_000, // optional, defaults to 30 s; null disables it
41
+ })
42
+
43
+ try {
44
+ const { accessToken, refreshToken, user } = await client.auth.login({
45
+ email: 'jane@example.com',
46
+ password: 'secret',
47
+ })
48
+ user.createdAt // Date — ISO timestamps are decoded into Date objects
49
+
50
+ const rotated = await client.auth.refresh({ refreshToken })
51
+ await client.auth.logout({ refreshToken: rotated.refreshToken })
52
+ } catch (error) {
53
+ if (error instanceof ApiError && error.code === ErrorCode.UNPROCESSABLE_ENTITY) {
54
+ console.log(error.status, error.message, error.issues) // [{ path, message, code }]
55
+ }
56
+ throw error
57
+ }
58
+ ```
59
+
60
+ - `getToken` may be sync or async; when it returns `null` no `Authorization` header is sent.
61
+ - Requests are **not** validated client-side (the API is the authority). Responses are parsed
62
+ with the SDK schema: a body that does not match throws `ApiError` with
63
+ `code: 'INVALID_RESPONSE'` (`ClientErrorCode.INVALID_RESPONSE`), the Zod error as `cause`.
64
+ - Any API error (`{ message, code, metadata }`) throws `ApiError` exposing `status`, `code`,
65
+ `message`, `metadata` and `issues` (`metadata.issues` of a 422, `[]` otherwise).
66
+ - When no HTTP response is received, the client also throws `ApiError`, with `status: 0` and
67
+ the original error as `cause`: `NETWORK_ERROR` (offline, DNS, CORS), `TIMEOUT` (`timeoutMs`
68
+ elapsed) or `ABORTED` (the caller's `signal` fired). `ApiError` is the only error type a
69
+ consumer has to handle.
70
+ - `message` is an English developer message, never meant for end users: UIs translate from
71
+ `code` (and `issues[].code` for a 422).
72
+ - There is no automatic refresh / 401 interceptor in 0.x yet: call `client.auth.refresh()`
73
+ yourself when an access token expires.
74
+
75
+ ### Picking only the domains you need
76
+
77
+ `createClient()` instantiates every domain. A consumer that only needs a few (e.g. the
78
+ extension) composes the core HTTP client with the domain factories, so bundlers drop the rest:
79
+
80
+ ```ts
81
+ import { createAuthClient, createHttpClient } from '@keimelion/sdk/client'
82
+
83
+ const http = createHttpClient({ baseUrl, getToken })
84
+ const auth = createAuthClient(http)
85
+ ```
86
+
87
+ ### Client layout (for SDK contributors)
88
+
89
+ ```
90
+ src/client/
91
+ _core/ http-client.ts, api-error.ts — transport, shared by every domain
92
+ <domain>/ <domain>.client.ts (createXClient(http)) + <domain>.paths.ts
93
+ admin/<res>/ one folder per admin resource, composed into client.admin.<res>
94
+ create-client.ts
95
+ ```
96
+
97
+ A domain method describes its request declaratively; `HttpClient.request` does the rest:
98
+
99
+ ```ts
100
+ http.request({
101
+ method: HttpMethod.GET,
102
+ path: '/v1/lists/:id', // `:name` segments are filled from pathParams, URL-encoded
103
+ pathParams: { id },
104
+ query: { page: 2, 'title[ilike]': 'xmas', tag: ['a', 'b'] }, // nullish values are skipped
105
+ auth: RequestAuthMode.NONE, // public route; or { token: 'rsv_…' } to bypass getToken
106
+ signal, // AbortSignal, forwarded to fetch
107
+ responseSchema: listDetailResponseSchema, // noContentResponseSchema for a 204
108
+ })
109
+ ```
110
+
111
+ ### Using the schemas
112
+
113
+ ```ts
114
+ import { loginResponseSchema, type LoginRequestInput } from '@keimelion/sdk/schemas'
115
+
116
+ const session = loginResponseSchema.parse(json) // session.user.createdAt is a Date
117
+ ```
118
+
119
+ ## Contract conventions
120
+
121
+ - `@keimelion/sdk/schemas` re-exports every domain **flat**, so every exported name must be
122
+ unique across the whole package (a collision fails `tsc` with TS2308). Name schemas
123
+ `<domain><Action><Kind>Schema`, where `<Kind>` is `Request`, `Response`, `Query` or
124
+ `Params`: `listsCreateRequestSchema`, `adminUsersListQuerySchema`,
125
+ `reservationsCancelResponseSchema`. Auth actions are unique on their own, so auth keeps
126
+ `loginRequestSchema`, `refreshResponseSchema`… Entity shapes reused across endpoints are
127
+ `<entity>DetailSchema` / `<entity>SummarySchema` (`userDetailSchema`).
128
+ - A schema used by more than one domain lives in `src/schemas/_shared/` (e.g.
129
+ `imageDetailSchema`, `emailSchema`), never in one domain imported by another.
130
+ - Every schema exports **two types** next to it: `XInput = z.input<typeof xSchema>` (what a
131
+ caller sends / what is on the wire) and `XParsed = z.output<typeof xSchema>` (what the API
132
+ handler receives / what the client returns). CI fails if one is missing.
133
+ - Response schemas are plain `z.object` (unknown keys are **stripped**, not rejected), so
134
+ additive API fields are non-breaking for older clients. Adding an **enum value** is not:
135
+ it requires an SDK release before the API starts sending it.
136
+ - Timestamps (`*_at` columns) use a codec: ISO string on the wire ↔ `Date` once parsed.
137
+ - Calendar dates without a time (`*_date` columns, e.g. a future `event_date`) stay
138
+ `YYYY-MM-DD` strings (`z.iso.date()`): turning them into a `Date` shifts the day depending
139
+ on the viewer's timezone.
140
+ - Postgres `numeric` columns (prices, FX rates) are **strings** on the wire, never numbers.
141
+ - Response schemas never declare internal columns (password / token hashes, internal
142
+ tokens).
143
+ - Enums are defined here and the API derives its `pgEnum`s from them: **changing an enum
144
+ requires a paired DB migration in Keimelion-API**.
145
+
146
+ ## SDK first, then the API
147
+
148
+ Any change to an API request or response shape is made **in this repo first**:
149
+
150
+ 1. SDK PR (schemas + client method + tests) → merged into `dev` → released to npm.
151
+ 2. API PR bumps `@keimelion/sdk` to the released version and adapts the endpoint.
152
+
153
+ The API types its mappers on the SDK output types and asserts each happy-path response with
154
+ `schema.parse(...)` in its tests, so a drift fails `tsc` or the test suite.
155
+
156
+ ## Local development with yalc
157
+
158
+ To develop the SDK and a consumer side by side without publishing:
159
+
160
+ ```bash
161
+ # in Keimelion-SDK
162
+ npm run build && npx yalc publish # once
163
+ npm run dev # tsup --watch, `yalc push` after each build
164
+
165
+ # in the consumer (Keimelion-API, frontend…)
166
+ npx yalc link @keimelion/sdk # symlink, package.json and lockfile untouched
167
+ npm ci # back to the registry version when done
168
+ ```
169
+
170
+ Always use `yalc link`, **never `yalc add`**: `add` rewrites `package.json` to
171
+ `file:.yalc/...` and breaks `npm ci` in CI. Consumers gitignore `.yalc/` and `yalc.lock`, and
172
+ a husky `pre-commit` hook rejects a `file:.yalc` dependency or a staged `yalc.lock`.
173
+
174
+ ## Scripts
175
+
176
+ | Script | Role |
177
+ | ------------------------- | ----------------------------------------------------------------------------------------------------------- |
178
+ | `npm run build` | `tsup` (ESM-only + `.d.ts`), then zod-not-bundled check, `publint --strict`, `attw` |
179
+ | `npm run lint` | ESLint (strict + stylistic type-checked, Node/server import guard) + schema type-export check |
180
+ | `npm run typecheck` | `tsc --noEmit` (strict, no `@types/node`) |
181
+ | `npm test` | Vitest |
182
+ | `npm run test:pack [dir]` | `npm pack`, install the tarball + zod in a scratch project, import every subpath from ESM and type-check it |
183
+
184
+ ## Release
185
+
186
+ Same pipeline as every Keimelion repo (reusable workflows of
187
+ [Keimelion-Infra](https://github.com/Keimelion/Keimelion-Infra), see its
188
+ `docs/release-process.md`): feature PRs are squash-merged into `dev` with a Conventional
189
+ Commit title; a `dev → main` release PR (merge commit) triggers CI → semantic-release
190
+ (tag, GitHub Release, `CHANGELOG.md`) → **npm-publish** (only when a version was tagged):
191
+ build, `publint`, `attw`, `npm publish --provenance --access public`.
192
+
193
+ The package is in **0.x**: a breaking change bumps the minor version (`0.1.0 → 0.2.0`), so
194
+ consumers should depend on `^0.x.0`.
195
+
196
+ ## License
197
+
198
+ [MIT](./LICENSE)
@@ -0,0 +1,26 @@
1
+ // src/enums/currency.ts
2
+ var SupportedCurrencies = {
3
+ EUR: "EUR",
4
+ USD: "USD",
5
+ GBP: "GBP",
6
+ CHF: "CHF",
7
+ CAD: "CAD",
8
+ AUD: "AUD",
9
+ JPY: "JPY"
10
+ };
11
+ var SUPPORTED_CURRENCY_VALUES = Object.values(SupportedCurrencies);
12
+
13
+ // src/enums/auth-provider.ts
14
+ var AUTH_PROVIDER_VALUES = ["email", "google"];
15
+
16
+ // src/enums/user-role.ts
17
+ var UserRoles = {
18
+ USER: "user",
19
+ MODERATOR: "moderator",
20
+ ADMIN: "admin"
21
+ };
22
+ var USER_ROLE_VALUES = Object.values(UserRoles);
23
+
24
+ export { AUTH_PROVIDER_VALUES, SUPPORTED_CURRENCY_VALUES, SupportedCurrencies, USER_ROLE_VALUES, UserRoles };
25
+ //# sourceMappingURL=chunk-2LLUUBMQ.js.map
26
+ //# sourceMappingURL=chunk-2LLUUBMQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/enums/currency.ts","../src/enums/auth-provider.ts","../src/enums/user-role.ts"],"names":[],"mappings":";AAMW,IAAM,mBAAA,GAAsB;AAAA,EACrC,GAAA,EAAK,KAAA;AAAA,EACL,GAAA,EAAK,KAAA;AAAA,EACL,GAAA,EAAK,KAAA;AAAA,EACL,GAAA,EAAK,KAAA;AAAA,EACL,GAAA,EAAK,KAAA;AAAA,EACL,GAAA,EAAK,KAAA;AAAA,EACL,GAAA,EAAK;AACP;AAIO,IAAM,yBAAA,GAA4B,MAAA,CAAO,MAAA,CAAO,mBAAmB;;;AClBnE,IAAM,oBAAA,GAAuB,CAAC,OAAA,EAAS,QAAQ;;;ACA/C,IAAM,SAAA,GAAY;AAAA,EACvB,IAAA,EAAM,MAAA;AAAA,EACN,SAAA,EAAW,WAAA;AAAA,EACX,KAAA,EAAO;AACT;AAIO,IAAM,gBAAA,GAAmB,MAAA,CAAO,MAAA,CAAO,SAAS","file":"chunk-2LLUUBMQ.js","sourcesContent":["/**\n * ISO 4217 currencies supported by the API for item source prices and\n * read-time FX normalization.\n *\n * The API seeds its `currencies` table from this set: adding or removing a code\n * requires a paired DB migration in Keimelion-API.\n */ export const SupportedCurrencies = {\n EUR: 'EUR',\n USD: 'USD',\n GBP: 'GBP',\n CHF: 'CHF',\n CAD: 'CAD',\n AUD: 'AUD',\n JPY: 'JPY',\n} as const\n\nexport type SupportedCurrency = (typeof SupportedCurrencies)[keyof typeof SupportedCurrencies]\n\nexport const SUPPORTED_CURRENCY_VALUES = Object.values(SupportedCurrencies) as [\n SupportedCurrency,\n ...SupportedCurrency[],\n]\n","export const AUTH_PROVIDER_VALUES = ['email', 'google'] as const\nexport type AuthProvider = (typeof AUTH_PROVIDER_VALUES)[number]\n","export const UserRoles = {\n USER: 'user',\n MODERATOR: 'moderator',\n ADMIN: 'admin',\n} as const\n\nexport type UserRole = (typeof UserRoles)[keyof typeof UserRoles]\n\nexport const USER_ROLE_VALUES = Object.values(UserRoles) as [UserRole, ...UserRole[]]\n"]}
@@ -0,0 +1,33 @@
1
+ // src/enums/http.ts
2
+ var HttpMethod = {
3
+ GET: "GET",
4
+ POST: "POST",
5
+ PUT: "PUT",
6
+ PATCH: "PATCH",
7
+ DELETE: "DELETE",
8
+ OPTIONS: "OPTIONS"
9
+ };
10
+ var HttpHeader = {
11
+ ACCEPT: "Accept",
12
+ CONTENT_TYPE: "Content-Type",
13
+ AUTHORIZATION: "Authorization"
14
+ };
15
+ var HttpStatus = {
16
+ OK: 200,
17
+ CREATED: 201,
18
+ NO_CONTENT: 204,
19
+ BAD_REQUEST: 400,
20
+ UNAUTHORIZED: 401,
21
+ FORBIDDEN: 403,
22
+ NOT_FOUND: 404,
23
+ CONFLICT: 409,
24
+ GONE: 410,
25
+ PAYLOAD_TOO_LARGE: 413,
26
+ UNPROCESSABLE_ENTITY: 422,
27
+ TOO_MANY_REQUESTS: 429,
28
+ INTERNAL_SERVER_ERROR: 500
29
+ };
30
+
31
+ export { HttpHeader, HttpMethod, HttpStatus };
32
+ //# sourceMappingURL=chunk-E3CTTWFQ.js.map
33
+ //# sourceMappingURL=chunk-E3CTTWFQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/enums/http.ts"],"names":[],"mappings":";AAAO,IAAM,UAAA,GAAa;AAAA,EACxB,GAAA,EAAK,KAAA;AAAA,EACL,IAAA,EAAM,MAAA;AAAA,EACN,GAAA,EAAK,KAAA;AAAA,EACL,KAAA,EAAO,OAAA;AAAA,EACP,MAAA,EAAQ,QAAA;AAAA,EACR,OAAA,EAAS;AACX;AAGO,IAAM,UAAA,GAAa;AAAA,EACxB,MAAA,EAAQ,QAAA;AAAA,EACR,YAAA,EAAc,cAAA;AAAA,EACd,aAAA,EAAe;AACjB;AAGO,IAAM,UAAA,GAAa;AAAA,EACxB,EAAA,EAAI,GAAA;AAAA,EACJ,OAAA,EAAS,GAAA;AAAA,EACT,UAAA,EAAY,GAAA;AAAA,EACZ,WAAA,EAAa,GAAA;AAAA,EACb,YAAA,EAAc,GAAA;AAAA,EACd,SAAA,EAAW,GAAA;AAAA,EACX,SAAA,EAAW,GAAA;AAAA,EACX,QAAA,EAAU,GAAA;AAAA,EACV,IAAA,EAAM,GAAA;AAAA,EACN,iBAAA,EAAmB,GAAA;AAAA,EACnB,oBAAA,EAAsB,GAAA;AAAA,EACtB,iBAAA,EAAmB,GAAA;AAAA,EACnB,qBAAA,EAAuB;AACzB","file":"chunk-E3CTTWFQ.js","sourcesContent":["export const HttpMethod = {\n GET: 'GET',\n POST: 'POST',\n PUT: 'PUT',\n PATCH: 'PATCH',\n DELETE: 'DELETE',\n OPTIONS: 'OPTIONS',\n} as const\nexport type HttpMethod = (typeof HttpMethod)[keyof typeof HttpMethod]\n\nexport const HttpHeader = {\n ACCEPT: 'Accept',\n CONTENT_TYPE: 'Content-Type',\n AUTHORIZATION: 'Authorization',\n} as const\nexport type HttpHeader = (typeof HttpHeader)[keyof typeof HttpHeader]\n\nexport const HttpStatus = {\n OK: 200,\n CREATED: 201,\n NO_CONTENT: 204,\n BAD_REQUEST: 400,\n UNAUTHORIZED: 401,\n FORBIDDEN: 403,\n NOT_FOUND: 404,\n CONFLICT: 409,\n GONE: 410,\n PAYLOAD_TOO_LARGE: 413,\n UNPROCESSABLE_ENTITY: 422,\n TOO_MANY_REQUESTS: 429,\n INTERNAL_SERVER_ERROR: 500,\n} as const\nexport type HttpStatus = (typeof HttpStatus)[keyof typeof HttpStatus]\n"]}
@@ -0,0 +1,126 @@
1
+ import { SupportedCurrencies, SUPPORTED_CURRENCY_VALUES, USER_ROLE_VALUES, AUTH_PROVIDER_VALUES } from './chunk-2LLUUBMQ.js';
2
+ import { z } from 'zod';
3
+
4
+ var DEFAULT_DISPLAY_CURRENCY = SupportedCurrencies.USD;
5
+ var supportedCurrencyEnum = z.enum(SupportedCurrencies, {
6
+ error: () => `currency must be one of: ${SUPPORTED_CURRENCY_VALUES.join(", ")}`
7
+ });
8
+ var displayCurrencyQuerySchema = z.object({
9
+ currency: supportedCurrencyEnum.optional()
10
+ });
11
+ var emailSchema = z.string().trim().toLowerCase().pipe(z.email());
12
+ var VALIDATION_ROOT_PATH = "<root>";
13
+ var validationIssueSchema = z.object({
14
+ path: z.string(),
15
+ message: z.string(),
16
+ code: z.string()
17
+ });
18
+ var validationErrorMetadataSchema = z.object({
19
+ issues: z.array(validationIssueSchema)
20
+ });
21
+ var apiErrorBodySchema = z.object({
22
+ message: z.string(),
23
+ code: z.string(),
24
+ metadata: z.record(z.string(), z.unknown())
25
+ });
26
+ var isoDateTimeSchema = z.codec(z.iso.datetime({ offset: true }), z.date(), {
27
+ decode: (isoString) => new Date(isoString),
28
+ encode: (date) => date.toISOString()
29
+ });
30
+ var imageUrlsSchema = z.object({
31
+ sm: z.url(),
32
+ md: z.url(),
33
+ lg: z.url()
34
+ });
35
+ var imageDetailSchema = z.object({
36
+ id: z.guid(),
37
+ hash: z.string(),
38
+ mime: z.string(),
39
+ sizeBytes: z.number().int().nonnegative(),
40
+ width: z.number().int().nonnegative(),
41
+ height: z.number().int().nonnegative(),
42
+ createdAt: isoDateTimeSchema,
43
+ urls: imageUrlsSchema
44
+ });
45
+ var messageResponseSchema = z.object({
46
+ message: z.string()
47
+ });
48
+ var MIN_PASSWORD_LENGTH = 8;
49
+ var MAX_PASSWORD_LENGTH = 72;
50
+ var passwordSchema = z.string().min(MIN_PASSWORD_LENGTH).max(MAX_PASSWORD_LENGTH);
51
+ var USERNAME_MIN_LENGTH = 1;
52
+ var USERNAME_MAX_LENGTH = 100;
53
+ var USERNAME_REGEX = new RegExp(
54
+ `^[\\p{L}\\p{N}_-]{${String(USERNAME_MIN_LENGTH)},${String(USERNAME_MAX_LENGTH)}}$`,
55
+ "u"
56
+ );
57
+ var usernameSchema = z.string().trim().regex(
58
+ USERNAME_REGEX,
59
+ `username must be ${String(USERNAME_MIN_LENGTH)}-${String(USERNAME_MAX_LENGTH)} letters, digits, underscores, or dashes`
60
+ );
61
+ var userDetailSchema = z.object({
62
+ id: z.guid(),
63
+ email: z.string(),
64
+ username: z.string().nullable(),
65
+ authProvider: z.enum(AUTH_PROVIDER_VALUES),
66
+ role: z.enum(USER_ROLE_VALUES),
67
+ avatarImageId: z.guid().nullable(),
68
+ avatar: imageDetailSchema.nullable(),
69
+ isCgvAccepted: z.boolean(),
70
+ cgvAcceptedAt: isoDateTimeSchema.nullable(),
71
+ isMarketingOptedIn: z.boolean(),
72
+ defaultCurrency: supportedCurrencyEnum,
73
+ emailVerifiedAt: isoDateTimeSchema.nullable(),
74
+ lastActiveAt: isoDateTimeSchema.nullable(),
75
+ createdAt: isoDateTimeSchema,
76
+ updatedAt: isoDateTimeSchema
77
+ });
78
+ var forgotPasswordRequestSchema = z.object({
79
+ email: emailSchema
80
+ });
81
+ var forgotPasswordResponseSchema = messageResponseSchema;
82
+ var loginRequestSchema = z.object({
83
+ email: emailSchema,
84
+ password: z.string().min(1)
85
+ });
86
+ var loginResponseSchema = z.object({
87
+ accessToken: z.string(),
88
+ refreshToken: z.string(),
89
+ user: userDetailSchema
90
+ });
91
+ var logoutRequestSchema = z.object({
92
+ refreshToken: z.string().min(1).optional()
93
+ });
94
+ var logoutResponseSchema = messageResponseSchema;
95
+ var refreshRequestSchema = z.object({
96
+ refreshToken: z.string().min(1)
97
+ });
98
+ var refreshResponseSchema = z.object({
99
+ accessToken: z.string(),
100
+ refreshToken: z.string()
101
+ });
102
+ var optionalUsernameSchema = usernameSchema.nullable().optional().transform((value) => value ?? null);
103
+ var registerRequestSchema = z.object({
104
+ email: emailSchema,
105
+ password: passwordSchema,
106
+ username: optionalUsernameSchema,
107
+ isMarketingOptedIn: z.boolean().default(false),
108
+ defaultCurrency: supportedCurrencyEnum.optional()
109
+ });
110
+ var registerResponseSchema = z.object({
111
+ user: userDetailSchema,
112
+ refreshToken: z.string()
113
+ });
114
+ var resetPasswordRequestSchema = z.object({
115
+ passwordResetToken: z.string().min(1),
116
+ password: passwordSchema
117
+ });
118
+ var resetPasswordResponseSchema = messageResponseSchema;
119
+ var verifyEmailRequestSchema = z.object({
120
+ token: z.guid()
121
+ });
122
+ var verifyEmailResponseSchema = messageResponseSchema;
123
+
124
+ export { DEFAULT_DISPLAY_CURRENCY, MAX_PASSWORD_LENGTH, MIN_PASSWORD_LENGTH, USERNAME_MAX_LENGTH, USERNAME_MIN_LENGTH, USERNAME_REGEX, VALIDATION_ROOT_PATH, apiErrorBodySchema, displayCurrencyQuerySchema, emailSchema, forgotPasswordRequestSchema, forgotPasswordResponseSchema, imageDetailSchema, imageUrlsSchema, isoDateTimeSchema, loginRequestSchema, loginResponseSchema, logoutRequestSchema, logoutResponseSchema, messageResponseSchema, passwordSchema, refreshRequestSchema, refreshResponseSchema, registerRequestSchema, registerResponseSchema, resetPasswordRequestSchema, resetPasswordResponseSchema, supportedCurrencyEnum, userDetailSchema, usernameSchema, validationErrorMetadataSchema, validationIssueSchema, verifyEmailRequestSchema, verifyEmailResponseSchema };
125
+ //# sourceMappingURL=chunk-VT6MXJE5.js.map
126
+ //# sourceMappingURL=chunk-VT6MXJE5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/schemas/_shared/currency.ts","../src/schemas/_shared/email.ts","../src/schemas/_shared/error.ts","../src/schemas/_shared/timestamp.ts","../src/schemas/_shared/image-detail.ts","../src/schemas/_shared/message-response.ts","../src/schemas/_shared/password.ts","../src/schemas/_shared/username.ts","../src/schemas/users/user-detail.ts","../src/schemas/auth/forgot-password.ts","../src/schemas/auth/login.ts","../src/schemas/auth/logout.ts","../src/schemas/auth/refresh.ts","../src/schemas/auth/register.ts","../src/schemas/auth/reset-password.ts","../src/schemas/auth/verify-email.ts"],"names":["z"],"mappings":"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","file":"chunk-VT6MXJE5.js","sourcesContent":["import { z } from 'zod'\nimport {\n SUPPORTED_CURRENCY_VALUES,\n SupportedCurrencies,\n type SupportedCurrency,\n} from '../../enums/currency.js'\n\nexport const DEFAULT_DISPLAY_CURRENCY: SupportedCurrency = SupportedCurrencies.USD\n\nexport const supportedCurrencyEnum = z.enum(SupportedCurrencies, {\n error: () => `currency must be one of: ${SUPPORTED_CURRENCY_VALUES.join(', ')}`,\n})\n\nexport type SupportedCurrencyInput = z.input<typeof supportedCurrencyEnum>\nexport type SupportedCurrencyParsed = z.output<typeof supportedCurrencyEnum>\n\nexport const displayCurrencyQuerySchema = z.object({\n currency: supportedCurrencyEnum.optional(),\n})\n\nexport type DisplayCurrencyQueryInput = z.input<typeof displayCurrencyQuerySchema>\nexport type DisplayCurrencyQueryParsed = z.output<typeof displayCurrencyQuerySchema>\n","import { z } from 'zod'\n\n// Normalise before validating: z.email() alone would reject surrounding whitespace.\nexport const emailSchema = z.string().trim().toLowerCase().pipe(z.email())\n\nexport type EmailInput = z.input<typeof emailSchema>\nexport type EmailParsed = z.output<typeof emailSchema>\n","import { z } from 'zod'\n\nexport const VALIDATION_ROOT_PATH = '<root>'\n\nexport const validationIssueSchema = z.object({\n path: z.string(),\n message: z.string(),\n code: z.string(),\n})\n\nexport type ValidationIssueInput = z.input<typeof validationIssueSchema>\nexport type ValidationIssueParsed = z.output<typeof validationIssueSchema>\n\nexport const validationErrorMetadataSchema = z.object({\n issues: z.array(validationIssueSchema),\n})\n\nexport type ValidationErrorMetadataInput = z.input<typeof validationErrorMetadataSchema>\nexport type ValidationErrorMetadataParsed = z.output<typeof validationErrorMetadataSchema>\n\nexport const apiErrorBodySchema = z.object({\n message: z.string(),\n code: z.string(),\n metadata: z.record(z.string(), z.unknown()),\n})\n\nexport type ApiErrorBodyInput = z.input<typeof apiErrorBodySchema>\nexport type ApiErrorBodyParsed = z.output<typeof apiErrorBodySchema>\n","import { z } from 'zod'\n\nexport const isoDateTimeSchema = z.codec(z.iso.datetime({ offset: true }), z.date(), {\n decode: (isoString) => new Date(isoString),\n encode: (date) => date.toISOString(),\n})\n\nexport type IsoDateTimeInput = z.input<typeof isoDateTimeSchema>\nexport type IsoDateTimeParsed = z.output<typeof isoDateTimeSchema>\n","import { z } from 'zod'\nimport { isoDateTimeSchema } from './timestamp.js'\n\nexport const imageUrlsSchema = z.object({\n sm: z.url(),\n md: z.url(),\n lg: z.url(),\n})\n\nexport type ImageUrlsInput = z.input<typeof imageUrlsSchema>\nexport type ImageUrlsParsed = z.output<typeof imageUrlsSchema>\n\nexport const imageDetailSchema = z.object({\n id: z.guid(),\n hash: z.string(),\n mime: z.string(),\n sizeBytes: z.number().int().nonnegative(),\n width: z.number().int().nonnegative(),\n height: z.number().int().nonnegative(),\n createdAt: isoDateTimeSchema,\n urls: imageUrlsSchema,\n})\n\nexport type ImageDetailInput = z.input<typeof imageDetailSchema>\nexport type ImageDetailParsed = z.output<typeof imageDetailSchema>\n","import { z } from 'zod'\n\nexport const messageResponseSchema = z.object({\n message: z.string(),\n})\n\nexport type MessageResponseInput = z.input<typeof messageResponseSchema>\nexport type MessageResponseParsed = z.output<typeof messageResponseSchema>\n","import { z } from 'zod'\n\nexport const MIN_PASSWORD_LENGTH = 8\nexport const MAX_PASSWORD_LENGTH = 72\n\nexport const passwordSchema = z.string().min(MIN_PASSWORD_LENGTH).max(MAX_PASSWORD_LENGTH)\n\nexport type PasswordInput = z.input<typeof passwordSchema>\nexport type PasswordParsed = z.output<typeof passwordSchema>\n","import { z } from 'zod'\n\nexport const USERNAME_MIN_LENGTH = 1\nexport const USERNAME_MAX_LENGTH = 100\nexport const USERNAME_REGEX = new RegExp(\n `^[\\\\p{L}\\\\p{N}_-]{${String(USERNAME_MIN_LENGTH)},${String(USERNAME_MAX_LENGTH)}}$`,\n 'u',\n)\n\nexport const usernameSchema = z\n .string()\n .trim()\n .regex(\n USERNAME_REGEX,\n `username must be ${String(USERNAME_MIN_LENGTH)}-${String(USERNAME_MAX_LENGTH)} letters, digits, underscores, or dashes`,\n )\n\nexport type UsernameInput = z.input<typeof usernameSchema>\nexport type UsernameParsed = z.output<typeof usernameSchema>\n","import { z } from 'zod'\nimport { AUTH_PROVIDER_VALUES } from '../../enums/auth-provider.js'\nimport { USER_ROLE_VALUES } from '../../enums/user-role.js'\nimport { supportedCurrencyEnum } from '../_shared/currency.js'\nimport { isoDateTimeSchema } from '../_shared/timestamp.js'\nimport { imageDetailSchema } from '../_shared/image-detail.js'\n\nexport const userDetailSchema = z.object({\n id: z.guid(),\n email: z.string(),\n username: z.string().nullable(),\n authProvider: z.enum(AUTH_PROVIDER_VALUES),\n role: z.enum(USER_ROLE_VALUES),\n avatarImageId: z.guid().nullable(),\n avatar: imageDetailSchema.nullable(),\n isCgvAccepted: z.boolean(),\n cgvAcceptedAt: isoDateTimeSchema.nullable(),\n isMarketingOptedIn: z.boolean(),\n defaultCurrency: supportedCurrencyEnum,\n emailVerifiedAt: isoDateTimeSchema.nullable(),\n lastActiveAt: isoDateTimeSchema.nullable(),\n createdAt: isoDateTimeSchema,\n updatedAt: isoDateTimeSchema,\n})\n\nexport type UserDetailInput = z.input<typeof userDetailSchema>\nexport type UserDetailParsed = z.output<typeof userDetailSchema>\n","import { z } from 'zod'\nimport { messageResponseSchema } from '../_shared/message-response.js'\nimport { emailSchema } from '../_shared/email.js'\n\nexport const forgotPasswordRequestSchema = z.object({\n email: emailSchema,\n})\n\nexport type ForgotPasswordRequestInput = z.input<typeof forgotPasswordRequestSchema>\nexport type ForgotPasswordRequestParsed = z.output<typeof forgotPasswordRequestSchema>\n\nexport const forgotPasswordResponseSchema = messageResponseSchema\n\nexport type ForgotPasswordResponseInput = z.input<typeof forgotPasswordResponseSchema>\nexport type ForgotPasswordResponseParsed = z.output<typeof forgotPasswordResponseSchema>\n","import { z } from 'zod'\nimport { userDetailSchema } from '../users/user-detail.js'\nimport { emailSchema } from '../_shared/email.js'\n\nexport const loginRequestSchema = z.object({\n email: emailSchema,\n password: z.string().min(1),\n})\n\nexport type LoginRequestInput = z.input<typeof loginRequestSchema>\nexport type LoginRequestParsed = z.output<typeof loginRequestSchema>\n\nexport const loginResponseSchema = z.object({\n accessToken: z.string(),\n refreshToken: z.string(),\n user: userDetailSchema,\n})\n\nexport type LoginResponseInput = z.input<typeof loginResponseSchema>\nexport type LoginResponseParsed = z.output<typeof loginResponseSchema>\n","import { z } from 'zod'\nimport { messageResponseSchema } from '../_shared/message-response.js'\n\nexport const logoutRequestSchema = z.object({\n refreshToken: z.string().min(1).optional(),\n})\n\nexport type LogoutRequestInput = z.input<typeof logoutRequestSchema>\nexport type LogoutRequestParsed = z.output<typeof logoutRequestSchema>\n\nexport const logoutResponseSchema = messageResponseSchema\n\nexport type LogoutResponseInput = z.input<typeof logoutResponseSchema>\nexport type LogoutResponseParsed = z.output<typeof logoutResponseSchema>\n","import { z } from 'zod'\n\nexport const refreshRequestSchema = z.object({\n refreshToken: z.string().min(1),\n})\n\nexport type RefreshRequestInput = z.input<typeof refreshRequestSchema>\nexport type RefreshRequestParsed = z.output<typeof refreshRequestSchema>\n\nexport const refreshResponseSchema = z.object({\n accessToken: z.string(),\n refreshToken: z.string(),\n})\n\nexport type RefreshResponseInput = z.input<typeof refreshResponseSchema>\nexport type RefreshResponseParsed = z.output<typeof refreshResponseSchema>\n","import { z } from 'zod'\nimport { passwordSchema } from '../_shared/password.js'\nimport { usernameSchema } from '../_shared/username.js'\nimport { supportedCurrencyEnum } from '../_shared/currency.js'\nimport { userDetailSchema } from '../users/user-detail.js'\nimport { emailSchema } from '../_shared/email.js'\n\nconst optionalUsernameSchema = usernameSchema\n .nullable()\n .optional()\n .transform((value) => value ?? null)\n\nexport const registerRequestSchema = z.object({\n email: emailSchema,\n password: passwordSchema,\n username: optionalUsernameSchema,\n isMarketingOptedIn: z.boolean().default(false),\n defaultCurrency: supportedCurrencyEnum.optional(),\n})\n\nexport type RegisterRequestInput = z.input<typeof registerRequestSchema>\nexport type RegisterRequestParsed = z.output<typeof registerRequestSchema>\n\nexport const registerResponseSchema = z.object({\n user: userDetailSchema,\n refreshToken: z.string(),\n})\n\nexport type RegisterResponseInput = z.input<typeof registerResponseSchema>\nexport type RegisterResponseParsed = z.output<typeof registerResponseSchema>\n","import { z } from 'zod'\nimport { passwordSchema } from '../_shared/password.js'\nimport { messageResponseSchema } from '../_shared/message-response.js'\n\nexport const resetPasswordRequestSchema = z.object({\n passwordResetToken: z.string().min(1),\n password: passwordSchema,\n})\n\nexport type ResetPasswordRequestInput = z.input<typeof resetPasswordRequestSchema>\nexport type ResetPasswordRequestParsed = z.output<typeof resetPasswordRequestSchema>\n\nexport const resetPasswordResponseSchema = messageResponseSchema\n\nexport type ResetPasswordResponseInput = z.input<typeof resetPasswordResponseSchema>\nexport type ResetPasswordResponseParsed = z.output<typeof resetPasswordResponseSchema>\n","import { z } from 'zod'\nimport { messageResponseSchema } from '../_shared/message-response.js'\n\nexport const verifyEmailRequestSchema = z.object({\n token: z.guid(),\n})\n\nexport type VerifyEmailRequestInput = z.input<typeof verifyEmailRequestSchema>\nexport type VerifyEmailRequestParsed = z.output<typeof verifyEmailRequestSchema>\n\nexport const verifyEmailResponseSchema = messageResponseSchema\n\nexport type VerifyEmailResponseInput = z.input<typeof verifyEmailResponseSchema>\nexport type VerifyEmailResponseParsed = z.output<typeof verifyEmailResponseSchema>\n"]}
@@ -0,0 +1,97 @@
1
+ import { RegisterRequestInput, RegisterResponseParsed, VerifyEmailRequestInput, VerifyEmailResponseParsed, LoginRequestInput, LoginResponseParsed, RefreshRequestInput, RefreshResponseParsed, LogoutRequestInput, LogoutResponseParsed, ForgotPasswordRequestInput, ForgotPasswordResponseParsed, ResetPasswordRequestInput, ResetPasswordResponseParsed, ValidationIssueParsed } from '../schemas/index.js';
2
+ import { z } from 'zod';
3
+ import { HttpMethod, ErrorCode } from '../enums/index.js';
4
+
5
+ declare const DEFAULT_TIMEOUT_MS = 30000;
6
+ type TokenProvider = () => string | null | Promise<string | null>;
7
+ type FetchFunction = (url: string, init: RequestInit) => Promise<Response>;
8
+ type PathParams = Record<string, string | number>;
9
+ type QueryValue = string | number | boolean | null | undefined;
10
+ type QueryParams = Record<string, QueryValue | readonly QueryValue[]>;
11
+ declare const RequestAuthMode: {
12
+ readonly TOKEN_PROVIDER: "token-provider";
13
+ readonly NONE: "none";
14
+ };
15
+ type RequestAuthMode = (typeof RequestAuthMode)[keyof typeof RequestAuthMode];
16
+ type RequestAuth = RequestAuthMode | {
17
+ token: string;
18
+ };
19
+ interface HttpRequest<TResponseSchema extends z.ZodType> {
20
+ method: HttpMethod;
21
+ path: string;
22
+ pathParams?: PathParams;
23
+ query?: QueryParams;
24
+ body?: unknown;
25
+ auth?: RequestAuth;
26
+ signal?: AbortSignal;
27
+ responseSchema: TResponseSchema;
28
+ }
29
+ interface HttpClient {
30
+ request<TResponseSchema extends z.ZodType>(request: HttpRequest<TResponseSchema>): Promise<z.output<TResponseSchema>>;
31
+ }
32
+ interface HttpClientOptions {
33
+ baseUrl: string;
34
+ getToken: TokenProvider;
35
+ fetch?: FetchFunction;
36
+ timeoutMs?: number | null;
37
+ }
38
+ declare function createHttpClient(options: HttpClientOptions): HttpClient;
39
+
40
+ interface AuthClient {
41
+ register(input: RegisterRequestInput): Promise<RegisterResponseParsed>;
42
+ verifyEmail(input: VerifyEmailRequestInput): Promise<VerifyEmailResponseParsed>;
43
+ login(input: LoginRequestInput): Promise<LoginResponseParsed>;
44
+ refresh(input: RefreshRequestInput): Promise<RefreshResponseParsed>;
45
+ logout(input?: LogoutRequestInput): Promise<LogoutResponseParsed>;
46
+ forgotPassword(input: ForgotPasswordRequestInput): Promise<ForgotPasswordResponseParsed>;
47
+ resetPassword(input: ResetPasswordRequestInput): Promise<ResetPasswordResponseParsed>;
48
+ }
49
+ declare function createAuthClient(http: HttpClient): AuthClient;
50
+
51
+ type CreateClientOptions = HttpClientOptions;
52
+ interface KeimelionClient {
53
+ http: HttpClient;
54
+ auth: AuthClient;
55
+ }
56
+ declare function createClient(options: CreateClientOptions): KeimelionClient;
57
+
58
+ declare const ClientErrorCode: {
59
+ readonly INVALID_RESPONSE: "INVALID_RESPONSE";
60
+ readonly NETWORK_ERROR: "NETWORK_ERROR";
61
+ readonly TIMEOUT: "TIMEOUT";
62
+ readonly ABORTED: "ABORTED";
63
+ };
64
+ type ClientErrorCode = (typeof ClientErrorCode)[keyof typeof ClientErrorCode];
65
+ type ApiErrorCode = ErrorCode | ClientErrorCode | (string & Record<never, never>);
66
+ declare const INVALID_RESPONSE_MESSAGE = "The API response does not match the expected contract";
67
+ declare const NETWORK_ERROR_MESSAGE = "The API could not be reached";
68
+ declare const TIMEOUT_MESSAGE = "The API did not respond in time";
69
+ declare const ABORTED_MESSAGE = "The request was aborted";
70
+ interface ApiErrorOptions {
71
+ status: number;
72
+ code: ApiErrorCode;
73
+ message: string;
74
+ metadata: Record<string, unknown>;
75
+ cause?: unknown;
76
+ }
77
+ declare class ApiError extends Error {
78
+ readonly name = "ApiError";
79
+ readonly status: number;
80
+ readonly code: ApiErrorCode;
81
+ readonly metadata: Record<string, unknown>;
82
+ readonly issues: ValidationIssueParsed[];
83
+ constructor(options: ApiErrorOptions);
84
+ }
85
+
86
+ declare const AuthPaths: {
87
+ readonly REGISTER: "/v1/auth/register";
88
+ readonly VERIFY_EMAIL: "/v1/auth/verify-email";
89
+ readonly LOGIN: "/v1/auth/login";
90
+ readonly REFRESH: "/v1/auth/refresh";
91
+ readonly LOGOUT: "/v1/auth/logout";
92
+ readonly FORGOT_PASSWORD: "/v1/auth/forgot-password";
93
+ readonly RESET_PASSWORD: "/v1/auth/reset-password";
94
+ };
95
+
96
+ export { ABORTED_MESSAGE, ApiError, AuthPaths, ClientErrorCode, DEFAULT_TIMEOUT_MS, INVALID_RESPONSE_MESSAGE, NETWORK_ERROR_MESSAGE, RequestAuthMode, TIMEOUT_MESSAGE, createAuthClient, createClient, createHttpClient };
97
+ export type { ApiErrorCode, ApiErrorOptions, AuthClient, CreateClientOptions, FetchFunction, HttpClient, HttpClientOptions, HttpRequest, KeimelionClient, PathParams, QueryParams, QueryValue, RequestAuth, TokenProvider };