@secondlayer/sdk 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +53 -24
- package/dist/index.js +79 -57
- package/dist/index.js.map +8 -5
- package/dist/streams/index.d.ts +34 -0
- package/dist/streams/index.js +142 -0
- package/dist/streams/index.js.map +12 -0
- package/dist/views/index.d.ts +34 -0
- package/dist/{client.js → views/index.js} +36 -96
- package/dist/views/index.js.map +12 -0
- package/package.json +7 -7
- package/dist/client.d.ts +0 -48
- package/dist/client.js.map +0 -11
- package/dist/errors.d.ts +0 -5
- package/dist/errors.js +0 -15
- package/dist/errors.js.map +0 -10
package/dist/index.d.ts
CHANGED
|
@@ -1,52 +1,81 @@
|
|
|
1
|
-
import { CreateStream, UpdateStream, StreamResponse, CreateStreamResponse, ListStreamsResponse, BulkPauseResponse, BulkResumeResponse
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
interface StreamsClientOptions {
|
|
1
|
+
import { CreateStream, UpdateStream, StreamResponse, CreateStreamResponse, ListStreamsResponse, BulkPauseResponse, BulkResumeResponse } from "@secondlayer/shared/schemas";
|
|
2
|
+
interface SecondLayerOptions {
|
|
3
|
+
/** Base URL of the Secondlayer API (trailing slashes are stripped). */
|
|
5
4
|
baseUrl: string;
|
|
5
|
+
/** Bearer token for authenticated requests. */
|
|
6
6
|
apiKey?: string;
|
|
7
7
|
}
|
|
8
|
-
declare class
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
constructor(options
|
|
8
|
+
declare abstract class BaseClient {
|
|
9
|
+
protected baseUrl: string;
|
|
10
|
+
protected apiKey?: string;
|
|
11
|
+
constructor(options?: Partial<SecondLayerOptions>);
|
|
12
12
|
static authHeaders(apiKey?: string): Record<string, string>;
|
|
13
|
-
|
|
13
|
+
protected request<T>(method: string, path: string, body?: unknown): Promise<T>;
|
|
14
|
+
}
|
|
15
|
+
declare class Streams extends BaseClient {
|
|
16
|
+
private requestWithStreamId;
|
|
14
17
|
resolveStreamId(partialId: string): Promise<string>;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
create(data: CreateStream): Promise<CreateStreamResponse>;
|
|
19
|
+
update(id: string, data: UpdateStream): Promise<StreamResponse>;
|
|
20
|
+
updateByName(name: string, data: CreateStream): Promise<StreamResponse>;
|
|
21
|
+
list(params?: {
|
|
19
22
|
status?: string
|
|
20
23
|
}): Promise<ListStreamsResponse>;
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
get(id: string): Promise<StreamResponse>;
|
|
25
|
+
delete(id: string): Promise<void>;
|
|
26
|
+
enable(id: string): Promise<StreamResponse>;
|
|
27
|
+
disable(id: string): Promise<StreamResponse>;
|
|
25
28
|
rotateSecret(id: string): Promise<{
|
|
26
29
|
secret: string
|
|
27
30
|
}>;
|
|
28
31
|
pauseAll(): Promise<BulkPauseResponse>;
|
|
29
32
|
resumeAll(): Promise<BulkResumeResponse>;
|
|
30
|
-
|
|
31
|
-
|
|
33
|
+
}
|
|
34
|
+
import { ViewSummary, ViewDetail, ViewQueryParams, ReindexResponse } from "@secondlayer/shared/schemas";
|
|
35
|
+
import { DeployViewRequest, DeployViewResponse } from "@secondlayer/shared/schemas/views";
|
|
36
|
+
declare class Views extends BaseClient {
|
|
37
|
+
list(): Promise<{
|
|
32
38
|
data: ViewSummary[]
|
|
33
39
|
}>;
|
|
34
|
-
|
|
35
|
-
|
|
40
|
+
get(name: string): Promise<ViewDetail>;
|
|
41
|
+
reindex(name: string, options?: {
|
|
36
42
|
fromBlock?: number
|
|
37
43
|
toBlock?: number
|
|
38
44
|
}): Promise<ReindexResponse>;
|
|
39
|
-
|
|
45
|
+
delete(name: string): Promise<{
|
|
40
46
|
message: string
|
|
41
47
|
}>;
|
|
42
|
-
|
|
48
|
+
deploy(data: DeployViewRequest): Promise<DeployViewResponse>;
|
|
43
49
|
queryTable(name: string, table: string, params?: ViewQueryParams): Promise<unknown[]>;
|
|
44
50
|
queryTableCount(name: string, table: string, params?: ViewQueryParams): Promise<{
|
|
45
51
|
count: number
|
|
46
52
|
}>;
|
|
47
53
|
}
|
|
54
|
+
import { QueueStats } from "@secondlayer/shared/types";
|
|
55
|
+
declare class SecondLayer extends BaseClient {
|
|
56
|
+
readonly streams: Streams;
|
|
57
|
+
readonly views: Views;
|
|
58
|
+
constructor(options?: Partial<SecondLayerOptions>);
|
|
59
|
+
getQueueStats(): Promise<QueueStats>;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Error thrown by {@link SecondLayer} when an API request fails.
|
|
63
|
+
* Includes the HTTP status code for programmatic error handling.
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```ts
|
|
67
|
+
* try {
|
|
68
|
+
* await client.streams.get("abc123");
|
|
69
|
+
* } catch (err) {
|
|
70
|
+
* if (err instanceof ApiError && err.status === 404) {
|
|
71
|
+
* console.log("Stream not found");
|
|
72
|
+
* }
|
|
73
|
+
* }
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
48
76
|
declare class ApiError extends Error {
|
|
77
|
+
/** HTTP status code (0 for network errors). */
|
|
49
78
|
status: number;
|
|
50
79
|
constructor(status: number, message: string);
|
|
51
80
|
}
|
|
52
|
-
export {
|
|
81
|
+
export { Views, Streams, SecondLayerOptions, SecondLayer, ApiError };
|
package/dist/index.js
CHANGED
|
@@ -8,12 +8,14 @@ class ApiError extends Error {
|
|
|
8
8
|
}
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
// src/
|
|
12
|
-
|
|
11
|
+
// src/base.ts
|
|
12
|
+
var DEFAULT_BASE_URL = "https://api.secondlayer.tools";
|
|
13
|
+
|
|
14
|
+
class BaseClient {
|
|
13
15
|
baseUrl;
|
|
14
16
|
apiKey;
|
|
15
|
-
constructor(options) {
|
|
16
|
-
this.baseUrl = options.baseUrl.replace(/\/+$/, "");
|
|
17
|
+
constructor(options = {}) {
|
|
18
|
+
this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
17
19
|
this.apiKey = options.apiKey;
|
|
18
20
|
}
|
|
19
21
|
static authHeaders(apiKey) {
|
|
@@ -25,7 +27,7 @@ class StreamsClient {
|
|
|
25
27
|
}
|
|
26
28
|
async request(method, path, body) {
|
|
27
29
|
const url = `${this.baseUrl}${path}`;
|
|
28
|
-
const headers =
|
|
30
|
+
const headers = BaseClient.authHeaders(this.apiKey);
|
|
29
31
|
let response;
|
|
30
32
|
try {
|
|
31
33
|
response = await fetch(url, {
|
|
@@ -64,12 +66,21 @@ class StreamsClient {
|
|
|
64
66
|
}
|
|
65
67
|
return response.json();
|
|
66
68
|
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// src/streams/client.ts
|
|
72
|
+
class Streams extends BaseClient {
|
|
73
|
+
async requestWithStreamId(method, pathTemplate, id, body) {
|
|
74
|
+
const fullId = await this.resolveStreamId(id);
|
|
75
|
+
return this.request(method, pathTemplate(fullId), body);
|
|
76
|
+
}
|
|
67
77
|
async resolveStreamId(partialId) {
|
|
68
78
|
if (partialId.length === 36 && partialId.includes("-")) {
|
|
69
79
|
return partialId;
|
|
70
80
|
}
|
|
71
|
-
const { streams } = await this.
|
|
72
|
-
const
|
|
81
|
+
const { streams } = await this.list();
|
|
82
|
+
const typedStreams = streams;
|
|
83
|
+
const matches = typedStreams.filter((s) => s.id.startsWith(partialId));
|
|
73
84
|
if (matches.length === 0) {
|
|
74
85
|
throw new ApiError(404, `No stream found matching "${partialId}"`);
|
|
75
86
|
}
|
|
@@ -78,22 +89,22 @@ class StreamsClient {
|
|
|
78
89
|
}
|
|
79
90
|
return matches[0].id;
|
|
80
91
|
}
|
|
81
|
-
async
|
|
92
|
+
async create(data) {
|
|
82
93
|
return this.request("POST", "/api/streams", data);
|
|
83
94
|
}
|
|
84
|
-
async
|
|
85
|
-
|
|
86
|
-
return this.request("PATCH", `/api/streams/${fullId}`, data);
|
|
95
|
+
async update(id, data) {
|
|
96
|
+
return this.requestWithStreamId("PATCH", (id2) => `/api/streams/${id2}`, id, data);
|
|
87
97
|
}
|
|
88
|
-
async
|
|
89
|
-
const { streams } = await this.
|
|
90
|
-
const
|
|
98
|
+
async updateByName(name, data) {
|
|
99
|
+
const { streams } = await this.list();
|
|
100
|
+
const typedStreams = streams;
|
|
101
|
+
const existing = typedStreams.find((s) => s.name === name);
|
|
91
102
|
if (!existing) {
|
|
92
103
|
throw new ApiError(404, `Stream with name "${name}" not found`);
|
|
93
104
|
}
|
|
94
|
-
return this.
|
|
105
|
+
return this.update(existing.id, data);
|
|
95
106
|
}
|
|
96
|
-
async
|
|
107
|
+
async list(params) {
|
|
97
108
|
const searchParams = new URLSearchParams;
|
|
98
109
|
if (params?.status)
|
|
99
110
|
searchParams.set("status", params.status);
|
|
@@ -101,25 +112,20 @@ class StreamsClient {
|
|
|
101
112
|
const path = query ? `/api/streams?${query}` : "/api/streams";
|
|
102
113
|
return this.request("GET", path);
|
|
103
114
|
}
|
|
104
|
-
async
|
|
105
|
-
|
|
106
|
-
return this.request("GET", `/api/streams/${fullId}`);
|
|
115
|
+
async get(id) {
|
|
116
|
+
return this.requestWithStreamId("GET", (id2) => `/api/streams/${id2}`, id);
|
|
107
117
|
}
|
|
108
|
-
async
|
|
109
|
-
|
|
110
|
-
return this.request("DELETE", `/api/streams/${fullId}`);
|
|
118
|
+
async delete(id) {
|
|
119
|
+
return this.requestWithStreamId("DELETE", (id2) => `/api/streams/${id2}`, id);
|
|
111
120
|
}
|
|
112
|
-
async
|
|
113
|
-
|
|
114
|
-
return this.request("POST", `/api/streams/${fullId}/enable`);
|
|
121
|
+
async enable(id) {
|
|
122
|
+
return this.requestWithStreamId("POST", (id2) => `/api/streams/${id2}/enable`, id);
|
|
115
123
|
}
|
|
116
|
-
async
|
|
117
|
-
|
|
118
|
-
return this.request("POST", `/api/streams/${fullId}/disable`);
|
|
124
|
+
async disable(id) {
|
|
125
|
+
return this.requestWithStreamId("POST", (id2) => `/api/streams/${id2}/disable`, id);
|
|
119
126
|
}
|
|
120
127
|
async rotateSecret(id) {
|
|
121
|
-
|
|
122
|
-
return this.request("POST", `/api/streams/${fullId}/rotate-secret`);
|
|
128
|
+
return this.requestWithStreamId("POST", (id2) => `/api/streams/${id2}/rotate-secret`, id);
|
|
123
129
|
}
|
|
124
130
|
async pauseAll() {
|
|
125
131
|
return this.request("POST", "/api/streams/pause");
|
|
@@ -127,32 +133,8 @@ class StreamsClient {
|
|
|
127
133
|
async resumeAll() {
|
|
128
134
|
return this.request("POST", "/api/streams/resume");
|
|
129
135
|
}
|
|
130
|
-
async getQueueStats() {
|
|
131
|
-
const status = await this.request("GET", "/status");
|
|
132
|
-
return status.queue;
|
|
133
|
-
}
|
|
134
|
-
async listViews() {
|
|
135
|
-
return this.request("GET", "/api/views");
|
|
136
|
-
}
|
|
137
|
-
async getView(name) {
|
|
138
|
-
return this.request("GET", `/api/views/${name}`);
|
|
139
|
-
}
|
|
140
|
-
async reindexView(name, options) {
|
|
141
|
-
return this.request("POST", `/api/views/${name}/reindex`, options);
|
|
142
|
-
}
|
|
143
|
-
async deleteView(name) {
|
|
144
|
-
return this.request("DELETE", `/api/views/${name}`);
|
|
145
|
-
}
|
|
146
|
-
async deployView(data) {
|
|
147
|
-
return this.request("POST", "/api/views", data);
|
|
148
|
-
}
|
|
149
|
-
async queryTable(name, table, params = {}) {
|
|
150
|
-
return this.request("GET", `/api/views/${name}/${table}${buildViewQueryString(params)}`);
|
|
151
|
-
}
|
|
152
|
-
async queryTableCount(name, table, params = {}) {
|
|
153
|
-
return this.request("GET", `/api/views/${name}/${table}/count${buildViewQueryString(params)}`);
|
|
154
|
-
}
|
|
155
136
|
}
|
|
137
|
+
// src/views/client.ts
|
|
156
138
|
function buildViewQueryString(params) {
|
|
157
139
|
const qs = new URLSearchParams;
|
|
158
140
|
if (params.sort)
|
|
@@ -173,10 +155,50 @@ function buildViewQueryString(params) {
|
|
|
173
155
|
const str = qs.toString();
|
|
174
156
|
return str ? `?${str}` : "";
|
|
175
157
|
}
|
|
158
|
+
|
|
159
|
+
class Views extends BaseClient {
|
|
160
|
+
async list() {
|
|
161
|
+
return this.request("GET", "/api/views");
|
|
162
|
+
}
|
|
163
|
+
async get(name) {
|
|
164
|
+
return this.request("GET", `/api/views/${name}`);
|
|
165
|
+
}
|
|
166
|
+
async reindex(name, options) {
|
|
167
|
+
return this.request("POST", `/api/views/${name}/reindex`, options);
|
|
168
|
+
}
|
|
169
|
+
async delete(name) {
|
|
170
|
+
return this.request("DELETE", `/api/views/${name}`);
|
|
171
|
+
}
|
|
172
|
+
async deploy(data) {
|
|
173
|
+
return this.request("POST", "/api/views", data);
|
|
174
|
+
}
|
|
175
|
+
async queryTable(name, table, params = {}) {
|
|
176
|
+
return this.request("GET", `/api/views/${name}/${table}${buildViewQueryString(params)}`);
|
|
177
|
+
}
|
|
178
|
+
async queryTableCount(name, table, params = {}) {
|
|
179
|
+
return this.request("GET", `/api/views/${name}/${table}/count${buildViewQueryString(params)}`);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
// src/client.ts
|
|
183
|
+
class SecondLayer extends BaseClient {
|
|
184
|
+
streams;
|
|
185
|
+
views;
|
|
186
|
+
constructor(options = {}) {
|
|
187
|
+
super(options);
|
|
188
|
+
this.streams = new Streams(options);
|
|
189
|
+
this.views = new Views(options);
|
|
190
|
+
}
|
|
191
|
+
async getQueueStats() {
|
|
192
|
+
const status = await this.request("GET", "/status");
|
|
193
|
+
return status.queue;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
176
196
|
export {
|
|
177
|
-
|
|
197
|
+
Views,
|
|
198
|
+
Streams,
|
|
199
|
+
SecondLayer,
|
|
178
200
|
ApiError
|
|
179
201
|
};
|
|
180
202
|
|
|
181
|
-
//# debugId=
|
|
203
|
+
//# debugId=3185A873B53583DC64756E2164756E21
|
|
182
204
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../src/errors.ts", "../src/client.ts"],
|
|
3
|
+
"sources": ["../src/errors.ts", "../src/base.ts", "../src/streams/client.ts", "../src/views/client.ts", "../src/client.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"
|
|
6
|
-
"import
|
|
5
|
+
"/**\n * Error thrown by {@link SecondLayer} when an API request fails.\n * Includes the HTTP status code for programmatic error handling.\n *\n * @example\n * ```ts\n * try {\n * await client.streams.get(\"abc123\");\n * } catch (err) {\n * if (err instanceof ApiError && err.status === 404) {\n * console.log(\"Stream not found\");\n * }\n * }\n * ```\n */\nexport class ApiError extends Error {\n constructor(\n /** HTTP status code (0 for network errors). */\n public status: number,\n message: string\n ) {\n super(message);\n this.name = \"ApiError\";\n }\n}\n",
|
|
6
|
+
"import { ApiError } from \"./errors.ts\";\n\nexport interface SecondLayerOptions {\n /** Base URL of the Secondlayer API (trailing slashes are stripped). */\n baseUrl: string;\n /** Bearer token for authenticated requests. */\n apiKey?: string;\n}\n\nconst DEFAULT_BASE_URL = \"https://api.secondlayer.tools\";\n\nexport abstract class BaseClient {\n protected baseUrl: string;\n protected apiKey?: string;\n\n constructor(options: Partial<SecondLayerOptions> = {}) {\n this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.apiKey = options.apiKey;\n }\n\n static authHeaders(apiKey?: string): Record<string, string> {\n const headers: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (apiKey) {\n headers[\"Authorization\"] = `Bearer ${apiKey}`;\n }\n return headers;\n }\n\n protected async request<T>(method: string, path: string, body?: unknown): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n const headers = BaseClient.authHeaders(this.apiKey);\n\n let response: Response;\n try {\n response = await fetch(url, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n });\n } catch {\n throw new ApiError(0, `Cannot reach API at ${this.baseUrl}. Check your connection or try again.`);\n }\n\n if (!response.ok) {\n if (response.status === 401) {\n throw new ApiError(401, \"API key invalid or expired.\");\n }\n\n if (response.status === 429) {\n const retryAfter = response.headers.get(\"Retry-After\");\n const msg = retryAfter\n ? `Rate limited. Wait ${retryAfter} seconds.`\n : \"Rate limited. Try again later.\";\n throw new ApiError(429, msg);\n }\n\n if (response.status >= 500) {\n throw new ApiError(response.status, `Server error. Try again or check status at ${this.baseUrl}/health`);\n }\n\n const errorBody = await response.text();\n let message = `HTTP ${response.status}`;\n try {\n const json = JSON.parse(errorBody);\n message = json.error || json.message || message;\n } catch {\n if (errorBody) message = errorBody;\n }\n throw new ApiError(response.status, message);\n }\n\n if (response.status === 204) {\n return undefined as T;\n }\n\n return response.json() as Promise<T>;\n }\n}\n",
|
|
7
|
+
"import type {\n CreateStream,\n UpdateStream,\n StreamResponse,\n CreateStreamResponse,\n ListStreamsResponse,\n BulkPauseResponse,\n BulkResumeResponse,\n} from \"@secondlayer/shared/schemas\";\nimport { ApiError } from \"../errors.ts\";\nimport { BaseClient } from \"../base.ts\";\n\nexport class Streams extends BaseClient {\n private async requestWithStreamId<T>(\n method: string,\n pathTemplate: (id: string) => string,\n id: string,\n body?: unknown\n ): Promise<T> {\n const fullId = await this.resolveStreamId(id);\n return this.request<T>(method, pathTemplate(fullId), body);\n }\n\n async resolveStreamId(partialId: string): Promise<string> {\n if (partialId.length === 36 && partialId.includes(\"-\")) {\n return partialId;\n }\n\n const { streams } = await this.list();\n const typedStreams = streams as { id: string }[];\n const matches = typedStreams.filter((s) => s.id.startsWith(partialId));\n\n if (matches.length === 0) {\n throw new ApiError(404, `No stream found matching \"${partialId}\"`);\n }\n if (matches.length > 1) {\n throw new ApiError(400, `Multiple streams match \"${partialId}\": ${matches.map((s) => s.id.slice(0, 8)).join(\", \")}`);\n }\n\n return matches[0]!.id;\n }\n\n async create(data: CreateStream): Promise<CreateStreamResponse> {\n return this.request<CreateStreamResponse>(\"POST\", \"/api/streams\", data);\n }\n\n async update(id: string, data: UpdateStream): Promise<StreamResponse> {\n return this.requestWithStreamId(\"PATCH\", (id) => `/api/streams/${id}`, id, data);\n }\n\n async updateByName(name: string, data: CreateStream): Promise<StreamResponse> {\n const { streams } = await this.list();\n const typedStreams = streams as { id: string; name: string }[];\n const existing = typedStreams.find((s) => s.name === name);\n if (!existing) {\n throw new ApiError(404, `Stream with name \"${name}\" not found`);\n }\n return this.update(existing.id, data);\n }\n\n async list(params?: { status?: string }): Promise<ListStreamsResponse> {\n const searchParams = new URLSearchParams();\n if (params?.status) searchParams.set(\"status\", params.status);\n const query = searchParams.toString();\n const path = query ? `/api/streams?${query}` : \"/api/streams\";\n return this.request<ListStreamsResponse>(\"GET\", path);\n }\n\n async get(id: string): Promise<StreamResponse> {\n return this.requestWithStreamId(\"GET\", (id) => `/api/streams/${id}`, id);\n }\n\n async delete(id: string): Promise<void> {\n return this.requestWithStreamId(\"DELETE\", (id) => `/api/streams/${id}`, id);\n }\n\n async enable(id: string): Promise<StreamResponse> {\n return this.requestWithStreamId(\"POST\", (id) => `/api/streams/${id}/enable`, id);\n }\n\n async disable(id: string): Promise<StreamResponse> {\n return this.requestWithStreamId(\"POST\", (id) => `/api/streams/${id}/disable`, id);\n }\n\n async rotateSecret(id: string): Promise<{ secret: string }> {\n return this.requestWithStreamId(\"POST\", (id) => `/api/streams/${id}/rotate-secret`, id);\n }\n\n async pauseAll(): Promise<BulkPauseResponse> {\n return this.request<BulkPauseResponse>(\"POST\", \"/api/streams/pause\");\n }\n\n async resumeAll(): Promise<BulkResumeResponse> {\n return this.request<BulkResumeResponse>(\"POST\", \"/api/streams/resume\");\n }\n}\n",
|
|
8
|
+
"import type {\n ViewSummary,\n ViewDetail,\n ViewQueryParams,\n ReindexResponse,\n} from \"@secondlayer/shared/schemas\";\nimport type { DeployViewRequest, DeployViewResponse } from \"@secondlayer/shared/schemas/views\";\nimport { BaseClient } from \"../base.ts\";\n\nfunction buildViewQueryString(params: ViewQueryParams): string {\n const qs = new URLSearchParams();\n if (params.sort) qs.set(\"_sort\", params.sort);\n if (params.order) qs.set(\"_order\", params.order);\n if (params.limit !== undefined) qs.set(\"_limit\", String(params.limit));\n if (params.offset !== undefined) qs.set(\"_offset\", String(params.offset));\n if (params.fields) qs.set(\"_fields\", params.fields);\n if (params.filters) {\n for (const [key, value] of Object.entries(params.filters)) {\n qs.set(key, value);\n }\n }\n const str = qs.toString();\n return str ? `?${str}` : \"\";\n}\n\nexport class Views extends BaseClient {\n async list(): Promise<{ data: ViewSummary[] }> {\n return this.request<{ data: ViewSummary[] }>(\"GET\", \"/api/views\");\n }\n\n async get(name: string): Promise<ViewDetail> {\n return this.request<ViewDetail>(\"GET\", `/api/views/${name}`);\n }\n\n async reindex(name: string, options?: { fromBlock?: number; toBlock?: number }): Promise<ReindexResponse> {\n return this.request<ReindexResponse>(\"POST\", `/api/views/${name}/reindex`, options);\n }\n\n async delete(name: string): Promise<{ message: string }> {\n return this.request<{ message: string }>(\"DELETE\", `/api/views/${name}`);\n }\n\n async deploy(data: DeployViewRequest): Promise<DeployViewResponse> {\n return this.request<DeployViewResponse>(\"POST\", \"/api/views\", data);\n }\n\n async queryTable(name: string, table: string, params: ViewQueryParams = {}): Promise<unknown[]> {\n return this.request<unknown[]>(\"GET\", `/api/views/${name}/${table}${buildViewQueryString(params)}`);\n }\n\n async queryTableCount(name: string, table: string, params: ViewQueryParams = {}): Promise<{ count: number }> {\n return this.request<{ count: number }>(\"GET\", `/api/views/${name}/${table}/count${buildViewQueryString(params)}`);\n }\n}\n",
|
|
9
|
+
"import type { QueueStats } from \"@secondlayer/shared/types\";\nimport { BaseClient } from \"./base.ts\";\nimport type { SecondLayerOptions } from \"./base.ts\";\nimport { Streams } from \"./streams/client.ts\";\nimport { Views } from \"./views/client.ts\";\n\nexport class SecondLayer extends BaseClient {\n readonly streams: Streams;\n readonly views: Views;\n\n constructor(options: Partial<SecondLayerOptions> = {}) {\n super(options);\n this.streams = new Streams(options);\n this.views = new Views(options);\n }\n\n async getQueueStats(): Promise<QueueStats> {\n const status = await this.request<{ queue: QueueStats }>(\"GET\", \"/status\");\n return status.queue;\n }\n}\n"
|
|
7
10
|
],
|
|
8
|
-
"mappings": ";
|
|
9
|
-
"debugId": "
|
|
11
|
+
"mappings": "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",
|
|
12
|
+
"debugId": "3185A873B53583DC64756E2164756E21",
|
|
10
13
|
"names": []
|
|
11
14
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { CreateStream, UpdateStream, StreamResponse, CreateStreamResponse, ListStreamsResponse, BulkPauseResponse, BulkResumeResponse } from "@secondlayer/shared/schemas";
|
|
2
|
+
interface SecondLayerOptions {
|
|
3
|
+
/** Base URL of the Secondlayer API (trailing slashes are stripped). */
|
|
4
|
+
baseUrl: string;
|
|
5
|
+
/** Bearer token for authenticated requests. */
|
|
6
|
+
apiKey?: string;
|
|
7
|
+
}
|
|
8
|
+
declare abstract class BaseClient {
|
|
9
|
+
protected baseUrl: string;
|
|
10
|
+
protected apiKey?: string;
|
|
11
|
+
constructor(options?: Partial<SecondLayerOptions>);
|
|
12
|
+
static authHeaders(apiKey?: string): Record<string, string>;
|
|
13
|
+
protected request<T>(method: string, path: string, body?: unknown): Promise<T>;
|
|
14
|
+
}
|
|
15
|
+
declare class Streams extends BaseClient {
|
|
16
|
+
private requestWithStreamId;
|
|
17
|
+
resolveStreamId(partialId: string): Promise<string>;
|
|
18
|
+
create(data: CreateStream): Promise<CreateStreamResponse>;
|
|
19
|
+
update(id: string, data: UpdateStream): Promise<StreamResponse>;
|
|
20
|
+
updateByName(name: string, data: CreateStream): Promise<StreamResponse>;
|
|
21
|
+
list(params?: {
|
|
22
|
+
status?: string
|
|
23
|
+
}): Promise<ListStreamsResponse>;
|
|
24
|
+
get(id: string): Promise<StreamResponse>;
|
|
25
|
+
delete(id: string): Promise<void>;
|
|
26
|
+
enable(id: string): Promise<StreamResponse>;
|
|
27
|
+
disable(id: string): Promise<StreamResponse>;
|
|
28
|
+
rotateSecret(id: string): Promise<{
|
|
29
|
+
secret: string
|
|
30
|
+
}>;
|
|
31
|
+
pauseAll(): Promise<BulkPauseResponse>;
|
|
32
|
+
resumeAll(): Promise<BulkResumeResponse>;
|
|
33
|
+
}
|
|
34
|
+
export { Streams, SecondLayerOptions };
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
// src/errors.ts
|
|
2
|
+
class ApiError extends Error {
|
|
3
|
+
status;
|
|
4
|
+
constructor(status, message) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.status = status;
|
|
7
|
+
this.name = "ApiError";
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// src/base.ts
|
|
12
|
+
var DEFAULT_BASE_URL = "https://api.secondlayer.tools";
|
|
13
|
+
|
|
14
|
+
class BaseClient {
|
|
15
|
+
baseUrl;
|
|
16
|
+
apiKey;
|
|
17
|
+
constructor(options = {}) {
|
|
18
|
+
this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
19
|
+
this.apiKey = options.apiKey;
|
|
20
|
+
}
|
|
21
|
+
static authHeaders(apiKey) {
|
|
22
|
+
const headers = { "Content-Type": "application/json" };
|
|
23
|
+
if (apiKey) {
|
|
24
|
+
headers["Authorization"] = `Bearer ${apiKey}`;
|
|
25
|
+
}
|
|
26
|
+
return headers;
|
|
27
|
+
}
|
|
28
|
+
async request(method, path, body) {
|
|
29
|
+
const url = `${this.baseUrl}${path}`;
|
|
30
|
+
const headers = BaseClient.authHeaders(this.apiKey);
|
|
31
|
+
let response;
|
|
32
|
+
try {
|
|
33
|
+
response = await fetch(url, {
|
|
34
|
+
method,
|
|
35
|
+
headers,
|
|
36
|
+
body: body ? JSON.stringify(body) : undefined
|
|
37
|
+
});
|
|
38
|
+
} catch {
|
|
39
|
+
throw new ApiError(0, `Cannot reach API at ${this.baseUrl}. Check your connection or try again.`);
|
|
40
|
+
}
|
|
41
|
+
if (!response.ok) {
|
|
42
|
+
if (response.status === 401) {
|
|
43
|
+
throw new ApiError(401, "API key invalid or expired.");
|
|
44
|
+
}
|
|
45
|
+
if (response.status === 429) {
|
|
46
|
+
const retryAfter = response.headers.get("Retry-After");
|
|
47
|
+
const msg = retryAfter ? `Rate limited. Wait ${retryAfter} seconds.` : "Rate limited. Try again later.";
|
|
48
|
+
throw new ApiError(429, msg);
|
|
49
|
+
}
|
|
50
|
+
if (response.status >= 500) {
|
|
51
|
+
throw new ApiError(response.status, `Server error. Try again or check status at ${this.baseUrl}/health`);
|
|
52
|
+
}
|
|
53
|
+
const errorBody = await response.text();
|
|
54
|
+
let message = `HTTP ${response.status}`;
|
|
55
|
+
try {
|
|
56
|
+
const json = JSON.parse(errorBody);
|
|
57
|
+
message = json.error || json.message || message;
|
|
58
|
+
} catch {
|
|
59
|
+
if (errorBody)
|
|
60
|
+
message = errorBody;
|
|
61
|
+
}
|
|
62
|
+
throw new ApiError(response.status, message);
|
|
63
|
+
}
|
|
64
|
+
if (response.status === 204) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
return response.json();
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// src/streams/client.ts
|
|
72
|
+
class Streams extends BaseClient {
|
|
73
|
+
async requestWithStreamId(method, pathTemplate, id, body) {
|
|
74
|
+
const fullId = await this.resolveStreamId(id);
|
|
75
|
+
return this.request(method, pathTemplate(fullId), body);
|
|
76
|
+
}
|
|
77
|
+
async resolveStreamId(partialId) {
|
|
78
|
+
if (partialId.length === 36 && partialId.includes("-")) {
|
|
79
|
+
return partialId;
|
|
80
|
+
}
|
|
81
|
+
const { streams } = await this.list();
|
|
82
|
+
const typedStreams = streams;
|
|
83
|
+
const matches = typedStreams.filter((s) => s.id.startsWith(partialId));
|
|
84
|
+
if (matches.length === 0) {
|
|
85
|
+
throw new ApiError(404, `No stream found matching "${partialId}"`);
|
|
86
|
+
}
|
|
87
|
+
if (matches.length > 1) {
|
|
88
|
+
throw new ApiError(400, `Multiple streams match "${partialId}": ${matches.map((s) => s.id.slice(0, 8)).join(", ")}`);
|
|
89
|
+
}
|
|
90
|
+
return matches[0].id;
|
|
91
|
+
}
|
|
92
|
+
async create(data) {
|
|
93
|
+
return this.request("POST", "/api/streams", data);
|
|
94
|
+
}
|
|
95
|
+
async update(id, data) {
|
|
96
|
+
return this.requestWithStreamId("PATCH", (id2) => `/api/streams/${id2}`, id, data);
|
|
97
|
+
}
|
|
98
|
+
async updateByName(name, data) {
|
|
99
|
+
const { streams } = await this.list();
|
|
100
|
+
const typedStreams = streams;
|
|
101
|
+
const existing = typedStreams.find((s) => s.name === name);
|
|
102
|
+
if (!existing) {
|
|
103
|
+
throw new ApiError(404, `Stream with name "${name}" not found`);
|
|
104
|
+
}
|
|
105
|
+
return this.update(existing.id, data);
|
|
106
|
+
}
|
|
107
|
+
async list(params) {
|
|
108
|
+
const searchParams = new URLSearchParams;
|
|
109
|
+
if (params?.status)
|
|
110
|
+
searchParams.set("status", params.status);
|
|
111
|
+
const query = searchParams.toString();
|
|
112
|
+
const path = query ? `/api/streams?${query}` : "/api/streams";
|
|
113
|
+
return this.request("GET", path);
|
|
114
|
+
}
|
|
115
|
+
async get(id) {
|
|
116
|
+
return this.requestWithStreamId("GET", (id2) => `/api/streams/${id2}`, id);
|
|
117
|
+
}
|
|
118
|
+
async delete(id) {
|
|
119
|
+
return this.requestWithStreamId("DELETE", (id2) => `/api/streams/${id2}`, id);
|
|
120
|
+
}
|
|
121
|
+
async enable(id) {
|
|
122
|
+
return this.requestWithStreamId("POST", (id2) => `/api/streams/${id2}/enable`, id);
|
|
123
|
+
}
|
|
124
|
+
async disable(id) {
|
|
125
|
+
return this.requestWithStreamId("POST", (id2) => `/api/streams/${id2}/disable`, id);
|
|
126
|
+
}
|
|
127
|
+
async rotateSecret(id) {
|
|
128
|
+
return this.requestWithStreamId("POST", (id2) => `/api/streams/${id2}/rotate-secret`, id);
|
|
129
|
+
}
|
|
130
|
+
async pauseAll() {
|
|
131
|
+
return this.request("POST", "/api/streams/pause");
|
|
132
|
+
}
|
|
133
|
+
async resumeAll() {
|
|
134
|
+
return this.request("POST", "/api/streams/resume");
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
export {
|
|
138
|
+
Streams
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
//# debugId=EFD3CCF7032CC87A64756E2164756E21
|
|
142
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/errors.ts", "../src/base.ts", "../src/streams/client.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"/**\n * Error thrown by {@link SecondLayer} when an API request fails.\n * Includes the HTTP status code for programmatic error handling.\n *\n * @example\n * ```ts\n * try {\n * await client.streams.get(\"abc123\");\n * } catch (err) {\n * if (err instanceof ApiError && err.status === 404) {\n * console.log(\"Stream not found\");\n * }\n * }\n * ```\n */\nexport class ApiError extends Error {\n constructor(\n /** HTTP status code (0 for network errors). */\n public status: number,\n message: string\n ) {\n super(message);\n this.name = \"ApiError\";\n }\n}\n",
|
|
6
|
+
"import { ApiError } from \"./errors.ts\";\n\nexport interface SecondLayerOptions {\n /** Base URL of the Secondlayer API (trailing slashes are stripped). */\n baseUrl: string;\n /** Bearer token for authenticated requests. */\n apiKey?: string;\n}\n\nconst DEFAULT_BASE_URL = \"https://api.secondlayer.tools\";\n\nexport abstract class BaseClient {\n protected baseUrl: string;\n protected apiKey?: string;\n\n constructor(options: Partial<SecondLayerOptions> = {}) {\n this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.apiKey = options.apiKey;\n }\n\n static authHeaders(apiKey?: string): Record<string, string> {\n const headers: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (apiKey) {\n headers[\"Authorization\"] = `Bearer ${apiKey}`;\n }\n return headers;\n }\n\n protected async request<T>(method: string, path: string, body?: unknown): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n const headers = BaseClient.authHeaders(this.apiKey);\n\n let response: Response;\n try {\n response = await fetch(url, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n });\n } catch {\n throw new ApiError(0, `Cannot reach API at ${this.baseUrl}. Check your connection or try again.`);\n }\n\n if (!response.ok) {\n if (response.status === 401) {\n throw new ApiError(401, \"API key invalid or expired.\");\n }\n\n if (response.status === 429) {\n const retryAfter = response.headers.get(\"Retry-After\");\n const msg = retryAfter\n ? `Rate limited. Wait ${retryAfter} seconds.`\n : \"Rate limited. Try again later.\";\n throw new ApiError(429, msg);\n }\n\n if (response.status >= 500) {\n throw new ApiError(response.status, `Server error. Try again or check status at ${this.baseUrl}/health`);\n }\n\n const errorBody = await response.text();\n let message = `HTTP ${response.status}`;\n try {\n const json = JSON.parse(errorBody);\n message = json.error || json.message || message;\n } catch {\n if (errorBody) message = errorBody;\n }\n throw new ApiError(response.status, message);\n }\n\n if (response.status === 204) {\n return undefined as T;\n }\n\n return response.json() as Promise<T>;\n }\n}\n",
|
|
7
|
+
"import type {\n CreateStream,\n UpdateStream,\n StreamResponse,\n CreateStreamResponse,\n ListStreamsResponse,\n BulkPauseResponse,\n BulkResumeResponse,\n} from \"@secondlayer/shared/schemas\";\nimport { ApiError } from \"../errors.ts\";\nimport { BaseClient } from \"../base.ts\";\n\nexport class Streams extends BaseClient {\n private async requestWithStreamId<T>(\n method: string,\n pathTemplate: (id: string) => string,\n id: string,\n body?: unknown\n ): Promise<T> {\n const fullId = await this.resolveStreamId(id);\n return this.request<T>(method, pathTemplate(fullId), body);\n }\n\n async resolveStreamId(partialId: string): Promise<string> {\n if (partialId.length === 36 && partialId.includes(\"-\")) {\n return partialId;\n }\n\n const { streams } = await this.list();\n const typedStreams = streams as { id: string }[];\n const matches = typedStreams.filter((s) => s.id.startsWith(partialId));\n\n if (matches.length === 0) {\n throw new ApiError(404, `No stream found matching \"${partialId}\"`);\n }\n if (matches.length > 1) {\n throw new ApiError(400, `Multiple streams match \"${partialId}\": ${matches.map((s) => s.id.slice(0, 8)).join(\", \")}`);\n }\n\n return matches[0]!.id;\n }\n\n async create(data: CreateStream): Promise<CreateStreamResponse> {\n return this.request<CreateStreamResponse>(\"POST\", \"/api/streams\", data);\n }\n\n async update(id: string, data: UpdateStream): Promise<StreamResponse> {\n return this.requestWithStreamId(\"PATCH\", (id) => `/api/streams/${id}`, id, data);\n }\n\n async updateByName(name: string, data: CreateStream): Promise<StreamResponse> {\n const { streams } = await this.list();\n const typedStreams = streams as { id: string; name: string }[];\n const existing = typedStreams.find((s) => s.name === name);\n if (!existing) {\n throw new ApiError(404, `Stream with name \"${name}\" not found`);\n }\n return this.update(existing.id, data);\n }\n\n async list(params?: { status?: string }): Promise<ListStreamsResponse> {\n const searchParams = new URLSearchParams();\n if (params?.status) searchParams.set(\"status\", params.status);\n const query = searchParams.toString();\n const path = query ? `/api/streams?${query}` : \"/api/streams\";\n return this.request<ListStreamsResponse>(\"GET\", path);\n }\n\n async get(id: string): Promise<StreamResponse> {\n return this.requestWithStreamId(\"GET\", (id) => `/api/streams/${id}`, id);\n }\n\n async delete(id: string): Promise<void> {\n return this.requestWithStreamId(\"DELETE\", (id) => `/api/streams/${id}`, id);\n }\n\n async enable(id: string): Promise<StreamResponse> {\n return this.requestWithStreamId(\"POST\", (id) => `/api/streams/${id}/enable`, id);\n }\n\n async disable(id: string): Promise<StreamResponse> {\n return this.requestWithStreamId(\"POST\", (id) => `/api/streams/${id}/disable`, id);\n }\n\n async rotateSecret(id: string): Promise<{ secret: string }> {\n return this.requestWithStreamId(\"POST\", (id) => `/api/streams/${id}/rotate-secret`, id);\n }\n\n async pauseAll(): Promise<BulkPauseResponse> {\n return this.request<BulkPauseResponse>(\"POST\", \"/api/streams/pause\");\n }\n\n async resumeAll(): Promise<BulkResumeResponse> {\n return this.request<BulkResumeResponse>(\"POST\", \"/api/streams/resume\");\n }\n}\n"
|
|
8
|
+
],
|
|
9
|
+
"mappings": "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",
|
|
10
|
+
"debugId": "EFD3CCF7032CC87A64756E2164756E21",
|
|
11
|
+
"names": []
|
|
12
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { ViewSummary, ViewDetail, ViewQueryParams, ReindexResponse } from "@secondlayer/shared/schemas";
|
|
2
|
+
import { DeployViewRequest, DeployViewResponse } from "@secondlayer/shared/schemas/views";
|
|
3
|
+
interface SecondLayerOptions {
|
|
4
|
+
/** Base URL of the Secondlayer API (trailing slashes are stripped). */
|
|
5
|
+
baseUrl: string;
|
|
6
|
+
/** Bearer token for authenticated requests. */
|
|
7
|
+
apiKey?: string;
|
|
8
|
+
}
|
|
9
|
+
declare abstract class BaseClient {
|
|
10
|
+
protected baseUrl: string;
|
|
11
|
+
protected apiKey?: string;
|
|
12
|
+
constructor(options?: Partial<SecondLayerOptions>);
|
|
13
|
+
static authHeaders(apiKey?: string): Record<string, string>;
|
|
14
|
+
protected request<T>(method: string, path: string, body?: unknown): Promise<T>;
|
|
15
|
+
}
|
|
16
|
+
declare class Views extends BaseClient {
|
|
17
|
+
list(): Promise<{
|
|
18
|
+
data: ViewSummary[]
|
|
19
|
+
}>;
|
|
20
|
+
get(name: string): Promise<ViewDetail>;
|
|
21
|
+
reindex(name: string, options?: {
|
|
22
|
+
fromBlock?: number
|
|
23
|
+
toBlock?: number
|
|
24
|
+
}): Promise<ReindexResponse>;
|
|
25
|
+
delete(name: string): Promise<{
|
|
26
|
+
message: string
|
|
27
|
+
}>;
|
|
28
|
+
deploy(data: DeployViewRequest): Promise<DeployViewResponse>;
|
|
29
|
+
queryTable(name: string, table: string, params?: ViewQueryParams): Promise<unknown[]>;
|
|
30
|
+
queryTableCount(name: string, table: string, params?: ViewQueryParams): Promise<{
|
|
31
|
+
count: number
|
|
32
|
+
}>;
|
|
33
|
+
}
|
|
34
|
+
export { Views, SecondLayerOptions };
|
|
@@ -8,12 +8,14 @@ class ApiError extends Error {
|
|
|
8
8
|
}
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
// src/
|
|
12
|
-
|
|
11
|
+
// src/base.ts
|
|
12
|
+
var DEFAULT_BASE_URL = "https://api.secondlayer.tools";
|
|
13
|
+
|
|
14
|
+
class BaseClient {
|
|
13
15
|
baseUrl;
|
|
14
16
|
apiKey;
|
|
15
|
-
constructor(options) {
|
|
16
|
-
this.baseUrl = options.baseUrl.replace(/\/+$/, "");
|
|
17
|
+
constructor(options = {}) {
|
|
18
|
+
this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
17
19
|
this.apiKey = options.apiKey;
|
|
18
20
|
}
|
|
19
21
|
static authHeaders(apiKey) {
|
|
@@ -25,7 +27,7 @@ class StreamsClient {
|
|
|
25
27
|
}
|
|
26
28
|
async request(method, path, body) {
|
|
27
29
|
const url = `${this.baseUrl}${path}`;
|
|
28
|
-
const headers =
|
|
30
|
+
const headers = BaseClient.authHeaders(this.apiKey);
|
|
29
31
|
let response;
|
|
30
32
|
try {
|
|
31
33
|
response = await fetch(url, {
|
|
@@ -64,95 +66,9 @@ class StreamsClient {
|
|
|
64
66
|
}
|
|
65
67
|
return response.json();
|
|
66
68
|
}
|
|
67
|
-
async resolveStreamId(partialId) {
|
|
68
|
-
if (partialId.length === 36 && partialId.includes("-")) {
|
|
69
|
-
return partialId;
|
|
70
|
-
}
|
|
71
|
-
const { streams } = await this.listStreams();
|
|
72
|
-
const matches = streams.filter((s) => s.id.startsWith(partialId));
|
|
73
|
-
if (matches.length === 0) {
|
|
74
|
-
throw new ApiError(404, `No stream found matching "${partialId}"`);
|
|
75
|
-
}
|
|
76
|
-
if (matches.length > 1) {
|
|
77
|
-
throw new ApiError(400, `Multiple streams match "${partialId}": ${matches.map((s) => s.id.slice(0, 8)).join(", ")}`);
|
|
78
|
-
}
|
|
79
|
-
return matches[0].id;
|
|
80
|
-
}
|
|
81
|
-
async createStream(data) {
|
|
82
|
-
return this.request("POST", "/api/streams", data);
|
|
83
|
-
}
|
|
84
|
-
async updateStream(id, data) {
|
|
85
|
-
const fullId = await this.resolveStreamId(id);
|
|
86
|
-
return this.request("PATCH", `/api/streams/${fullId}`, data);
|
|
87
|
-
}
|
|
88
|
-
async updateStreamByName(name, data) {
|
|
89
|
-
const { streams } = await this.listStreams();
|
|
90
|
-
const existing = streams.find((s) => s.name === name);
|
|
91
|
-
if (!existing) {
|
|
92
|
-
throw new ApiError(404, `Stream with name "${name}" not found`);
|
|
93
|
-
}
|
|
94
|
-
return this.updateStream(existing.id, data);
|
|
95
|
-
}
|
|
96
|
-
async listStreams(params) {
|
|
97
|
-
const searchParams = new URLSearchParams;
|
|
98
|
-
if (params?.status)
|
|
99
|
-
searchParams.set("status", params.status);
|
|
100
|
-
const query = searchParams.toString();
|
|
101
|
-
const path = query ? `/api/streams?${query}` : "/api/streams";
|
|
102
|
-
return this.request("GET", path);
|
|
103
|
-
}
|
|
104
|
-
async getStream(id) {
|
|
105
|
-
const fullId = await this.resolveStreamId(id);
|
|
106
|
-
return this.request("GET", `/api/streams/${fullId}`);
|
|
107
|
-
}
|
|
108
|
-
async deleteStream(id) {
|
|
109
|
-
const fullId = await this.resolveStreamId(id);
|
|
110
|
-
return this.request("DELETE", `/api/streams/${fullId}`);
|
|
111
|
-
}
|
|
112
|
-
async enableStream(id) {
|
|
113
|
-
const fullId = await this.resolveStreamId(id);
|
|
114
|
-
return this.request("POST", `/api/streams/${fullId}/enable`);
|
|
115
|
-
}
|
|
116
|
-
async disableStream(id) {
|
|
117
|
-
const fullId = await this.resolveStreamId(id);
|
|
118
|
-
return this.request("POST", `/api/streams/${fullId}/disable`);
|
|
119
|
-
}
|
|
120
|
-
async rotateSecret(id) {
|
|
121
|
-
const fullId = await this.resolveStreamId(id);
|
|
122
|
-
return this.request("POST", `/api/streams/${fullId}/rotate-secret`);
|
|
123
|
-
}
|
|
124
|
-
async pauseAll() {
|
|
125
|
-
return this.request("POST", "/api/streams/pause");
|
|
126
|
-
}
|
|
127
|
-
async resumeAll() {
|
|
128
|
-
return this.request("POST", "/api/streams/resume");
|
|
129
|
-
}
|
|
130
|
-
async getQueueStats() {
|
|
131
|
-
const status = await this.request("GET", "/status");
|
|
132
|
-
return status.queue;
|
|
133
|
-
}
|
|
134
|
-
async listViews() {
|
|
135
|
-
return this.request("GET", "/api/views");
|
|
136
|
-
}
|
|
137
|
-
async getView(name) {
|
|
138
|
-
return this.request("GET", `/api/views/${name}`);
|
|
139
|
-
}
|
|
140
|
-
async reindexView(name, options) {
|
|
141
|
-
return this.request("POST", `/api/views/${name}/reindex`, options);
|
|
142
|
-
}
|
|
143
|
-
async deleteView(name) {
|
|
144
|
-
return this.request("DELETE", `/api/views/${name}`);
|
|
145
|
-
}
|
|
146
|
-
async deployView(data) {
|
|
147
|
-
return this.request("POST", "/api/views", data);
|
|
148
|
-
}
|
|
149
|
-
async queryTable(name, table, params = {}) {
|
|
150
|
-
return this.request("GET", `/api/views/${name}/${table}${buildViewQueryString(params)}`);
|
|
151
|
-
}
|
|
152
|
-
async queryTableCount(name, table, params = {}) {
|
|
153
|
-
return this.request("GET", `/api/views/${name}/${table}/count${buildViewQueryString(params)}`);
|
|
154
|
-
}
|
|
155
69
|
}
|
|
70
|
+
|
|
71
|
+
// src/views/client.ts
|
|
156
72
|
function buildViewQueryString(params) {
|
|
157
73
|
const qs = new URLSearchParams;
|
|
158
74
|
if (params.sort)
|
|
@@ -173,9 +89,33 @@ function buildViewQueryString(params) {
|
|
|
173
89
|
const str = qs.toString();
|
|
174
90
|
return str ? `?${str}` : "";
|
|
175
91
|
}
|
|
92
|
+
|
|
93
|
+
class Views extends BaseClient {
|
|
94
|
+
async list() {
|
|
95
|
+
return this.request("GET", "/api/views");
|
|
96
|
+
}
|
|
97
|
+
async get(name) {
|
|
98
|
+
return this.request("GET", `/api/views/${name}`);
|
|
99
|
+
}
|
|
100
|
+
async reindex(name, options) {
|
|
101
|
+
return this.request("POST", `/api/views/${name}/reindex`, options);
|
|
102
|
+
}
|
|
103
|
+
async delete(name) {
|
|
104
|
+
return this.request("DELETE", `/api/views/${name}`);
|
|
105
|
+
}
|
|
106
|
+
async deploy(data) {
|
|
107
|
+
return this.request("POST", "/api/views", data);
|
|
108
|
+
}
|
|
109
|
+
async queryTable(name, table, params = {}) {
|
|
110
|
+
return this.request("GET", `/api/views/${name}/${table}${buildViewQueryString(params)}`);
|
|
111
|
+
}
|
|
112
|
+
async queryTableCount(name, table, params = {}) {
|
|
113
|
+
return this.request("GET", `/api/views/${name}/${table}/count${buildViewQueryString(params)}`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
176
116
|
export {
|
|
177
|
-
|
|
117
|
+
Views
|
|
178
118
|
};
|
|
179
119
|
|
|
180
|
-
//# debugId=
|
|
181
|
-
//# sourceMappingURL=
|
|
120
|
+
//# debugId=5FCD78685AE9CEC764756E2164756E21
|
|
121
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/errors.ts", "../src/base.ts", "../src/views/client.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"/**\n * Error thrown by {@link SecondLayer} when an API request fails.\n * Includes the HTTP status code for programmatic error handling.\n *\n * @example\n * ```ts\n * try {\n * await client.streams.get(\"abc123\");\n * } catch (err) {\n * if (err instanceof ApiError && err.status === 404) {\n * console.log(\"Stream not found\");\n * }\n * }\n * ```\n */\nexport class ApiError extends Error {\n constructor(\n /** HTTP status code (0 for network errors). */\n public status: number,\n message: string\n ) {\n super(message);\n this.name = \"ApiError\";\n }\n}\n",
|
|
6
|
+
"import { ApiError } from \"./errors.ts\";\n\nexport interface SecondLayerOptions {\n /** Base URL of the Secondlayer API (trailing slashes are stripped). */\n baseUrl: string;\n /** Bearer token for authenticated requests. */\n apiKey?: string;\n}\n\nconst DEFAULT_BASE_URL = \"https://api.secondlayer.tools\";\n\nexport abstract class BaseClient {\n protected baseUrl: string;\n protected apiKey?: string;\n\n constructor(options: Partial<SecondLayerOptions> = {}) {\n this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.apiKey = options.apiKey;\n }\n\n static authHeaders(apiKey?: string): Record<string, string> {\n const headers: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (apiKey) {\n headers[\"Authorization\"] = `Bearer ${apiKey}`;\n }\n return headers;\n }\n\n protected async request<T>(method: string, path: string, body?: unknown): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n const headers = BaseClient.authHeaders(this.apiKey);\n\n let response: Response;\n try {\n response = await fetch(url, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n });\n } catch {\n throw new ApiError(0, `Cannot reach API at ${this.baseUrl}. Check your connection or try again.`);\n }\n\n if (!response.ok) {\n if (response.status === 401) {\n throw new ApiError(401, \"API key invalid or expired.\");\n }\n\n if (response.status === 429) {\n const retryAfter = response.headers.get(\"Retry-After\");\n const msg = retryAfter\n ? `Rate limited. Wait ${retryAfter} seconds.`\n : \"Rate limited. Try again later.\";\n throw new ApiError(429, msg);\n }\n\n if (response.status >= 500) {\n throw new ApiError(response.status, `Server error. Try again or check status at ${this.baseUrl}/health`);\n }\n\n const errorBody = await response.text();\n let message = `HTTP ${response.status}`;\n try {\n const json = JSON.parse(errorBody);\n message = json.error || json.message || message;\n } catch {\n if (errorBody) message = errorBody;\n }\n throw new ApiError(response.status, message);\n }\n\n if (response.status === 204) {\n return undefined as T;\n }\n\n return response.json() as Promise<T>;\n }\n}\n",
|
|
7
|
+
"import type {\n ViewSummary,\n ViewDetail,\n ViewQueryParams,\n ReindexResponse,\n} from \"@secondlayer/shared/schemas\";\nimport type { DeployViewRequest, DeployViewResponse } from \"@secondlayer/shared/schemas/views\";\nimport { BaseClient } from \"../base.ts\";\n\nfunction buildViewQueryString(params: ViewQueryParams): string {\n const qs = new URLSearchParams();\n if (params.sort) qs.set(\"_sort\", params.sort);\n if (params.order) qs.set(\"_order\", params.order);\n if (params.limit !== undefined) qs.set(\"_limit\", String(params.limit));\n if (params.offset !== undefined) qs.set(\"_offset\", String(params.offset));\n if (params.fields) qs.set(\"_fields\", params.fields);\n if (params.filters) {\n for (const [key, value] of Object.entries(params.filters)) {\n qs.set(key, value);\n }\n }\n const str = qs.toString();\n return str ? `?${str}` : \"\";\n}\n\nexport class Views extends BaseClient {\n async list(): Promise<{ data: ViewSummary[] }> {\n return this.request<{ data: ViewSummary[] }>(\"GET\", \"/api/views\");\n }\n\n async get(name: string): Promise<ViewDetail> {\n return this.request<ViewDetail>(\"GET\", `/api/views/${name}`);\n }\n\n async reindex(name: string, options?: { fromBlock?: number; toBlock?: number }): Promise<ReindexResponse> {\n return this.request<ReindexResponse>(\"POST\", `/api/views/${name}/reindex`, options);\n }\n\n async delete(name: string): Promise<{ message: string }> {\n return this.request<{ message: string }>(\"DELETE\", `/api/views/${name}`);\n }\n\n async deploy(data: DeployViewRequest): Promise<DeployViewResponse> {\n return this.request<DeployViewResponse>(\"POST\", \"/api/views\", data);\n }\n\n async queryTable(name: string, table: string, params: ViewQueryParams = {}): Promise<unknown[]> {\n return this.request<unknown[]>(\"GET\", `/api/views/${name}/${table}${buildViewQueryString(params)}`);\n }\n\n async queryTableCount(name: string, table: string, params: ViewQueryParams = {}): Promise<{ count: number }> {\n return this.request<{ count: number }>(\"GET\", `/api/views/${name}/${table}/count${buildViewQueryString(params)}`);\n }\n}\n"
|
|
8
|
+
],
|
|
9
|
+
"mappings": "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",
|
|
10
|
+
"debugId": "5FCD78685AE9CEC764756E2164756E21",
|
|
11
|
+
"names": []
|
|
12
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@secondlayer/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -9,13 +9,13 @@
|
|
|
9
9
|
"types": "./dist/index.d.ts",
|
|
10
10
|
"import": "./dist/index.js"
|
|
11
11
|
},
|
|
12
|
-
"./
|
|
13
|
-
"types": "./dist/
|
|
14
|
-
"import": "./dist/
|
|
12
|
+
"./streams": {
|
|
13
|
+
"types": "./dist/streams/index.d.ts",
|
|
14
|
+
"import": "./dist/streams/index.js"
|
|
15
15
|
},
|
|
16
|
-
"./
|
|
17
|
-
"types": "./dist/
|
|
18
|
-
"import": "./dist/
|
|
16
|
+
"./views": {
|
|
17
|
+
"types": "./dist/views/index.d.ts",
|
|
18
|
+
"import": "./dist/views/index.js"
|
|
19
19
|
}
|
|
20
20
|
},
|
|
21
21
|
"files": [
|
package/dist/client.d.ts
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { CreateStream, UpdateStream, StreamResponse, CreateStreamResponse, ListStreamsResponse, BulkPauseResponse, BulkResumeResponse, ViewSummary, ViewDetail, ViewQueryParams, ReindexResponse } from "@secondlayer/shared/schemas";
|
|
2
|
-
import { DeployViewRequest, DeployViewResponse } from "@secondlayer/shared/schemas/views";
|
|
3
|
-
import { QueueStats } from "@secondlayer/shared/types";
|
|
4
|
-
interface StreamsClientOptions {
|
|
5
|
-
baseUrl: string;
|
|
6
|
-
apiKey?: string;
|
|
7
|
-
}
|
|
8
|
-
declare class StreamsClient {
|
|
9
|
-
private baseUrl;
|
|
10
|
-
private apiKey?;
|
|
11
|
-
constructor(options: StreamsClientOptions);
|
|
12
|
-
static authHeaders(apiKey?: string): Record<string, string>;
|
|
13
|
-
private request;
|
|
14
|
-
resolveStreamId(partialId: string): Promise<string>;
|
|
15
|
-
createStream(data: CreateStream): Promise<CreateStreamResponse>;
|
|
16
|
-
updateStream(id: string, data: UpdateStream): Promise<StreamResponse>;
|
|
17
|
-
updateStreamByName(name: string, data: CreateStream): Promise<StreamResponse>;
|
|
18
|
-
listStreams(params?: {
|
|
19
|
-
status?: string
|
|
20
|
-
}): Promise<ListStreamsResponse>;
|
|
21
|
-
getStream(id: string): Promise<StreamResponse>;
|
|
22
|
-
deleteStream(id: string): Promise<void>;
|
|
23
|
-
enableStream(id: string): Promise<StreamResponse>;
|
|
24
|
-
disableStream(id: string): Promise<StreamResponse>;
|
|
25
|
-
rotateSecret(id: string): Promise<{
|
|
26
|
-
secret: string
|
|
27
|
-
}>;
|
|
28
|
-
pauseAll(): Promise<BulkPauseResponse>;
|
|
29
|
-
resumeAll(): Promise<BulkResumeResponse>;
|
|
30
|
-
getQueueStats(): Promise<QueueStats>;
|
|
31
|
-
listViews(): Promise<{
|
|
32
|
-
data: ViewSummary[]
|
|
33
|
-
}>;
|
|
34
|
-
getView(name: string): Promise<ViewDetail>;
|
|
35
|
-
reindexView(name: string, options?: {
|
|
36
|
-
fromBlock?: number
|
|
37
|
-
toBlock?: number
|
|
38
|
-
}): Promise<ReindexResponse>;
|
|
39
|
-
deleteView(name: string): Promise<{
|
|
40
|
-
message: string
|
|
41
|
-
}>;
|
|
42
|
-
deployView(data: DeployViewRequest): Promise<DeployViewResponse>;
|
|
43
|
-
queryTable(name: string, table: string, params?: ViewQueryParams): Promise<unknown[]>;
|
|
44
|
-
queryTableCount(name: string, table: string, params?: ViewQueryParams): Promise<{
|
|
45
|
-
count: number
|
|
46
|
-
}>;
|
|
47
|
-
}
|
|
48
|
-
export { StreamsClientOptions, StreamsClient };
|
package/dist/client.js.map
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/errors.ts", "../src/client.ts"],
|
|
4
|
-
"sourcesContent": [
|
|
5
|
-
"export class ApiError extends Error {\n constructor(\n public status: number,\n message: string\n ) {\n super(message);\n this.name = \"ApiError\";\n }\n}\n",
|
|
6
|
-
"import type {\n CreateStream,\n UpdateStream,\n StreamResponse,\n CreateStreamResponse,\n ListStreamsResponse,\n BulkPauseResponse,\n BulkResumeResponse,\n ViewSummary,\n ViewDetail,\n ViewQueryParams,\n ReindexResponse,\n} from \"@secondlayer/shared/schemas\";\nimport type { DeployViewRequest, DeployViewResponse } from \"@secondlayer/shared/schemas/views\";\nimport type { QueueStats } from \"@secondlayer/shared/types\";\nimport { ApiError } from \"./errors.ts\";\n\nexport interface StreamsClientOptions {\n baseUrl: string;\n apiKey?: string;\n}\n\nexport class StreamsClient {\n private baseUrl: string;\n private apiKey?: string;\n\n constructor(options: StreamsClientOptions) {\n this.baseUrl = options.baseUrl.replace(/\\/+$/, \"\");\n this.apiKey = options.apiKey;\n }\n\n // ── Helpers ───────────────────────────────────────────────────────────\n\n static authHeaders(apiKey?: string): Record<string, string> {\n const headers: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (apiKey) {\n headers[\"Authorization\"] = `Bearer ${apiKey}`;\n }\n return headers;\n }\n\n private async request<T>(method: string, path: string, body?: unknown): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n const headers = StreamsClient.authHeaders(this.apiKey);\n\n let response: Response;\n try {\n response = await fetch(url, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n });\n } catch {\n throw new ApiError(0, `Cannot reach API at ${this.baseUrl}. Check your connection or try again.`);\n }\n\n if (!response.ok) {\n if (response.status === 401) {\n throw new ApiError(401, \"API key invalid or expired.\");\n }\n\n if (response.status === 429) {\n const retryAfter = response.headers.get(\"Retry-After\");\n const msg = retryAfter\n ? `Rate limited. Wait ${retryAfter} seconds.`\n : \"Rate limited. Try again later.\";\n throw new ApiError(429, msg);\n }\n\n if (response.status >= 500) {\n throw new ApiError(response.status, `Server error. Try again or check status at ${this.baseUrl}/health`);\n }\n\n const errorBody = await response.text();\n let message = `HTTP ${response.status}`;\n try {\n const json = JSON.parse(errorBody);\n message = json.error || json.message || message;\n } catch {\n if (errorBody) message = errorBody;\n }\n throw new ApiError(response.status, message);\n }\n\n if (response.status === 204) {\n return undefined as T;\n }\n\n return response.json() as Promise<T>;\n }\n\n // ── Stream ID Resolution ──────────────────────────────────────────────\n\n async resolveStreamId(partialId: string): Promise<string> {\n if (partialId.length === 36 && partialId.includes(\"-\")) {\n return partialId;\n }\n\n const { streams } = await this.listStreams();\n const matches = streams.filter((s) => s.id.startsWith(partialId));\n\n if (matches.length === 0) {\n throw new ApiError(404, `No stream found matching \"${partialId}\"`);\n }\n if (matches.length > 1) {\n throw new ApiError(400, `Multiple streams match \"${partialId}\": ${matches.map((s) => s.id.slice(0, 8)).join(\", \")}`);\n }\n\n return matches[0]!.id;\n }\n\n // ── Streams ───────────────────────────────────────────────────────────\n\n async createStream(data: CreateStream): Promise<CreateStreamResponse> {\n return this.request<CreateStreamResponse>(\"POST\", \"/api/streams\", data);\n }\n\n async updateStream(id: string, data: UpdateStream): Promise<StreamResponse> {\n const fullId = await this.resolveStreamId(id);\n return this.request<StreamResponse>(\"PATCH\", `/api/streams/${fullId}`, data);\n }\n\n async updateStreamByName(name: string, data: CreateStream): Promise<StreamResponse> {\n const { streams } = await this.listStreams();\n const existing = streams.find((s) => s.name === name);\n if (!existing) {\n throw new ApiError(404, `Stream with name \"${name}\" not found`);\n }\n return this.updateStream(existing.id, data);\n }\n\n async listStreams(params?: { status?: string }): Promise<ListStreamsResponse> {\n const searchParams = new URLSearchParams();\n if (params?.status) searchParams.set(\"status\", params.status);\n const query = searchParams.toString();\n const path = query ? `/api/streams?${query}` : \"/api/streams\";\n return this.request<ListStreamsResponse>(\"GET\", path);\n }\n\n async getStream(id: string): Promise<StreamResponse> {\n const fullId = await this.resolveStreamId(id);\n return this.request<StreamResponse>(\"GET\", `/api/streams/${fullId}`);\n }\n\n async deleteStream(id: string): Promise<void> {\n const fullId = await this.resolveStreamId(id);\n return this.request<void>(\"DELETE\", `/api/streams/${fullId}`);\n }\n\n async enableStream(id: string): Promise<StreamResponse> {\n const fullId = await this.resolveStreamId(id);\n return this.request<StreamResponse>(\"POST\", `/api/streams/${fullId}/enable`);\n }\n\n async disableStream(id: string): Promise<StreamResponse> {\n const fullId = await this.resolveStreamId(id);\n return this.request<StreamResponse>(\"POST\", `/api/streams/${fullId}/disable`);\n }\n\n async rotateSecret(id: string): Promise<{ secret: string }> {\n const fullId = await this.resolveStreamId(id);\n return this.request<{ secret: string }>(\"POST\", `/api/streams/${fullId}/rotate-secret`);\n }\n\n async pauseAll(): Promise<BulkPauseResponse> {\n return this.request<BulkPauseResponse>(\"POST\", \"/api/streams/pause\");\n }\n\n async resumeAll(): Promise<BulkResumeResponse> {\n return this.request<BulkResumeResponse>(\"POST\", \"/api/streams/resume\");\n }\n\n // ── Queue ─────────────────────────────────────────────────────────────\n\n async getQueueStats(): Promise<QueueStats> {\n const status = await this.request<{ queue: QueueStats }>(\"GET\", \"/status\");\n return status.queue;\n }\n\n // ── Views ─────────────────────────────────────────────────────────────\n\n async listViews(): Promise<{ data: ViewSummary[] }> {\n return this.request<{ data: ViewSummary[] }>(\"GET\", \"/api/views\");\n }\n\n async getView(name: string): Promise<ViewDetail> {\n return this.request<ViewDetail>(\"GET\", `/api/views/${name}`);\n }\n\n async reindexView(name: string, options?: { fromBlock?: number; toBlock?: number }): Promise<ReindexResponse> {\n return this.request<ReindexResponse>(\"POST\", `/api/views/${name}/reindex`, options);\n }\n\n async deleteView(name: string): Promise<{ message: string }> {\n return this.request<{ message: string }>(\"DELETE\", `/api/views/${name}`);\n }\n\n async deployView(data: DeployViewRequest): Promise<DeployViewResponse> {\n return this.request<DeployViewResponse>(\"POST\", \"/api/views\", data);\n }\n\n async queryTable(name: string, table: string, params: ViewQueryParams = {}): Promise<unknown[]> {\n return this.request<unknown[]>(\"GET\", `/api/views/${name}/${table}${buildViewQueryString(params)}`);\n }\n\n async queryTableCount(name: string, table: string, params: ViewQueryParams = {}): Promise<{ count: number }> {\n return this.request<{ count: number }>(\"GET\", `/api/views/${name}/${table}/count${buildViewQueryString(params)}`);\n }\n}\n\nfunction buildViewQueryString(params: ViewQueryParams): string {\n const qs = new URLSearchParams();\n if (params.sort) qs.set(\"_sort\", params.sort);\n if (params.order) qs.set(\"_order\", params.order);\n if (params.limit !== undefined) qs.set(\"_limit\", String(params.limit));\n if (params.offset !== undefined) qs.set(\"_offset\", String(params.offset));\n if (params.fields) qs.set(\"_fields\", params.fields);\n if (params.filters) {\n for (const [key, value] of Object.entries(params.filters)) {\n qs.set(key, value);\n }\n }\n const str = qs.toString();\n return str ? `?${str}` : \"\";\n}\n"
|
|
7
|
-
],
|
|
8
|
-
"mappings": "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",
|
|
9
|
-
"debugId": "2645915545BCF30D64756E2164756E21",
|
|
10
|
-
"names": []
|
|
11
|
-
}
|
package/dist/errors.d.ts
DELETED
package/dist/errors.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
// src/errors.ts
|
|
2
|
-
class ApiError extends Error {
|
|
3
|
-
status;
|
|
4
|
-
constructor(status, message) {
|
|
5
|
-
super(message);
|
|
6
|
-
this.status = status;
|
|
7
|
-
this.name = "ApiError";
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
|
-
export {
|
|
11
|
-
ApiError
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
//# debugId=7DCD1AB2054ADEE564756E2164756E21
|
|
15
|
-
//# sourceMappingURL=errors.js.map
|
package/dist/errors.js.map
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/errors.ts"],
|
|
4
|
-
"sourcesContent": [
|
|
5
|
-
"export class ApiError extends Error {\n constructor(\n public status: number,\n message: string\n ) {\n super(message);\n this.name = \"ApiError\";\n }\n}\n"
|
|
6
|
-
],
|
|
7
|
-
"mappings": ";AAAO,MAAM,iBAAiB,MAAM;AAAA,EAEzB;AAAA,EADT,WAAW,CACF,QACP,SACA;AAAA,IACA,MAAM,OAAO;AAAA,IAHN;AAAA,IAIP,KAAK,OAAO;AAAA;AAEhB;",
|
|
8
|
-
"debugId": "7DCD1AB2054ADEE564756E2164756E21",
|
|
9
|
-
"names": []
|
|
10
|
-
}
|