@softr/sdk 0.0.33 → 0.0.35-alpha.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/dist/action.d.ts +4 -4
- package/dist/action.js +2 -2
- package/dist/core/integration.js +1 -1
- package/dist/datasource/chart.js +6 -6
- package/dist/datasource/record.js +18 -18
- package/dist/package.js +1 -1
- package/package.json +1 -1
- package/skills/softr-sdk/SKILL.md +1 -1
- package/skills/softr-sdk/auth/SKILL.md +1 -1
- package/skills/softr-sdk/charts-and-metrics/SKILL.md +1 -1
- package/skills/softr-sdk/current-user/SKILL.md +1 -1
- package/skills/softr-sdk/file-uploads/SKILL.md +1 -1
- package/skills/softr-sdk/integrations/SKILL.md +5 -5
- package/skills/softr-sdk/record-mutations/SKILL.md +1 -1
- package/skills/softr-sdk/record-queries/SKILL.md +1 -1
- package/skills/softr-sdk/routes-and-visibility/SKILL.md +1 -1
- package/skills/softr-sdk/workflows/SKILL.md +1 -1
package/dist/action.d.ts
CHANGED
|
@@ -200,25 +200,25 @@ type WorkflowDefinition<TId extends string> = {
|
|
|
200
200
|
declare function defineWorkflow<const TId extends string>(definition: WorkflowDefinition<TId>): WorkflowAction<TId>;
|
|
201
201
|
type IntegrationResource = {
|
|
202
202
|
type: "INTEGRATION";
|
|
203
|
-
|
|
203
|
+
integrationId: string;
|
|
204
204
|
};
|
|
205
205
|
type IntegrationAction<TId extends string = string> = Action<IntegrationResource> & {
|
|
206
206
|
id: TId;
|
|
207
207
|
};
|
|
208
208
|
type IntegrationDefinition<TId extends string> = {
|
|
209
209
|
id: TId;
|
|
210
|
-
|
|
210
|
+
integrationId: string;
|
|
211
211
|
permissions: ActionPermissions;
|
|
212
212
|
};
|
|
213
213
|
/**
|
|
214
|
-
* Declares an integration: which
|
|
214
|
+
* Declares an integration: which workspace integration to call through, and who may call it.
|
|
215
215
|
*
|
|
216
216
|
* Pass the returned object to `integration.createFetcher()` to get a bound fetcher.
|
|
217
217
|
*
|
|
218
218
|
* @example
|
|
219
219
|
* const googleCalendar = defineIntegration({
|
|
220
220
|
* id: "googleCalendar",
|
|
221
|
-
*
|
|
221
|
+
* integrationId: "25d60213-ef4f-4fa0-b094-a46931b2d120",
|
|
222
222
|
* permissions: { userGroup: "LOGGED_IN_USERS" },
|
|
223
223
|
* })
|
|
224
224
|
*
|
package/dist/action.js
CHANGED
|
@@ -38,12 +38,12 @@ function defineWorkflow(definition) {
|
|
|
38
38
|
};
|
|
39
39
|
}
|
|
40
40
|
function defineIntegration(definition) {
|
|
41
|
-
const { id,
|
|
41
|
+
const { id, integrationId, permissions } = definition;
|
|
42
42
|
return {
|
|
43
43
|
id,
|
|
44
44
|
resource: {
|
|
45
45
|
type: "INTEGRATION",
|
|
46
|
-
|
|
46
|
+
integrationId
|
|
47
47
|
},
|
|
48
48
|
permissions
|
|
49
49
|
};
|
package/dist/core/integration.js
CHANGED
|
@@ -12,7 +12,7 @@ async function integrationFetch(action, url, { method = "GET", headers = {}, bod
|
|
|
12
12
|
headers
|
|
13
13
|
};
|
|
14
14
|
if (upperMethod !== "GET" && upperMethod !== "HEAD" && body !== void 0) payload.body = body;
|
|
15
|
-
return fetch(`${dsUrl(action.
|
|
15
|
+
return fetch(`${dsUrl(action.id)}/proxy`, {
|
|
16
16
|
method: "POST",
|
|
17
17
|
headers: {
|
|
18
18
|
"Content-Type": "application/json",
|
package/dist/datasource/chart.js
CHANGED
|
@@ -191,9 +191,9 @@ function mapChartRows(columns, data) {
|
|
|
191
191
|
});
|
|
192
192
|
}
|
|
193
193
|
async function executeChart(query, state) {
|
|
194
|
-
const {
|
|
194
|
+
const { actionId, select } = resolveTarget(query, "read");
|
|
195
195
|
const { body, columns } = buildChartRequest(state, select);
|
|
196
|
-
const res = await fetch(`${dsUrl(
|
|
196
|
+
const res = await fetch(`${dsUrl(actionId)}/chart/data`, {
|
|
197
197
|
method: "POST",
|
|
198
198
|
headers: {
|
|
199
199
|
"Content-Type": "application/json",
|
|
@@ -202,7 +202,7 @@ async function executeChart(query, state) {
|
|
|
202
202
|
},
|
|
203
203
|
body: JSON.stringify(body)
|
|
204
204
|
});
|
|
205
|
-
if (!res.ok) throw new Error(`Softr datasource chart failed for "${
|
|
205
|
+
if (!res.ok) throw new Error(`Softr datasource chart failed for action "${actionId}": ${res.status}`);
|
|
206
206
|
const payload = await res.json();
|
|
207
207
|
return {
|
|
208
208
|
data: mapChartRows(columns, payload.data),
|
|
@@ -264,9 +264,9 @@ function readMetricValue(responseKey, data) {
|
|
|
264
264
|
return row[responseKey];
|
|
265
265
|
}
|
|
266
266
|
async function executeMetric(query, handle, filters) {
|
|
267
|
-
const {
|
|
267
|
+
const { actionId, select } = resolveTarget(query, "read");
|
|
268
268
|
const { body, responseKey } = buildMetricRequest(handle, filters, select);
|
|
269
|
-
const res = await fetch(`${dsUrl(
|
|
269
|
+
const res = await fetch(`${dsUrl(actionId)}/chart/data`, {
|
|
270
270
|
method: "POST",
|
|
271
271
|
headers: {
|
|
272
272
|
"Content-Type": "application/json",
|
|
@@ -275,7 +275,7 @@ async function executeMetric(query, handle, filters) {
|
|
|
275
275
|
},
|
|
276
276
|
body: JSON.stringify(body)
|
|
277
277
|
});
|
|
278
|
-
if (!res.ok) throw new Error(`Softr datasource metric failed for "${
|
|
278
|
+
if (!res.ok) throw new Error(`Softr datasource metric failed for action "${actionId}": ${res.status}`);
|
|
279
279
|
const payload = await res.json();
|
|
280
280
|
return {
|
|
281
281
|
value: readMetricValue(responseKey, payload.data),
|
|
@@ -8,12 +8,12 @@ import { andAll, makeFieldSet, makeSortSet } from "./fields.js";
|
|
|
8
8
|
|
|
9
9
|
//#region src/datasource/record.ts
|
|
10
10
|
const MAX_RECORD_COUNT = 100;
|
|
11
|
-
const dsUrl = (
|
|
11
|
+
const dsUrl = (actionId) => {
|
|
12
12
|
const datasourceApiUrl = process.env.SOFTR_DATASOURCE_API_URL;
|
|
13
13
|
if (!datasourceApiUrl) panic("SOFTR_DATASOURCE_API_URL is not set.");
|
|
14
14
|
const applicationId = process.env.SOFTR_APPLICATION_ID;
|
|
15
15
|
if (!applicationId) panic("SOFTR_APPLICATION_ID is not set.");
|
|
16
|
-
return `${withoutTrailingSlash(datasourceApiUrl)}/v1/datasource/vibe/applications/${applicationId}/
|
|
16
|
+
return `${withoutTrailingSlash(datasourceApiUrl)}/v1/datasource/vibe/applications/${applicationId}/actions/${actionId}`;
|
|
17
17
|
};
|
|
18
18
|
/**
|
|
19
19
|
* Queries a list of records from the datasource.
|
|
@@ -65,12 +65,12 @@ function listRecords(query) {
|
|
|
65
65
|
return builder;
|
|
66
66
|
}
|
|
67
67
|
async function executeList(query, args) {
|
|
68
|
-
const {
|
|
68
|
+
const { actionId, select } = resolveTarget(query, "read");
|
|
69
69
|
const count = Math.min(args.limit ?? 20, MAX_RECORD_COUNT);
|
|
70
70
|
const offset = args.offset ?? null;
|
|
71
71
|
const filterCriteria = args.filters.length ? dealiasFilterCriteria(buildFilterCriteria(andAll(args.filters)), select) : {};
|
|
72
72
|
const sortingOption = args.orderBy.length ? dealiasOrderBy(buildOrderBy(args.orderBy), select) : void 0;
|
|
73
|
-
const res = await fetch(`${dsUrl(
|
|
73
|
+
const res = await fetch(`${dsUrl(actionId)}/records`, {
|
|
74
74
|
method: "POST",
|
|
75
75
|
headers: {
|
|
76
76
|
"Content-Type": "application/json",
|
|
@@ -87,7 +87,7 @@ async function executeList(query, args) {
|
|
|
87
87
|
}
|
|
88
88
|
})
|
|
89
89
|
});
|
|
90
|
-
if (!res.ok) throw new Error(`Softr datasource list failed for "${
|
|
90
|
+
if (!res.ok) throw new Error(`Softr datasource list failed for "${actionId}": ${res.status}`);
|
|
91
91
|
const payload = await res.json();
|
|
92
92
|
const nextOffset = payload.offset < payload.total ? payload.offset : null;
|
|
93
93
|
return {
|
|
@@ -139,9 +139,9 @@ function getRecord(query, options) {
|
|
|
139
139
|
}
|
|
140
140
|
async function executeGet(query, id, filters) {
|
|
141
141
|
assert(id, "a record id must not be empty");
|
|
142
|
-
const {
|
|
142
|
+
const { actionId, select } = resolveTarget(query, "read");
|
|
143
143
|
const filterCriteria = filters.length ? dealiasFilterCriteria(buildFilterCriteria(andAll(filters)), select) : {};
|
|
144
|
-
const res = await fetch(`${dsUrl(
|
|
144
|
+
const res = await fetch(`${dsUrl(actionId)}/records/${id}`, {
|
|
145
145
|
method: "POST",
|
|
146
146
|
headers: {
|
|
147
147
|
"Content-Type": "application/json",
|
|
@@ -153,7 +153,7 @@ async function executeGet(query, id, filters) {
|
|
|
153
153
|
filterCriteria
|
|
154
154
|
})
|
|
155
155
|
});
|
|
156
|
-
if (!res.ok) throw new Error(`Softr datasource get failed for "${
|
|
156
|
+
if (!res.ok) throw new Error(`Softr datasource get failed for action "${actionId}": ${res.status}`);
|
|
157
157
|
const contentLength = res.headers.get("Content-Length");
|
|
158
158
|
if (contentLength && parseInt(contentLength, 10) === 0) return null;
|
|
159
159
|
const record = await res.json();
|
|
@@ -171,10 +171,10 @@ async function executeGet(query, id, filters) {
|
|
|
171
171
|
* })
|
|
172
172
|
*/
|
|
173
173
|
async function createRecord(action, options) {
|
|
174
|
-
const {
|
|
174
|
+
const { actionId, select } = resolveTarget(action, "create");
|
|
175
175
|
const data = options.data;
|
|
176
176
|
const rawFields = dealiasData(data, select);
|
|
177
|
-
const res = await fetch(`${dsUrl(
|
|
177
|
+
const res = await fetch(`${dsUrl(actionId)}/records/new`, {
|
|
178
178
|
method: "POST",
|
|
179
179
|
headers: {
|
|
180
180
|
"Content-Type": "application/json",
|
|
@@ -182,7 +182,7 @@ async function createRecord(action, options) {
|
|
|
182
182
|
},
|
|
183
183
|
body: JSON.stringify({ fields: rawFields })
|
|
184
184
|
});
|
|
185
|
-
if (!res.ok) throw new Error(`Softr datasource create failed for "${
|
|
185
|
+
if (!res.ok) throw new Error(`Softr datasource create failed for action "${actionId}": ${res.status}`);
|
|
186
186
|
const record = await res.json();
|
|
187
187
|
return {
|
|
188
188
|
id: record.id,
|
|
@@ -200,10 +200,10 @@ async function createRecord(action, options) {
|
|
|
200
200
|
*/
|
|
201
201
|
async function updateRecord(action, options) {
|
|
202
202
|
if (!options.id) throw new Error(`Softr datasource update: id must not be empty`);
|
|
203
|
-
const {
|
|
203
|
+
const { actionId, select } = resolveTarget(action, "update");
|
|
204
204
|
const data = options.data;
|
|
205
205
|
const rawFields = dealiasData(data, select);
|
|
206
|
-
const res = await fetch(`${dsUrl(
|
|
206
|
+
const res = await fetch(`${dsUrl(actionId)}/records/${options.id}`, {
|
|
207
207
|
method: "PATCH",
|
|
208
208
|
headers: {
|
|
209
209
|
"Content-Type": "application/json",
|
|
@@ -211,7 +211,7 @@ async function updateRecord(action, options) {
|
|
|
211
211
|
},
|
|
212
212
|
body: JSON.stringify({ fields: rawFields })
|
|
213
213
|
});
|
|
214
|
-
if (!res.ok) throw new Error(`Softr datasource update failed for "${
|
|
214
|
+
if (!res.ok) throw new Error(`Softr datasource update failed for action "${actionId}": ${res.status}`);
|
|
215
215
|
const record = await res.json();
|
|
216
216
|
return {
|
|
217
217
|
id: record.id,
|
|
@@ -225,12 +225,12 @@ async function updateRecord(action, options) {
|
|
|
225
225
|
* await ds.delete(removePost, { id: "record-id" })
|
|
226
226
|
*/
|
|
227
227
|
async function deleteRecord(action, options) {
|
|
228
|
-
const {
|
|
229
|
-
const res = await fetch(`${dsUrl(
|
|
228
|
+
const { actionId } = resolveTarget(action, "delete");
|
|
229
|
+
const res = await fetch(`${dsUrl(actionId)}/records/${options.id}`, {
|
|
230
230
|
method: "DELETE",
|
|
231
231
|
headers: { Authorization: `Bearer ${readSessionToken()}` }
|
|
232
232
|
});
|
|
233
|
-
if (!res.ok) throw new Error(`Softr datasource delete failed for "${
|
|
233
|
+
if (!res.ok) throw new Error(`Softr datasource delete failed for action "${actionId}": ${res.status}`);
|
|
234
234
|
}
|
|
235
235
|
function resolveTarget(subject, operation) {
|
|
236
236
|
const declaredBy = operation === "read" ? "defineQuery" : "defineMutation";
|
|
@@ -238,7 +238,7 @@ function resolveTarget(subject, operation) {
|
|
|
238
238
|
const action = subject;
|
|
239
239
|
assert(action.resource.operation === operation, () => `action "${action.id}" is declared as ${action.resource.operation}, not ${operation}`);
|
|
240
240
|
return {
|
|
241
|
-
|
|
241
|
+
actionId: action.id,
|
|
242
242
|
select: action.resource.fields ?? {}
|
|
243
243
|
};
|
|
244
244
|
}
|
package/dist/package.js
CHANGED
package/package.json
CHANGED
|
@@ -16,7 +16,7 @@ description: >-
|
|
|
16
16
|
metadata:
|
|
17
17
|
type: sub-skill
|
|
18
18
|
library: softr-sdk
|
|
19
|
-
library_version: 0.0.
|
|
19
|
+
library_version: 0.0.35-alpha.0
|
|
20
20
|
---
|
|
21
21
|
|
|
22
22
|
**Boundary.** `auth` lives on `@softr/sdk/server` and runs only inside a `createServerFn` handler — importing it into a component fails the build. `defineVisibility`, the hooks and every type come from `@softr/sdk`. The app is already wired (`src/start.ts`, `src/router.tsx`, `src/routes/__root.tsx`); never add a second registration. Load the core `softr-sdk` skill only if you are unsure this is the right sub-skill.
|
|
@@ -12,7 +12,7 @@ description: >-
|
|
|
12
12
|
metadata:
|
|
13
13
|
type: sub-skill
|
|
14
14
|
library: softr-sdk
|
|
15
|
-
library_version: 0.0.
|
|
15
|
+
library_version: 0.0.35-alpha.0
|
|
16
16
|
---
|
|
17
17
|
|
|
18
18
|
**Boundary.** `ds` lives on `@softr/sdk/server` and runs only inside a `createServerFn` handler or a server-side route hook — importing it into a component fails the build. `defineQuery` and every type come from `@softr/sdk` and can be imported anywhere. The app is already wired (`src/start.ts`, `src/router.tsx`, `src/routes/__root.tsx`); never add a second registration. Load the core `softr-sdk` skill only if you are unsure this is the right sub-skill.
|
|
@@ -10,7 +10,7 @@ description: >-
|
|
|
10
10
|
metadata:
|
|
11
11
|
type: sub-skill
|
|
12
12
|
library: softr-sdk
|
|
13
|
-
library_version: 0.0.
|
|
13
|
+
library_version: 0.0.35-alpha.0
|
|
14
14
|
---
|
|
15
15
|
|
|
16
16
|
**Boundary.** `useCurrentUser`, `usePermissions` and every type come from `@softr/sdk` and work anywhere; `ds` and `auth` live on `@softr/sdk/server` and run only inside a `createServerFn` handler. The app is already wired — `src/start.ts` registers `softrAuthMiddleware`, `src/routes/__root.tsx` publishes the visitor as route context — never add a second registration. Load the core `softr-sdk` skill only if you are unsure this is the right sub-skill.
|
|
@@ -9,7 +9,7 @@ description: >-
|
|
|
9
9
|
metadata:
|
|
10
10
|
type: sub-skill
|
|
11
11
|
library: softr-sdk
|
|
12
|
-
library_version: 0.0.
|
|
12
|
+
library_version: 0.0.35-alpha.0
|
|
13
13
|
---
|
|
14
14
|
|
|
15
15
|
**Boundary.** `upload` lives on `@softr/sdk/server` and runs inside server functions. `useFileUpload` and `FileItem` live on `@softr/sdk/client` and run only in components. `FileAttachment` comes from `@softr/sdk` and can be imported anywhere.
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
name: integrations
|
|
3
3
|
description: >-
|
|
4
4
|
Call a third-party service connected to the app as an integration:
|
|
5
|
-
defineIntegration from @softr/sdk declares the action with its
|
|
5
|
+
defineIntegration from @softr/sdk declares the action with its integrationId
|
|
6
6
|
and permissions; integration.createFetcher from @softr/sdk/server binds it and
|
|
7
7
|
returns a fetcher function you call with url, optional method, headers, and
|
|
8
8
|
body. Check res.ok before res.json().
|
|
9
9
|
metadata:
|
|
10
10
|
type: sub-skill
|
|
11
11
|
library: softr-sdk
|
|
12
|
-
library_version: 0.0.
|
|
12
|
+
library_version: 0.0.35-alpha.0
|
|
13
13
|
---
|
|
14
14
|
|
|
15
15
|
**Boundary.** `integration` lives on `@softr/sdk/server` and runs only inside a `createServerFn` handler — importing it into a component fails the build. `defineIntegration` and every type come from `@softr/sdk` and can be imported anywhere. Load the core `softr-sdk` skill only if you are unsure this is the right sub-skill.
|
|
@@ -34,14 +34,14 @@ When the user attaches integrations to the chat, they appear in the `## Attached
|
|
|
34
34
|
- "Gmail" — database `<databaseId>`, integration `<integrationId>`, type `GMAIL`
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
Pass the `integration` value as `integrationId` in `defineIntegration`. The `database` value is the table coordinate; integrations do not use it, so do not pass it anywhere. Use `integrationType` (e.g. `GMAIL`) to look up the base URL from the reference table below — then construct the full URL path, including any query parameters, directly in the `url` string.
|
|
38
38
|
|
|
39
39
|
## Declare the integration action
|
|
40
40
|
|
|
41
41
|
```ts
|
|
42
42
|
const googleCalendar = defineIntegration({
|
|
43
43
|
id: 'googleCalendar',
|
|
44
|
-
|
|
44
|
+
integrationId: '25d60213-ef4f-4fa0-b094-a46931b2d120',
|
|
45
45
|
permissions: { userGroup: 'LOGGED_IN_USERS' },
|
|
46
46
|
})
|
|
47
47
|
```
|
|
@@ -71,7 +71,7 @@ Include query parameters directly in the `url` string — there is no separate `
|
|
|
71
71
|
```ts
|
|
72
72
|
const slackDs = defineIntegration({
|
|
73
73
|
id: 'slack',
|
|
74
|
-
|
|
74
|
+
integrationId: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
|
|
75
75
|
permissions: { userGroup: 'LOGGED_IN_USERS' },
|
|
76
76
|
})
|
|
77
77
|
|
|
@@ -11,7 +11,7 @@ description: >-
|
|
|
11
11
|
metadata:
|
|
12
12
|
type: sub-skill
|
|
13
13
|
library: softr-sdk
|
|
14
|
-
library_version: 0.0.
|
|
14
|
+
library_version: 0.0.35-alpha.0
|
|
15
15
|
---
|
|
16
16
|
|
|
17
17
|
**Boundary.** `ds` lives on `@softr/sdk/server` and runs only inside a `createServerFn` handler — importing it into a component fails the build. `defineMutation` and every type come from `@softr/sdk` and can be imported anywhere. The app is already wired (`src/start.ts`, `src/router.tsx`, `src/routes/__root.tsx`); never add a second registration. Load the core `softr-sdk` skill only if you are unsure this is the right sub-skill.
|
|
@@ -12,7 +12,7 @@ description: >-
|
|
|
12
12
|
metadata:
|
|
13
13
|
type: sub-skill
|
|
14
14
|
library: softr-sdk
|
|
15
|
-
library_version: 0.0.
|
|
15
|
+
library_version: 0.0.35-alpha.0
|
|
16
16
|
---
|
|
17
17
|
|
|
18
18
|
**Boundary.** `ds` lives on `@softr/sdk/server` and runs only inside a `createServerFn` handler or a server-side route hook — importing it into a component fails the build. `defineQuery` and every type come from `@softr/sdk` and can be imported anywhere. The app is already wired (`src/start.ts`, `src/router.tsx`, `src/routes/__root.tsx`); never add a second registration. Load the core `softr-sdk` skill only if you are unsure this is the right sub-skill.
|
|
@@ -12,7 +12,7 @@ description: >-
|
|
|
12
12
|
metadata:
|
|
13
13
|
type: sub-skill
|
|
14
14
|
library: softr-sdk
|
|
15
|
-
library_version: 0.0.
|
|
15
|
+
library_version: 0.0.35-alpha.0
|
|
16
16
|
---
|
|
17
17
|
|
|
18
18
|
**Boundary.** `defineVisibility`, the error predicates and every type come from `@softr/sdk` and work anywhere; `ds` and `auth` live on `@softr/sdk/server` and run only inside a `createServerFn` handler. The app is already wired — `src/start.ts` registers `softrAuthMiddleware`, `src/routes/__root.tsx` publishes the visitor as route context — never add a second registration. Load the core `softr-sdk` skill only if you are unsure this is the right sub-skill.
|
|
@@ -9,7 +9,7 @@ description: >-
|
|
|
9
9
|
metadata:
|
|
10
10
|
type: sub-skill
|
|
11
11
|
library: softr-sdk
|
|
12
|
-
library_version: 0.0.
|
|
12
|
+
library_version: 0.0.35-alpha.0
|
|
13
13
|
---
|
|
14
14
|
|
|
15
15
|
**Boundary.** `workflow` lives on `@softr/sdk/server` and runs only inside a `createServerFn` handler — importing it into a component fails the build. `defineWorkflow` and every type come from `@softr/sdk` and can be imported anywhere. Load the core `softr-sdk` skill only if you are unsure this is the right sub-skill.
|