@withstudiocms/sdk 0.0.0-beta.0 → 0.1.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/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 +37 -0
- package/dist/consts.js +35 -0
- package/dist/context.d.ts +208 -0
- package/dist/context.js +40 -0
- package/dist/errors.d.ts +9 -0
- package/dist/errors.js +6 -0
- package/dist/index.d.ts +1024 -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 +222 -0
- package/dist/lib/pluginUtils.js +87 -0
- package/dist/lib/storage-manager.d.ts +10 -0
- package/dist/lib/storage-manager.js +17 -0
- package/dist/migrations/20251025T040912_init.d.ts +17 -0
- package/dist/migrations/20251025T040912_init.js +260 -0
- package/dist/migrations/20251130T150847_drop_deprecated.d.ts +13 -0
- package/dist/migrations/20251130T150847_drop_deprecated.js +262 -0
- package/dist/migrations/20251221T002125_url-mapping.d.ts +13 -0
- package/dist/migrations/20251221T002125_url-mapping.js +228 -0
- package/dist/migrator.d.ts +25 -0
- package/dist/migrator.js +21 -0
- package/dist/modules/auth/index.d.ts +419 -0
- package/dist/modules/auth/index.js +436 -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 +224 -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 +141 -0
- package/dist/modules/delete/index.js +279 -0
- package/dist/modules/diffTracking/index.d.ts +188 -0
- package/dist/modules/diffTracking/index.js +277 -0
- package/dist/modules/get/index.d.ts +372 -0
- package/dist/modules/get/index.js +579 -0
- package/dist/modules/index.d.ts +883 -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 +167 -0
- package/dist/modules/plugins/index.js +272 -0
- package/dist/modules/post/index.d.ts +306 -0
- package/dist/modules/post/index.js +337 -0
- package/dist/modules/resetTokenBucket/index.d.ts +91 -0
- package/dist/modules/resetTokenBucket/index.js +96 -0
- package/dist/modules/rest_api/index.d.ts +92 -0
- package/dist/modules/rest_api/index.js +117 -0
- package/dist/modules/update/index.d.ts +184 -0
- package/dist/modules/update/index.js +192 -0
- package/dist/modules/util/collectors.d.ts +125 -0
- package/dist/modules/util/collectors.js +168 -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 +199 -0
- package/dist/modules/util/getFromNPM.js +106 -0
- package/dist/modules/util/index.d.ts +100 -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/tables.d.ts +433 -0
- package/dist/tables.js +169 -0
- package/dist/types.d.ts +359 -0
- package/dist/types.js +10 -0
- package/package.json +67 -7
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
import { Data, Effect, Schema } from "@withstudiocms/effect";
|
|
2
|
+
import { DBClientLive } from "../../context.js";
|
|
3
|
+
import { createTwoFilesPatch, diffHTML } from "../../lib/diff.js";
|
|
4
|
+
import { StudioCMSDiffTracking, StudioCMSPageData } from "../../tables.js";
|
|
5
|
+
import { SDKParsers } from "../util/parsers.js";
|
|
6
|
+
class DiffTrackingError extends Data.TaggedError("DiffTrackingError") {
|
|
7
|
+
}
|
|
8
|
+
const SDKDiffTrackingModule = Effect.gen(function* () {
|
|
9
|
+
const [{ withCodec, withEncoder }, { fixDiff }] = yield* Effect.all([DBClientLive, SDKParsers]);
|
|
10
|
+
const _selectDiffByPageId = withCodec({
|
|
11
|
+
encoder: Schema.String,
|
|
12
|
+
decoder: Schema.Array(StudioCMSDiffTracking.Select),
|
|
13
|
+
callbackFn: (db, pageId) => db(
|
|
14
|
+
(client) => client.selectFrom("StudioCMSDiffTracking").selectAll().where("pageId", "=", pageId).orderBy("timestamp", "asc").execute()
|
|
15
|
+
)
|
|
16
|
+
});
|
|
17
|
+
const _selectDiffByUserId = withCodec({
|
|
18
|
+
encoder: Schema.String,
|
|
19
|
+
decoder: Schema.Array(StudioCMSDiffTracking.Select),
|
|
20
|
+
callbackFn: (db, userId) => db(
|
|
21
|
+
(client) => client.selectFrom("StudioCMSDiffTracking").selectAll().where("userId", "=", userId).orderBy("timestamp", "asc").execute()
|
|
22
|
+
)
|
|
23
|
+
});
|
|
24
|
+
const _selectDiffById = withCodec({
|
|
25
|
+
encoder: Schema.String,
|
|
26
|
+
decoder: Schema.UndefinedOr(StudioCMSDiffTracking.Select),
|
|
27
|
+
callbackFn: (db, diffId) => db(
|
|
28
|
+
(client) => client.selectFrom("StudioCMSDiffTracking").selectAll().where("id", "=", diffId).executeTakeFirst()
|
|
29
|
+
)
|
|
30
|
+
});
|
|
31
|
+
const _deleteDiffById = withEncoder({
|
|
32
|
+
encoder: Schema.String,
|
|
33
|
+
callbackFn: (db, diffId) => db((client) => client.deleteFrom("StudioCMSDiffTracking").where("id", "=", diffId).execute())
|
|
34
|
+
});
|
|
35
|
+
const _insertNewDiff = withCodec({
|
|
36
|
+
encoder: StudioCMSDiffTracking.Insert,
|
|
37
|
+
decoder: StudioCMSDiffTracking.Select,
|
|
38
|
+
callbackFn: (db, diff) => db(
|
|
39
|
+
(client) => client.transaction().execute(async (trx) => {
|
|
40
|
+
await trx.insertInto("StudioCMSDiffTracking").values(diff).executeTakeFirstOrThrow();
|
|
41
|
+
return await trx.selectFrom("StudioCMSDiffTracking").selectAll().where("id", "=", diff.id).executeTakeFirstOrThrow();
|
|
42
|
+
})
|
|
43
|
+
)
|
|
44
|
+
});
|
|
45
|
+
const clearPageDiffs = withEncoder({
|
|
46
|
+
encoder: Schema.String,
|
|
47
|
+
callbackFn: (db, pageId) => db(
|
|
48
|
+
(client) => client.deleteFrom("StudioCMSDiffTracking").where("pageId", "=", pageId).execute()
|
|
49
|
+
)
|
|
50
|
+
});
|
|
51
|
+
const _setPageData = withEncoder({
|
|
52
|
+
encoder: StudioCMSPageData.Update,
|
|
53
|
+
callbackFn: (db, data) => db(
|
|
54
|
+
(client) => client.updateTable("StudioCMSPageData").set(data).where("id", "=", data.id).execute()
|
|
55
|
+
)
|
|
56
|
+
});
|
|
57
|
+
const _setPageContent = withEncoder({
|
|
58
|
+
encoder: Schema.Struct({
|
|
59
|
+
contentId: Schema.String,
|
|
60
|
+
content: Schema.String
|
|
61
|
+
}),
|
|
62
|
+
callbackFn: (db, data) => db(
|
|
63
|
+
(client) => client.updateTable("StudioCMSPageContent").set({ content: data.content }).where("contentId", "=", data.contentId).execute()
|
|
64
|
+
)
|
|
65
|
+
});
|
|
66
|
+
const _checkDiffsLengthAndRemoveOldestIfTooLong = Effect.fn(function* (pageId, maxDiffs) {
|
|
67
|
+
const diffs = yield* _selectDiffByPageId(pageId);
|
|
68
|
+
if (diffs.length > maxDiffs) {
|
|
69
|
+
const diffsToDelete = diffs.length - maxDiffs;
|
|
70
|
+
for (let i = 0; i < diffsToDelete; i++) {
|
|
71
|
+
const oldestDiff = diffs[i];
|
|
72
|
+
yield* _deleteDiffById(oldestDiff.id);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
const _insert = Effect.fn(
|
|
77
|
+
(userId, pageId, data, diffLength) => createTwoFilesPatch(
|
|
78
|
+
(patch) => patch("Content", "Content", data.content.start, data.content.end)
|
|
79
|
+
).pipe(
|
|
80
|
+
Effect.tap(() => _checkDiffsLengthAndRemoveOldestIfTooLong(pageId, diffLength)),
|
|
81
|
+
Effect.flatMap(
|
|
82
|
+
(diff) => _insertNewDiff({
|
|
83
|
+
id: crypto.randomUUID(),
|
|
84
|
+
pageId,
|
|
85
|
+
userId,
|
|
86
|
+
diff,
|
|
87
|
+
pageContentStart: data.content.start,
|
|
88
|
+
pageMetaData: JSON.stringify(data.metaData),
|
|
89
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
90
|
+
})
|
|
91
|
+
),
|
|
92
|
+
Effect.flatMap((insertedDiff) => fixDiff(insertedDiff))
|
|
93
|
+
)
|
|
94
|
+
);
|
|
95
|
+
const _getByPageIdAll = Effect.fn(
|
|
96
|
+
(pageId) => _selectDiffByPageId(pageId).pipe(Effect.flatMap((diffs) => fixDiff(diffs)))
|
|
97
|
+
);
|
|
98
|
+
const _getByPageIdLatest = Effect.fn(
|
|
99
|
+
(pageId, count) => _getByPageIdAll(pageId).pipe(Effect.map((diffs) => diffs.slice(0, count)))
|
|
100
|
+
);
|
|
101
|
+
const _getByUserIdAll = Effect.fn(
|
|
102
|
+
(userId) => _selectDiffByUserId(userId).pipe(Effect.flatMap((diffs) => fixDiff(diffs)))
|
|
103
|
+
);
|
|
104
|
+
const _getByUserIdLatest = Effect.fn(
|
|
105
|
+
(userId, count) => _getByUserIdAll(userId).pipe(Effect.map((diffs) => diffs.slice(0, count)))
|
|
106
|
+
);
|
|
107
|
+
const _getSingleDiffById = Effect.fn(
|
|
108
|
+
(diffId) => _selectDiffById(diffId).pipe(
|
|
109
|
+
Effect.flatMap(
|
|
110
|
+
(diffOrNull) => diffOrNull ? fixDiff(diffOrNull) : Effect.succeed(void 0)
|
|
111
|
+
)
|
|
112
|
+
)
|
|
113
|
+
);
|
|
114
|
+
const _revertToDiff = Effect.fn(function* (id, type) {
|
|
115
|
+
const diffEntry = yield* _selectDiffById(id);
|
|
116
|
+
if (!diffEntry) {
|
|
117
|
+
return yield* new DiffTrackingError({ message: "Diff entry not found" });
|
|
118
|
+
}
|
|
119
|
+
const shouldRevertData = type === "data" || type === "both";
|
|
120
|
+
const shouldRevertContent = type === "content" || type === "both";
|
|
121
|
+
if (shouldRevertData) {
|
|
122
|
+
const pageData = diffEntry.pageMetaData;
|
|
123
|
+
if (!pageData.end.id || !pageData.start.id) {
|
|
124
|
+
return yield* new DiffTrackingError({ message: "Invalid page metadata for revert" });
|
|
125
|
+
}
|
|
126
|
+
yield* Schema.encode(StudioCMSPageData.Select)(pageData.start).pipe(
|
|
127
|
+
Effect.flatMap(Schema.decode(StudioCMSPageData.Update)),
|
|
128
|
+
Effect.flatMap(_setPageData)
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
if (shouldRevertContent) {
|
|
132
|
+
yield* _setPageContent({
|
|
133
|
+
content: diffEntry.pageContentStart,
|
|
134
|
+
contentId: diffEntry.pageId
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
const allDiffs = yield* _selectDiffByPageId(diffEntry.pageId);
|
|
138
|
+
const diffIndex = allDiffs.findIndex((d) => d.id === id);
|
|
139
|
+
for (let i = diffIndex + 1; i < allDiffs.length; i++) {
|
|
140
|
+
const diffToDelete = allDiffs[i];
|
|
141
|
+
yield* _deleteDiffById(diffToDelete.id);
|
|
142
|
+
}
|
|
143
|
+
return yield* fixDiff(diffEntry);
|
|
144
|
+
});
|
|
145
|
+
const _getMetaDataDifferences = Effect.fn(function* (obj1, obj2) {
|
|
146
|
+
const differences = [];
|
|
147
|
+
const Labels = {
|
|
148
|
+
package: "Page Type",
|
|
149
|
+
title: "Page Title",
|
|
150
|
+
description: "Page Description",
|
|
151
|
+
showOnNav: "Show in Navigation",
|
|
152
|
+
slug: "Page Slug",
|
|
153
|
+
contentLang: "Content Language",
|
|
154
|
+
heroImage: "Hero/OG Image",
|
|
155
|
+
categories: "Page Categories",
|
|
156
|
+
tags: "Page Tags",
|
|
157
|
+
showAuthor: "Show Author",
|
|
158
|
+
showContributors: "Show Contributors",
|
|
159
|
+
parentFolder: "Parent Folder",
|
|
160
|
+
draft: "Draft"
|
|
161
|
+
};
|
|
162
|
+
const processLabel = (label) => Effect.sync(() => Labels[label] ? Labels[label] : label);
|
|
163
|
+
for (const label in obj1) {
|
|
164
|
+
const blackListedLabels = [
|
|
165
|
+
"publishedAt",
|
|
166
|
+
"updatedAt",
|
|
167
|
+
"authorId",
|
|
168
|
+
"contributorIds"
|
|
169
|
+
];
|
|
170
|
+
if (blackListedLabels.includes(label)) continue;
|
|
171
|
+
if (Object.hasOwn(obj1, label) && Object.hasOwn(obj2, label)) {
|
|
172
|
+
if (obj1[label] !== obj2[label]) {
|
|
173
|
+
if (Array.isArray(obj1[label]) && Array.isArray(obj2[label])) {
|
|
174
|
+
const arr1 = obj1[label];
|
|
175
|
+
const arr2 = obj2[label];
|
|
176
|
+
if (arr1.length === arr2.length && arr1.every((val, index) => val === arr2[index]))
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
differences.push({
|
|
180
|
+
label: yield* processLabel(label),
|
|
181
|
+
previous: obj1[label],
|
|
182
|
+
current: obj2[label]
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return differences;
|
|
188
|
+
});
|
|
189
|
+
return {
|
|
190
|
+
/**
|
|
191
|
+
* Inserts a new diff tracking record into the database.
|
|
192
|
+
*
|
|
193
|
+
* @param userId - The ID of the user making the change.
|
|
194
|
+
* @param pageId - The ID of the page being changed.
|
|
195
|
+
* @param data - An object containing the start and end content and metadata.
|
|
196
|
+
* @param diffLength - The maximum number of diffs to retain for the page.
|
|
197
|
+
* @returns The inserted diff tracking record with parsed metadata.
|
|
198
|
+
*/
|
|
199
|
+
insert: _insert,
|
|
200
|
+
/**
|
|
201
|
+
* Clears all diff tracking records for a given page ID.
|
|
202
|
+
*
|
|
203
|
+
* @param pageId - The ID of the page to clear diff tracking records for.
|
|
204
|
+
* @returns The number of rows affected by the delete operation.
|
|
205
|
+
*/
|
|
206
|
+
clear: clearPageDiffs,
|
|
207
|
+
/**
|
|
208
|
+
* Utility functions for retrieving diff tracking records.
|
|
209
|
+
*/
|
|
210
|
+
get: {
|
|
211
|
+
/**
|
|
212
|
+
* Retrieves all diff tracking records for a given page ID.
|
|
213
|
+
*/
|
|
214
|
+
byPageId: {
|
|
215
|
+
/**
|
|
216
|
+
* Retrieves all diff tracking records for a given page ID.
|
|
217
|
+
*/
|
|
218
|
+
all: _getByPageIdAll,
|
|
219
|
+
/**
|
|
220
|
+
* Retrieves the latest `count` diff tracking records for a given page ID.
|
|
221
|
+
*/
|
|
222
|
+
latest: _getByPageIdLatest
|
|
223
|
+
},
|
|
224
|
+
/**
|
|
225
|
+
* Retrieves all diff tracking records for a given user ID.
|
|
226
|
+
*/
|
|
227
|
+
byUserId: {
|
|
228
|
+
/**
|
|
229
|
+
* Retrieves all diff tracking records for a given user ID.
|
|
230
|
+
*/
|
|
231
|
+
all: _getByUserIdAll,
|
|
232
|
+
/**
|
|
233
|
+
* Retrieves the latest `count` diff tracking records for a given user ID.
|
|
234
|
+
*/
|
|
235
|
+
latest: _getByUserIdLatest
|
|
236
|
+
},
|
|
237
|
+
/**
|
|
238
|
+
* Retrieves a single diff tracking record by its ID.
|
|
239
|
+
*/
|
|
240
|
+
single: _getSingleDiffById
|
|
241
|
+
},
|
|
242
|
+
/**
|
|
243
|
+
* Reverts the page data and/or content to the state represented by the specified diff ID.
|
|
244
|
+
*
|
|
245
|
+
* @param id - The ID of the diff tracking record to revert to.
|
|
246
|
+
* @param type - The type of revert operation: 'content', 'data', or 'both'.
|
|
247
|
+
* @returns The reverted diff tracking record with parsed metadata.
|
|
248
|
+
*/
|
|
249
|
+
revertToDiff: _revertToDiff,
|
|
250
|
+
/**
|
|
251
|
+
* Utility functions for diff tracking.
|
|
252
|
+
*/
|
|
253
|
+
utils: {
|
|
254
|
+
/**
|
|
255
|
+
* Compares two metadata objects and returns the differences.
|
|
256
|
+
*
|
|
257
|
+
* @param obj1 - The first metadata object to compare.
|
|
258
|
+
* @param obj2 - The second metadata object to compare.
|
|
259
|
+
* @returns An array of differences, each containing the label, previous value, and current value.
|
|
260
|
+
*/
|
|
261
|
+
getMetaDataDifferences: _getMetaDataDifferences,
|
|
262
|
+
/**
|
|
263
|
+
* Generates the HTML representation of a unified diff string.
|
|
264
|
+
*
|
|
265
|
+
* @param diff - The unified diff string to convert to HTML.
|
|
266
|
+
* @returns The HTML representation of the diff.
|
|
267
|
+
*/
|
|
268
|
+
getDiffHTML: diffHTML
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
});
|
|
272
|
+
var diffTracking_default = SDKDiffTrackingModule;
|
|
273
|
+
export {
|
|
274
|
+
DiffTrackingError,
|
|
275
|
+
SDKDiffTrackingModule,
|
|
276
|
+
diffTracking_default as default
|
|
277
|
+
};
|
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
import { Effect, type ParseResult } from '@withstudiocms/effect';
|
|
2
|
+
import type { DBCallbackFailure } from '@withstudiocms/kysely/client';
|
|
3
|
+
import type { DatabaseError } from '@withstudiocms/kysely/core/errors';
|
|
4
|
+
import CacheService from '../../cache.js';
|
|
5
|
+
import { DBClientLive, SDKDefaults } from '../../context.js';
|
|
6
|
+
import type { CombinedPageData, MetaOnlyPageData, SingleRank } from '../../types.js';
|
|
7
|
+
import { type CollectorError } from '../util/collectors.js';
|
|
8
|
+
import { type FolderTreeError } from '../util/folderTree.js';
|
|
9
|
+
import { type UsersError } from '../util/users.js';
|
|
10
|
+
/**
|
|
11
|
+
* Input parameters for paginated queries.
|
|
12
|
+
*
|
|
13
|
+
* @property limit - The maximum number of items to return.
|
|
14
|
+
* @property offset - The number of items to skip before starting to collect the result set.
|
|
15
|
+
*/
|
|
16
|
+
export type PaginateInput = {
|
|
17
|
+
limit: number;
|
|
18
|
+
offset: number;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Error class for pagination-related issues.
|
|
22
|
+
*/
|
|
23
|
+
export declare class PaginateError extends Error {
|
|
24
|
+
readonly _tag = "PaginateError";
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* KillSwitch used to short-circuit Effect chains.
|
|
28
|
+
*/
|
|
29
|
+
export declare class KillSwitch {
|
|
30
|
+
readonly _tag = "KillSwitch";
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* SDKGetModule
|
|
34
|
+
*
|
|
35
|
+
* Effect generator that assembles and returns a read-only "GET" API for the StudioCMS SDK.
|
|
36
|
+
* The module wires together database access, collectors, folder-tree utilities, caching/memoization,
|
|
37
|
+
* schema decoding/encoding and other supporting services to produce a single object with
|
|
38
|
+
* convenient, type-safe Effect-based getters.
|
|
39
|
+
*
|
|
40
|
+
* Key characteristics
|
|
41
|
+
* - Returns an object `GET` containing grouped read operations (permissions, users, folders, pages, site config, etc.).
|
|
42
|
+
* - All operations return Effect-based results (Effect.Effect<...>) and are composed with validation, decoding and error handling.
|
|
43
|
+
* - Uses memoization with cache keys/tags for page-, folder- and tree-related queries to avoid redundant work.
|
|
44
|
+
* - Uses collectors to supplement raw DB rows with computed/aggregated "collected" data for pages and users.
|
|
45
|
+
* - Read-only: operations query database and services but do not mutate state.
|
|
46
|
+
*
|
|
47
|
+
* Main API surface (high level)
|
|
48
|
+
* - GET.permissionsLists
|
|
49
|
+
* - all: returns combined ranks with their users.
|
|
50
|
+
* - <rank>s: dynamically generated convenience functions for each rank (e.g. owners, admins, editors, visitors).
|
|
51
|
+
*
|
|
52
|
+
* - GET.users
|
|
53
|
+
* - all(): returns all users (ghost user filtered out) with collected user data.
|
|
54
|
+
* - byId(id): returns collected user data for a user id or undefined if not found.
|
|
55
|
+
* - byUsername(username): returns collected user data for a username or undefined if not found.
|
|
56
|
+
* - byEmail(email): returns collected user data for an email or undefined if not found.
|
|
57
|
+
*
|
|
58
|
+
* - GET.folder(folderId)
|
|
59
|
+
* - Returns a memoized folder lookup by id (decoded).
|
|
60
|
+
*
|
|
61
|
+
* - GET.folderTree()
|
|
62
|
+
* - Returns the folder structure built from folder definitions (memoized).
|
|
63
|
+
*
|
|
64
|
+
* - GET.folderList()
|
|
65
|
+
* - Returns a list of available folders (memoized).
|
|
66
|
+
*
|
|
67
|
+
* - GET.siteConfig
|
|
68
|
+
* - Proxy to SDK config getter for site configuration.
|
|
69
|
+
*
|
|
70
|
+
* - GET.latestVersion()
|
|
71
|
+
* - Fetches the latest published version of StudioCMS from NPM.
|
|
72
|
+
*
|
|
73
|
+
* - GET.pages(includeDrafts?, metaOnly?, paginate?)
|
|
74
|
+
* - Returns all pages (optionally paginated) and supports:
|
|
75
|
+
* - includeDrafts: include drafts when true.
|
|
76
|
+
* - metaOnly: when true returns meta-only representations (no defaultContent / multiLangContent).
|
|
77
|
+
* - Validates pagination inputs (non-negative; default limit fallback).
|
|
78
|
+
* - Uses memoized per-page collectors and returns either CombinedPageData[] or MetaOnlyPageData[].
|
|
79
|
+
* - Errors are typed (e.g. DBCallbackFailure, FolderTreeError, DatabaseError, ParseResult.ParseError,
|
|
80
|
+
* PaginateError, CollectorError) — all surfaced through Effects.
|
|
81
|
+
*
|
|
82
|
+
* - GET.page.byId(id, metaOnly?)
|
|
83
|
+
* - Fetches a single page by id, collects full page data (or meta-only when requested).
|
|
84
|
+
* - Returns the page data or `undefined` when not found.
|
|
85
|
+
*
|
|
86
|
+
* - GET.page.bySlug(slug, metaOnly?)
|
|
87
|
+
* - Fetches a single page by slug, collects full page data (or meta-only when requested).
|
|
88
|
+
* - Returns the page data or `undefined` when not found.
|
|
89
|
+
*
|
|
90
|
+
* - GET.packagePages(packageName, metaOnly?)
|
|
91
|
+
* - Returns pages associated with a package. If none found, returns an empty array.
|
|
92
|
+
*
|
|
93
|
+
* - GET.folderPages(idOrName, includeDrafts?, metaOnly?, paginate?)
|
|
94
|
+
* - Returns pages that belong to the given folder (identified by id or name).
|
|
95
|
+
* - Supports same filtering, metaOnly and pagination semantics as GET.pages.
|
|
96
|
+
*
|
|
97
|
+
* - GET.pageFolderTree(excludeDrafts?)
|
|
98
|
+
* - Returns a full folder tree structure enriched with pages placed into their folders.
|
|
99
|
+
* - Built by merging folder definitions and page data, memoized for efficiency.
|
|
100
|
+
* - Supports excluding draft pages when `excludeDrafts` is true.
|
|
101
|
+
*
|
|
102
|
+
* Implementation notes
|
|
103
|
+
* - Internal helpers:
|
|
104
|
+
* - Schema-validated DB accessors (withCodec/withDecoder) provide typed DB reads.
|
|
105
|
+
* - collectUserData / collectPageData transform raw DB rows into richer domain objects.
|
|
106
|
+
* - memoize wraps potentially expensive collectors with cache keys and tags.
|
|
107
|
+
* - validatePagination enforces sane paging and returns a PaginateError for invalid input.
|
|
108
|
+
* - convertCombinedPageDataToMetaOnly strips content fields to produce meta-only return shapes.
|
|
109
|
+
* - Some flows use a KillSwitch sentinel to convert "not found" database results into benign undefined/empty results.
|
|
110
|
+
*
|
|
111
|
+
* Errors
|
|
112
|
+
* - All functions return their results wrapped in Effect.Effect; errors from decoding, DB callbacks,
|
|
113
|
+
* collectors, pagination validation, or folder-tree construction flow through the Effect error channel.
|
|
114
|
+
* - Page-related getters document a union of possible errors (DBCallbackFailure | FolderTreeError | DatabaseError |
|
|
115
|
+
* ParseResult.ParseError | PaginateError | CollectorError).
|
|
116
|
+
*
|
|
117
|
+
* Example usage (conceptual)
|
|
118
|
+
* - GET.users.all() -> Effect yielding collected user list
|
|
119
|
+
* - GET.page.byId("abc") -> Effect yielding CombinedPageData | undefined
|
|
120
|
+
*
|
|
121
|
+
* Returns
|
|
122
|
+
* - An object (`GET`) with the described grouped read-only operations; each operation is an Effect-producing function.
|
|
123
|
+
*/
|
|
124
|
+
export declare const SDKGetModule: Effect.Effect<{
|
|
125
|
+
/**
|
|
126
|
+
* Lists of permissions categorized by user ranks.
|
|
127
|
+
*/
|
|
128
|
+
permissionsLists: {
|
|
129
|
+
owners: () => Effect.Effect<SingleRank[], UsersError | DBCallbackFailure | DatabaseError, never>;
|
|
130
|
+
admins: () => Effect.Effect<SingleRank[], UsersError | DBCallbackFailure | DatabaseError, never>;
|
|
131
|
+
editors: () => Effect.Effect<SingleRank[], UsersError | DBCallbackFailure | DatabaseError, never>;
|
|
132
|
+
visitors: () => Effect.Effect<SingleRank[], UsersError | DBCallbackFailure | DatabaseError, never>;
|
|
133
|
+
/**
|
|
134
|
+
* Retrieves all combined ranks with their corresponding users.
|
|
135
|
+
*
|
|
136
|
+
* @returns An array of combined rank records.
|
|
137
|
+
*/
|
|
138
|
+
all: () => Effect.Effect<import("../../types.js").CombinedRank[], DBCallbackFailure | DatabaseError | UsersError, never>;
|
|
139
|
+
};
|
|
140
|
+
/**
|
|
141
|
+
* User-related GET operations.
|
|
142
|
+
*/
|
|
143
|
+
users: {
|
|
144
|
+
/**
|
|
145
|
+
* Retrieves all users excluding the ghost user.
|
|
146
|
+
*
|
|
147
|
+
* @returns An array of user data records.
|
|
148
|
+
*/
|
|
149
|
+
all: () => Effect.Effect<import("../../types.js").CombinedUserData[], DBCallbackFailure | DatabaseError, never>;
|
|
150
|
+
/**
|
|
151
|
+
* Retrieves a user by their ID.
|
|
152
|
+
*
|
|
153
|
+
* @param userId - The ID of the user to fetch.
|
|
154
|
+
* @returns The user data record if found, otherwise undefined.
|
|
155
|
+
*/
|
|
156
|
+
byId: (userId: string) => Effect.Effect<import("../../types.js").CombinedUserData | undefined, DBCallbackFailure | DatabaseError, never>;
|
|
157
|
+
/**
|
|
158
|
+
* Retrieves a user by their username.
|
|
159
|
+
*
|
|
160
|
+
* @param username - The username of the user to fetch.
|
|
161
|
+
* @returns The user data record if found, otherwise undefined.
|
|
162
|
+
*/
|
|
163
|
+
byUsername: (username: string) => Effect.Effect<import("../../types.js").CombinedUserData | undefined, DBCallbackFailure | DatabaseError, never>;
|
|
164
|
+
/**
|
|
165
|
+
* Retrieves a user by their email.
|
|
166
|
+
*
|
|
167
|
+
* @param email - The email of the user to fetch.
|
|
168
|
+
* @returns The user data record if found, otherwise undefined.
|
|
169
|
+
*/
|
|
170
|
+
byEmail: (email: string) => Effect.Effect<import("../../types.js").CombinedUserData | undefined, DBCallbackFailure | DatabaseError, never>;
|
|
171
|
+
};
|
|
172
|
+
/**
|
|
173
|
+
* Retrieves a folder by its ID.
|
|
174
|
+
*
|
|
175
|
+
* @param folderId - The ID of the folder to fetch.
|
|
176
|
+
* @returns The folder record if found, otherwise undefined.
|
|
177
|
+
*/
|
|
178
|
+
folder: (folderId: string) => Effect.Effect<{
|
|
179
|
+
readonly id: string;
|
|
180
|
+
readonly name: string;
|
|
181
|
+
readonly parent?: string | null | undefined;
|
|
182
|
+
} | undefined, DBCallbackFailure | DatabaseError, never>;
|
|
183
|
+
/**
|
|
184
|
+
* Retrieves the folder tree structure.
|
|
185
|
+
*
|
|
186
|
+
* @returns The folder tree structure.
|
|
187
|
+
*/
|
|
188
|
+
folderTree: () => Effect.Effect<import("../../types.js").FolderNode[], DBCallbackFailure | DatabaseError | FolderTreeError, never>;
|
|
189
|
+
/**
|
|
190
|
+
* Retrieves a list of folders.
|
|
191
|
+
*
|
|
192
|
+
* @returns An array of folder records.
|
|
193
|
+
*/
|
|
194
|
+
folderList: () => Effect.Effect<import("../../types.js").FolderListItem[], DBCallbackFailure | DatabaseError, never>;
|
|
195
|
+
/**
|
|
196
|
+
* Retrieves the site configuration.
|
|
197
|
+
*
|
|
198
|
+
* @returns The site configuration object.
|
|
199
|
+
*/
|
|
200
|
+
siteConfig: <T extends import("../../types.js").StudioCMSSiteConfig>() => Effect.Effect<import("../../types.js").DynamicConfigEntry<T> | undefined, import("effect/Cause").UnknownException | DBCallbackFailure | DatabaseError, never>;
|
|
201
|
+
/**
|
|
202
|
+
* Retrieves the latest version of StudioCMS from NPM.
|
|
203
|
+
*
|
|
204
|
+
* @returns The latest version string.
|
|
205
|
+
*/
|
|
206
|
+
latestVersion: () => Effect.Effect<{
|
|
207
|
+
version: string;
|
|
208
|
+
lastCacheUpdate: Date;
|
|
209
|
+
}, import("effect/Cause").UnknownException | ParseResult.ParseError | import("../util/getFromNPM.js").GetFromNPMError, never>;
|
|
210
|
+
/**
|
|
211
|
+
* Retrieves all pages.
|
|
212
|
+
*
|
|
213
|
+
* @returns An array of page data records.
|
|
214
|
+
*/
|
|
215
|
+
pages: {
|
|
216
|
+
(includeDrafts?: boolean, metaOnly?: false, paginate?: PaginateInput): Effect.Effect<CombinedPageData[], ParseResult.ParseError | DBCallbackFailure | DatabaseError | FolderTreeError | CollectorError | PaginateError, never>;
|
|
217
|
+
(includeDrafts?: boolean, metaOnly?: true, paginate?: PaginateInput): Effect.Effect<MetaOnlyPageData[], ParseResult.ParseError | DBCallbackFailure | DatabaseError | FolderTreeError | CollectorError | PaginateError, never>;
|
|
218
|
+
};
|
|
219
|
+
/**
|
|
220
|
+
* Utilities to get pages by specific criteria.
|
|
221
|
+
*/
|
|
222
|
+
page: {
|
|
223
|
+
/**
|
|
224
|
+
* Retrieves a page by its ID.
|
|
225
|
+
*
|
|
226
|
+
* @param id - The ID of the page to fetch.
|
|
227
|
+
* @returns The page data record if found, otherwise undefined.
|
|
228
|
+
*/
|
|
229
|
+
byId: {
|
|
230
|
+
(id: string): Effect.Effect<CombinedPageData | undefined, ParseResult.ParseError | DBCallbackFailure | DatabaseError | FolderTreeError | CollectorError | PaginateError, never>;
|
|
231
|
+
(id: string, metaOnly?: boolean): Effect.Effect<MetaOnlyPageData | undefined, ParseResult.ParseError | DBCallbackFailure | DatabaseError | FolderTreeError | CollectorError | PaginateError, never>;
|
|
232
|
+
};
|
|
233
|
+
/**
|
|
234
|
+
* Retrieves a page by its slug.
|
|
235
|
+
*
|
|
236
|
+
* @param slug - The slug of the page to fetch.
|
|
237
|
+
* @returns The page data record if found, otherwise undefined.
|
|
238
|
+
*/
|
|
239
|
+
bySlug: {
|
|
240
|
+
(slug: string): Effect.Effect<CombinedPageData | undefined, ParseResult.ParseError | DBCallbackFailure | DatabaseError | FolderTreeError | CollectorError | PaginateError, never>;
|
|
241
|
+
(slug: string, metaOnly?: boolean): Effect.Effect<MetaOnlyPageData | undefined, ParseResult.ParseError | DBCallbackFailure | DatabaseError | FolderTreeError | CollectorError | PaginateError, never>;
|
|
242
|
+
};
|
|
243
|
+
};
|
|
244
|
+
/**
|
|
245
|
+
* Retrieves pages associated with a specific package.
|
|
246
|
+
*
|
|
247
|
+
* @param packageName - The name of the package to fetch pages for.
|
|
248
|
+
* @returns An array of page data records associated with the specified package.
|
|
249
|
+
*/
|
|
250
|
+
packagePages: {
|
|
251
|
+
(packageName: string): Effect.Effect<CombinedPageData[], ParseResult.ParseError | DBCallbackFailure | DatabaseError | FolderTreeError | CollectorError | PaginateError, never>;
|
|
252
|
+
(packageName: string, metaOnly?: boolean): Effect.Effect<MetaOnlyPageData[], ParseResult.ParseError | DBCallbackFailure | DatabaseError | FolderTreeError | CollectorError | PaginateError, never>;
|
|
253
|
+
};
|
|
254
|
+
/**
|
|
255
|
+
* Retrieves pages within a specific folder.
|
|
256
|
+
*
|
|
257
|
+
* @param idOrName - The ID or name of the folder.
|
|
258
|
+
* @returns An array of page data records within the specified folder.
|
|
259
|
+
*/
|
|
260
|
+
folderPages: {
|
|
261
|
+
(idOrName: string, includeDrafts?: boolean, metaOnly?: false, paginate?: PaginateInput): Effect.Effect<CombinedPageData[], ParseResult.ParseError | DBCallbackFailure | DatabaseError | FolderTreeError | CollectorError | PaginateError, never>;
|
|
262
|
+
(idOrName: string, includeDrafts?: boolean, metaOnly?: true, paginate?: PaginateInput): Effect.Effect<MetaOnlyPageData[], ParseResult.ParseError | DBCallbackFailure | DatabaseError | FolderTreeError | CollectorError | PaginateError, never>;
|
|
263
|
+
};
|
|
264
|
+
/**
|
|
265
|
+
* Retrieves the page folder tree structure.
|
|
266
|
+
*
|
|
267
|
+
* @returns The page folder tree structure.
|
|
268
|
+
*/
|
|
269
|
+
pageFolderTree: (excludeDrafts?: boolean) => Effect.Effect<import("../../types.js").FolderNode[], ParseResult.ParseError | DBCallbackFailure | import("@withstudiocms/kysely/core/errors").QueryParseError | import("@withstudiocms/kysely/core/errors").QueryError | import("@withstudiocms/kysely/core/errors").NotFoundError | FolderTreeError | CollectorError | PaginateError, never>;
|
|
270
|
+
/**
|
|
271
|
+
* Category-related GET operations.
|
|
272
|
+
*/
|
|
273
|
+
categories: {
|
|
274
|
+
/**
|
|
275
|
+
* Retrieves all categories.
|
|
276
|
+
*
|
|
277
|
+
* @returns An array of category records.
|
|
278
|
+
*/
|
|
279
|
+
getAll: () => Effect.Effect<readonly {
|
|
280
|
+
readonly id: number;
|
|
281
|
+
readonly name: string;
|
|
282
|
+
readonly description: string;
|
|
283
|
+
readonly parent?: number | null | undefined;
|
|
284
|
+
readonly slug: string;
|
|
285
|
+
readonly meta: {
|
|
286
|
+
readonly [x: string]: unknown;
|
|
287
|
+
};
|
|
288
|
+
}[], DBCallbackFailure | DatabaseError, never>;
|
|
289
|
+
/**
|
|
290
|
+
* Retrieves a category by its ID.
|
|
291
|
+
*
|
|
292
|
+
* @param categoryId - The ID of the category to fetch.
|
|
293
|
+
* @returns The category record if found, otherwise undefined.
|
|
294
|
+
*/
|
|
295
|
+
byId: (categoryId: number) => Effect.Effect<{
|
|
296
|
+
readonly id: number;
|
|
297
|
+
readonly name: string;
|
|
298
|
+
readonly description: string;
|
|
299
|
+
readonly parent?: number | null | undefined;
|
|
300
|
+
readonly slug: string;
|
|
301
|
+
readonly meta: {
|
|
302
|
+
readonly [x: string]: unknown;
|
|
303
|
+
};
|
|
304
|
+
} | undefined, DBCallbackFailure | DatabaseError, never>;
|
|
305
|
+
/**
|
|
306
|
+
* Retrieves a category by its slug.
|
|
307
|
+
*
|
|
308
|
+
* @param slug - The slug of the category to fetch.
|
|
309
|
+
* @returns The category record if found, otherwise undefined.
|
|
310
|
+
*/
|
|
311
|
+
bySlug: (slug: string) => Effect.Effect<{
|
|
312
|
+
readonly id: number;
|
|
313
|
+
readonly name: string;
|
|
314
|
+
readonly description: string;
|
|
315
|
+
readonly parent?: number | null | undefined;
|
|
316
|
+
readonly slug: string;
|
|
317
|
+
readonly meta: {
|
|
318
|
+
readonly [x: string]: unknown;
|
|
319
|
+
};
|
|
320
|
+
} | undefined, DBCallbackFailure | DatabaseError, never>;
|
|
321
|
+
};
|
|
322
|
+
/**
|
|
323
|
+
* Tag-related GET operations.
|
|
324
|
+
*/
|
|
325
|
+
tags: {
|
|
326
|
+
/**
|
|
327
|
+
* Retrieves all tags.
|
|
328
|
+
*
|
|
329
|
+
* @returns An array of tag records.
|
|
330
|
+
*/
|
|
331
|
+
getAll: () => Effect.Effect<readonly {
|
|
332
|
+
readonly id: number;
|
|
333
|
+
readonly name: string;
|
|
334
|
+
readonly description: string;
|
|
335
|
+
readonly slug: string;
|
|
336
|
+
readonly meta: {
|
|
337
|
+
readonly [x: string]: unknown;
|
|
338
|
+
};
|
|
339
|
+
}[], DBCallbackFailure | DatabaseError, never>;
|
|
340
|
+
/**
|
|
341
|
+
* Retrieves a tag by its ID.
|
|
342
|
+
*
|
|
343
|
+
* @param tagId - The ID of the tag to fetch.
|
|
344
|
+
* @returns The tag record if found, otherwise undefined.
|
|
345
|
+
*/
|
|
346
|
+
byId: (tagId: number) => Effect.Effect<{
|
|
347
|
+
readonly id: number;
|
|
348
|
+
readonly name: string;
|
|
349
|
+
readonly description: string;
|
|
350
|
+
readonly slug: string;
|
|
351
|
+
readonly meta: {
|
|
352
|
+
readonly [x: string]: unknown;
|
|
353
|
+
};
|
|
354
|
+
} | undefined, DBCallbackFailure | DatabaseError, never>;
|
|
355
|
+
/**
|
|
356
|
+
* Retrieves a tag by its slug.
|
|
357
|
+
*
|
|
358
|
+
* @param slug - The slug of the tag to fetch.
|
|
359
|
+
* @returns The tag record if found, otherwise undefined.
|
|
360
|
+
*/
|
|
361
|
+
bySlug: (slug: string) => Effect.Effect<{
|
|
362
|
+
readonly id: number;
|
|
363
|
+
readonly name: string;
|
|
364
|
+
readonly description: string;
|
|
365
|
+
readonly slug: string;
|
|
366
|
+
readonly meta: {
|
|
367
|
+
readonly [x: string]: unknown;
|
|
368
|
+
};
|
|
369
|
+
} | undefined, DBCallbackFailure | DatabaseError, never>;
|
|
370
|
+
};
|
|
371
|
+
}, never, DBClientLive | SDKDefaults | import("../../context.js").StorageManagerResolver | CacheService | import("@withstudiocms/effect").Deepmerge>;
|
|
372
|
+
export default SDKGetModule;
|