@withstudiocms/sdk 0.0.0-beta.0 → 0.1.0-beta.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/LICENSE +21 -0
- package/README.md +21 -0
- package/dist/cache.d.ts +109 -0
- package/dist/cache.js +94 -0
- package/dist/consts.d.ts +28 -0
- package/dist/consts.js +26 -0
- package/dist/context.d.ts +188 -0
- package/dist/context.js +33 -0
- package/dist/index.d.ts +1136 -0
- package/dist/index.js +24 -0
- package/dist/lib/diff.d.ts +39 -0
- package/dist/lib/diff.js +29 -0
- package/dist/lib/logger.d.ts +31 -0
- package/dist/lib/logger.js +131 -0
- package/dist/lib/pluginUtils.d.ts +221 -0
- package/dist/lib/pluginUtils.js +80 -0
- package/dist/modules/auth/index.d.ts +463 -0
- package/dist/modules/auth/index.js +412 -0
- package/dist/modules/clear/index.d.ts +72 -0
- package/dist/modules/clear/index.js +52 -0
- package/dist/modules/config/consts.d.ts +32 -0
- package/dist/modules/config/consts.js +18 -0
- package/dist/modules/config/index.d.ts +100 -0
- package/dist/modules/config/index.js +205 -0
- package/dist/modules/config/templates/mailer.d.ts +36 -0
- package/dist/modules/config/templates/mailer.js +218 -0
- package/dist/modules/config/type-utils.d.ts +13 -0
- package/dist/modules/config/type-utils.js +11 -0
- package/dist/modules/delete/index.d.ts +140 -0
- package/dist/modules/delete/index.js +274 -0
- package/dist/modules/diffTracking/index.d.ts +188 -0
- package/dist/modules/diffTracking/index.js +276 -0
- package/dist/modules/get/index.d.ts +272 -0
- package/dist/modules/get/index.js +466 -0
- package/dist/modules/index.d.ts +1003 -0
- package/dist/modules/index.js +37 -0
- package/dist/modules/init/index.d.ts +60 -0
- package/dist/modules/init/index.js +38 -0
- package/dist/modules/middleware/index.d.ts +56 -0
- package/dist/modules/middleware/index.js +50 -0
- package/dist/modules/notificationSettings/index.d.ts +57 -0
- package/dist/modules/notificationSettings/index.js +39 -0
- package/dist/modules/plugins/index.d.ts +166 -0
- package/dist/modules/plugins/index.js +261 -0
- package/dist/modules/post/index.d.ts +305 -0
- package/dist/modules/post/index.js +305 -0
- package/dist/modules/resetTokenBucket/index.d.ts +91 -0
- package/dist/modules/resetTokenBucket/index.js +93 -0
- package/dist/modules/rest_api/index.d.ts +92 -0
- package/dist/modules/rest_api/index.js +113 -0
- package/dist/modules/update/index.d.ts +184 -0
- package/dist/modules/update/index.js +174 -0
- package/dist/modules/util/collectors.d.ts +261 -0
- package/dist/modules/util/collectors.js +141 -0
- package/dist/modules/util/folderTree.d.ts +100 -0
- package/dist/modules/util/folderTree.js +176 -0
- package/dist/modules/util/generators.d.ts +83 -0
- package/dist/modules/util/generators.js +106 -0
- package/dist/modules/util/getFromNPM.d.ts +191 -0
- package/dist/modules/util/getFromNPM.js +100 -0
- package/dist/modules/util/index.d.ts +236 -0
- package/dist/modules/util/index.js +20 -0
- package/dist/modules/util/parsers.d.ts +60 -0
- package/dist/modules/util/parsers.js +43 -0
- package/dist/modules/util/slugify.d.ts +22 -0
- package/dist/modules/util/slugify.js +19 -0
- package/dist/modules/util/users.d.ts +99 -0
- package/dist/modules/util/users.js +78 -0
- package/dist/types.d.ts +360 -0
- package/dist/types.js +10 -0
- package/package.json +55 -7
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import { Effect } from '@withstudiocms/effect';
|
|
2
|
+
/**
|
|
3
|
+
* SDK Util Module
|
|
4
|
+
*
|
|
5
|
+
* This module aggregates various utility functionalities of the SDK.
|
|
6
|
+
*/
|
|
7
|
+
export declare const SDKUtilModule: Effect.Effect<{
|
|
8
|
+
Collectors: {
|
|
9
|
+
collectCategories: (input: {
|
|
10
|
+
readonly [x: number]: number;
|
|
11
|
+
readonly length: number;
|
|
12
|
+
toString: {};
|
|
13
|
+
toLocaleString: {};
|
|
14
|
+
concat: {};
|
|
15
|
+
join: {};
|
|
16
|
+
slice: {};
|
|
17
|
+
indexOf: {};
|
|
18
|
+
lastIndexOf: {};
|
|
19
|
+
every: {};
|
|
20
|
+
some: {};
|
|
21
|
+
forEach: {};
|
|
22
|
+
map: {};
|
|
23
|
+
filter: {};
|
|
24
|
+
reduce: {};
|
|
25
|
+
reduceRight: {};
|
|
26
|
+
find: {};
|
|
27
|
+
findIndex: {};
|
|
28
|
+
entries: {};
|
|
29
|
+
keys: {};
|
|
30
|
+
values: {};
|
|
31
|
+
includes: {};
|
|
32
|
+
flatMap: {};
|
|
33
|
+
flat: {};
|
|
34
|
+
at: {};
|
|
35
|
+
findLast: {};
|
|
36
|
+
findLastIndex: {};
|
|
37
|
+
toReversed: {};
|
|
38
|
+
toSorted: {};
|
|
39
|
+
toSpliced: {};
|
|
40
|
+
with: {};
|
|
41
|
+
[Symbol.iterator]: {};
|
|
42
|
+
readonly [Symbol.unscopables]: {
|
|
43
|
+
readonly [x: number]: boolean | undefined;
|
|
44
|
+
readonly length?: boolean | undefined;
|
|
45
|
+
toString?: boolean | undefined;
|
|
46
|
+
toLocaleString?: boolean | undefined;
|
|
47
|
+
concat?: boolean | undefined;
|
|
48
|
+
join?: boolean | undefined;
|
|
49
|
+
slice?: boolean | undefined;
|
|
50
|
+
indexOf?: boolean | undefined;
|
|
51
|
+
lastIndexOf?: boolean | undefined;
|
|
52
|
+
every?: boolean | undefined;
|
|
53
|
+
some?: boolean | undefined;
|
|
54
|
+
forEach?: boolean | undefined;
|
|
55
|
+
map?: boolean | undefined;
|
|
56
|
+
filter?: boolean | undefined;
|
|
57
|
+
reduce?: boolean | undefined;
|
|
58
|
+
reduceRight?: boolean | undefined;
|
|
59
|
+
find?: boolean | undefined;
|
|
60
|
+
findIndex?: boolean | undefined;
|
|
61
|
+
entries?: boolean | undefined;
|
|
62
|
+
keys?: boolean | undefined;
|
|
63
|
+
values?: boolean | undefined;
|
|
64
|
+
includes?: boolean | undefined;
|
|
65
|
+
flatMap?: boolean | undefined;
|
|
66
|
+
flat?: boolean | undefined;
|
|
67
|
+
at?: boolean | undefined;
|
|
68
|
+
findLast?: boolean | undefined;
|
|
69
|
+
findLastIndex?: boolean | undefined;
|
|
70
|
+
toReversed?: boolean | undefined;
|
|
71
|
+
toSorted?: boolean | undefined;
|
|
72
|
+
toSpliced?: boolean | undefined;
|
|
73
|
+
with?: boolean | undefined;
|
|
74
|
+
[Symbol.iterator]?: boolean | undefined;
|
|
75
|
+
readonly [Symbol.unscopables]?: boolean | undefined;
|
|
76
|
+
};
|
|
77
|
+
}) => Effect.Effect<readonly {
|
|
78
|
+
readonly name: string;
|
|
79
|
+
readonly id: number;
|
|
80
|
+
readonly parent: number | null | undefined;
|
|
81
|
+
readonly description: string;
|
|
82
|
+
readonly slug: string;
|
|
83
|
+
readonly meta: {
|
|
84
|
+
readonly [x: string]: unknown;
|
|
85
|
+
};
|
|
86
|
+
}[], import("@withstudiocms/kysely").DBCallbackFailure | import("@withstudiocms/kysely/core/errors").DatabaseError, never>;
|
|
87
|
+
collectTags: (input: {
|
|
88
|
+
readonly [x: number]: number;
|
|
89
|
+
readonly length: number;
|
|
90
|
+
toString: {};
|
|
91
|
+
toLocaleString: {};
|
|
92
|
+
concat: {};
|
|
93
|
+
join: {};
|
|
94
|
+
slice: {};
|
|
95
|
+
indexOf: {};
|
|
96
|
+
lastIndexOf: {};
|
|
97
|
+
every: {};
|
|
98
|
+
some: {};
|
|
99
|
+
forEach: {};
|
|
100
|
+
map: {};
|
|
101
|
+
filter: {};
|
|
102
|
+
reduce: {};
|
|
103
|
+
reduceRight: {};
|
|
104
|
+
find: {};
|
|
105
|
+
findIndex: {};
|
|
106
|
+
entries: {};
|
|
107
|
+
keys: {};
|
|
108
|
+
values: {};
|
|
109
|
+
includes: {};
|
|
110
|
+
flatMap: {};
|
|
111
|
+
flat: {};
|
|
112
|
+
at: {};
|
|
113
|
+
findLast: {};
|
|
114
|
+
findLastIndex: {};
|
|
115
|
+
toReversed: {};
|
|
116
|
+
toSorted: {};
|
|
117
|
+
toSpliced: {};
|
|
118
|
+
with: {};
|
|
119
|
+
[Symbol.iterator]: {};
|
|
120
|
+
readonly [Symbol.unscopables]: {
|
|
121
|
+
readonly [x: number]: boolean | undefined;
|
|
122
|
+
readonly length?: boolean | undefined;
|
|
123
|
+
toString?: boolean | undefined;
|
|
124
|
+
toLocaleString?: boolean | undefined;
|
|
125
|
+
concat?: boolean | undefined;
|
|
126
|
+
join?: boolean | undefined;
|
|
127
|
+
slice?: boolean | undefined;
|
|
128
|
+
indexOf?: boolean | undefined;
|
|
129
|
+
lastIndexOf?: boolean | undefined;
|
|
130
|
+
every?: boolean | undefined;
|
|
131
|
+
some?: boolean | undefined;
|
|
132
|
+
forEach?: boolean | undefined;
|
|
133
|
+
map?: boolean | undefined;
|
|
134
|
+
filter?: boolean | undefined;
|
|
135
|
+
reduce?: boolean | undefined;
|
|
136
|
+
reduceRight?: boolean | undefined;
|
|
137
|
+
find?: boolean | undefined;
|
|
138
|
+
findIndex?: boolean | undefined;
|
|
139
|
+
entries?: boolean | undefined;
|
|
140
|
+
keys?: boolean | undefined;
|
|
141
|
+
values?: boolean | undefined;
|
|
142
|
+
includes?: boolean | undefined;
|
|
143
|
+
flatMap?: boolean | undefined;
|
|
144
|
+
flat?: boolean | undefined;
|
|
145
|
+
at?: boolean | undefined;
|
|
146
|
+
findLast?: boolean | undefined;
|
|
147
|
+
findLastIndex?: boolean | undefined;
|
|
148
|
+
toReversed?: boolean | undefined;
|
|
149
|
+
toSorted?: boolean | undefined;
|
|
150
|
+
toSpliced?: boolean | undefined;
|
|
151
|
+
with?: boolean | undefined;
|
|
152
|
+
[Symbol.iterator]?: boolean | undefined;
|
|
153
|
+
readonly [Symbol.unscopables]?: boolean | undefined;
|
|
154
|
+
};
|
|
155
|
+
}) => Effect.Effect<readonly {
|
|
156
|
+
readonly name: string;
|
|
157
|
+
readonly id: number;
|
|
158
|
+
readonly description: string;
|
|
159
|
+
readonly slug: string;
|
|
160
|
+
readonly meta: {
|
|
161
|
+
readonly [x: string]: unknown;
|
|
162
|
+
};
|
|
163
|
+
}[], import("@withstudiocms/kysely").DBCallbackFailure | import("@withstudiocms/kysely/core/errors").DatabaseError, never>;
|
|
164
|
+
collectPageData: {
|
|
165
|
+
(page: import("../../types.js").tsPageDataSelect, tree: import("../../types.js").FolderNode[]): Effect.Effect<import("../../types.js").CombinedPageData, import("./collectors.js").CollectorError | import("./folderTree.js").FolderTreeError | import("@withstudiocms/kysely").DBCallbackFailure | import("@withstudiocms/kysely/core/errors").DatabaseError | import("effect/ParseResult").ParseError, never>;
|
|
166
|
+
(page: import("../../types.js").tsPageDataSelect, tree: import("../../types.js").FolderNode[], metaOnly: boolean): Effect.Effect<import("../../types.js").MetaOnlyPageData, import("./collectors.js").CollectorError | import("./folderTree.js").FolderTreeError | import("@withstudiocms/kysely").DBCallbackFailure | import("@withstudiocms/kysely/core/errors").DatabaseError | import("effect/ParseResult").ParseError, never>;
|
|
167
|
+
};
|
|
168
|
+
collectUserData: (user: {
|
|
169
|
+
readonly name: string;
|
|
170
|
+
readonly id: string;
|
|
171
|
+
readonly url: string | null | undefined;
|
|
172
|
+
readonly email: string | null | undefined;
|
|
173
|
+
readonly avatar: string | null | undefined;
|
|
174
|
+
readonly username: string;
|
|
175
|
+
readonly password: string | null | undefined;
|
|
176
|
+
readonly updatedAt: Date;
|
|
177
|
+
readonly createdAt: Date;
|
|
178
|
+
readonly emailVerified: boolean;
|
|
179
|
+
readonly notifications: string | null | undefined;
|
|
180
|
+
}) => Effect.Effect<import("../../types.js").CombinedUserData, import("@withstudiocms/kysely").DBCallbackFailure | import("@withstudiocms/kysely/core/errors").DatabaseError, never>;
|
|
181
|
+
};
|
|
182
|
+
FolderTree: {
|
|
183
|
+
generateFolderTree: (folders: readonly {
|
|
184
|
+
readonly name: string;
|
|
185
|
+
readonly id: string;
|
|
186
|
+
readonly parent: string | null | undefined;
|
|
187
|
+
}[]) => Effect.Effect<import("../../types.js").FolderNode[], import("./folderTree.js").FolderTreeError, never>;
|
|
188
|
+
getFullPath: (tree: import("../../types.js").FolderNode[], path: string[]) => Effect.Effect<string[], import("./folderTree.js").FolderTreeError, never>;
|
|
189
|
+
findNodeByPath: (tree: import("../../types.js").FolderNode[], path: string[]) => Effect.Effect<import("../../types.js").FolderNode | null, import("./folderTree.js").FolderTreeError, never>;
|
|
190
|
+
findNodesAlongPath: (tree: import("../../types.js").FolderNode[], path: string[]) => Effect.Effect<import("../../types.js").FolderNode[], import("./folderTree.js").FolderTreeError, never>;
|
|
191
|
+
findNodesAlongPathToId: (tree: import("../../types.js").FolderNode[], id: string) => Effect.Effect<import("../../types.js").FolderNode[], import("./folderTree.js").FolderTreeError, never>;
|
|
192
|
+
findNodeById: (tree: import("../../types.js").FolderNode[], id: string) => Effect.Effect<import("../../types.js").FolderNode | null, import("./folderTree.js").FolderTreeError, never>;
|
|
193
|
+
addPageToFolderTree: (tree: import("../../types.js").FolderNode[], folderId: string, newPage: import("../../types.js").FolderNode) => Effect.Effect<import("../../types.js").FolderNode[], import("./folderTree.js").FolderTreeError, never>;
|
|
194
|
+
buildFolderTree: Effect.Effect<import("../../types.js").FolderNode[], import("@withstudiocms/kysely").DBCallbackFailure | import("@withstudiocms/kysely/core/errors").DatabaseError | import("./folderTree.js").FolderTreeError, never>;
|
|
195
|
+
getAvailableFolders: Effect.Effect<import("../../types.js").FolderListItem[], import("@withstudiocms/kysely").DBCallbackFailure | import("@withstudiocms/kysely/core/errors").DatabaseError, never>;
|
|
196
|
+
};
|
|
197
|
+
Generators: {
|
|
198
|
+
generateRandomIDNumber: (length: number) => Effect.Effect<number, import("./generators.js").GeneratorError, never>;
|
|
199
|
+
generateRandomPassword: (length: number) => Effect.Effect<string, import("./generators.js").GeneratorError, never>;
|
|
200
|
+
generateToken: (userId: string, noExpire?: boolean | undefined) => Effect.Effect<string, import("./generators.js").GeneratorError, never>;
|
|
201
|
+
testToken: (token: string) => Effect.Effect<import("../../types.js").JwtVerificationResult, import("./generators.js").GeneratorError, never>;
|
|
202
|
+
};
|
|
203
|
+
GetFromNPM: {
|
|
204
|
+
getVersion: (pkg: string, ver?: string | undefined) => Effect.Effect<{
|
|
205
|
+
version: string;
|
|
206
|
+
lastCacheUpdate: Date;
|
|
207
|
+
}, import("effect/Cause").UnknownException | Error | import("effect/ParseResult").ParseError, never>;
|
|
208
|
+
getDataFromNPM: (pkg: string, ver?: string | undefined) => Effect.Effect<import("./getFromNPM.js").NpmRegistryResponseSchema, import("effect/Cause").UnknownException | Error | import("effect/ParseResult").ParseError, never>;
|
|
209
|
+
};
|
|
210
|
+
Parsers: {
|
|
211
|
+
parseIdNumberArray: (ids: unknown) => Effect.Effect<readonly number[], import("effect/ParseResult").ParseError, never>;
|
|
212
|
+
parseIdStringArray: (ids: unknown) => Effect.Effect<readonly string[], import("effect/ParseResult").ParseError, never>;
|
|
213
|
+
fixDiff: <T extends import("../../types.js").diffItem | import("../../types.js").diffItem[]>(items: T) => Effect.Effect<import("../../types.js").DiffReturnType<T>, import("./parsers.js").ParsersError, never>;
|
|
214
|
+
};
|
|
215
|
+
Users: {
|
|
216
|
+
verifyRank: (users: readonly {
|
|
217
|
+
readonly name: string;
|
|
218
|
+
readonly id: string;
|
|
219
|
+
readonly url: string | null | undefined;
|
|
220
|
+
readonly email: string | null | undefined;
|
|
221
|
+
readonly avatar: string | null | undefined;
|
|
222
|
+
readonly username: string;
|
|
223
|
+
readonly password: string | null | undefined;
|
|
224
|
+
readonly updatedAt: Date;
|
|
225
|
+
readonly createdAt: Date;
|
|
226
|
+
readonly emailVerified: boolean;
|
|
227
|
+
readonly notifications: string | null | undefined;
|
|
228
|
+
}[], permissions: readonly {
|
|
229
|
+
readonly user: string;
|
|
230
|
+
readonly rank: "owner" | "admin" | "editor" | "visitor" | "unknown";
|
|
231
|
+
}[], rank: string) => Effect.Effect<import("../../types.js").SingleRank[], import("./users.js").UsersError, never>;
|
|
232
|
+
combineRanks: (rank: string, users: import("../../types.js").SingleRank[]) => Effect.Effect<import("../../types.js").CombinedRank[], import("./users.js").UsersError, never>;
|
|
233
|
+
clearUserReferences: (userId: string) => Effect.Effect<boolean, import("@withstudiocms/kysely").DBCallbackFailure | import("@withstudiocms/kysely/core/errors").QueryError | import("@withstudiocms/kysely/core/errors").NotFoundError, never>;
|
|
234
|
+
};
|
|
235
|
+
}, import("effect/ConfigError").ConfigError, import("../../context.js").DBClientLive | import("../../context.js").SDKDefaults | import("../../cache.js").CacheService>;
|
|
236
|
+
export default SDKUtilModule;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Effect } from "@withstudiocms/effect";
|
|
2
|
+
import { SDKCollectors as Collectors } from "./collectors.js";
|
|
3
|
+
import { SDKFolderTree as FolderTree } from "./folderTree.js";
|
|
4
|
+
import { SDKGenerators as Generators } from "./generators.js";
|
|
5
|
+
import { GetFromNPM } from "./getFromNPM.js";
|
|
6
|
+
import { SDKParsers as Parsers } from "./parsers.js";
|
|
7
|
+
import { SDKUsers as Users } from "./users.js";
|
|
8
|
+
const SDKUtilModule = Effect.all({
|
|
9
|
+
Collectors,
|
|
10
|
+
FolderTree,
|
|
11
|
+
Generators,
|
|
12
|
+
GetFromNPM,
|
|
13
|
+
Parsers,
|
|
14
|
+
Users
|
|
15
|
+
});
|
|
16
|
+
var util_default = SDKUtilModule;
|
|
17
|
+
export {
|
|
18
|
+
SDKUtilModule,
|
|
19
|
+
util_default as default
|
|
20
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { Effect } from '@withstudiocms/effect';
|
|
2
|
+
import type { DiffReturnType, diffItem } from '../../types.js';
|
|
3
|
+
declare const ParsersError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => import("effect/Cause").YieldableError & {
|
|
4
|
+
readonly _tag: "ParsersError";
|
|
5
|
+
} & Readonly<A>;
|
|
6
|
+
/**
|
|
7
|
+
* Error class for parser errors.
|
|
8
|
+
*/
|
|
9
|
+
export declare class ParsersError extends ParsersError_base<{
|
|
10
|
+
cause: unknown;
|
|
11
|
+
}> {
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Utility function to handle errors in parser functions.
|
|
15
|
+
*
|
|
16
|
+
* @param _try - The function to execute that may throw an error.
|
|
17
|
+
* @returns An effect that either yields the result of the function or a ParsersError.
|
|
18
|
+
*/
|
|
19
|
+
export declare const useParsersError: <T>(_try: () => T) => Effect.Effect<T, ParsersError, never>;
|
|
20
|
+
/**
|
|
21
|
+
* SDKParsers
|
|
22
|
+
*
|
|
23
|
+
* Produces a collection of Effect-aware parser utilities used by the SDK.
|
|
24
|
+
*
|
|
25
|
+
* The returned object contains three helpers:
|
|
26
|
+
* - parseIdNumberArray(ids): Parses an unknown value into an array of numbers using the
|
|
27
|
+
* SDK's NumberArraySchema and returns an Effect that yields the parsed array or a parse error.
|
|
28
|
+
* - parseIdStringArray(ids): Parses an unknown value into an array of strings using the
|
|
29
|
+
* SDK's StringArraySchema and returns an Effect that yields the parsed array or a parse error.
|
|
30
|
+
* - fixDiff(items): Accepts a single diff item or an array of diff items and returns an Effect
|
|
31
|
+
* that yields the same shape with the `pageMetaData` field parsed from a JSON string into an
|
|
32
|
+
* object shaped as { start: Partial<tsPageDataSelect>, end: Partial<tsPageDataSelect> }.
|
|
33
|
+
*
|
|
34
|
+
* @remarks
|
|
35
|
+
* - Each helper is implemented as an Effect.fn so callers receive an Effect that encapsulates
|
|
36
|
+
* parsing work and errors.
|
|
37
|
+
* - fixDiff uses JSON.parse on the pageMetaData field and wraps failures using the SDK's parser
|
|
38
|
+
* error handling, so JSON or schema parsing problems are surfaced as a ParsersError.
|
|
39
|
+
* - The functions preserve all other fields on the diff items while only transforming pageMetaData.
|
|
40
|
+
*
|
|
41
|
+
* @typeParam T - For fixDiff: the input type, constrained to either a single diffItem or an array of diffItem.
|
|
42
|
+
*
|
|
43
|
+
* @returns An object with three properties:
|
|
44
|
+
* - parseIdNumberArray: (ids: unknown) => Effect<..., number[], ...> — yields a number array on success.
|
|
45
|
+
* - parseIdStringArray: (ids: unknown) => Effect<..., string[], ...> — yields a string array on success.
|
|
46
|
+
* - fixDiff: <T extends diffItem | diffItem[]>(items: T) => Effect<..., DiffReturnType<T>, ...> —
|
|
47
|
+
* yields the input diff item(s) with parsed pageMetaData.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* // (pseudo-code demonstrating usage in an Effect context)
|
|
51
|
+
* const parsers = yield* SDKParsers;
|
|
52
|
+
* const numbers = yield* parsers.parseIdNumberArray(someUnknown);
|
|
53
|
+
* const fixed = yield* parsers.fixDiff(someDiffOrArray);
|
|
54
|
+
*/
|
|
55
|
+
export declare const SDKParsers: Effect.Effect<{
|
|
56
|
+
parseIdNumberArray: (ids: unknown) => Effect.Effect<readonly number[], import("effect/ParseResult").ParseError, never>;
|
|
57
|
+
parseIdStringArray: (ids: unknown) => Effect.Effect<readonly string[], import("effect/ParseResult").ParseError, never>;
|
|
58
|
+
fixDiff: <T extends diffItem | diffItem[]>(items: T) => Effect.Effect<DiffReturnType<T>, ParsersError, never>;
|
|
59
|
+
}, never, never>;
|
|
60
|
+
export {};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Data, Effect, Schema } from "@withstudiocms/effect";
|
|
2
|
+
class ParsersError extends Data.TaggedError("ParsersError") {
|
|
3
|
+
}
|
|
4
|
+
const useParsersError = (_try) => Effect.try({
|
|
5
|
+
try: _try,
|
|
6
|
+
catch: (cause) => new ParsersError({ cause })
|
|
7
|
+
});
|
|
8
|
+
const SDKParsers = Effect.gen(function* () {
|
|
9
|
+
const parseIdNumberArray = Effect.fn(
|
|
10
|
+
(ids) => Schema.decodeUnknown(Schema.Array(Schema.Number))(ids)
|
|
11
|
+
);
|
|
12
|
+
const parseIdStringArray = Effect.fn(
|
|
13
|
+
(ids) => Schema.decodeUnknown(Schema.Array(Schema.String))(ids)
|
|
14
|
+
);
|
|
15
|
+
const fixDiff = Effect.fn(
|
|
16
|
+
(items) => useParsersError(() => {
|
|
17
|
+
if (Array.isArray(items)) {
|
|
18
|
+
const toReturn = [];
|
|
19
|
+
for (const { pageMetaData, ...rest } of items) {
|
|
20
|
+
toReturn.push({
|
|
21
|
+
...rest,
|
|
22
|
+
pageMetaData
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
return toReturn;
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
...items,
|
|
29
|
+
pageMetaData: items.pageMetaData
|
|
30
|
+
};
|
|
31
|
+
})
|
|
32
|
+
);
|
|
33
|
+
return {
|
|
34
|
+
parseIdNumberArray,
|
|
35
|
+
parseIdStringArray,
|
|
36
|
+
fixDiff
|
|
37
|
+
};
|
|
38
|
+
});
|
|
39
|
+
export {
|
|
40
|
+
ParsersError,
|
|
41
|
+
SDKParsers,
|
|
42
|
+
useParsersError
|
|
43
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Options for the slugify function
|
|
3
|
+
*/
|
|
4
|
+
export interface SlugifyOptions {
|
|
5
|
+
/**
|
|
6
|
+
* The separator to use in the slug
|
|
7
|
+
* @default '-'
|
|
8
|
+
*/
|
|
9
|
+
separator?: string;
|
|
10
|
+
/**
|
|
11
|
+
* Whether to convert the slug to lowercase
|
|
12
|
+
* @default true
|
|
13
|
+
*/
|
|
14
|
+
lowercase?: boolean;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Converts a string into a URL-safe slug
|
|
18
|
+
* @param text - The text to slugify
|
|
19
|
+
* @param options - Optional configuration
|
|
20
|
+
* @returns A URL-safe slug string
|
|
21
|
+
*/
|
|
22
|
+
export declare function slugify(text: string, options?: SlugifyOptions): string;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
function escapeRegExp(str) {
|
|
2
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3
|
+
}
|
|
4
|
+
function emptyStringToUndefined(value) {
|
|
5
|
+
return value.trim() === "" ? void 0 : value;
|
|
6
|
+
}
|
|
7
|
+
function slugify(text, options = {}) {
|
|
8
|
+
const { separator: rawSeparator = "-", lowercase = true } = options;
|
|
9
|
+
const separator = emptyStringToUndefined(rawSeparator) || "-";
|
|
10
|
+
const escapedSeparator = escapeRegExp(separator);
|
|
11
|
+
let slug = text.toString().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(new RegExp(`[^a-zA-Z0-9\\s${escapedSeparator}]`, "g"), "").trim().replace(/\s+/g, separator).replace(new RegExp(`(?:${escapedSeparator})+`, "g"), separator);
|
|
12
|
+
if (lowercase) {
|
|
13
|
+
slug = slug.toLowerCase();
|
|
14
|
+
}
|
|
15
|
+
return slug;
|
|
16
|
+
}
|
|
17
|
+
export {
|
|
18
|
+
slugify
|
|
19
|
+
};
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { Effect } from '@withstudiocms/effect';
|
|
2
|
+
import { DBClientLive, SDKDefaults } from '../../context.js';
|
|
3
|
+
import type { CombinedRank, SingleRank } from '../../types.js';
|
|
4
|
+
declare const UsersError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => import("effect/Cause").YieldableError & {
|
|
5
|
+
readonly _tag: "UsersError";
|
|
6
|
+
} & Readonly<A>;
|
|
7
|
+
/**
|
|
8
|
+
* Custom error class for user-related operations in the SDK.
|
|
9
|
+
*/
|
|
10
|
+
export declare class UsersError extends UsersError_base<{
|
|
11
|
+
cause: unknown;
|
|
12
|
+
}> {
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Helper function to wrap user-related operations with error handling.
|
|
16
|
+
*
|
|
17
|
+
* @param _try - A function that performs the desired operation.
|
|
18
|
+
* @returns An Effect that either succeeds with the result of the operation or fails with a UsersError.
|
|
19
|
+
*/
|
|
20
|
+
export declare const useUsersError: <T>(_try: () => T) => Effect.Effect<T, UsersError, never>;
|
|
21
|
+
/**
|
|
22
|
+
* SDKUsers
|
|
23
|
+
*
|
|
24
|
+
* An Effect-based service that provides user-related utility functions for verifying ranks,
|
|
25
|
+
* combining rank metadata, and clearing all database references to a user.
|
|
26
|
+
*
|
|
27
|
+
* This Effect generator depends on SDKDefaults and DBClientLive to obtain:
|
|
28
|
+
* - GhostUserDefaults: used as the fallback/ghost user id when reassigning records
|
|
29
|
+
* - effectDb: an Effect wrapper around the database client used for queries/updates
|
|
30
|
+
*
|
|
31
|
+
* The yielded object contains the following functions:
|
|
32
|
+
*
|
|
33
|
+
* - verifyRank(users, permissions, rank)
|
|
34
|
+
* - Purpose: Determine which users from a provided user list hold a specific rank based
|
|
35
|
+
* on a permissions collection.
|
|
36
|
+
* - Parameters:
|
|
37
|
+
* - users: an array of user rows/objects (tsUsersSelect[]), expected to include `id` and `name`.
|
|
38
|
+
* - permissions: an array of permission rows/objects (tsPermissions['Select']['Type'][]) that include a `user` reference and a `rank` string.
|
|
39
|
+
* - rank: the rank string to filter by.
|
|
40
|
+
* - Behavior: Filters the permissions by the provided rank, finds the corresponding user
|
|
41
|
+
* objects by id from the `users` array, and returns an array of SingleRank objects
|
|
42
|
+
* ({ id, name }) for the matching users.
|
|
43
|
+
* - Errors: Execution is wrapped in the users error handling helper (useUsersError), so
|
|
44
|
+
* input or mapping errors are surfaced through that wrapper.
|
|
45
|
+
*
|
|
46
|
+
* - combineRanks(rank, users)
|
|
47
|
+
* - Purpose: Attach a rank to a set of SingleRank entries, producing CombinedRank entries.
|
|
48
|
+
* - Parameters:
|
|
49
|
+
* - rank: the rank string to assign to each user.
|
|
50
|
+
* - users: an array of SingleRank objects (each with `id` and `name`).
|
|
51
|
+
* - Behavior: Returns a new array where each user object is shallow-copied and augmented
|
|
52
|
+
* with the provided `rank` property. Execution is wrapped in useUsersError for consistent error handling.
|
|
53
|
+
*
|
|
54
|
+
* - clearUserReferences(userId)
|
|
55
|
+
* - Purpose: Remove or reassign all database references to a user when that user must be
|
|
56
|
+
* cleaned up (e.g., account deletion).
|
|
57
|
+
* - Parameters:
|
|
58
|
+
* - userId: the id of the user whose references should be removed or reassigned.
|
|
59
|
+
* - Behavior: Performs a sequence of effectful DB operations (via effectDb):
|
|
60
|
+
* 1. Deletes reset tokens from StudioCMSUserResetTokens for the userId.
|
|
61
|
+
* 2. Deletes OAuth accounts from StudioCMSOAuthAccounts for the userId.
|
|
62
|
+
* 3. Deletes permission rows from StudioCMSPermissions for the userId.
|
|
63
|
+
* 4. Deletes session rows from StudioCMSSessionTable for the userId.
|
|
64
|
+
* 5. Updates StudioCMSDiffTracking rows to set `userId` => GhostUserDefaults.id where they referenced the deleted user.
|
|
65
|
+
* 6. Updates StudioCMSPageData rows to set `authorId` => GhostUserDefaults.id where they referenced the deleted user.
|
|
66
|
+
* - Each DB call uses executeTakeFirstOrThrow semantics, so failures in any step will throw.
|
|
67
|
+
* - Returns: A boolean true on successful completion of all operations.
|
|
68
|
+
*
|
|
69
|
+
* Notes:
|
|
70
|
+
* - SDKUsers itself is an Effect value; consumers must run/interpret the Effect to obtain the utilities.
|
|
71
|
+
* - verifyRank and combineRanks are lightweight, in-memory operations wrapped with the users error helper;
|
|
72
|
+
* clearUserReferences performs real database operations and may throw on failure.
|
|
73
|
+
*
|
|
74
|
+
* Example:
|
|
75
|
+
* @example
|
|
76
|
+
* const usersEffect = SDKUsers; // Effect that yields { verifyRank, combineRanks, clearUserReferences }
|
|
77
|
+
* // run the effect in your runtime to access the utilities and then call the functions as needed.
|
|
78
|
+
*/
|
|
79
|
+
export declare const SDKUsers: Effect.Effect<{
|
|
80
|
+
verifyRank: (users: readonly {
|
|
81
|
+
readonly name: string;
|
|
82
|
+
readonly id: string;
|
|
83
|
+
readonly url: string | null | undefined;
|
|
84
|
+
readonly email: string | null | undefined;
|
|
85
|
+
readonly avatar: string | null | undefined;
|
|
86
|
+
readonly username: string;
|
|
87
|
+
readonly password: string | null | undefined;
|
|
88
|
+
readonly updatedAt: Date;
|
|
89
|
+
readonly createdAt: Date;
|
|
90
|
+
readonly emailVerified: boolean;
|
|
91
|
+
readonly notifications: string | null | undefined;
|
|
92
|
+
}[], permissions: readonly {
|
|
93
|
+
readonly user: string;
|
|
94
|
+
readonly rank: "owner" | "admin" | "editor" | "visitor" | "unknown";
|
|
95
|
+
}[], rank: string) => Effect.Effect<SingleRank[], UsersError, never>;
|
|
96
|
+
combineRanks: (rank: string, users: SingleRank[]) => Effect.Effect<CombinedRank[], UsersError, never>;
|
|
97
|
+
clearUserReferences: (userId: string) => Effect.Effect<boolean, import("@withstudiocms/kysely").DBCallbackFailure | import("@withstudiocms/kysely/core/errors").QueryError | import("@withstudiocms/kysely/core/errors").NotFoundError, never>;
|
|
98
|
+
}, never, DBClientLive | SDKDefaults>;
|
|
99
|
+
export {};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { Data, Effect } from "@withstudiocms/effect";
|
|
2
|
+
import { DBClientLive, SDKDefaults } from "../../context.js";
|
|
3
|
+
class UsersError extends Data.TaggedError("UsersError") {
|
|
4
|
+
}
|
|
5
|
+
const useUsersError = (_try) => Effect.try({
|
|
6
|
+
try: _try,
|
|
7
|
+
catch: (error) => new UsersError({ cause: error })
|
|
8
|
+
});
|
|
9
|
+
const SDKUsers = Effect.gen(function* () {
|
|
10
|
+
const [{ GhostUserDefaults }, { effectDb }] = yield* Effect.all([SDKDefaults, DBClientLive]);
|
|
11
|
+
const verifyRank = Effect.fn(
|
|
12
|
+
(users, permissions, rank) => useUsersError(() => {
|
|
13
|
+
const filteredUsers = permissions.filter((user) => user.rank === rank);
|
|
14
|
+
const permitted = [];
|
|
15
|
+
for (const user of filteredUsers) {
|
|
16
|
+
const foundUser = users.find((u) => u.id === user.user);
|
|
17
|
+
if (foundUser) {
|
|
18
|
+
permitted.push({ id: foundUser.id, name: foundUser.name });
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return permitted;
|
|
22
|
+
})
|
|
23
|
+
);
|
|
24
|
+
const combineRanks = Effect.fn(
|
|
25
|
+
(rank, users) => useUsersError(() => users.map((user) => ({ ...user, rank })))
|
|
26
|
+
);
|
|
27
|
+
const clearUserReferences = Effect.fn(function* (userId) {
|
|
28
|
+
yield* Effect.all([
|
|
29
|
+
...[
|
|
30
|
+
{
|
|
31
|
+
table: "StudioCMSUserResetTokens",
|
|
32
|
+
lhs: "userId"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
table: "StudioCMSOAuthAccounts",
|
|
36
|
+
lhs: "userId"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
table: "StudioCMSPermissions",
|
|
40
|
+
lhs: "user"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
table: "StudioCMSSessionTable",
|
|
44
|
+
lhs: "userId"
|
|
45
|
+
}
|
|
46
|
+
].map(
|
|
47
|
+
({ table, lhs }) => effectDb((db) => db.deleteFrom(table).where(lhs, "=", userId).executeTakeFirstOrThrow())
|
|
48
|
+
),
|
|
49
|
+
...[
|
|
50
|
+
{
|
|
51
|
+
table: "StudioCMSDiffTracking",
|
|
52
|
+
lhs: "userId",
|
|
53
|
+
update: { userId: GhostUserDefaults.id }
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
table: "StudioCMSPageData",
|
|
57
|
+
lhs: "authorId",
|
|
58
|
+
update: { authorId: GhostUserDefaults.id }
|
|
59
|
+
}
|
|
60
|
+
].map(
|
|
61
|
+
({ table, lhs, update }) => effectDb(
|
|
62
|
+
(db) => db.updateTable(table).set(update).where(lhs, "=", userId).executeTakeFirstOrThrow()
|
|
63
|
+
)
|
|
64
|
+
)
|
|
65
|
+
]);
|
|
66
|
+
return true;
|
|
67
|
+
});
|
|
68
|
+
return {
|
|
69
|
+
verifyRank,
|
|
70
|
+
combineRanks,
|
|
71
|
+
clearUserReferences
|
|
72
|
+
};
|
|
73
|
+
});
|
|
74
|
+
export {
|
|
75
|
+
SDKUsers,
|
|
76
|
+
UsersError,
|
|
77
|
+
useUsersError
|
|
78
|
+
};
|