@softr/sdk 0.0.13 → 0.0.15

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 CHANGED
@@ -1,3 +1 @@
1
- import { useUserTimezone } from "./client/timezone.js";
2
- import "@tanstack/react-start/client-only";
3
- export { useUserTimezone };
1
+ import "@tanstack/react-start/client-only";
package/dist/client.js CHANGED
@@ -1,4 +1,3 @@
1
- import { useUserTimezone } from "./client/timezone.js";
2
1
  import "@tanstack/react-start/client-only";
3
2
 
4
- export { useUserTimezone };
3
+ export { };
@@ -1,18 +1,25 @@
1
1
  import { buildFilterCriteria, buildOrderBy, dealiasFilterCriteria, dealiasOrderBy } from "./query.js";
2
+ import { panic } from "../assertions.js";
2
3
  import { readUserTimezone } from "../cookies.js";
4
+ import { sessionConfig } from "../auth/config.js";
3
5
  import { readSessionToken } from "../auth/session.js";
4
6
 
5
7
  //#region src/core/datasource.ts
6
8
  const MAX_RECORD_COUNT = 100;
7
9
  const COUNT_CNT = "COUNT_CNT";
8
- const BASE_URL = () => (import.meta.env.VITE_SOFTR_BASE_URL ?? "").replace(/\/$/, "");
10
+ const dsUrl = (datasourceId) => {
11
+ const datasourceApiUrl = process.env.SOFTR_DATASOURCE_API_URL || "https://datasource-api-staging12.softr.io";
12
+ if (!datasourceApiUrl) panic("SOFTR_DATASOURCE_API_URL is not set.");
13
+ const { applicationId } = sessionConfig();
14
+ return `${withoutTrailingSlash(datasourceApiUrl)}/v1/datasource/vibe/applications/${applicationId}/datasources/${datasourceId}`;
15
+ };
9
16
  async function listRecords(datasourceId, options = {}) {
10
17
  const { select, where, orderBy } = options;
11
18
  const count = Math.min(options.limit ?? 20, MAX_RECORD_COUNT);
12
19
  const offset = options.offset ?? null;
13
20
  const filterCriteria = where ? dealiasFilterCriteria(buildFilterCriteria(where), select ?? {}) : {};
14
21
  const sortingOption = orderBy ? dealiasOrderBy(buildOrderBy(orderBy), select ?? {}) : void 0;
15
- const res = await fetch(`${BASE_URL()}/api/datasources/${datasourceId}/records`, {
22
+ const res = await fetch(`${dsUrl(datasourceId)}/records`, {
16
23
  method: "POST",
17
24
  headers: {
18
25
  "Content-Type": "application/json",
@@ -44,7 +51,7 @@ async function listRecords(datasourceId, options = {}) {
44
51
  async function getRecord(datasourceId, options) {
45
52
  if (options.id !== void 0) {
46
53
  if (!options.id) throw new Error(`Softr datasource get: id must not be empty`);
47
- const res = await fetch(`${BASE_URL()}/api/datasources/${datasourceId}/records/${options.id}`, {
54
+ const res = await fetch(`${dsUrl(datasourceId)}/records/${options.id}`, {
48
55
  method: "POST",
49
56
  headers: {
50
57
  "Content-Type": "application/json",
@@ -65,32 +72,42 @@ async function getRecord(datasourceId, options) {
65
72
  })).records[0] ?? null;
66
73
  }
67
74
  async function createRecord(datasourceId, options) {
68
- const res = await fetch(`${BASE_URL()}/api/datasources/${datasourceId}/records`, {
75
+ const rawFields = options.select ? dealiasData(options.data, options.select) : options.data;
76
+ const res = await fetch(`${dsUrl(datasourceId)}/records/new`, {
69
77
  method: "POST",
70
78
  headers: {
71
79
  "Content-Type": "application/json",
72
80
  "Authorization": `Bearer ${readSessionToken()}`
73
81
  },
74
- body: JSON.stringify({ fields: options.fields })
82
+ body: JSON.stringify({ fields: rawFields })
75
83
  });
76
84
  if (!res.ok) throw new Error(`Softr datasource create failed for "${datasourceId}": ${res.status}`);
77
- return (await res.json()).record;
85
+ const record = await res.json();
86
+ return options.select ? {
87
+ id: record.id,
88
+ fields: aliasFields(record.fields, options.select)
89
+ } : record;
78
90
  }
79
91
  async function updateRecord(datasourceId, options) {
80
92
  if (!options.id) throw new Error(`Softr datasource update: id must not be empty`);
81
- const res = await fetch(`${BASE_URL()}/api/datasources/${datasourceId}/records/${options.id}`, {
93
+ const rawFields = options.select ? dealiasData(options.data, options.select) : options.data;
94
+ const res = await fetch(`${dsUrl(datasourceId)}/records/${options.id}`, {
82
95
  method: "PATCH",
83
96
  headers: {
84
97
  "Content-Type": "application/json",
85
98
  "Authorization": `Bearer ${readSessionToken()}`
86
99
  },
87
- body: JSON.stringify({ fields: options.fields })
100
+ body: JSON.stringify({ fields: rawFields })
88
101
  });
89
102
  if (!res.ok) throw new Error(`Softr datasource update failed for "${datasourceId}": ${res.status}`);
90
- return (await res.json()).record;
103
+ const record = await res.json();
104
+ return options.select ? {
105
+ id: record.id,
106
+ fields: aliasFields(record.fields, options.select)
107
+ } : record;
91
108
  }
92
109
  async function deleteRecord(datasourceId, id) {
93
- const res = await fetch(`${BASE_URL()}/api/datasources/${datasourceId}/records/${id}`, {
110
+ const res = await fetch(`${dsUrl(datasourceId)}/records/${id}`, {
94
111
  method: "DELETE",
95
112
  headers: { "Authorization": `Bearer ${readSessionToken()}` }
96
113
  });
@@ -100,7 +117,7 @@ async function getMetric(datasourceId, options) {
100
117
  const { select, where, aggregation, field } = options;
101
118
  const fieldId = field ? select?.[field] ?? field : void 0;
102
119
  const filterCriteria = where ? dealiasFilterCriteria(buildFilterCriteria(where), select ?? {}) : {};
103
- const res = await fetch(`${BASE_URL()}/api/datasources/${datasourceId}/chartMetricData`, {
120
+ const res = await fetch(`${dsUrl(datasourceId)}/metric/data`, {
104
121
  method: "POST",
105
122
  headers: {
106
123
  "Content-Type": "application/json",
@@ -139,7 +156,7 @@ async function getChartData(datasourceId, options) {
139
156
  field: field ? select?.[field] ?? field : void 0,
140
157
  aggregation
141
158
  }));
142
- const res = await fetch(`${BASE_URL()}/api/datasources/${datasourceId}/chartData`, {
159
+ const res = await fetch(`${dsUrl(datasourceId)}/chart`, {
143
160
  method: "POST",
144
161
  headers: {
145
162
  "Content-Type": "application/json",
@@ -182,6 +199,11 @@ function aliasFields(fields, aliases) {
182
199
  for (const [alias, fieldId] of Object.entries(aliases)) result[alias] = fields[fieldId];
183
200
  return result;
184
201
  }
202
+ function dealiasData(data, select) {
203
+ const result = {};
204
+ for (const [alias, value] of Object.entries(data)) result[select[alias] ?? alias] = value;
205
+ return result;
206
+ }
185
207
  const ds = {
186
208
  list: listRecords,
187
209
  get: getRecord,
@@ -191,6 +213,9 @@ const ds = {
191
213
  metric: getMetric,
192
214
  chartData: getChartData
193
215
  };
216
+ function withoutTrailingSlash(url) {
217
+ return url.replace(/\/+$/, "");
218
+ }
194
219
 
195
220
  //#endregion
196
221
  export { ds };
package/dist/index.d.ts CHANGED
@@ -5,4 +5,5 @@ import { Permissions } from "./auth/permissions.js";
5
5
  import { SoftrContext } from "./auth/context.js";
6
6
  import { AccessBehaviour, AccessCheck, AccessError, AccessReason, RouteVisibility, VisibilityHandle, defineVisibility, isAccessError, isAlreadySignedInError, isForbiddenError, isUnauthenticatedError } from "./routes/visibility.js";
7
7
  import { getSoftrContext, initialSoftrContext, softrAuthMiddleware, useCurrentUser, usePermissions } from "./auth/isomorphic.js";
8
- export { type AccessBehaviour, type AccessCheck, type AccessError, type AccessReason, type AggregationFunction, type ChartDataOptions, type ChartDataResult, type CreateOptions, type DatasourcePermissions, type GetOptions, type ListOptions, type ListResult, type MetricOptions, type MetricResult, type Permissions, type RouteVisibility, type SoftrContext, type SoftrMe, type SoftrPermissions, type SoftrRecord, type SoftrUser, type SoftrUserGroupId, type SoftrUserGroups, type UpdateOptions, type User, type VisibilityHandle, defineVisibility, getSoftrContext, initialSoftrContext, isAccessError, isAlreadySignedInError, isForbiddenError, isUnauthenticatedError, q, softrAuthMiddleware, useCurrentUser, usePermissions };
8
+ import { useUserTimezone } from "./timezone.js";
9
+ export { type AccessBehaviour, type AccessCheck, type AccessError, type AccessReason, type AggregationFunction, type ChartDataOptions, type ChartDataResult, type CreateOptions, type DatasourcePermissions, type GetOptions, type ListOptions, type ListResult, type MetricOptions, type MetricResult, type Permissions, type RouteVisibility, type SoftrContext, type SoftrMe, type SoftrPermissions, type SoftrRecord, type SoftrUser, type SoftrUserGroupId, type SoftrUserGroups, type UpdateOptions, type User, type VisibilityHandle, defineVisibility, getSoftrContext, initialSoftrContext, isAccessError, isAlreadySignedInError, isForbiddenError, isUnauthenticatedError, q, softrAuthMiddleware, useCurrentUser, usePermissions, useUserTimezone };
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { q } from "./core/query.js";
2
2
  import { defineVisibility, isAccessError, isAlreadySignedInError, isForbiddenError, isUnauthenticatedError } from "./routes/visibility.js";
3
3
  import { getSoftrContext, initialSoftrContext, softrAuthMiddleware, useCurrentUser, usePermissions } from "./auth/isomorphic.js";
4
+ import { useUserTimezone } from "./timezone.js";
4
5
 
5
- export { defineVisibility, getSoftrContext, initialSoftrContext, isAccessError, isAlreadySignedInError, isForbiddenError, isUnauthenticatedError, q, softrAuthMiddleware, useCurrentUser, usePermissions };
6
+ export { defineVisibility, getSoftrContext, initialSoftrContext, isAccessError, isAlreadySignedInError, isForbiddenError, isUnauthenticatedError, q, softrAuthMiddleware, useCurrentUser, usePermissions, useUserTimezone };
@@ -0,0 +1,4 @@
1
+ //#region src/timezone.d.ts
2
+ declare function useUserTimezone(): void;
3
+ //#endregion
4
+ export { useUserTimezone };
@@ -1,6 +1,6 @@
1
1
  import { useEffect } from "react";
2
2
 
3
- //#region src/client/timezone.ts
3
+ //#region src/timezone.ts
4
4
  function useUserTimezone() {
5
5
  useEffect(() => {
6
6
  document.cookie = `user-timezone=${Intl.DateTimeFormat().resolvedOptions().timeZone}; path=/`;
package/dist/types.d.ts CHANGED
@@ -95,11 +95,21 @@ interface ChartDataResult {
95
95
  executionTimestamp: Date;
96
96
  }
97
97
  interface CreateOptions {
98
- fields: Record<string, unknown>;
98
+ /**
99
+ * Maps human-readable aliases to Softr field IDs.
100
+ * When provided, `data` keys are interpreted as aliases.
101
+ */
102
+ select?: Record<string, string>;
103
+ data: Record<string, unknown>;
99
104
  }
100
105
  interface UpdateOptions {
101
106
  id: string;
102
- fields: Record<string, unknown>;
107
+ /**
108
+ * Maps human-readable aliases to Softr field IDs.
109
+ * When provided, `data` keys are interpreted as aliases.
110
+ */
111
+ select?: Record<string, string>;
112
+ data: Record<string, unknown>;
103
113
  }
104
114
  //#endregion
105
115
  export { AggregationFunction, ChartDataOptions, ChartDataResult, CreateOptions, DatasourcePermissions, GetOptions, ListOptions, ListResult, MetricOptions, MetricResult, SoftrMe, SoftrPermissions, SoftrRecord, SoftrUser, UpdateOptions };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@softr/sdk",
3
- "version": "0.0.13",
3
+ "version": "0.0.15",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": { "types": "./dist/index.d.ts", "import": "./dist/index.js" },
@@ -1,4 +0,0 @@
1
- //#region src/client/timezone.d.ts
2
- declare function useUserTimezone(): void;
3
- //#endregion
4
- export { useUserTimezone };