@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.
Files changed (71) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +21 -0
  3. package/dist/cache.d.ts +109 -0
  4. package/dist/cache.js +94 -0
  5. package/dist/consts.d.ts +28 -0
  6. package/dist/consts.js +26 -0
  7. package/dist/context.d.ts +188 -0
  8. package/dist/context.js +33 -0
  9. package/dist/index.d.ts +1136 -0
  10. package/dist/index.js +24 -0
  11. package/dist/lib/diff.d.ts +39 -0
  12. package/dist/lib/diff.js +29 -0
  13. package/dist/lib/logger.d.ts +31 -0
  14. package/dist/lib/logger.js +131 -0
  15. package/dist/lib/pluginUtils.d.ts +221 -0
  16. package/dist/lib/pluginUtils.js +80 -0
  17. package/dist/modules/auth/index.d.ts +463 -0
  18. package/dist/modules/auth/index.js +412 -0
  19. package/dist/modules/clear/index.d.ts +72 -0
  20. package/dist/modules/clear/index.js +52 -0
  21. package/dist/modules/config/consts.d.ts +32 -0
  22. package/dist/modules/config/consts.js +18 -0
  23. package/dist/modules/config/index.d.ts +100 -0
  24. package/dist/modules/config/index.js +205 -0
  25. package/dist/modules/config/templates/mailer.d.ts +36 -0
  26. package/dist/modules/config/templates/mailer.js +218 -0
  27. package/dist/modules/config/type-utils.d.ts +13 -0
  28. package/dist/modules/config/type-utils.js +11 -0
  29. package/dist/modules/delete/index.d.ts +140 -0
  30. package/dist/modules/delete/index.js +274 -0
  31. package/dist/modules/diffTracking/index.d.ts +188 -0
  32. package/dist/modules/diffTracking/index.js +276 -0
  33. package/dist/modules/get/index.d.ts +272 -0
  34. package/dist/modules/get/index.js +466 -0
  35. package/dist/modules/index.d.ts +1003 -0
  36. package/dist/modules/index.js +37 -0
  37. package/dist/modules/init/index.d.ts +60 -0
  38. package/dist/modules/init/index.js +38 -0
  39. package/dist/modules/middleware/index.d.ts +56 -0
  40. package/dist/modules/middleware/index.js +50 -0
  41. package/dist/modules/notificationSettings/index.d.ts +57 -0
  42. package/dist/modules/notificationSettings/index.js +39 -0
  43. package/dist/modules/plugins/index.d.ts +166 -0
  44. package/dist/modules/plugins/index.js +261 -0
  45. package/dist/modules/post/index.d.ts +305 -0
  46. package/dist/modules/post/index.js +305 -0
  47. package/dist/modules/resetTokenBucket/index.d.ts +91 -0
  48. package/dist/modules/resetTokenBucket/index.js +93 -0
  49. package/dist/modules/rest_api/index.d.ts +92 -0
  50. package/dist/modules/rest_api/index.js +113 -0
  51. package/dist/modules/update/index.d.ts +184 -0
  52. package/dist/modules/update/index.js +174 -0
  53. package/dist/modules/util/collectors.d.ts +261 -0
  54. package/dist/modules/util/collectors.js +141 -0
  55. package/dist/modules/util/folderTree.d.ts +100 -0
  56. package/dist/modules/util/folderTree.js +176 -0
  57. package/dist/modules/util/generators.d.ts +83 -0
  58. package/dist/modules/util/generators.js +106 -0
  59. package/dist/modules/util/getFromNPM.d.ts +191 -0
  60. package/dist/modules/util/getFromNPM.js +100 -0
  61. package/dist/modules/util/index.d.ts +236 -0
  62. package/dist/modules/util/index.js +20 -0
  63. package/dist/modules/util/parsers.d.ts +60 -0
  64. package/dist/modules/util/parsers.js +43 -0
  65. package/dist/modules/util/slugify.d.ts +22 -0
  66. package/dist/modules/util/slugify.js +19 -0
  67. package/dist/modules/util/users.d.ts +99 -0
  68. package/dist/modules/util/users.js +78 -0
  69. package/dist/types.d.ts +360 -0
  70. package/dist/types.js +10 -0
  71. package/package.json +55 -7
@@ -0,0 +1,466 @@
1
+ import { Effect, Schema } from "@withstudiocms/effect";
2
+ import {
3
+ StudioCMSPageData,
4
+ StudioCMSPageFolderStructure,
5
+ StudioCMSPermissions,
6
+ StudioCMSUsersTable
7
+ } from "@withstudiocms/kysely";
8
+ import CacheService from "../../cache.js";
9
+ import { cacheKeyGetters, cacheTags } from "../../consts.js";
10
+ import { DBClientLive, SDKDefaults } from "../../context.js";
11
+ import SDKConfigModule from "../config/index.js";
12
+ import { SDKCollectors } from "../util/collectors.js";
13
+ import { SDKFolderTree } from "../util/folderTree.js";
14
+ import { GetFromNPM } from "../util/getFromNPM.js";
15
+ import { SDKUsers } from "../util/users.js";
16
+ const ranks = ["owner", "admin", "editor", "visitor"];
17
+ class PaginateError extends Error {
18
+ _tag = "PaginateError";
19
+ }
20
+ class KillSwitch {
21
+ _tag = "KillSwitch";
22
+ }
23
+ const SDKGetModule = Effect.gen(function* () {
24
+ const [
25
+ { withCodec, withDecoder },
26
+ { verifyRank, combineRanks },
27
+ { collectUserData, collectPageData },
28
+ { siteConfig: sdkSiteConfig },
29
+ { GhostUserDefaults },
30
+ { memoize },
31
+ { buildFolderTree, getAvailableFolders, addPageToFolderTree },
32
+ { getVersion }
33
+ ] = yield* Effect.all([
34
+ DBClientLive,
35
+ SDKUsers,
36
+ SDKCollectors,
37
+ SDKConfigModule,
38
+ SDKDefaults,
39
+ CacheService,
40
+ SDKFolderTree,
41
+ GetFromNPM
42
+ ]);
43
+ const _getUsers = withDecoder({
44
+ decoder: Schema.Array(StudioCMSUsersTable.Select),
45
+ callbackFn: (db) => db((client) => client.selectFrom("StudioCMSUsersTable").selectAll().execute())
46
+ });
47
+ const _getUserById = withCodec({
48
+ encoder: Schema.String,
49
+ decoder: Schema.UndefinedOr(StudioCMSUsersTable.Select),
50
+ callbackFn: (db, userId) => db(
51
+ (client) => client.selectFrom("StudioCMSUsersTable").selectAll().where("id", "=", userId).executeTakeFirst()
52
+ )
53
+ });
54
+ const _getUserByUsername = withCodec({
55
+ encoder: Schema.String,
56
+ decoder: Schema.UndefinedOr(StudioCMSUsersTable.Select),
57
+ callbackFn: (db, username) => db(
58
+ (client) => client.selectFrom("StudioCMSUsersTable").selectAll().where("username", "=", username).executeTakeFirst()
59
+ )
60
+ });
61
+ const _getUserByEmail = withCodec({
62
+ encoder: Schema.String,
63
+ decoder: Schema.UndefinedOr(StudioCMSUsersTable.Select),
64
+ callbackFn: (db, email) => db(
65
+ (client) => client.selectFrom("StudioCMSUsersTable").selectAll().where("email", "=", email).executeTakeFirst()
66
+ )
67
+ });
68
+ const _getCurrentPermissions = withDecoder({
69
+ decoder: Schema.Array(StudioCMSPermissions.Select),
70
+ callbackFn: (db) => db((client) => client.selectFrom("StudioCMSPermissions").selectAll().execute())
71
+ });
72
+ const _getFolder = withCodec({
73
+ encoder: Schema.String,
74
+ decoder: Schema.UndefinedOr(StudioCMSPageFolderStructure.Select),
75
+ callbackFn: (db, folderId) => db(
76
+ (client) => client.selectFrom("StudioCMSPageFolderStructure").selectAll().where("id", "=", folderId).executeTakeFirst()
77
+ )
78
+ });
79
+ const _getAllPagesPaginated = withCodec({
80
+ encoder: Schema.Struct({
81
+ limit: Schema.Number,
82
+ offset: Schema.Number
83
+ }),
84
+ decoder: Schema.Array(StudioCMSPageData.Select),
85
+ callbackFn: (db, { limit, offset }) => db(
86
+ (client) => client.selectFrom("StudioCMSPageData").selectAll().orderBy("title", "asc").limit(limit).offset(offset).execute()
87
+ )
88
+ });
89
+ const _getAllPagesBase = withDecoder({
90
+ decoder: Schema.Array(StudioCMSPageData.Select),
91
+ callbackFn: (db) => db(
92
+ (client) => client.selectFrom("StudioCMSPageData").selectAll().orderBy("title", "asc").execute()
93
+ )
94
+ });
95
+ const _getPageByIdFromDB = withCodec({
96
+ encoder: Schema.String,
97
+ decoder: Schema.UndefinedOr(StudioCMSPageData.Select),
98
+ callbackFn: (db, pageId) => db(
99
+ (client) => client.selectFrom("StudioCMSPageData").selectAll().where("id", "=", pageId).executeTakeFirst()
100
+ )
101
+ });
102
+ const _getPageBySlugFromDB = withCodec({
103
+ encoder: Schema.String,
104
+ decoder: Schema.UndefinedOr(StudioCMSPageData.Select),
105
+ callbackFn: (db, slug) => db(
106
+ (client) => client.selectFrom("StudioCMSPageData").selectAll().where("slug", "=", slug).executeTakeFirst()
107
+ )
108
+ });
109
+ const _getPageByPackageFromDB = withCodec({
110
+ encoder: Schema.String,
111
+ decoder: Schema.UndefinedOr(StudioCMSPageData.Select),
112
+ callbackFn: (db, packageId) => db(
113
+ (client) => client.selectFrom("StudioCMSPageData").selectAll().where("package", "=", packageId).executeTakeFirst()
114
+ )
115
+ });
116
+ const _getFolderByNameOrId = withCodec({
117
+ encoder: Schema.String,
118
+ decoder: StudioCMSPageFolderStructure.Select,
119
+ callbackFn: (db, folderId) => db(
120
+ (client) => client.selectFrom("StudioCMSPageFolderStructure").selectAll().where((eb) => eb.or([eb("id", "=", folderId), eb("name", "=", folderId)])).executeTakeFirstOrThrow()
121
+ )
122
+ });
123
+ const _verifyRank = (rank) => Effect.fn(
124
+ ({
125
+ users,
126
+ permissions
127
+ }) => verifyRank(users, permissions, rank)
128
+ );
129
+ const _getPermissionsByRank = (rank) => Effect.all({
130
+ permissions: _getCurrentPermissions(),
131
+ users: _getUsers()
132
+ }).pipe(Effect.flatMap(_verifyRank(rank)));
133
+ const _combineRanks = ([rank, users]) => combineRanks(rank, users);
134
+ const _processAndVerifyRanks = (ranks2) => Effect.fn(
135
+ ({
136
+ users,
137
+ permissions
138
+ }) => Effect.forEach(
139
+ ranks2,
140
+ (rank) => verifyRank(users, permissions, rank).pipe(Effect.map((res) => [rank, res]))
141
+ )
142
+ );
143
+ const _getCombinedRanks = Effect.fn(
144
+ () => Effect.all({
145
+ permissions: _getCurrentPermissions(),
146
+ users: _getUsers()
147
+ }).pipe(
148
+ Effect.flatMap(_processAndVerifyRanks(ranks)),
149
+ Effect.flatMap(Effect.forEach(_combineRanks)),
150
+ Effect.map((data) => data.flat())
151
+ )
152
+ );
153
+ const _filterOutGhostUser = Effect.fn(
154
+ (users) => Effect.succeed(users.filter((user) => user.id !== GhostUserDefaults.id))
155
+ );
156
+ const _getAllUsers = Effect.fn(
157
+ () => _getUsers().pipe(
158
+ Effect.flatMap(_filterOutGhostUser),
159
+ Effect.flatMap(Effect.forEach(collectUserData))
160
+ )
161
+ );
162
+ const _getUserByIdExposed = Effect.fn(
163
+ (userId) => _getUserById(userId).pipe(
164
+ Effect.flatMap((user) => user ? collectUserData(user) : Effect.succeed(void 0))
165
+ )
166
+ );
167
+ const _getUserByUsernameExposed = Effect.fn(
168
+ (username) => _getUserByUsername(username).pipe(
169
+ Effect.flatMap((user) => user ? collectUserData(user) : Effect.succeed(void 0))
170
+ )
171
+ );
172
+ const _getUserByEmailExposed = Effect.fn(
173
+ (email) => _getUserByEmail(email).pipe(
174
+ Effect.flatMap((user) => user ? collectUserData(user) : Effect.succeed(void 0))
175
+ )
176
+ );
177
+ const validatePagination = Effect.fn(function* (paginate) {
178
+ if (paginate.limit < 0 || paginate.offset < 0) {
179
+ return yield* Effect.fail(new PaginateError("Pagination values must be non-negative"));
180
+ }
181
+ if (paginate.limit === 0) {
182
+ paginate.limit = 10;
183
+ }
184
+ return paginate;
185
+ });
186
+ const __filterPagesByDraftAndIndex = Effect.fn(
187
+ (pages, includeDrafts, hideDefaultIndex) => Effect.succeed(
188
+ pages.filter(
189
+ ({ draft, slug }) => (includeDrafts || draft === false || draft === null) && (!hideDefaultIndex || slug !== "index")
190
+ )
191
+ )
192
+ );
193
+ function convertCombinedPageDataToMetaOnly(data) {
194
+ if (Array.isArray(data)) {
195
+ return data.map(
196
+ ({ defaultContent, multiLangContent, ...data2 }) => data2
197
+ );
198
+ }
199
+ const { defaultContent: _dump1, multiLangContent: _dump2, ...metaOnlyData } = data;
200
+ return metaOnlyData;
201
+ }
202
+ const __getPagesPossiblyPaginated = (paginate) => paginate ? validatePagination(paginate).pipe(Effect.flatMap(_getAllPagesPaginated)) : _getAllPagesBase();
203
+ function _getAllPages(includeDrafts = false, hideDefaultIndex = false, metaOnly = false, paginate) {
204
+ return __getPagesPossiblyPaginated(paginate).pipe(
205
+ Effect.flatMap(
206
+ (pagesRaw) => Effect.all({
207
+ pages: __filterPagesByDraftAndIndex(pagesRaw, includeDrafts, hideDefaultIndex),
208
+ tree: GET.folderTree()
209
+ })
210
+ ),
211
+ Effect.flatMap(
212
+ ({ pages, tree }) => Effect.forEach(
213
+ pages,
214
+ (page) => memoize(cacheKeyGetters.page(page.id), collectPageData(page, tree), {
215
+ tags: cacheTags.pages
216
+ })
217
+ )
218
+ ),
219
+ Effect.map((data) => metaOnly ? convertCombinedPageDataToMetaOnly(data) : data)
220
+ );
221
+ }
222
+ function _getPageById(id, metaOnly = false) {
223
+ return _getPageByIdFromDB(id).pipe(
224
+ Effect.flatMap((page) => page ? Effect.succeed(page) : Effect.fail(new KillSwitch())),
225
+ Effect.flatMap(
226
+ (page) => GET.folderTree().pipe(
227
+ Effect.flatMap(
228
+ (tree) => memoize(cacheKeyGetters.page(page.id), collectPageData(page, tree), {
229
+ tags: cacheTags.pages
230
+ })
231
+ )
232
+ )
233
+ ),
234
+ Effect.map((data) => metaOnly === true ? convertCombinedPageDataToMetaOnly(data) : data),
235
+ Effect.catchTag("KillSwitch", () => Effect.succeed(void 0))
236
+ );
237
+ }
238
+ function _getPageBySlug(slug, metaOnly = false) {
239
+ return _getPageBySlugFromDB(slug).pipe(
240
+ Effect.flatMap((page) => page ? Effect.succeed(page) : Effect.fail(new KillSwitch())),
241
+ Effect.flatMap(
242
+ (page) => GET.folderTree().pipe(
243
+ Effect.flatMap(
244
+ (tree) => memoize(cacheKeyGetters.page(page.id), collectPageData(page, tree), {
245
+ tags: cacheTags.pages
246
+ })
247
+ )
248
+ )
249
+ ),
250
+ Effect.map((data) => metaOnly === true ? convertCombinedPageDataToMetaOnly(data) : data),
251
+ Effect.catchTag("KillSwitch", () => Effect.succeed(void 0))
252
+ );
253
+ }
254
+ function _getPackagesPages(packageName, metaOnly = false) {
255
+ return _getPageByPackageFromDB(packageName).pipe(
256
+ Effect.flatMap((page) => page ? Effect.succeed(page) : Effect.fail(new KillSwitch())),
257
+ Effect.flatMap(
258
+ (page) => GET.folderTree().pipe(
259
+ Effect.flatMap(
260
+ (tree) => memoize(cacheKeyGetters.page(page.id), collectPageData(page, tree), {
261
+ tags: cacheTags.pages
262
+ })
263
+ )
264
+ )
265
+ ),
266
+ Effect.map((data) => metaOnly === true ? convertCombinedPageDataToMetaOnly(data) : data),
267
+ Effect.catchTag("KillSwitch", () => Effect.succeed([]))
268
+ );
269
+ }
270
+ function _folderPages(idOrName, includeDrafts = false, hideDefaultIndex = false, metaOnly = false, paginate) {
271
+ return _getFolderByNameOrId(idOrName).pipe(
272
+ Effect.flatMap(
273
+ ({ id: folderId }) => __getPagesPossiblyPaginated(paginate).pipe(
274
+ Effect.flatMap(
275
+ (pagesRaw) => __filterPagesByDraftAndIndex(
276
+ pagesRaw.filter((page) => page.parentFolder === folderId),
277
+ includeDrafts,
278
+ hideDefaultIndex
279
+ )
280
+ ),
281
+ Effect.flatMap(
282
+ (pages) => Effect.all({
283
+ pages: Effect.succeed(pages),
284
+ tree: GET.folderTree()
285
+ })
286
+ ),
287
+ Effect.flatMap(
288
+ ({ pages, tree }) => Effect.forEach(
289
+ pages,
290
+ (page) => memoize(cacheKeyGetters.page(page.id), collectPageData(page, tree), {
291
+ tags: cacheTags.pages
292
+ })
293
+ )
294
+ ),
295
+ Effect.map((data) => metaOnly ? convertCombinedPageDataToMetaOnly(data) : data)
296
+ )
297
+ )
298
+ );
299
+ }
300
+ const _pageFolderTree = (hideDefaultIndex = false) => Effect.gen(function* () {
301
+ const [tree, pages] = yield* Effect.all([
302
+ GET.folderTree(),
303
+ _getAllPages(true, hideDefaultIndex)
304
+ ]);
305
+ for (const page of pages) {
306
+ if (page.parentFolder) {
307
+ yield* addPageToFolderTree(tree, page.parentFolder, {
308
+ id: page.id,
309
+ name: page.title,
310
+ page: true,
311
+ pageData: page,
312
+ children: []
313
+ });
314
+ } else {
315
+ tree.push({
316
+ id: page.id,
317
+ name: page.title,
318
+ page: true,
319
+ pageData: page,
320
+ children: []
321
+ });
322
+ }
323
+ }
324
+ return tree;
325
+ });
326
+ const GET = {
327
+ /**
328
+ * Lists of permissions categorized by user ranks.
329
+ */
330
+ permissionsLists: {
331
+ /**
332
+ * Retrieves all combined ranks with their corresponding users.
333
+ *
334
+ * @returns An array of combined rank records.
335
+ */
336
+ all: _getCombinedRanks,
337
+ // Dynamically generate functions for each rank (e.g., owners, admins, editors, visitors)
338
+ ...ranks.reduce((acc, rank) => {
339
+ acc[`${rank}s`] = () => _getPermissionsByRank(rank);
340
+ return acc;
341
+ }, {})
342
+ },
343
+ /**
344
+ * User-related GET operations.
345
+ */
346
+ users: {
347
+ /**
348
+ * Retrieves all users excluding the ghost user.
349
+ *
350
+ * @returns An array of user data records.
351
+ */
352
+ all: _getAllUsers,
353
+ /**
354
+ * Retrieves a user by their ID.
355
+ *
356
+ * @param userId - The ID of the user to fetch.
357
+ * @returns The user data record if found, otherwise undefined.
358
+ */
359
+ byId: _getUserByIdExposed,
360
+ /**
361
+ * Retrieves a user by their username.
362
+ *
363
+ * @param username - The username of the user to fetch.
364
+ * @returns The user data record if found, otherwise undefined.
365
+ */
366
+ byUsername: _getUserByUsernameExposed,
367
+ /**
368
+ * Retrieves a user by their email.
369
+ *
370
+ * @param email - The email of the user to fetch.
371
+ * @returns The user data record if found, otherwise undefined.
372
+ */
373
+ byEmail: _getUserByEmailExposed
374
+ },
375
+ /**
376
+ * Retrieves a folder by its ID.
377
+ *
378
+ * @param folderId - The ID of the folder to fetch.
379
+ * @returns The folder record if found, otherwise undefined.
380
+ */
381
+ folder: Effect.fn(
382
+ (folderId) => memoize(cacheKeyGetters.folder(folderId), _getFolder(folderId), {
383
+ tags: cacheTags.folder
384
+ })
385
+ ),
386
+ /**
387
+ * Retrieves the folder tree structure.
388
+ *
389
+ * @returns The folder tree structure.
390
+ */
391
+ folderTree: () => buildFolderTree,
392
+ /**
393
+ * Retrieves a list of folders.
394
+ *
395
+ * @returns An array of folder records.
396
+ */
397
+ folderList: () => memoize(cacheKeyGetters.folderList(), getAvailableFolders, {
398
+ tags: cacheTags.folderList
399
+ }),
400
+ /**
401
+ * Retrieves the site configuration.
402
+ *
403
+ * @returns The site configuration object.
404
+ */
405
+ siteConfig: sdkSiteConfig.get,
406
+ /**
407
+ * Retrieves the latest version of StudioCMS from NPM.
408
+ *
409
+ * @returns The latest version string.
410
+ */
411
+ latestVersion: () => getVersion("studiocms"),
412
+ /**
413
+ * Retrieves all pages.
414
+ *
415
+ * @returns An array of page data records.
416
+ */
417
+ pages: _getAllPages,
418
+ /**
419
+ * Utilities to get pages by specific criteria.
420
+ */
421
+ page: {
422
+ /**
423
+ * Retrieves a page by its ID.
424
+ *
425
+ * @param id - The ID of the page to fetch.
426
+ * @returns The page data record if found, otherwise undefined.
427
+ */
428
+ byId: _getPageById,
429
+ /**
430
+ * Retrieves a page by its slug.
431
+ *
432
+ * @param slug - The slug of the page to fetch.
433
+ * @returns The page data record if found, otherwise undefined.
434
+ */
435
+ bySlug: _getPageBySlug
436
+ },
437
+ /**
438
+ * Retrieves pages associated with a specific package.
439
+ *
440
+ * @param packageName - The name of the package to fetch pages for.
441
+ * @returns An array of page data records associated with the specified package.
442
+ */
443
+ packagePages: _getPackagesPages,
444
+ /**
445
+ * Retrieves pages within a specific folder.
446
+ *
447
+ * @param idOrName - The ID or name of the folder.
448
+ * @returns An array of page data records within the specified folder.
449
+ */
450
+ folderPages: _folderPages,
451
+ /**
452
+ * Retrieves the page folder tree structure.
453
+ *
454
+ * @returns The page folder tree structure.
455
+ */
456
+ pageFolderTree: _pageFolderTree
457
+ };
458
+ return GET;
459
+ });
460
+ var get_default = SDKGetModule;
461
+ export {
462
+ KillSwitch,
463
+ PaginateError,
464
+ SDKGetModule,
465
+ get_default as default
466
+ };