mtlx-sdk 0.0.0-stage → 0.11.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 +21 -0
- package/README.md +174 -2
- package/dist/client.d.ts +67 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +141 -0
- package/dist/client.js.map +1 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/buildPath.d.ts +19 -0
- package/dist/lib/buildPath.d.ts.map +1 -0
- package/dist/lib/buildPath.js +46 -0
- package/dist/lib/buildPath.js.map +1 -0
- package/dist/lib/dashboardLinks.d.ts +19 -0
- package/dist/lib/dashboardLinks.d.ts.map +1 -0
- package/dist/lib/dashboardLinks.js +37 -0
- package/dist/lib/dashboardLinks.js.map +1 -0
- package/dist/lib/enums.d.ts +41 -0
- package/dist/lib/enums.d.ts.map +1 -0
- package/dist/lib/enums.js +293 -0
- package/dist/lib/enums.js.map +1 -0
- package/dist/lib/eventRouter.d.ts +41 -0
- package/dist/lib/eventRouter.d.ts.map +1 -0
- package/dist/lib/eventRouter.js +43 -0
- package/dist/lib/eventRouter.js.map +1 -0
- package/dist/lib/fetchBinary.d.ts +15 -0
- package/dist/lib/fetchBinary.d.ts.map +1 -0
- package/dist/lib/fetchBinary.js +35 -0
- package/dist/lib/fetchBinary.js.map +1 -0
- package/dist/lib/fileFormats.d.ts +67 -0
- package/dist/lib/fileFormats.d.ts.map +1 -0
- package/dist/lib/fileFormats.js +92 -0
- package/dist/lib/fileFormats.js.map +1 -0
- package/dist/lib/list.d.ts +59 -0
- package/dist/lib/list.d.ts.map +1 -0
- package/dist/lib/list.js +53 -0
- package/dist/lib/list.js.map +1 -0
- package/dist/lib/parseResult.d.ts +14 -0
- package/dist/lib/parseResult.d.ts.map +1 -0
- package/dist/lib/parseResult.js +13 -0
- package/dist/lib/parseResult.js.map +1 -0
- package/dist/lib/schemas.d.ts +48 -0
- package/dist/lib/schemas.d.ts.map +1 -0
- package/dist/lib/schemas.js +43 -0
- package/dist/lib/schemas.js.map +1 -0
- package/dist/lib/types.d.ts +46 -0
- package/dist/lib/types.d.ts.map +1 -0
- package/dist/lib/types.js +22 -0
- package/dist/lib/types.js.map +1 -0
- package/dist/lib/upload.d.ts +36 -0
- package/dist/lib/upload.d.ts.map +1 -0
- package/dist/lib/upload.js +79 -0
- package/dist/lib/upload.js.map +1 -0
- package/dist/lib/url.d.ts +7 -0
- package/dist/lib/url.d.ts.map +1 -0
- package/dist/lib/url.js +26 -0
- package/dist/lib/url.js.map +1 -0
- package/dist/routes/apiTokens.d.ts +172 -0
- package/dist/routes/apiTokens.d.ts.map +1 -0
- package/dist/routes/apiTokens.js +133 -0
- package/dist/routes/apiTokens.js.map +1 -0
- package/dist/routes/assets.d.ts +545 -0
- package/dist/routes/assets.d.ts.map +1 -0
- package/dist/routes/assets.js +275 -0
- package/dist/routes/assets.js.map +1 -0
- package/dist/routes/auth.d.ts +102 -0
- package/dist/routes/auth.d.ts.map +1 -0
- package/dist/routes/auth.js +98 -0
- package/dist/routes/auth.js.map +1 -0
- package/dist/routes/avatars.d.ts +130 -0
- package/dist/routes/avatars.d.ts.map +1 -0
- package/dist/routes/avatars.js +121 -0
- package/dist/routes/avatars.js.map +1 -0
- package/dist/routes/comments.d.ts +165 -0
- package/dist/routes/comments.d.ts.map +1 -0
- package/dist/routes/comments.js +106 -0
- package/dist/routes/comments.js.map +1 -0
- package/dist/routes/error.d.ts +10 -0
- package/dist/routes/error.d.ts.map +1 -0
- package/dist/routes/error.js +12 -0
- package/dist/routes/error.js.map +1 -0
- package/dist/routes/files.d.ts +70 -0
- package/dist/routes/files.d.ts.map +1 -0
- package/dist/routes/files.js +80 -0
- package/dist/routes/files.js.map +1 -0
- package/dist/routes/health.d.ts +10 -0
- package/dist/routes/health.d.ts.map +1 -0
- package/dist/routes/health.js +12 -0
- package/dist/routes/health.js.map +1 -0
- package/dist/routes/media.d.ts +22 -0
- package/dist/routes/media.d.ts.map +1 -0
- package/dist/routes/media.js +18 -0
- package/dist/routes/media.js.map +1 -0
- package/dist/routes/notifications.d.ts +164 -0
- package/dist/routes/notifications.d.ts.map +1 -0
- package/dist/routes/notifications.js +97 -0
- package/dist/routes/notifications.js.map +1 -0
- package/dist/routes/oembed.d.ts +80 -0
- package/dist/routes/oembed.d.ts.map +1 -0
- package/dist/routes/oembed.js +74 -0
- package/dist/routes/oembed.js.map +1 -0
- package/dist/routes/serverEvents.d.ts +521 -0
- package/dist/routes/serverEvents.d.ts.map +1 -0
- package/dist/routes/serverEvents.js +136 -0
- package/dist/routes/serverEvents.js.map +1 -0
- package/dist/routes/tasks.d.ts +242 -0
- package/dist/routes/tasks.d.ts.map +1 -0
- package/dist/routes/tasks.js +185 -0
- package/dist/routes/tasks.js.map +1 -0
- package/dist/routes/users.d.ts +1055 -0
- package/dist/routes/users.d.ts.map +1 -0
- package/dist/routes/users.js +233 -0
- package/dist/routes/users.js.map +1 -0
- package/package.json +49 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ben Houston
|
|
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,175 @@
|
|
|
1
|
-
|
|
1
|
+
[](https://codecov.io/gh/bhouston/mtlx)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
# mtlx-sdk
|
|
4
|
+
|
|
5
|
+
Official SDK for the [MTLX.ai](https://mtlx.ai) REST API.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install mtlx-sdk
|
|
11
|
+
# or
|
|
12
|
+
pnpm add mtlx-sdk
|
|
13
|
+
# or
|
|
14
|
+
yarn add mtlx-sdk
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
18
|
+
|
|
19
|
+
The SDK uses a **functional approach** - all API operations are exported as standalone functions that take a client instance as their first parameter. Every material belongs directly to a user (there are no organizations or projects).
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
import { createSecretTokenInstance, listAssets, getAsset } from 'mtlx-sdk';
|
|
23
|
+
|
|
24
|
+
const userName = 'alice';
|
|
25
|
+
|
|
26
|
+
// Create a client instance (host defaults to https://api.mtlx.ai)
|
|
27
|
+
const client = createSecretTokenInstance({
|
|
28
|
+
secretToken: 'your-api-token',
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// List a user's materials
|
|
32
|
+
const assets = await listAssets(client, {
|
|
33
|
+
query: { userName },
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// Get a specific material
|
|
37
|
+
const asset = await getAsset(client, {
|
|
38
|
+
params: { userName, assetName: 'copper' },
|
|
39
|
+
});
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Features
|
|
43
|
+
|
|
44
|
+
- **Functional API design** - All operations are exported as standalone functions
|
|
45
|
+
- Full TypeScript support with complete type definitions
|
|
46
|
+
- Zod schema validation for requests and responses
|
|
47
|
+
- Axios-based HTTP client with automatic error handling
|
|
48
|
+
- Support for all MTLX.ai API endpoints:
|
|
49
|
+
- Materials (MaterialX assets, always stored as `.mtlx.zip`)
|
|
50
|
+
- Users and authentication
|
|
51
|
+
- Comments and notifications
|
|
52
|
+
- File uploads and downloads
|
|
53
|
+
- API tokens
|
|
54
|
+
|
|
55
|
+
## Uploading a Material
|
|
56
|
+
|
|
57
|
+
The SDK provides a simple helper function for uploading files. Here's a complete example:
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
import { readFile } from 'node:fs/promises';
|
|
61
|
+
import { basename } from 'node:path';
|
|
62
|
+
import { createSecretTokenInstance, uploadFile, createAsset } from 'mtlx-sdk';
|
|
63
|
+
|
|
64
|
+
const userName = 'alice';
|
|
65
|
+
|
|
66
|
+
const client = createSecretTokenInstance({
|
|
67
|
+
secretToken: 'your-api-token',
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// Read the file and extract filename (loose `.mtlx` or packaged `.mtlx.zip`)
|
|
71
|
+
const fileData = await readFile('copper.mtlx.zip');
|
|
72
|
+
const filename = basename('copper.mtlx.zip');
|
|
73
|
+
|
|
74
|
+
// Upload the file (infers MIME type and uploads)
|
|
75
|
+
const uploadToken = await uploadFile(client, {
|
|
76
|
+
params: { userName },
|
|
77
|
+
fileData,
|
|
78
|
+
filename,
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// Create the asset record with the upload token. The API validates the
|
|
82
|
+
// MaterialX document during ingest and rejects malformed content with 400.
|
|
83
|
+
const asset = await createAsset(client, {
|
|
84
|
+
params: { userName },
|
|
85
|
+
body: {
|
|
86
|
+
name: 'copper',
|
|
87
|
+
description: 'A brushed copper material',
|
|
88
|
+
type: 'MATERIAL',
|
|
89
|
+
uploadToken,
|
|
90
|
+
visibility: 'PUBLIC',
|
|
91
|
+
shareLicense: 'CC_BY',
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
The `uploadFile` helper:
|
|
97
|
+
|
|
98
|
+
- Accepts file data (Buffer or Uint8Array) and filename
|
|
99
|
+
- Infers the MIME type from the file extension
|
|
100
|
+
- Prepares the upload and gets a signed URL
|
|
101
|
+
- Uploads the file to the signed URL
|
|
102
|
+
- Returns the upload token for use in `createAsset`
|
|
103
|
+
|
|
104
|
+
**Note:** In Node.js environments, you'll need to read the file yourself using `readFile` from `node:fs/promises` before calling `uploadFile`. In browser environments, you can pass a `File` object directly to `uploadFileToUploadUrl()` or convert it to an `ArrayBuffer`/`Uint8Array` for `uploadFile`.
|
|
105
|
+
|
|
106
|
+
For more control, you can use `prepareAssetUpload()` and `uploadFileToUploadUrl()` directly.
|
|
107
|
+
|
|
108
|
+
## API Reference
|
|
109
|
+
|
|
110
|
+
### Client Configuration
|
|
111
|
+
|
|
112
|
+
The SDK provides several client creation functions depending on your authentication method:
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
import {
|
|
116
|
+
createSecretTokenInstance, // For API tokens (most common)
|
|
117
|
+
createFrontendTokenInstance, // For frontend tokens
|
|
118
|
+
createSessionInstance, // For user sessions
|
|
119
|
+
createAnonymousClient, // For anonymous access
|
|
120
|
+
} from 'mtlx-sdk';
|
|
121
|
+
|
|
122
|
+
// Most common: API token authentication
|
|
123
|
+
// host defaults to 'https://api.mtlx.ai' if not provided
|
|
124
|
+
const client = createSecretTokenInstance({
|
|
125
|
+
secretToken: 'your-api-token',
|
|
126
|
+
// host: 'https://api.mtlx.ai', // Optional, defaults to production API
|
|
127
|
+
});
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
**Note:** For normal users, you typically don't need to specify the `host` parameter as it defaults to `https://api.mtlx.ai`. Only internal developers may need to override this for testing against different environments.
|
|
131
|
+
|
|
132
|
+
### Available Functions
|
|
133
|
+
|
|
134
|
+
The SDK exports functions for all API operations. Here are the main categories:
|
|
135
|
+
|
|
136
|
+
**Assets (materials):**
|
|
137
|
+
|
|
138
|
+
- `listAssets()` - List a user's materials (or search public ones)
|
|
139
|
+
- `getAsset()` - Get material metadata, including the parsed `materialInfo`
|
|
140
|
+
- `createAsset()` - Create a new material
|
|
141
|
+
- `updateAsset()` - Update material metadata or replace its file
|
|
142
|
+
- `deleteAsset()` - Delete a material
|
|
143
|
+
- `uploadFile()` - Upload a file and get upload token (helper function)
|
|
144
|
+
- `prepareAssetUpload()` - Get signed upload URL and token
|
|
145
|
+
- `uploadFileToUploadUrl()` - Upload file to signed URL
|
|
146
|
+
|
|
147
|
+
**Other resources:**
|
|
148
|
+
|
|
149
|
+
- Users and authentication
|
|
150
|
+
- Comments and notifications
|
|
151
|
+
- API tokens
|
|
152
|
+
|
|
153
|
+
All functions follow the pattern: `functionName(client, props)` where `client` is the API client instance and `props` contains the request parameters.
|
|
154
|
+
|
|
155
|
+
## Zod Schemas
|
|
156
|
+
|
|
157
|
+
The SDK exports Zod schemas for all API request and response types, enabling runtime validation:
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
import { assetSchema, createAssetBodySchema } from 'mtlx-sdk';
|
|
161
|
+
|
|
162
|
+
// Validate an asset object
|
|
163
|
+
const validatedAsset = assetSchema.parse(assetData);
|
|
164
|
+
|
|
165
|
+
// Validate create asset input
|
|
166
|
+
const validatedInput = createAssetBodySchema.parse(createAssetInput);
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Requirements
|
|
170
|
+
|
|
171
|
+
- Node.js >= 23.0.0
|
|
172
|
+
|
|
173
|
+
## License
|
|
174
|
+
|
|
175
|
+
MIT
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { type AxiosInstance, type AxiosRequestConfig } from 'axios';
|
|
2
|
+
import type * as z from 'zod';
|
|
3
|
+
export type ApiAuthType = 'frontendToken' | 'access-token' | 'session' | 'anonymous';
|
|
4
|
+
export type ApiAuthFrontendToken = {
|
|
5
|
+
authType: 'frontendToken';
|
|
6
|
+
frontendToken: string;
|
|
7
|
+
};
|
|
8
|
+
export type ApiAuthSecretToken = {
|
|
9
|
+
authType: 'secretToken';
|
|
10
|
+
secretToken: string;
|
|
11
|
+
};
|
|
12
|
+
export type ApiAuthUserSession = {
|
|
13
|
+
authType: 'userSession';
|
|
14
|
+
userSessionToken: string;
|
|
15
|
+
};
|
|
16
|
+
export type ApiAuthAnonymous = {
|
|
17
|
+
authType: 'anonymous';
|
|
18
|
+
};
|
|
19
|
+
export type ApiAuth = ApiAuthFrontendToken | ApiAuthSecretToken | ApiAuthUserSession | ApiAuthAnonymous;
|
|
20
|
+
export type ApiClient = {
|
|
21
|
+
axios: AxiosInstance;
|
|
22
|
+
host: string;
|
|
23
|
+
auth: ApiAuth;
|
|
24
|
+
validateResults?: boolean;
|
|
25
|
+
};
|
|
26
|
+
export declare class ClientFetchError extends Error {
|
|
27
|
+
status: number;
|
|
28
|
+
constructor(message: string, status: number);
|
|
29
|
+
}
|
|
30
|
+
export type ApiRequest = {
|
|
31
|
+
path: string;
|
|
32
|
+
params?: Record<string, string | number | boolean | undefined>;
|
|
33
|
+
init?: Omit<AxiosRequestConfig, 'url' | 'params'>;
|
|
34
|
+
};
|
|
35
|
+
export type CreateInstanceParams = {
|
|
36
|
+
host: string;
|
|
37
|
+
};
|
|
38
|
+
export type CreateFrontendTokenInstanceParams = CreateInstanceParams & {
|
|
39
|
+
frontendToken: string;
|
|
40
|
+
};
|
|
41
|
+
export declare const createFrontendTokenInstance: ({ host, frontendToken }: CreateFrontendTokenInstanceParams) => ApiClient;
|
|
42
|
+
export type CreateSecretTokenInstanceParams = CreateInstanceParams & {
|
|
43
|
+
secretToken: string;
|
|
44
|
+
accessToken?: string;
|
|
45
|
+
};
|
|
46
|
+
export declare const createSecretTokenInstance: ({ host, secretToken, accessToken, }: CreateSecretTokenInstanceParams) => ApiClient;
|
|
47
|
+
export type CreateSessionInstanceParams = CreateInstanceParams & {
|
|
48
|
+
userSessionToken: string;
|
|
49
|
+
accessToken?: string;
|
|
50
|
+
};
|
|
51
|
+
export declare const createSessionInstance: ({ host, userSessionToken, accessToken, }: CreateSessionInstanceParams) => ApiClient;
|
|
52
|
+
export type CreateAnonymousClientParams = CreateInstanceParams;
|
|
53
|
+
export declare const createAnonymousClient: ({ host }: CreateAnonymousClientParams) => ApiClient;
|
|
54
|
+
export declare const clientFetchUrl: (client: ApiClient, request: ApiRequest) => URL;
|
|
55
|
+
export declare const clientFetch: (client: ApiClient, request: ApiRequest) => Promise<import("axios").AxiosResponse<any, any, {}, Record<string, string | number | boolean | undefined>>>;
|
|
56
|
+
/**
|
|
57
|
+
* Conditionally parses API response data using a zod schema.
|
|
58
|
+
* If client.validateResults is true, validates and parses the data.
|
|
59
|
+
* Otherwise, returns the data with a type assertion based on the schema's inferred type.
|
|
60
|
+
*
|
|
61
|
+
* @param client - The API client instance (unused, kept for backward compatibility)
|
|
62
|
+
* @param schema - The zod schema to use for validation/type inference
|
|
63
|
+
* @param data - The raw response data to parse
|
|
64
|
+
* @returns The parsed or type-asserted data matching the schema's inferred type
|
|
65
|
+
*/
|
|
66
|
+
export declare const parseResult: <T extends z.ZodTypeAny>(client: ApiClient, schema: T, data: unknown) => z.infer<T>;
|
|
67
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAc,EAAE,KAAK,aAAa,EAAE,KAAK,kBAAkB,EAAmC,MAAM,OAAO,CAAC;AAC5G,OAAO,KAAK,KAAK,CAAC,MAAM,KAAK,CAAC;AAK9B,MAAM,MAAM,WAAW,GAAG,eAAe,GAAG,cAAc,GAAG,SAAS,GAAG,WAAW,CAAC;AAGrF,MAAM,MAAM,oBAAoB,GAAG;IACjC,QAAQ,EAAE,eAAe,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE,aAAa,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE,aAAa,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,EAAE,WAAW,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG,oBAAoB,GAAG,kBAAkB,GAAG,kBAAkB,GAAG,gBAAgB,CAAC;AAExG,MAAM,MAAM,SAAS,GAAG;IACtB,KAAK,EAAE,aAAa,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,CAAC;IACd,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B,CAAC;AAEF,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAG1C;CACF;AAED,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,CAAC;IAC/D,IAAI,CAAC,EAAE,IAAI,CAAC,kBAAkB,EAAE,KAAK,GAAG,QAAQ,CAAC,CAAC;CACnD,CAAC;AAcF,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,iCAAiC,GAAG,oBAAoB,GAAG;IACrE,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,eAAO,MAAM,2BAA2B,4BAA6B,iCAAiC,KAAG,SAmBxG,CAAC;AAqDF,MAAM,MAAM,+BAA+B,GAAG,oBAAoB,GAAG;IACnE,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,eAAO,MAAM,yBAAyB,wCAInC,+BAA+B,KAAG,SASpC,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG,oBAAoB,GAAG;IAC/D,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,eAAO,MAAM,qBAAqB,6CAI/B,2BAA2B,KAAG,SAShC,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG,oBAAoB,CAAC;AAE/D,eAAO,MAAM,qBAAqB,aAAc,2BAA2B,KAAG,SAW7E,CAAC;AAEF,eAAO,MAAM,cAAc,WAAY,SAAS,WAAW,UAAU,QASpE,CAAC;AAEF,eAAO,MAAM,WAAW,WAAkB,SAAS,WAAW,UAAU,gHAQvE,CAAC;AAMF;;;;;;;;;GASG;AACH,eAAO,MAAM,WAAW,GAAI,CAAC,SAAS,CAAC,CAAC,UAAU,UAAU,SAAS,UAAU,CAAC,QAAQ,OAAO,KAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAC9D,CAAC"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
import { makeUrl } from './lib/url.js';
|
|
3
|
+
import { refreshAccessToken } from './routes/auth.js';
|
|
4
|
+
export class ClientFetchError extends Error {
|
|
5
|
+
status;
|
|
6
|
+
constructor(message, status) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.status = status;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
const validateHost = (host) => {
|
|
12
|
+
if (!host.includes('://')) {
|
|
13
|
+
throw new Error(`host must include protocol, either http:// or https://, but it doesn't: ${host}`);
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
const validatePath = (path) => {
|
|
17
|
+
if (!path.startsWith('/api')) {
|
|
18
|
+
throw new Error(`path must start with "api", but it does not: ${path}`);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
export const createFrontendTokenInstance = ({ host, frontendToken }) => {
|
|
22
|
+
validateHost(host);
|
|
23
|
+
// CDN friendly as it puts the public key in the URL.
|
|
24
|
+
const axiosInstance = axios.create({
|
|
25
|
+
baseURL: host,
|
|
26
|
+
params: {
|
|
27
|
+
frontendToken,
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
return {
|
|
31
|
+
axios: axiosInstance,
|
|
32
|
+
host,
|
|
33
|
+
auth: {
|
|
34
|
+
authType: 'frontendToken',
|
|
35
|
+
frontendToken,
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
const createJWTInstance = (host, refreshToken, accessToken) => {
|
|
40
|
+
validateHost(host);
|
|
41
|
+
const axiosInstance = axios.create({
|
|
42
|
+
baseURL: host,
|
|
43
|
+
});
|
|
44
|
+
// Set initial access token if provided
|
|
45
|
+
if (accessToken) {
|
|
46
|
+
axiosInstance.defaults.headers.common.Authorization = `Bearer ${accessToken}`;
|
|
47
|
+
}
|
|
48
|
+
const refresh = async (config) => {
|
|
49
|
+
const newAccessToken = await refreshAccessToken(host, {
|
|
50
|
+
body: {
|
|
51
|
+
refreshToken,
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
config.headers.set('Authorization', `Bearer ${newAccessToken.accessToken}`);
|
|
55
|
+
axiosInstance.defaults.headers.common.Authorization = `Bearer ${newAccessToken.accessToken}`;
|
|
56
|
+
};
|
|
57
|
+
axiosInstance.interceptors.request.use(async (config) => {
|
|
58
|
+
if (!config.headers.Authorization) {
|
|
59
|
+
await refresh(config);
|
|
60
|
+
}
|
|
61
|
+
return config;
|
|
62
|
+
});
|
|
63
|
+
axiosInstance.interceptors.response.use(async (response) => response, async (error) => {
|
|
64
|
+
const requestConfig = error.config;
|
|
65
|
+
// Only attempt refresh once per request
|
|
66
|
+
if (error.response?.status === 401 && !requestConfig._retried) {
|
|
67
|
+
requestConfig._retried = true;
|
|
68
|
+
await refresh(requestConfig);
|
|
69
|
+
// Retry the request once if refresh succeeded
|
|
70
|
+
return axiosInstance(requestConfig);
|
|
71
|
+
}
|
|
72
|
+
throw error;
|
|
73
|
+
});
|
|
74
|
+
return {
|
|
75
|
+
axios: axiosInstance,
|
|
76
|
+
host,
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
export const createSecretTokenInstance = ({ host, secretToken, accessToken, }) => {
|
|
80
|
+
validateHost(host);
|
|
81
|
+
return {
|
|
82
|
+
...createJWTInstance(host, secretToken, accessToken),
|
|
83
|
+
auth: {
|
|
84
|
+
authType: 'secretToken',
|
|
85
|
+
secretToken,
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
};
|
|
89
|
+
export const createSessionInstance = ({ host, userSessionToken, accessToken, }) => {
|
|
90
|
+
validateHost(host);
|
|
91
|
+
return {
|
|
92
|
+
...createJWTInstance(host, userSessionToken, accessToken),
|
|
93
|
+
auth: {
|
|
94
|
+
authType: 'userSession',
|
|
95
|
+
userSessionToken,
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
export const createAnonymousClient = ({ host }) => {
|
|
100
|
+
validateHost(host);
|
|
101
|
+
return {
|
|
102
|
+
axios: axios.create({
|
|
103
|
+
baseURL: host,
|
|
104
|
+
}),
|
|
105
|
+
host,
|
|
106
|
+
auth: {
|
|
107
|
+
authType: 'anonymous',
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
};
|
|
111
|
+
export const clientFetchUrl = (client, request) => {
|
|
112
|
+
validatePath(request.path);
|
|
113
|
+
let params = request.params;
|
|
114
|
+
if (client.auth.authType === 'frontendToken') {
|
|
115
|
+
params = { ...params, frontendToken: client.auth.frontendToken };
|
|
116
|
+
}
|
|
117
|
+
return makeUrl(client.host, request.path, params);
|
|
118
|
+
};
|
|
119
|
+
export const clientFetch = async (client, request) => {
|
|
120
|
+
validatePath(request.path);
|
|
121
|
+
return await client.axios.request({
|
|
122
|
+
...request.init,
|
|
123
|
+
url: request.path,
|
|
124
|
+
params: request.params,
|
|
125
|
+
});
|
|
126
|
+
};
|
|
127
|
+
// Re-export parseResult from lib to maintain backward compatibility
|
|
128
|
+
// This breaks the circular dependency since routes/auth.ts imports from lib/parseResult.ts directly
|
|
129
|
+
import { parseResultWithClient } from './lib/parseResult.js';
|
|
130
|
+
/**
|
|
131
|
+
* Conditionally parses API response data using a zod schema.
|
|
132
|
+
* If client.validateResults is true, validates and parses the data.
|
|
133
|
+
* Otherwise, returns the data with a type assertion based on the schema's inferred type.
|
|
134
|
+
*
|
|
135
|
+
* @param client - The API client instance (unused, kept for backward compatibility)
|
|
136
|
+
* @param schema - The zod schema to use for validation/type inference
|
|
137
|
+
* @param data - The raw response data to parse
|
|
138
|
+
* @returns The parsed or type-asserted data matching the schema's inferred type
|
|
139
|
+
*/
|
|
140
|
+
export const parseResult = (client, schema, data) => parseResultWithClient(client, schema, data);
|
|
141
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAuF,MAAM,OAAO,CAAC;AAG5G,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAiCtD,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IACzC,MAAM,CAAS;IACf,YAAY,OAAe,EAAE,MAAc;QACzC,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF;AAQD,MAAM,YAAY,GAAG,CAAC,IAAY,EAAE,EAAE;IACpC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,2EAA2E,IAAI,EAAE,CAAC,CAAC;IACrG,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,YAAY,GAAG,CAAC,IAAY,EAAE,EAAE;IACpC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,gDAAgD,IAAI,EAAE,CAAC,CAAC;IAC1E,CAAC;AACH,CAAC,CAAC;AAUF,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,EAAE,IAAI,EAAE,aAAa,EAAqC,EAAa,EAAE;IACnH,YAAY,CAAC,IAAI,CAAC,CAAC;IAEnB,qDAAqD;IACrD,MAAM,aAAa,GAAG,KAAK,CAAC,MAAM,CAAC;QACjC,OAAO,EAAE,IAAI;QACb,MAAM,EAAE;YACN,aAAa;SACd;KACF,CAAC,CAAC;IAEH,OAAO;QACL,KAAK,EAAE,aAAa;QACpB,IAAI;QACJ,IAAI,EAAE;YACJ,QAAQ,EAAE,eAAe;YACzB,aAAa;SACd;KACF,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,iBAAiB,GAAG,CAAC,IAAY,EAAE,YAAoB,EAAE,WAAoB,EAAE,EAAE;IACrF,YAAY,CAAC,IAAI,CAAC,CAAC;IAEnB,MAAM,aAAa,GAAG,KAAK,CAAC,MAAM,CAAC;QACjC,OAAO,EAAE,IAAI;KACd,CAAC,CAAC;IAEH,uCAAuC;IACvC,IAAI,WAAW,EAAE,CAAC;QAChB,aAAa,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,aAAa,GAAG,UAAU,WAAW,EAAE,CAAC;IAChF,CAAC;IAED,MAAM,OAAO,GAAG,KAAK,EAAE,MAAkC,EAAE,EAAE;QAC3D,MAAM,cAAc,GAAG,MAAM,kBAAkB,CAAC,IAAI,EAAE;YACpD,IAAI,EAAE;gBACJ,YAAY;aACb;SACF,CAAC,CAAC;QACH,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,UAAU,cAAc,CAAC,WAAW,EAAE,CAAC,CAAC;QAC5E,aAAa,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,aAAa,GAAG,UAAU,cAAc,CAAC,WAAW,EAAE,CAAC;IAC/F,CAAC,CAAC;IAEF,aAAa,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE;QACtD,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;YAClC,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;QACxB,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC,CAAC;IACH,aAAa,CAAC,YAAY,CAAC,QAAQ,CAAC,GAAG,CACrC,KAAK,EAAE,QAAQ,EAAE,EAAE,CAAC,QAAQ,EAC5B,KAAK,EAAE,KAAK,EAAE,EAAE;QACd,MAAM,aAAa,GAAG,KAAK,CAAC,MAA6D,CAAC;QAE1F,wCAAwC;QACxC,IAAI,KAAK,CAAC,QAAQ,EAAE,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC;YAC9D,aAAa,CAAC,QAAQ,GAAG,IAAI,CAAC;YAC9B,MAAM,OAAO,CAAC,aAAa,CAAC,CAAC;YAC7B,8CAA8C;YAC9C,OAAO,aAAa,CAAC,aAAa,CAAC,CAAC;QACtC,CAAC;QAED,MAAM,KAAK,CAAC;IACd,CAAC,CACF,CAAC;IAEF,OAAO;QACL,KAAK,EAAE,aAAa;QACpB,IAAI;KACL,CAAC;AACJ,CAAC,CAAC;AAOF,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,EACxC,IAAI,EACJ,WAAW,EACX,WAAW,GACqB,EAAa,EAAE;IAC/C,YAAY,CAAC,IAAI,CAAC,CAAC;IACnB,OAAO;QACL,GAAG,iBAAiB,CAAC,IAAI,EAAE,WAAW,EAAE,WAAW,CAAC;QACpD,IAAI,EAAE;YACJ,QAAQ,EAAE,aAAa;YACvB,WAAW;SACZ;KACF,CAAC;AACJ,CAAC,CAAC;AAOF,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,EACpC,IAAI,EACJ,gBAAgB,EAChB,WAAW,GACiB,EAAa,EAAE;IAC3C,YAAY,CAAC,IAAI,CAAC,CAAC;IACnB,OAAO;QACL,GAAG,iBAAiB,CAAC,IAAI,EAAE,gBAAgB,EAAE,WAAW,CAAC;QACzD,IAAI,EAAE;YACJ,QAAQ,EAAE,aAAa;YACvB,gBAAgB;SACjB;KACF,CAAC;AACJ,CAAC,CAAC;AAIF,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,EAAE,IAAI,EAA+B,EAAa,EAAE;IACxF,YAAY,CAAC,IAAI,CAAC,CAAC;IACnB,OAAO;QACL,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC;YAClB,OAAO,EAAE,IAAI;SACd,CAAC;QACF,IAAI;QACJ,IAAI,EAAE;YACJ,QAAQ,EAAE,WAAW;SACtB;KACF,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,MAAiB,EAAE,OAAmB,EAAE,EAAE;IACvE,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAE3B,IAAI,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAC5B,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,KAAK,eAAe,EAAE,CAAC;QAC7C,MAAM,GAAG,EAAE,GAAG,MAAM,EAAE,aAAa,EAAE,MAAM,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;IACnE,CAAC;IAED,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AACpD,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAAE,MAAiB,EAAE,OAAmB,EAAE,EAAE;IAC1E,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAE3B,OAAO,MAAM,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC;QAChC,GAAG,OAAO,CAAC,IAAI;QACf,GAAG,EAAE,OAAO,CAAC,IAAI;QACjB,MAAM,EAAE,OAAO,CAAC,MAAM;KACvB,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,oEAAoE;AACpE,oGAAoG;AACpG,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAE7D;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAyB,MAAiB,EAAE,MAAS,EAAE,IAAa,EAAc,EAAE,CAC7G,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export * from './client.js';
|
|
2
|
+
export * from './lib/buildPath.js';
|
|
3
|
+
export * from './lib/dashboardLinks.js';
|
|
4
|
+
export * from './lib/enums.js';
|
|
5
|
+
export * from './lib/eventRouter.js';
|
|
6
|
+
export * from './lib/fileFormats.js';
|
|
7
|
+
export * from './lib/list.js';
|
|
8
|
+
export * from './lib/schemas.js';
|
|
9
|
+
export * from './lib/types.js';
|
|
10
|
+
export * from './lib/upload.js';
|
|
11
|
+
export * from './lib/url.js';
|
|
12
|
+
export * from './routes/apiTokens.js';
|
|
13
|
+
export * from './routes/assets.js';
|
|
14
|
+
export * from './routes/auth.js';
|
|
15
|
+
export * from './routes/avatars.js';
|
|
16
|
+
export * from './routes/comments.js';
|
|
17
|
+
export * from './routes/error.js';
|
|
18
|
+
export * from './routes/files.js';
|
|
19
|
+
export * from './routes/health.js';
|
|
20
|
+
export * from './routes/media.js';
|
|
21
|
+
export * from './routes/notifications.js';
|
|
22
|
+
export * from './routes/oembed.js';
|
|
23
|
+
export * from './routes/serverEvents.js';
|
|
24
|
+
export * from './routes/tasks.js';
|
|
25
|
+
export * from './routes/users.js';
|
|
26
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,yBAAyB,CAAC;AACxC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,uBAAuB,CAAC;AACtC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export * from './client.js';
|
|
2
|
+
export * from './lib/buildPath.js';
|
|
3
|
+
export * from './lib/dashboardLinks.js';
|
|
4
|
+
export * from './lib/enums.js';
|
|
5
|
+
export * from './lib/eventRouter.js';
|
|
6
|
+
export * from './lib/fileFormats.js';
|
|
7
|
+
export * from './lib/list.js';
|
|
8
|
+
export * from './lib/schemas.js';
|
|
9
|
+
export * from './lib/types.js';
|
|
10
|
+
export * from './lib/upload.js';
|
|
11
|
+
export * from './lib/url.js';
|
|
12
|
+
export * from './routes/apiTokens.js';
|
|
13
|
+
export * from './routes/assets.js';
|
|
14
|
+
export * from './routes/auth.js';
|
|
15
|
+
export * from './routes/avatars.js';
|
|
16
|
+
export * from './routes/comments.js';
|
|
17
|
+
export * from './routes/error.js';
|
|
18
|
+
export * from './routes/files.js';
|
|
19
|
+
export * from './routes/health.js';
|
|
20
|
+
export * from './routes/media.js';
|
|
21
|
+
export * from './routes/notifications.js';
|
|
22
|
+
export * from './routes/oembed.js';
|
|
23
|
+
export * from './routes/serverEvents.js';
|
|
24
|
+
export * from './routes/tasks.js';
|
|
25
|
+
export * from './routes/users.js';
|
|
26
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,yBAAyB,CAAC;AACxC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,uBAAuB,CAAC;AACtC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds a path by replacing path parameters with their values.
|
|
3
|
+
* The params object is type-checked to match the parameters in the path string.
|
|
4
|
+
*
|
|
5
|
+
* @param path - Path template with parameters like `/api/$orgId/test`
|
|
6
|
+
* @param params - Object containing parameter values matching the path template
|
|
7
|
+
* @returns Resolved path with parameters substituted
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* buildPath('/users/$userName', { userName: 'john-doe' })
|
|
12
|
+
* // Returns: '/users/john-doe'
|
|
13
|
+
*
|
|
14
|
+
* // Type error if parameter is missing:
|
|
15
|
+
* buildPath('/users/$userName', {}) // Error: Property 'userName' is missing
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export declare const buildPath: (path: string, params: Record<string, string | number>) => string;
|
|
19
|
+
//# sourceMappingURL=buildPath.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buildPath.d.ts","sources":["../../src/lib/buildPath.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,SAAS,SAAU,MAAM,UAAU,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,KAAG,MA6BjF,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// This should match paths like: /api/$orgId/test or /api/$orgId/$projectId/test
|
|
2
|
+
const paramRegex = /\$(\w+)/g;
|
|
3
|
+
/**
|
|
4
|
+
* Builds a path by replacing path parameters with their values.
|
|
5
|
+
* The params object is type-checked to match the parameters in the path string.
|
|
6
|
+
*
|
|
7
|
+
* @param path - Path template with parameters like `/api/$orgId/test`
|
|
8
|
+
* @param params - Object containing parameter values matching the path template
|
|
9
|
+
* @returns Resolved path with parameters substituted
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* buildPath('/users/$userName', { userName: 'john-doe' })
|
|
14
|
+
* // Returns: '/users/john-doe'
|
|
15
|
+
*
|
|
16
|
+
* // Type error if parameter is missing:
|
|
17
|
+
* buildPath('/users/$userName', {}) // Error: Property 'userName' is missing
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export const buildPath = (path, params) => {
|
|
21
|
+
// Collect all parameter names used in the path
|
|
22
|
+
const pathParams = new Set();
|
|
23
|
+
for (const match of path.matchAll(paramRegex)) {
|
|
24
|
+
const paramName = match[1]; // Extract parameter name without $ prefix (capture group)
|
|
25
|
+
if (paramName) {
|
|
26
|
+
pathParams.add(paramName);
|
|
27
|
+
// Check if param exists in params object
|
|
28
|
+
if (!(paramName in params)) {
|
|
29
|
+
throw new Error(`Param $${paramName} from path ${path} is not in the params object: ${JSON.stringify(params)}`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
// Check for unused parameters
|
|
34
|
+
const remainingParams = Object.keys(params).filter((key) => !pathParams.has(key));
|
|
35
|
+
if (remainingParams.length > 0) {
|
|
36
|
+
throw new Error(`Params ${remainingParams.join(', ')} from path ${path} are not all used: ${JSON.stringify(params)}`);
|
|
37
|
+
}
|
|
38
|
+
return path.replace(paramRegex, (_match, p1) => {
|
|
39
|
+
const param = params[p1];
|
|
40
|
+
if (param === undefined || param === null) {
|
|
41
|
+
throw new Error(`Param ${p1} from path ${path} is not in the params object: ${JSON.stringify(params)}`);
|
|
42
|
+
}
|
|
43
|
+
return encodeURIComponent(String(param));
|
|
44
|
+
});
|
|
45
|
+
};
|
|
46
|
+
//# sourceMappingURL=buildPath.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buildPath.js","sources":["../../src/lib/buildPath.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,MAAM,UAAU,GAAG,UAAU,CAAC;AAE9B;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,IAAY,EAAE,MAAuC,EAAU,EAAE;IACzF,+CAA+C;IAC/C,MAAM,UAAU,GAAG,IAAI,GAAG,EAAU,CAAC;IACrC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;QAC9C,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,0DAA0D;QACtF,IAAI,SAAS,EAAE,CAAC;YACd,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YAC1B,yCAAyC;YACzC,IAAI,CAAC,CAAC,SAAS,IAAI,MAAM,CAAC,EAAE,CAAC;gBAC3B,MAAM,IAAI,KAAK,CAAC,UAAU,SAAS,cAAc,IAAI,iCAAiC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAClH,CAAC;QACH,CAAC;IACH,CAAC;IAED,8BAA8B;IAC9B,MAAM,eAAe,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IAClF,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CACb,UAAU,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,IAAI,sBAAsB,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CACrG,CAAC;IACJ,CAAC;IAED,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE;QAC7C,MAAM,KAAK,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC;QACzB,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YAC1C,MAAM,IAAI,KAAK,CAAC,SAAS,EAAE,cAAc,IAAI,iCAAiC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC1G,CAAC;QACD,OAAO,kBAAkB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export declare const dashboardUserLinkRegex: RegExp;
|
|
2
|
+
export declare const dashboardAssetLinkRegex: RegExp;
|
|
3
|
+
export declare const dashboardAssetCommentLinkRegex: RegExp;
|
|
4
|
+
export declare const dashboardSettingsInvitesLinkRegex: RegExp;
|
|
5
|
+
export declare const validDashboardLinkTargets: RegExp[];
|
|
6
|
+
export declare function dashboardUserLink({ userName }: {
|
|
7
|
+
userName: string;
|
|
8
|
+
}): string;
|
|
9
|
+
export declare function dashboardAssetLink({ userName, assetName }: {
|
|
10
|
+
userName: string;
|
|
11
|
+
assetName: string;
|
|
12
|
+
}): string;
|
|
13
|
+
export declare function dashboardAssetCommentLink({ userName, assetName, commentHash, }: {
|
|
14
|
+
userName: string;
|
|
15
|
+
assetName: string;
|
|
16
|
+
commentHash: string;
|
|
17
|
+
}): string;
|
|
18
|
+
export declare function dashboardSettingsInvitesLink(): string;
|
|
19
|
+
//# sourceMappingURL=dashboardLinks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboardLinks.d.ts","sources":["../../src/lib/dashboardLinks.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,sBAAsB,QAA0C,CAAC;AAC9E,eAAO,MAAM,uBAAuB,QAAiE,CAAC;AACtG,eAAO,MAAM,8BAA8B,QAE1C,CAAC;AACF,eAAO,MAAM,iCAAiC,QAA0B,CAAC;AAEzE,eAAO,MAAM,yBAAyB,EAAE,MAAM,EAK7C,CAAC;AASF,wBAAgB,iBAAiB,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAG5E;AAED,wBAAgB,kBAAkB,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAG3G;AAED,wBAAgB,yBAAyB,CAAC,EACxC,QAAQ,EACR,SAAS,EACT,WAAW,GACZ,EAAE;IACD,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB,GAAG,MAAM,CAGT;AAED,wBAAgB,4BAA4B,IAAI,MAAM,CAGrD"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { coreEntityNameRegex } from './schemas.js';
|
|
2
|
+
// Comment hash allows alphanumeric IDs (e.g. numeric comment.id or string "test")
|
|
3
|
+
const commentHashRegex = '[a-zA-Z0-9][a-zA-Z0-9-]*';
|
|
4
|
+
// Validation regexes for dashboard link paths (include leading slash to match actual link format)
|
|
5
|
+
export const dashboardUserLinkRegex = new RegExp(`^/${coreEntityNameRegex}$`);
|
|
6
|
+
export const dashboardAssetLinkRegex = new RegExp(`^/${coreEntityNameRegex}/${coreEntityNameRegex}$`);
|
|
7
|
+
export const dashboardAssetCommentLinkRegex = new RegExp(`^/${coreEntityNameRegex}/${coreEntityNameRegex}#comment-${commentHashRegex}$`);
|
|
8
|
+
export const dashboardSettingsInvitesLinkRegex = /^\/settings\/invites$/;
|
|
9
|
+
export const validDashboardLinkTargets = [
|
|
10
|
+
dashboardUserLinkRegex,
|
|
11
|
+
dashboardAssetLinkRegex,
|
|
12
|
+
dashboardAssetCommentLinkRegex,
|
|
13
|
+
dashboardSettingsInvitesLinkRegex,
|
|
14
|
+
];
|
|
15
|
+
function validateAndReturn(path, regex) {
|
|
16
|
+
if (!regex.test(path)) {
|
|
17
|
+
throw new Error(`Invalid dashboard link: ${path}`);
|
|
18
|
+
}
|
|
19
|
+
return path;
|
|
20
|
+
}
|
|
21
|
+
export function dashboardUserLink({ userName }) {
|
|
22
|
+
const path = `/${userName}`;
|
|
23
|
+
return validateAndReturn(path, dashboardUserLinkRegex);
|
|
24
|
+
}
|
|
25
|
+
export function dashboardAssetLink({ userName, assetName }) {
|
|
26
|
+
const path = `/${userName}/${assetName}`;
|
|
27
|
+
return validateAndReturn(path, dashboardAssetLinkRegex);
|
|
28
|
+
}
|
|
29
|
+
export function dashboardAssetCommentLink({ userName, assetName, commentHash, }) {
|
|
30
|
+
const path = `/${userName}/${assetName}#comment-${commentHash}`;
|
|
31
|
+
return validateAndReturn(path, dashboardAssetCommentLinkRegex);
|
|
32
|
+
}
|
|
33
|
+
export function dashboardSettingsInvitesLink() {
|
|
34
|
+
const path = '/settings/invites';
|
|
35
|
+
return validateAndReturn(path, dashboardSettingsInvitesLinkRegex);
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=dashboardLinks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboardLinks.js","sources":["../../src/lib/dashboardLinks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEnD,kFAAkF;AAClF,MAAM,gBAAgB,GAAG,0BAA0B,CAAC;AAEpD,kGAAkG;AAClG,MAAM,CAAC,MAAM,sBAAsB,GAAG,IAAI,MAAM,CAAC,KAAK,mBAAmB,GAAG,CAAC,CAAC;AAC9E,MAAM,CAAC,MAAM,uBAAuB,GAAG,IAAI,MAAM,CAAC,KAAK,mBAAmB,IAAI,mBAAmB,GAAG,CAAC,CAAC;AACtG,MAAM,CAAC,MAAM,8BAA8B,GAAG,IAAI,MAAM,CACtD,KAAK,mBAAmB,IAAI,mBAAmB,YAAY,gBAAgB,GAAG,CAC/E,CAAC;AACF,MAAM,CAAC,MAAM,iCAAiC,GAAG,uBAAuB,CAAC;AAEzE,MAAM,CAAC,MAAM,yBAAyB,GAAa;IACjD,sBAAsB;IACtB,uBAAuB;IACvB,8BAA8B;IAC9B,iCAAiC;CAClC,CAAC;AAEF,SAAS,iBAAiB,CAAC,IAAY,EAAE,KAAa;IACpD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,2BAA2B,IAAI,EAAE,CAAC,CAAC;IACrD,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,EAAE,QAAQ,EAAwB;IAClE,MAAM,IAAI,GAAG,IAAI,QAAQ,EAAE,CAAC;IAC5B,OAAO,iBAAiB,CAAC,IAAI,EAAE,sBAAsB,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,EAAE,QAAQ,EAAE,SAAS,EAA2C;IACjG,MAAM,IAAI,GAAG,IAAI,QAAQ,IAAI,SAAS,EAAE,CAAC;IACzC,OAAO,iBAAiB,CAAC,IAAI,EAAE,uBAAuB,CAAC,CAAC;AAC1D,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,EACxC,QAAQ,EACR,SAAS,EACT,WAAW,GAKZ;IACC,MAAM,IAAI,GAAG,IAAI,QAAQ,IAAI,SAAS,YAAY,WAAW,EAAE,CAAC;IAChE,OAAO,iBAAiB,CAAC,IAAI,EAAE,8BAA8B,CAAC,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,4BAA4B;IAC1C,MAAM,IAAI,GAAG,mBAAmB,CAAC;IACjC,OAAO,iBAAiB,CAAC,IAAI,EAAE,iCAAiC,CAAC,CAAC;AACpE,CAAC"}
|