@softr/sdk 0.0.25 → 0.0.26
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 +195 -0
- package/dist/action.js +21 -0
- package/dist/auth/isomorphic.d.ts +1 -2
- package/dist/auth/permissions.d.ts +7 -2
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +639 -0
- package/dist/codegen/datasource-types.js +471 -0
- package/dist/codegen/softr-env.js +103 -0
- package/dist/codegen/user-groups.js +11 -0
- package/dist/core/integration.js +1 -1
- package/dist/datasource/chart.d.ts +196 -0
- package/dist/datasource/chart.js +289 -0
- package/dist/datasource/datasource.d.ts +16 -0
- package/dist/datasource/datasource.js +17 -0
- package/dist/datasource/fields.d.ts +122 -0
- package/dist/datasource/fields.js +82 -0
- package/dist/datasource/filter.d.ts +30 -0
- package/dist/datasource/filter.js +146 -0
- package/dist/datasource/record.d.ts +138 -0
- package/dist/datasource/record.js +258 -0
- package/dist/index.d.ts +3 -5
- package/dist/index.js +2 -2
- package/dist/package.js +5 -0
- package/dist/routes/visibility.d.ts +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.js +1 -1
- package/package.json +2 -1
- package/skills/softr-sdk/SKILL.md +6 -2
- package/skills/softr-sdk/auth/SKILL.md +1 -1
- package/skills/softr-sdk/current-user/SKILL.md +1 -1
- package/skills/softr-sdk/data-mutations/SKILL.md +1 -1
- package/skills/softr-sdk/integrations/SKILL.md +140 -0
- package/skills/softr-sdk/reading-records/SKILL.md +1 -1
- package/skills/softr-sdk/routes-and-visibility/SKILL.md +1 -1
- package/dist/core/datasource.d.ts +0 -31
- package/dist/core/datasource.js +0 -226
- package/dist/core/query.d.ts +0 -354
- package/dist/core/query.js +0 -528
- package/dist/core/utils.js +0 -14
- package/dist/types.d.ts +0 -128
package/dist/action.d.ts
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { SoftrUserGroupId } from "./auth/user.js";
|
|
2
|
+
|
|
3
|
+
//#region src/action.d.ts
|
|
4
|
+
type ActionOperation = "read" | "create" | "update" | "delete";
|
|
5
|
+
type ActionPermission = {
|
|
6
|
+
userGroup: "ALL_USERS";
|
|
7
|
+
} | {
|
|
8
|
+
userGroup: "NON_LOGGED_IN_USERS";
|
|
9
|
+
} | {
|
|
10
|
+
userGroup: "LOGGED_IN_USERS";
|
|
11
|
+
userGroupIds?: Array<SoftrUserGroupId>;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Describes the datasources available in the app and their read, create and update types.
|
|
15
|
+
*
|
|
16
|
+
* This lets datasource IDs and fields in actions be type-checked.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* declare module "@softr/sdk" {
|
|
20
|
+
* interface SoftrDatasources {
|
|
21
|
+
* FrkQIVpeTtfJDT: {
|
|
22
|
+
* name: "Cafes"
|
|
23
|
+
* primaryField: "9QrOA"
|
|
24
|
+
* read: CafesRead
|
|
25
|
+
* create: CafesCreate
|
|
26
|
+
* update: CafesUpdate
|
|
27
|
+
* fieldTypes: { "9QrOA": "SINGLE_LINE_TEXT"; "1G3aA": "DATETIME" }
|
|
28
|
+
* }
|
|
29
|
+
* }
|
|
30
|
+
* }
|
|
31
|
+
*/
|
|
32
|
+
interface SoftrDatasources {}
|
|
33
|
+
type SoftrDatasourceId = keyof SoftrDatasources extends never ? string : keyof SoftrDatasources & string;
|
|
34
|
+
/** The read type one datasource returns. */
|
|
35
|
+
type ReadOf<TDatasource$1> = TDatasource$1 extends keyof SoftrDatasources ? SoftrDatasources[TDatasource$1] extends {
|
|
36
|
+
read: infer TRecord;
|
|
37
|
+
} ? TRecord : never : never;
|
|
38
|
+
/**
|
|
39
|
+
* The DSv2 type name one field declares, as codegen emitted it: `"NUMBER"`, `"SELECT[]"`.
|
|
40
|
+
* `never` for a field no augmentation describes.
|
|
41
|
+
*/
|
|
42
|
+
type FieldTypeOf<TDatasource$1, TFieldId> = TDatasource$1 extends keyof SoftrDatasources ? SoftrDatasources[TDatasource$1] extends {
|
|
43
|
+
fieldTypes: infer TTypes;
|
|
44
|
+
} ? TFieldId extends keyof TTypes ? TTypes[TFieldId] : never : never : never;
|
|
45
|
+
/** The write type one datasource accepts for one operation. */
|
|
46
|
+
type WriteOf<TDatasource$1, TOperation$1> = TDatasource$1 extends keyof SoftrDatasources ? TOperation$1 extends keyof SoftrDatasources[TDatasource$1] ? SoftrDatasources[TDatasource$1][TOperation$1] : never : never;
|
|
47
|
+
/** The field ids a write may name. Any string, until {@link SoftrDatasources} is declared. */
|
|
48
|
+
type FieldIdOf<TDatasource$1, TOperation$1> = keyof SoftrDatasources extends never ? string : keyof WriteOf<TDatasource$1, TOperation$1> & string;
|
|
49
|
+
/**
|
|
50
|
+
* The field ids a read may name. Any string, until {@link SoftrDatasources} is declared.
|
|
51
|
+
*
|
|
52
|
+
* A read constrains against the record type rather than a write type, because a read may
|
|
53
|
+
* name a field no write can: a formula or a lookup is on the record and on neither.
|
|
54
|
+
*/
|
|
55
|
+
type ReadFieldIdOf<TDatasource$1> = keyof SoftrDatasources extends never ? string : keyof ReadOf<TDatasource$1> & string;
|
|
56
|
+
/**
|
|
57
|
+
* What an action declares, as the type layer reads it. `permission` is absent because no
|
|
58
|
+
* call site depends on it, and the build reads it off the value.
|
|
59
|
+
*/
|
|
60
|
+
type ActionShape = {
|
|
61
|
+
id: string;
|
|
62
|
+
datasource: SoftrDatasourceId;
|
|
63
|
+
operation: ActionOperation;
|
|
64
|
+
fields?: Record<string, string>;
|
|
65
|
+
};
|
|
66
|
+
/** What a read declares. A read is the whole field list, so `fields` is not optional. */
|
|
67
|
+
type ReadShape = ActionShape & {
|
|
68
|
+
operation: "read";
|
|
69
|
+
fields: Record<string, string>;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* What one action writes: its own aliases, each resolved to the value that field accepts.
|
|
73
|
+
*
|
|
74
|
+
* An alias renames the field, and a mapped type keeps a property's docstring only while it
|
|
75
|
+
* keeps the key, so the prose that sits on the field in `softr-env.d.ts` does not reach the
|
|
76
|
+
* call site. The type does.
|
|
77
|
+
*/
|
|
78
|
+
type ActionData<TShape extends ActionShape> = keyof SoftrDatasources extends never ? Record<string, unknown> : TShape extends {
|
|
79
|
+
datasource: infer TDatasource;
|
|
80
|
+
operation: infer TOperation;
|
|
81
|
+
fields: infer TFields;
|
|
82
|
+
} ? { [Alias in keyof TFields]?: WriteOf<TDatasource, TOperation>[TFields[Alias] & keyof WriteOf<TDatasource, TOperation>] } : Record<string, unknown>;
|
|
83
|
+
/**
|
|
84
|
+
* What a mutation reads back: the same aliases, resolved against the table's read type.
|
|
85
|
+
*
|
|
86
|
+
* A write returns the record it wrote, and the SDK aliases its fields on the way out, so a
|
|
87
|
+
* field the action never declared is absent from the result as well as from the payload.
|
|
88
|
+
*
|
|
89
|
+
* Every alias the action does declare is present. An empty field reads as `null`, so nothing
|
|
90
|
+
* here is optional.
|
|
91
|
+
*/
|
|
92
|
+
type ActionRecord<TShape extends ActionShape> = keyof SoftrDatasources extends never ? Record<string, unknown> : TShape extends {
|
|
93
|
+
datasource: infer TDatasource;
|
|
94
|
+
fields: infer TFields;
|
|
95
|
+
} ? { [Alias in keyof TFields]: ReadOf<TDatasource>[TFields[Alias] & keyof ReadOf<TDatasource>] } : Record<string, unknown>;
|
|
96
|
+
declare const brand: unique symbol;
|
|
97
|
+
/**
|
|
98
|
+
* A handle to a declared action, and the only thing a mutation accepts. The brand keeps it
|
|
99
|
+
* nominal, so an object literal of the same shape will not do and no mutation can be reached
|
|
100
|
+
* without passing through a declaration the build reads.
|
|
101
|
+
*
|
|
102
|
+
* The brand carries the declaration itself, which is what lets a call site resolve what the
|
|
103
|
+
* action writes without codegen having said anything about this action.
|
|
104
|
+
*/
|
|
105
|
+
type Action<TShape extends ActionShape = ActionShape> = {
|
|
106
|
+
type: "action";
|
|
107
|
+
id: TShape["id"];
|
|
108
|
+
} & {
|
|
109
|
+
readonly [brand]: TShape;
|
|
110
|
+
};
|
|
111
|
+
/** What a write action declares. */
|
|
112
|
+
type WriteDeclaration<TId extends string, TDatasource$1, TOperation$1, TFields$1> = {
|
|
113
|
+
id: TId;
|
|
114
|
+
datasource: TDatasource$1;
|
|
115
|
+
operation: TOperation$1;
|
|
116
|
+
fields: TFields$1;
|
|
117
|
+
permission: ActionPermission;
|
|
118
|
+
};
|
|
119
|
+
/** What a read action declares. */
|
|
120
|
+
type ReadDeclaration<TId extends string, TDatasource$1, TFields$1> = {
|
|
121
|
+
id: TId;
|
|
122
|
+
datasource: TDatasource$1;
|
|
123
|
+
operation: "read";
|
|
124
|
+
fields: TFields$1;
|
|
125
|
+
permission: ActionPermission;
|
|
126
|
+
};
|
|
127
|
+
/** What a delete action declares. `fields?: never` so a stray one is rejected rather than ignored. */
|
|
128
|
+
type DeleteDeclaration<TId extends string, TDatasource$1> = {
|
|
129
|
+
id: TId;
|
|
130
|
+
datasource: TDatasource$1;
|
|
131
|
+
operation: "delete";
|
|
132
|
+
fields?: never;
|
|
133
|
+
permission: ActionPermission;
|
|
134
|
+
};
|
|
135
|
+
/** The whole declaration, which is what an action is at runtime and in the manifest. */
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Declares a data operation: which datasource, which of the four operations, which fields
|
|
139
|
+
* participate, and who may run it.
|
|
140
|
+
*
|
|
141
|
+
* One call per action, at module scope, with a literal: the build reads these declarations
|
|
142
|
+
* to publish what the app may read and write.
|
|
143
|
+
*
|
|
144
|
+
* The keys of `fields` are aliases the app chooses and the values are field ids of the
|
|
145
|
+
* datasource the action names. The result, `data`, `where` and `orderBy` at the call site
|
|
146
|
+
* are all keyed by those aliases, so nothing there restates what the action already says.
|
|
147
|
+
*
|
|
148
|
+
* A read fixes the table and the columns. It does not fix which rows: `where`, `orderBy` and
|
|
149
|
+
* the paging arguments stay at the call site, because a list screen changes them as the user
|
|
150
|
+
* types and a declaration cannot follow that.
|
|
151
|
+
*
|
|
152
|
+
* @example
|
|
153
|
+
* const publishedPosts = defineAction({
|
|
154
|
+
* id: "publishedPosts",
|
|
155
|
+
* datasource: "8f14e45f-ceea-467a-9d0b-2c1a0e3b5d77",
|
|
156
|
+
* operation: "read",
|
|
157
|
+
* fields: { title: "V1StGXR8", author: "Z7pQm4Kd", publishedAt: "Xp2dLh6v" },
|
|
158
|
+
* permission: { userGroup: "ALL_USERS" },
|
|
159
|
+
* })
|
|
160
|
+
*
|
|
161
|
+
* const { records } = await ds
|
|
162
|
+
* .list(publishedPosts)
|
|
163
|
+
* .where((q) => q.publishedAt.lte(today))
|
|
164
|
+
* .orderBy((q) => q.publishedAt.desc)
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* const closeOrderAction = defineAction({
|
|
168
|
+
* id: "closeOrder",
|
|
169
|
+
* datasource: "8f14e45f-ceea-467a-9d0b-2c1a0e3b5d77",
|
|
170
|
+
* operation: "update",
|
|
171
|
+
* fields: { status: "V1StGXR8", closedAt: "Z7pQm4Kd" },
|
|
172
|
+
* permission: { userGroup: "LOGGED_IN_USERS", userGroupIds: ["grp_staff"] },
|
|
173
|
+
* })
|
|
174
|
+
*
|
|
175
|
+
* await ds.update(closeOrderAction, { id, data: { status: "closed" } })
|
|
176
|
+
*/
|
|
177
|
+
declare function defineAction<const TId extends string, const TDatasource$1 extends SoftrDatasourceId, const TFields$1 extends Record<string, ReadFieldIdOf<TDatasource$1>>>(definition: ReadDeclaration<TId, TDatasource$1, TFields$1>): Action<{
|
|
178
|
+
id: TId;
|
|
179
|
+
datasource: TDatasource$1;
|
|
180
|
+
operation: "read";
|
|
181
|
+
fields: TFields$1;
|
|
182
|
+
}>;
|
|
183
|
+
declare function defineAction<const TId extends string, const TDatasource$1 extends SoftrDatasourceId, const TOperation$1 extends "create" | "update", const TFields$1 extends Record<string, FieldIdOf<TDatasource$1, TOperation$1>>>(definition: WriteDeclaration<TId, TDatasource$1, TOperation$1, TFields$1>): Action<{
|
|
184
|
+
id: TId;
|
|
185
|
+
datasource: TDatasource$1;
|
|
186
|
+
operation: TOperation$1;
|
|
187
|
+
fields: TFields$1;
|
|
188
|
+
}>;
|
|
189
|
+
declare function defineAction<const TId extends string, const TDatasource$1 extends SoftrDatasourceId>(definition: DeleteDeclaration<TId, TDatasource$1>): Action<{
|
|
190
|
+
id: TId;
|
|
191
|
+
datasource: TDatasource$1;
|
|
192
|
+
operation: "delete";
|
|
193
|
+
}>;
|
|
194
|
+
//#endregion
|
|
195
|
+
export { Action, ActionData, ActionRecord, ActionShape, FieldTypeOf, ReadOf, ReadShape, SoftrDatasources, defineAction };
|
package/dist/action.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
//#region src/action.ts
|
|
2
|
+
function defineAction(definition) {
|
|
3
|
+
return {
|
|
4
|
+
type: "action",
|
|
5
|
+
...definition
|
|
6
|
+
};
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* True for anything {@link defineAction} produced, whatever its operation.
|
|
10
|
+
*
|
|
11
|
+
* Matched on `type` rather than with `instanceof`, so two copies of the SDK in one
|
|
12
|
+
* dependency tree still recognise each other's actions.
|
|
13
|
+
*/
|
|
14
|
+
function isAction(value) {
|
|
15
|
+
if (typeof value !== "object" || value === null) return false;
|
|
16
|
+
const candidate = value;
|
|
17
|
+
return candidate.type === "action" && typeof candidate.id === "string" && typeof candidate.datasource === "string";
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
//#endregion
|
|
21
|
+
export { defineAction, isAction };
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { User } from "./user.js";
|
|
2
|
-
import { DatasourcePermissions } from "
|
|
3
|
-
import { Permissions } from "./permissions.js";
|
|
2
|
+
import { DatasourcePermissions, Permissions } from "./permissions.js";
|
|
4
3
|
import { Session, SoftrContext } from "./context.js";
|
|
5
4
|
import * as _tanstack_react_start0 from "@tanstack/react-start";
|
|
6
5
|
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { DatasourcePermissions } from "../types.js";
|
|
2
1
|
import { z } from "zod";
|
|
3
2
|
|
|
4
3
|
//#region src/auth/permissions.d.ts
|
|
@@ -9,9 +8,15 @@ import { z } from "zod";
|
|
|
9
8
|
* Rendering hints, not enforcement: every data request is authorized again
|
|
10
9
|
* server-side, and these may go stale between the two.
|
|
11
10
|
*/
|
|
11
|
+
type DatasourcePermissions = {
|
|
12
|
+
read: boolean;
|
|
13
|
+
create: boolean;
|
|
14
|
+
update: boolean;
|
|
15
|
+
delete: boolean;
|
|
16
|
+
};
|
|
12
17
|
type Permissions = {
|
|
13
18
|
/** Keyed by datasource id. */
|
|
14
19
|
datasources: Record<string, DatasourcePermissions>;
|
|
15
20
|
};
|
|
16
21
|
//#endregion
|
|
17
|
-
export { Permissions };
|
|
22
|
+
export { DatasourcePermissions, Permissions };
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|