@softr/sdk 0.0.7 → 0.0.10
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/client.d.ts +6 -0
- package/dist/{react.js → client.js} +2 -1
- package/dist/index.d.ts +659 -11
- package/dist/index.js +874 -24
- package/dist/server.d.ts +85 -0
- package/dist/server.js +202 -0
- package/dist/session-Blx62HHJ.js +334 -0
- package/dist/user-D23hwTsf.d.ts +28 -0
- package/dist/vite.d.ts +6 -3
- package/dist/vite.js +28 -2
- package/package.json +6 -5
- package/dist/query-C6022JhD.js +0 -528
- package/dist/react.d.ts +0 -4
- package/dist/tanstack.d.ts +0 -18
- package/dist/tanstack.js +0 -320
- package/dist/types-CjB4xUg-.d.ts +0 -661
package/dist/tanstack.js
DELETED
|
@@ -1,320 +0,0 @@
|
|
|
1
|
-
import { i as dealiasOrderBy, n as buildOrderBy, r as dealiasFilterCriteria, t as buildFilterCriteria } from "./query-C6022JhD.js";
|
|
2
|
-
import { createMiddleware } from "@tanstack/start";
|
|
3
|
-
|
|
4
|
-
//#region src/core/datasource.ts
|
|
5
|
-
const MAX_RECORD_COUNT = 100;
|
|
6
|
-
const COUNT_CNT = "COUNT_CNT";
|
|
7
|
-
var DatasourceAPIImpl = class {
|
|
8
|
-
id;
|
|
9
|
-
fetch;
|
|
10
|
-
userTimezone;
|
|
11
|
-
constructor(id, fetch$1, userTimezone = "UTC") {
|
|
12
|
-
this.id = id;
|
|
13
|
-
this.fetch = fetch$1;
|
|
14
|
-
this.userTimezone = userTimezone;
|
|
15
|
-
}
|
|
16
|
-
async list(options = {}) {
|
|
17
|
-
const { select, where, orderBy } = options;
|
|
18
|
-
const count = Math.min(options.limit ?? 20, MAX_RECORD_COUNT);
|
|
19
|
-
const offset = options.offset ?? null;
|
|
20
|
-
const filterCriteria = where ? dealiasFilterCriteria(buildFilterCriteria(where), select ?? {}) : {};
|
|
21
|
-
const sortingOption = orderBy ? dealiasOrderBy(buildOrderBy(orderBy), select ?? {}) : void 0;
|
|
22
|
-
const res = await this.fetch(`/api/datasources/${this.id}/records`, {
|
|
23
|
-
method: "POST",
|
|
24
|
-
headers: {
|
|
25
|
-
"Content-Type": "application/json",
|
|
26
|
-
"X-User-Timezone": options.timeZone ?? this.userTimezone
|
|
27
|
-
},
|
|
28
|
-
body: JSON.stringify({
|
|
29
|
-
options: { userLocale: "en-US" },
|
|
30
|
-
filterCriteria,
|
|
31
|
-
sortingOption,
|
|
32
|
-
pagingOption: {
|
|
33
|
-
offset,
|
|
34
|
-
count
|
|
35
|
-
}
|
|
36
|
-
})
|
|
37
|
-
});
|
|
38
|
-
if (!res.ok) throw new Error(`Softr datasource list failed for "${this.id}": ${res.status}`);
|
|
39
|
-
const payload = await res.json();
|
|
40
|
-
const nextOffset = payload.offset < payload.total ? payload.offset : null;
|
|
41
|
-
return {
|
|
42
|
-
records: payload.items.map((item) => ({
|
|
43
|
-
id: item.id,
|
|
44
|
-
fields: select ? aliasFields(item.fields, select) : item.fields
|
|
45
|
-
})),
|
|
46
|
-
total: payload.total,
|
|
47
|
-
nextOffset
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
async get(options) {
|
|
51
|
-
if (options.id !== void 0) {
|
|
52
|
-
if (!options.id) throw new Error(`Softr datasource get: id must not be empty`);
|
|
53
|
-
const res = await this.fetch(`/api/datasources/${this.id}/records/${options.id}`, {
|
|
54
|
-
method: "POST",
|
|
55
|
-
headers: {
|
|
56
|
-
"Content-Type": "application/json",
|
|
57
|
-
"X-User-Timezone": options.timeZone ?? this.userTimezone
|
|
58
|
-
},
|
|
59
|
-
body: JSON.stringify({ options: { userLocale: "en-US" } })
|
|
60
|
-
});
|
|
61
|
-
if (!res.ok) throw new Error(`Softr datasource get failed for "${this.id}": ${res.status}`);
|
|
62
|
-
const contentLength = res.headers.get("Content-Length");
|
|
63
|
-
if (contentLength && parseInt(contentLength, 10) === 0) return null;
|
|
64
|
-
return res.json();
|
|
65
|
-
}
|
|
66
|
-
return (await this.list({
|
|
67
|
-
where: options.where,
|
|
68
|
-
limit: 1,
|
|
69
|
-
timeZone: options.timeZone
|
|
70
|
-
})).records[0] ?? null;
|
|
71
|
-
}
|
|
72
|
-
async create(options) {
|
|
73
|
-
const res = await this.fetch(`/api/datasources/${this.id}/records`, {
|
|
74
|
-
method: "POST",
|
|
75
|
-
headers: { "Content-Type": "application/json" },
|
|
76
|
-
body: JSON.stringify({ fields: options.fields })
|
|
77
|
-
});
|
|
78
|
-
if (!res.ok) throw new Error(`Softr datasource create failed for "${this.id}": ${res.status}`);
|
|
79
|
-
return (await res.json()).record;
|
|
80
|
-
}
|
|
81
|
-
async update(options) {
|
|
82
|
-
if (!options.id) throw new Error(`Softr datasource update: id must not be empty`);
|
|
83
|
-
const res = await this.fetch(`/api/datasources/${this.id}/records/${options.id}`, {
|
|
84
|
-
method: "PATCH",
|
|
85
|
-
headers: { "Content-Type": "application/json" },
|
|
86
|
-
body: JSON.stringify({ fields: options.fields })
|
|
87
|
-
});
|
|
88
|
-
if (!res.ok) throw new Error(`Softr datasource update failed for "${this.id}": ${res.status}`);
|
|
89
|
-
return (await res.json()).record;
|
|
90
|
-
}
|
|
91
|
-
async delete(id) {
|
|
92
|
-
const res = await this.fetch(`/api/datasources/${this.id}/records/${id}`, { method: "DELETE" });
|
|
93
|
-
if (!res.ok) throw new Error(`Softr datasource delete failed for "${this.id}": ${res.status}`);
|
|
94
|
-
}
|
|
95
|
-
async metric(options) {
|
|
96
|
-
const { select, where, aggregation, field } = options;
|
|
97
|
-
const fieldId = field ? select?.[field] ?? field : void 0;
|
|
98
|
-
const filterCriteria = where ? dealiasFilterCriteria(buildFilterCriteria(where), select ?? {}) : {};
|
|
99
|
-
const res = await this.fetch(`/api/datasources/${this.id}/chartMetricData`, {
|
|
100
|
-
method: "POST",
|
|
101
|
-
headers: {
|
|
102
|
-
"Content-Type": "application/json",
|
|
103
|
-
"X-User-Timezone": options.timeZone ?? this.userTimezone
|
|
104
|
-
},
|
|
105
|
-
body: JSON.stringify({
|
|
106
|
-
options: { userLocale: "en-US" },
|
|
107
|
-
calculationField: {
|
|
108
|
-
field: fieldId,
|
|
109
|
-
aggregation
|
|
110
|
-
},
|
|
111
|
-
filterCriteria
|
|
112
|
-
})
|
|
113
|
-
});
|
|
114
|
-
if (!res.ok) throw new Error(`Softr datasource metric failed for "${this.id}": ${res.status}`);
|
|
115
|
-
const payload = await res.json();
|
|
116
|
-
const executionTimestamp = /* @__PURE__ */ new Date(payload.executionTimestamp * 1e3);
|
|
117
|
-
let value;
|
|
118
|
-
if (aggregation === "COUNT") value = payload.data.find((item) => COUNT_CNT in item)?.[COUNT_CNT] ?? null;
|
|
119
|
-
else {
|
|
120
|
-
if (!fieldId) throw new Error(`field is required for aggregation "${aggregation}"`);
|
|
121
|
-
value = payload.data.find((item) => fieldId in item)?.[fieldId] ?? null;
|
|
122
|
-
}
|
|
123
|
-
return {
|
|
124
|
-
value,
|
|
125
|
-
executionTimestamp
|
|
126
|
-
};
|
|
127
|
-
}
|
|
128
|
-
async chartData(options) {
|
|
129
|
-
const { select, where, groupBy, metrics, orderBy } = options;
|
|
130
|
-
const filterCriteria = where ? dealiasFilterCriteria(buildFilterCriteria(where), select ?? {}) : {};
|
|
131
|
-
const sortingOption = orderBy ? dealiasOrderBy(buildOrderBy(orderBy), select ?? {})[0] : void 0;
|
|
132
|
-
const groupByFields = (Array.isArray(groupBy) ? groupBy : [groupBy]).map((field) => ({ field: select?.[field] ?? field }));
|
|
133
|
-
const yAxisFields = Object.values(metrics).map(({ field, aggregation }) => ({
|
|
134
|
-
field: field ? select?.[field] ?? field : void 0,
|
|
135
|
-
aggregation
|
|
136
|
-
}));
|
|
137
|
-
const res = await this.fetch(`/api/datasources/${this.id}/chartData`, {
|
|
138
|
-
method: "POST",
|
|
139
|
-
headers: {
|
|
140
|
-
"Content-Type": "application/json",
|
|
141
|
-
"X-User-Timezone": options.timeZone ?? this.userTimezone
|
|
142
|
-
},
|
|
143
|
-
body: JSON.stringify({
|
|
144
|
-
options: { userLocale: "en-US" },
|
|
145
|
-
filterCriteria,
|
|
146
|
-
sortingOption,
|
|
147
|
-
xAxisFields: groupByFields,
|
|
148
|
-
yAxisFields
|
|
149
|
-
})
|
|
150
|
-
});
|
|
151
|
-
if (!res.ok) throw new Error(`Softr datasource chartData failed for "${this.id}": ${res.status}`);
|
|
152
|
-
const payload = await res.json();
|
|
153
|
-
const executionTimestamp = /* @__PURE__ */ new Date(payload.executionTimestamp * 1e3);
|
|
154
|
-
const aliases = {};
|
|
155
|
-
const multipleMetrics = Object.keys(metrics).length > 1;
|
|
156
|
-
for (const [alias, { field, aggregation }] of Object.entries(metrics)) if (aggregation === "COUNT") aliases[COUNT_CNT] = alias;
|
|
157
|
-
else {
|
|
158
|
-
const fieldId = field ? select?.[field] ?? field : field;
|
|
159
|
-
if (fieldId) {
|
|
160
|
-
const suffix = multipleMetrics ? `_${aggregation.toLowerCase()}` : "";
|
|
161
|
-
aliases[fieldId + suffix] = alias;
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
for (const field of Array.isArray(groupBy) ? groupBy : [groupBy]) aliases[select?.[field] ?? field] = field;
|
|
165
|
-
return {
|
|
166
|
-
data: payload.data.map((item) => {
|
|
167
|
-
const row = {};
|
|
168
|
-
for (const [rawKey, alias] of Object.entries(aliases)) if (rawKey in item) row[alias] = item[rawKey];
|
|
169
|
-
return row;
|
|
170
|
-
}),
|
|
171
|
-
executionTimestamp
|
|
172
|
-
};
|
|
173
|
-
}
|
|
174
|
-
};
|
|
175
|
-
function aliasFields(fields, aliases) {
|
|
176
|
-
const result = {};
|
|
177
|
-
for (const [alias, fieldId] of Object.entries(aliases)) result[alias] = fields[fieldId];
|
|
178
|
-
return result;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
//#endregion
|
|
182
|
-
//#region src/core/integration.ts
|
|
183
|
-
var IntegrationAPIImpl = class {
|
|
184
|
-
id;
|
|
185
|
-
request;
|
|
186
|
-
constructor(id, fetch$1) {
|
|
187
|
-
this.id = id;
|
|
188
|
-
this.request = fetch$1;
|
|
189
|
-
}
|
|
190
|
-
async fetch(input, init) {
|
|
191
|
-
const req = new Request(input, init);
|
|
192
|
-
if (req.signal.aborted) throw req.signal.reason ?? new DOMException("The operation was aborted.", "AbortError");
|
|
193
|
-
const headers = {};
|
|
194
|
-
new Headers(req.headers).forEach((value, key) => {
|
|
195
|
-
headers[key] = value;
|
|
196
|
-
});
|
|
197
|
-
const payload = {
|
|
198
|
-
method: req.method,
|
|
199
|
-
url: req.url,
|
|
200
|
-
headers
|
|
201
|
-
};
|
|
202
|
-
const method = req.method.toUpperCase();
|
|
203
|
-
if (method !== "GET" && method !== "HEAD" && req.body !== null) payload.body = await req.clone().text();
|
|
204
|
-
return this.request(`/api/integrations/${this.id}/proxy`, {
|
|
205
|
-
method: "POST",
|
|
206
|
-
headers: { "Content-Type": "application/json" },
|
|
207
|
-
body: JSON.stringify(payload),
|
|
208
|
-
signal: req.signal
|
|
209
|
-
});
|
|
210
|
-
}
|
|
211
|
-
};
|
|
212
|
-
|
|
213
|
-
//#endregion
|
|
214
|
-
//#region src/core/workflow.ts
|
|
215
|
-
var WorkflowAPIImpl = class {
|
|
216
|
-
id;
|
|
217
|
-
fetch;
|
|
218
|
-
constructor(id, fetch$1) {
|
|
219
|
-
this.id = id;
|
|
220
|
-
this.fetch = fetch$1;
|
|
221
|
-
}
|
|
222
|
-
async trigger(payload) {
|
|
223
|
-
const res = await this.fetch(`/api/workflows/${this.id}/trigger`, {
|
|
224
|
-
method: "POST",
|
|
225
|
-
...payload ? {
|
|
226
|
-
headers: { "Content-Type": "application/json" },
|
|
227
|
-
body: JSON.stringify(payload)
|
|
228
|
-
} : {}
|
|
229
|
-
});
|
|
230
|
-
if (!res.ok) throw new Error(`Softr workflow trigger failed: ${res.status}`);
|
|
231
|
-
}
|
|
232
|
-
};
|
|
233
|
-
|
|
234
|
-
//#endregion
|
|
235
|
-
//#region src/core/sdk.ts
|
|
236
|
-
var SoftrSDKImpl = class {
|
|
237
|
-
baseUrl;
|
|
238
|
-
userTimezone;
|
|
239
|
-
extraHeaders;
|
|
240
|
-
cachedMe = null;
|
|
241
|
-
constructor(config) {
|
|
242
|
-
this.baseUrl = config.baseUrl.replace(/\/$/, "");
|
|
243
|
-
this.userTimezone = config.userTimezone ?? import.meta.env.VITE_APP_TIMEZONE ?? "UTC";
|
|
244
|
-
this.extraHeaders = config.headers;
|
|
245
|
-
}
|
|
246
|
-
async me() {
|
|
247
|
-
if (this.cachedMe) return this.cachedMe;
|
|
248
|
-
const res = await this._fetch("/me");
|
|
249
|
-
if (!res.ok) throw new Error(`Softr /me failed: ${res.status}`);
|
|
250
|
-
this.cachedMe = await res.json();
|
|
251
|
-
return this.cachedMe;
|
|
252
|
-
}
|
|
253
|
-
auth = {
|
|
254
|
-
login: async ({ email, password }) => {
|
|
255
|
-
const res = await this._fetch("/auth/login", {
|
|
256
|
-
method: "POST",
|
|
257
|
-
headers: { "Content-Type": "application/json" },
|
|
258
|
-
body: JSON.stringify({
|
|
259
|
-
email,
|
|
260
|
-
password
|
|
261
|
-
})
|
|
262
|
-
});
|
|
263
|
-
if (!res.ok) throw new Error(`Login failed: ${res.status}`);
|
|
264
|
-
this.cachedMe = null;
|
|
265
|
-
},
|
|
266
|
-
logout: async () => {
|
|
267
|
-
const res = await this._fetch("/auth/logout", { method: "POST" });
|
|
268
|
-
if (!res.ok) throw new Error(`Logout failed: ${res.status}`);
|
|
269
|
-
this.cachedMe = null;
|
|
270
|
-
}
|
|
271
|
-
};
|
|
272
|
-
datasource(id) {
|
|
273
|
-
return new DatasourceAPIImpl(id, this._fetch.bind(this), this.userTimezone);
|
|
274
|
-
}
|
|
275
|
-
integration(id) {
|
|
276
|
-
return new IntegrationAPIImpl(id, this._fetch.bind(this));
|
|
277
|
-
}
|
|
278
|
-
workflow(id) {
|
|
279
|
-
return new WorkflowAPIImpl(id, this._fetch.bind(this));
|
|
280
|
-
}
|
|
281
|
-
_fetch(path, init) {
|
|
282
|
-
const headers = new Headers(this.extraHeaders);
|
|
283
|
-
if (init?.headers) new Headers(init.headers).forEach((v, k) => headers.set(k, v));
|
|
284
|
-
const isServer = typeof window === "undefined";
|
|
285
|
-
return fetch(`${this.baseUrl}${path}`, {
|
|
286
|
-
...init,
|
|
287
|
-
credentials: isServer ? "omit" : "include",
|
|
288
|
-
headers
|
|
289
|
-
});
|
|
290
|
-
}
|
|
291
|
-
};
|
|
292
|
-
function createSoftrSDKFromRequest(request, baseUrl) {
|
|
293
|
-
const cookieHeader = request.headers.get("cookie") ?? "";
|
|
294
|
-
return new SoftrSDKImpl({
|
|
295
|
-
baseUrl,
|
|
296
|
-
userTimezone: parseCookie(cookieHeader, "user-timezone"),
|
|
297
|
-
headers: { cookie: cookieHeader }
|
|
298
|
-
});
|
|
299
|
-
}
|
|
300
|
-
function parseCookie(cookieHeader, name) {
|
|
301
|
-
return cookieHeader.split(";").map((c) => c.trim().split("=")).find(([k]) => k === name)?.[1];
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
//#endregion
|
|
305
|
-
//#region src/tanstack.ts
|
|
306
|
-
/**
|
|
307
|
-
* TanStack Start middleware. Injects a per-request Softr SDK instance with
|
|
308
|
-
* cookies forwarded automatically. The base URL is read from VITE_SOFTR_BASE_URL.
|
|
309
|
-
*
|
|
310
|
-
* @example
|
|
311
|
-
* import { withSDK } from '@softr/sdk/tanstack'
|
|
312
|
-
*
|
|
313
|
-
* export const getProjects = createServerFn()
|
|
314
|
-
* .middleware([withSDK])
|
|
315
|
-
* .handler(({ context }) => context.sdk.datasource('ds_projects').list())
|
|
316
|
-
*/
|
|
317
|
-
const withSDK = createMiddleware().server(({ next, request }) => next({ context: { sdk: createSoftrSDKFromRequest(request, import.meta.env.VITE_SOFTR_BASE_URL) } }));
|
|
318
|
-
|
|
319
|
-
//#endregion
|
|
320
|
-
export { withSDK };
|