@prosewire/sdk 0.2.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/dist/index.mjs ADDED
@@ -0,0 +1,315 @@
1
+ import { Effect, Schema } from "effect";
2
+ import { HttpApi, HttpApiClient, HttpApiEndpoint, HttpApiGroup, HttpApiSchema, OpenApi } from "effect/unstable/httpapi";
3
+ import { FetchHttpClient, HttpClient, HttpClientRequest } from "effect/unstable/http";
4
+ //#region ../contract/src/schemas.ts
5
+ const withDefault = (schema, value) => Schema.withDecodingDefaultKey(Effect.succeed(value))(schema);
6
+ const uuid$2 = Schema.String.check(Schema.isUUID());
7
+ const isoDateTime = Schema.String.check(Schema.isPattern(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/));
8
+ const url = Schema.String.check(Schema.isPattern(/^[a-z][a-z\d+.-]*:\/\/\S+$/i));
9
+ const nullable = (schema) => Schema.NullOr(schema);
10
+ const postStatus = Schema.Literals([
11
+ "draft",
12
+ "scheduled",
13
+ "published",
14
+ "archived"
15
+ ]);
16
+ const authorOutput = Schema.Struct({
17
+ id: uuid$2,
18
+ name: Schema.String,
19
+ slug: Schema.String,
20
+ bio: nullable(Schema.String),
21
+ avatarUrl: nullable(Schema.String),
22
+ jobTitle: nullable(Schema.String),
23
+ credentials: nullable(Schema.String)
24
+ });
25
+ const categoryOutput = Schema.Struct({
26
+ id: uuid$2,
27
+ name: Schema.String,
28
+ slug: Schema.String,
29
+ description: nullable(Schema.String)
30
+ });
31
+ const postOutput = Schema.Struct({
32
+ id: uuid$2,
33
+ blogId: uuid$2,
34
+ title: Schema.String,
35
+ slug: Schema.String,
36
+ excerpt: Schema.String,
37
+ contentMarkdown: Schema.String,
38
+ contentHtml: Schema.String,
39
+ coverImageUrl: nullable(Schema.String),
40
+ coverImageAlt: nullable(Schema.String),
41
+ status: postStatus,
42
+ locale: Schema.String,
43
+ featured: Schema.Boolean,
44
+ seoTitle: nullable(Schema.String),
45
+ seoDescription: nullable(Schema.String),
46
+ focusKeyword: nullable(Schema.String),
47
+ canonicalUrl: nullable(Schema.String),
48
+ publishedAt: nullable(isoDateTime),
49
+ scheduledAt: nullable(isoDateTime),
50
+ createdAt: isoDateTime,
51
+ updatedAt: isoDateTime,
52
+ author: authorOutput,
53
+ categories: Schema.Array(categoryOutput)
54
+ });
55
+ const authorId = uuid$2;
56
+ const title = Schema.Trim.pipe(Schema.check(Schema.isMinLength(1), Schema.isMaxLength(180)));
57
+ const slug = Schema.Trim.pipe(Schema.check(Schema.isMinLength(1), Schema.isMaxLength(120), Schema.isPattern(/^[a-z0-9]+(?:-[a-z0-9]+)*$/)));
58
+ const excerpt = Schema.String.check(Schema.isMaxLength(500));
59
+ const contentMarkdown = Schema.String;
60
+ const coverImageUrl = nullable(url);
61
+ const coverImageAlt = nullable(Schema.String.check(Schema.isMaxLength(180)));
62
+ const locale = Schema.String.check(Schema.isMinLength(2), Schema.isMaxLength(10));
63
+ const featured = Schema.Boolean;
64
+ const seoTitle = nullable(Schema.String.check(Schema.isMaxLength(70)));
65
+ const seoDescription = nullable(Schema.String.check(Schema.isMaxLength(180)));
66
+ const focusKeyword = nullable(Schema.String.check(Schema.isMaxLength(120)));
67
+ const canonicalUrl = nullable(url);
68
+ const scheduledAt = nullable(isoDateTime);
69
+ const categoryIds = Schema.Array(uuid$2);
70
+ const postCreateInput = Schema.Struct({
71
+ blogId: uuid$2,
72
+ authorId,
73
+ title,
74
+ slug,
75
+ excerpt: Schema.optionalKey(excerpt),
76
+ contentMarkdown: withDefault(contentMarkdown, ""),
77
+ coverImageUrl: Schema.optionalKey(coverImageUrl),
78
+ coverImageAlt: Schema.optionalKey(coverImageAlt),
79
+ status: withDefault(postStatus, "draft"),
80
+ locale: withDefault(locale, "en"),
81
+ featured: withDefault(featured, false),
82
+ seoTitle: Schema.optionalKey(seoTitle),
83
+ seoDescription: Schema.optionalKey(seoDescription),
84
+ focusKeyword: Schema.optionalKey(focusKeyword),
85
+ canonicalUrl: Schema.optionalKey(canonicalUrl),
86
+ scheduledAt: Schema.optionalKey(scheduledAt),
87
+ categoryIds: withDefault(categoryIds, [])
88
+ });
89
+ const postUpdateInput = Schema.Struct({
90
+ authorId: Schema.optionalKey(authorId),
91
+ title: Schema.optionalKey(title),
92
+ slug: Schema.optionalKey(slug),
93
+ excerpt: Schema.optionalKey(excerpt),
94
+ contentMarkdown: Schema.optionalKey(contentMarkdown),
95
+ coverImageUrl: Schema.optionalKey(coverImageUrl),
96
+ coverImageAlt: Schema.optionalKey(coverImageAlt),
97
+ status: Schema.optionalKey(postStatus),
98
+ locale: Schema.optionalKey(locale),
99
+ featured: Schema.optionalKey(featured),
100
+ seoTitle: Schema.optionalKey(seoTitle),
101
+ seoDescription: Schema.optionalKey(seoDescription),
102
+ focusKeyword: Schema.optionalKey(focusKeyword),
103
+ canonicalUrl: Schema.optionalKey(canonicalUrl),
104
+ scheduledAt: Schema.optionalKey(scheduledAt),
105
+ categoryIds: Schema.optionalKey(categoryIds)
106
+ });
107
+ const blogOutput = Schema.Struct({
108
+ id: uuid$2,
109
+ name: Schema.String,
110
+ slug: Schema.String,
111
+ description: Schema.String,
112
+ locale: Schema.String,
113
+ accentColor: Schema.String,
114
+ customCss: Schema.String,
115
+ publicUrl: nullable(Schema.String),
116
+ createdAt: isoDateTime,
117
+ updatedAt: isoDateTime
118
+ });
119
+ const publicBlogOutput = Schema.Struct({
120
+ id: uuid$2,
121
+ name: Schema.String,
122
+ slug: Schema.String,
123
+ description: Schema.String,
124
+ locale: Schema.String,
125
+ accentColor: Schema.String,
126
+ publicUrl: nullable(Schema.String),
127
+ createdAt: isoDateTime,
128
+ updatedAt: isoDateTime
129
+ });
130
+ const publicPostOutput = Schema.Struct({
131
+ id: uuid$2,
132
+ slug: Schema.String,
133
+ title: Schema.String,
134
+ excerpt: Schema.String,
135
+ contentMarkdown: Schema.String,
136
+ contentHtml: Schema.String,
137
+ coverImageUrl: nullable(Schema.String),
138
+ coverImageAlt: nullable(Schema.String),
139
+ status: postStatus,
140
+ locale: Schema.String,
141
+ featured: Schema.Boolean,
142
+ publishedAt: nullable(isoDateTime),
143
+ updatedAt: isoDateTime,
144
+ readingMinutes: Schema.Number,
145
+ seoTitle: nullable(Schema.String),
146
+ seoDescription: nullable(Schema.String),
147
+ canonicalUrl: nullable(Schema.String),
148
+ author: authorOutput,
149
+ categories: Schema.Array(categoryOutput)
150
+ });
151
+ const publicPostPage = Schema.Struct({
152
+ blog: publicBlogOutput,
153
+ posts: Schema.Array(publicPostOutput),
154
+ categories: Schema.Array(categoryOutput),
155
+ pagination: Schema.Struct({
156
+ page: Schema.Int,
157
+ pageSize: Schema.Int,
158
+ hasMore: Schema.Boolean
159
+ })
160
+ });
161
+ const publicPostResult = Schema.Struct({
162
+ blog: publicBlogOutput,
163
+ post: publicPostOutput
164
+ });
165
+ const paginatedPosts = Schema.Struct({
166
+ items: Schema.Array(postOutput),
167
+ total: Schema.Int,
168
+ page: Schema.Int,
169
+ pageSize: Schema.Int
170
+ });
171
+ //#endregion
172
+ //#region ../contract/src/router.ts
173
+ var ApiInputRejected = class extends Schema.TaggedError()("ApiInputRejected", { message: Schema.String }, { httpApiStatus: 400 }) {};
174
+ var ApiAuthenticationFailed = class extends Schema.TaggedError()("ApiAuthenticationFailed", { message: Schema.String }, { httpApiStatus: 401 }) {};
175
+ var ApiAccessDenied = class extends Schema.TaggedError()("ApiAccessDenied", { message: Schema.String }, { httpApiStatus: 403 }) {};
176
+ var ApiPostNotFound = class extends Schema.TaggedError()("ApiPostNotFound", { message: Schema.String }, { httpApiStatus: 404 }) {};
177
+ var ApiUnavailable = class extends Schema.TaggedError()("ApiUnavailable", { message: Schema.String }, { httpApiStatus: 500 }) {};
178
+ const apiErrors = [
179
+ ApiInputRejected,
180
+ ApiAuthenticationFailed,
181
+ ApiAccessDenied,
182
+ ApiPostNotFound,
183
+ ApiUnavailable
184
+ ];
185
+ const uuid$1 = Schema.String.check(Schema.isUUID());
186
+ const pageNumber$1 = Schema.NumberFromString.pipe(Schema.check(Schema.isInt(), Schema.isGreaterThanOrEqualTo(1)));
187
+ const pageSize$1 = Schema.NumberFromString.pipe(Schema.check(Schema.isInt(), Schema.isGreaterThanOrEqualTo(1), Schema.isLessThanOrEqualTo(100)));
188
+ const health = HttpApiGroup.make("health").add(HttpApiEndpoint.get("check", "/health", {
189
+ success: Schema.Struct({
190
+ status: Schema.Literal("ok"),
191
+ version: Schema.String
192
+ }),
193
+ error: ApiUnavailable
194
+ }).annotate(OpenApi.Summary, "Database readiness probe"));
195
+ const blogs = HttpApiGroup.make("blogs").add(HttpApiEndpoint.get("list", "/blogs", {
196
+ success: Schema.Array(blogOutput),
197
+ error: apiErrors
198
+ }).annotate(OpenApi.Summary, "List blogs"));
199
+ const posts = HttpApiGroup.make("posts").add(HttpApiEndpoint.get("list", "/posts", {
200
+ query: {
201
+ blog: Schema.optionalKey(Schema.String),
202
+ search: Schema.optionalKey(Schema.String),
203
+ status: Schema.optionalKey(postStatus),
204
+ page: Schema.optionalKey(pageNumber$1),
205
+ pageSize: Schema.optionalKey(pageSize$1)
206
+ },
207
+ success: paginatedPosts,
208
+ error: apiErrors
209
+ }).annotate(OpenApi.Summary, "List posts")).add(HttpApiEndpoint.get("get", "/posts/:id", {
210
+ params: { id: uuid$1 },
211
+ success: postOutput,
212
+ error: apiErrors
213
+ }).annotate(OpenApi.Summary, "Get a post")).add(HttpApiEndpoint.post("create", "/posts", {
214
+ payload: postCreateInput,
215
+ success: postOutput.pipe(HttpApiSchema.status(200)),
216
+ error: apiErrors
217
+ }).annotate(OpenApi.Summary, "Create a post")).add(HttpApiEndpoint.patch("update", "/posts/:id", {
218
+ params: { id: uuid$1 },
219
+ payload: postUpdateInput,
220
+ success: postOutput,
221
+ error: apiErrors
222
+ }).annotate(OpenApi.Summary, "Update a post")).add(HttpApiEndpoint.delete("archive", "/posts/:id", {
223
+ params: { id: uuid$1 },
224
+ success: Schema.Struct({ ok: Schema.Literal(true) }),
225
+ error: apiErrors
226
+ }).annotate(OpenApi.Summary, "Archive a post"));
227
+ const api = HttpApi.make("ProsewireApi").add(health, blogs, posts).prefix("/api/v1").annotate(OpenApi.Title, "Prosewire private API").annotate(OpenApi.Version, "1.0.0");
228
+ Schema.String.check(Schema.isUUID());
229
+ Schema.NumberFromString.pipe(Schema.check(Schema.isInt(), Schema.isGreaterThanOrEqualTo(1)));
230
+ Schema.NumberFromString.pipe(Schema.check(Schema.isInt(), Schema.isGreaterThanOrEqualTo(1), Schema.isLessThanOrEqualTo(100)));
231
+ //#endregion
232
+ //#region src/index.ts
233
+ function normalizedCreateInput(input) {
234
+ return {
235
+ ...input,
236
+ contentMarkdown: input.contentMarkdown ?? "",
237
+ status: input.status ?? "draft",
238
+ locale: input.locale ?? "en",
239
+ featured: input.featured ?? false,
240
+ categoryIds: input.categoryIds ?? []
241
+ };
242
+ }
243
+ function createEffectClient(options) {
244
+ const baseUrl = options.baseUrl.replace(/\/$/, "");
245
+ const generated = Effect.runSync(HttpApiClient.make(api, {
246
+ baseUrl,
247
+ transformClient: options.apiKey ? HttpClient.mapRequest(HttpClientRequest.bearerToken(options.apiKey)) : void 0
248
+ }).pipe(Effect.provide(FetchHttpClient.layer)));
249
+ const provideFetch = (effect) => effect.pipe(Effect.provideService(FetchHttpClient.Fetch, options.fetch ?? globalThis.fetch));
250
+ return {
251
+ health: () => provideFetch(generated.health.check()),
252
+ blogs: { list: () => provideFetch(generated.blogs.list()) },
253
+ posts: {
254
+ list: (input = {}) => provideFetch(generated.posts.list({ query: input })),
255
+ get: (input) => provideFetch(generated.posts.get(input)),
256
+ create: (input) => provideFetch(generated.posts.create({ payload: normalizedCreateInput(input) })),
257
+ update: (input) => provideFetch(generated.posts.update({
258
+ params: input.params,
259
+ payload: input.body
260
+ })),
261
+ archive: (input) => provideFetch(generated.posts.archive(input))
262
+ }
263
+ };
264
+ }
265
+ function createClient(options) {
266
+ const client = createEffectClient(options);
267
+ return {
268
+ health: () => Effect.runPromise(client.health()),
269
+ blogs: { list: () => Effect.runPromise(client.blogs.list()) },
270
+ posts: {
271
+ list: (input = {}) => Effect.runPromise(client.posts.list(input)),
272
+ get: (input) => Effect.runPromise(client.posts.get(input)),
273
+ create: (input) => Effect.runPromise(client.posts.create(input)),
274
+ update: (input) => Effect.runPromise(client.posts.update(input)),
275
+ archive: (input) => Effect.runPromise(client.posts.archive(input))
276
+ }
277
+ };
278
+ }
279
+ async function decodeResponse(schema, response) {
280
+ return Schema.decodeUnknownPromise(schema)(await response.json());
281
+ }
282
+ function createPublicClient(options) {
283
+ const request = options.fetch ?? fetch;
284
+ const base = options.baseUrl.replace(/\/$/, "");
285
+ const blog = encodeURIComponent(options.blog);
286
+ return {
287
+ async listPosts(input = {}) {
288
+ const query = new URLSearchParams();
289
+ if (input.search) query.set("search", input.search);
290
+ if (input.category) query.set("category", input.category);
291
+ if (input.page) query.set("page", String(input.page));
292
+ if (input.pageSize) query.set("pageSize", String(input.pageSize));
293
+ if (input.limit) query.set("limit", String(input.limit));
294
+ const suffix = query.size ? `?${query.toString()}` : "";
295
+ const response = await request(`${base}/api/public/${blog}/posts${suffix}`);
296
+ if (!response.ok) throw new Error(`Prosewire request failed (${String(response.status)})`);
297
+ return decodeResponse(publicPostPage, response);
298
+ },
299
+ async getPost(slug) {
300
+ const response = await request(`${base}/api/public/${blog}/posts/${encodeURIComponent(slug)}`);
301
+ if (!response.ok) throw new Error(`Prosewire request failed (${String(response.status)})`);
302
+ return decodeResponse(publicPostResult, response);
303
+ },
304
+ async getRendered(path = "") {
305
+ const encodedPath = path.replace(/^\//, "").split("/").filter(Boolean).map(encodeURIComponent).join("/");
306
+ const response = await request(`${base}/api/rendered/${blog}/${encodedPath}`);
307
+ if (!response.ok) throw new Error(`Prosewire request failed (${String(response.status)})`);
308
+ return response.text();
309
+ }
310
+ };
311
+ }
312
+ //#endregion
313
+ export { createClient, createEffectClient, createPublicClient };
314
+
315
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":["uuid","uuid","pageNumber","pageSize"],"sources":["../../contract/src/schemas.ts","../../contract/src/router.ts","../../contract/src/transport.ts","../src/index.ts"],"sourcesContent":["import { Effect, Schema } from \"effect\";\n\nconst withDefault = <S extends Schema.Constraint>(\n schema: S,\n value: S[\"Encoded\"],\n) => Schema.withDecodingDefaultKey(Effect.succeed(value))(schema);\n\nconst uuid = Schema.String.check(Schema.isUUID());\nconst isoDateTime = Schema.String.check(\n Schema.isPattern(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:Z|[+-]\\d{2}:\\d{2})$/),\n);\nconst url = Schema.String.check(\n Schema.isPattern(/^[a-z][a-z\\d+.-]*:\\/\\/\\S+$/i),\n);\nconst nullable = <S extends Schema.Top>(schema: S) => Schema.NullOr(schema);\n\nexport const postStatus = Schema.Literals([\n \"draft\",\n \"scheduled\",\n \"published\",\n \"archived\",\n]);\n\nexport const authorOutput = Schema.Struct({\n id: uuid,\n name: Schema.String,\n slug: Schema.String,\n bio: nullable(Schema.String),\n avatarUrl: nullable(Schema.String),\n jobTitle: nullable(Schema.String),\n credentials: nullable(Schema.String),\n});\n\nexport const categoryOutput = Schema.Struct({\n id: uuid,\n name: Schema.String,\n slug: Schema.String,\n description: nullable(Schema.String),\n});\n\nexport const postOutput = Schema.Struct({\n id: uuid,\n blogId: uuid,\n title: Schema.String,\n slug: Schema.String,\n excerpt: Schema.String,\n contentMarkdown: Schema.String,\n contentHtml: Schema.String,\n coverImageUrl: nullable(Schema.String),\n coverImageAlt: nullable(Schema.String),\n status: postStatus,\n locale: Schema.String,\n featured: Schema.Boolean,\n seoTitle: nullable(Schema.String),\n seoDescription: nullable(Schema.String),\n focusKeyword: nullable(Schema.String),\n canonicalUrl: nullable(Schema.String),\n publishedAt: nullable(isoDateTime),\n scheduledAt: nullable(isoDateTime),\n createdAt: isoDateTime,\n updatedAt: isoDateTime,\n author: authorOutput,\n categories: Schema.Array(categoryOutput),\n});\n\nconst authorId = uuid;\nconst title = Schema.Trim.pipe(\n Schema.check(Schema.isMinLength(1), Schema.isMaxLength(180)),\n);\nconst slug = Schema.Trim.pipe(\n Schema.check(\n Schema.isMinLength(1),\n Schema.isMaxLength(120),\n Schema.isPattern(/^[a-z0-9]+(?:-[a-z0-9]+)*$/),\n ),\n);\nconst excerpt = Schema.String.check(Schema.isMaxLength(500));\nconst contentMarkdown = Schema.String;\nconst coverImageUrl = nullable(url);\nconst coverImageAlt = nullable(\n Schema.String.check(Schema.isMaxLength(180)),\n);\nconst locale = Schema.String.check(\n Schema.isMinLength(2),\n Schema.isMaxLength(10),\n);\nconst featured = Schema.Boolean;\nconst seoTitle = nullable(Schema.String.check(Schema.isMaxLength(70)));\nconst seoDescription = nullable(\n Schema.String.check(Schema.isMaxLength(180)),\n);\nconst focusKeyword = nullable(\n Schema.String.check(Schema.isMaxLength(120)),\n);\nconst canonicalUrl = nullable(url);\nconst scheduledAt = nullable(isoDateTime);\nconst categoryIds = Schema.Array(uuid);\n\nexport const postCreateInput = Schema.Struct({\n blogId: uuid,\n authorId,\n title,\n slug,\n excerpt: Schema.optionalKey(excerpt),\n contentMarkdown: withDefault(contentMarkdown, \"\"),\n coverImageUrl: Schema.optionalKey(coverImageUrl),\n coverImageAlt: Schema.optionalKey(coverImageAlt),\n status: withDefault(postStatus, \"draft\"),\n locale: withDefault(locale, \"en\"),\n featured: withDefault(featured, false),\n seoTitle: Schema.optionalKey(seoTitle),\n seoDescription: Schema.optionalKey(seoDescription),\n focusKeyword: Schema.optionalKey(focusKeyword),\n canonicalUrl: Schema.optionalKey(canonicalUrl),\n scheduledAt: Schema.optionalKey(scheduledAt),\n categoryIds: withDefault(categoryIds, []),\n});\n\nexport const postUpdateInput = Schema.Struct({\n authorId: Schema.optionalKey(authorId),\n title: Schema.optionalKey(title),\n slug: Schema.optionalKey(slug),\n excerpt: Schema.optionalKey(excerpt),\n contentMarkdown: Schema.optionalKey(contentMarkdown),\n coverImageUrl: Schema.optionalKey(coverImageUrl),\n coverImageAlt: Schema.optionalKey(coverImageAlt),\n status: Schema.optionalKey(postStatus),\n locale: Schema.optionalKey(locale),\n featured: Schema.optionalKey(featured),\n seoTitle: Schema.optionalKey(seoTitle),\n seoDescription: Schema.optionalKey(seoDescription),\n focusKeyword: Schema.optionalKey(focusKeyword),\n canonicalUrl: Schema.optionalKey(canonicalUrl),\n scheduledAt: Schema.optionalKey(scheduledAt),\n categoryIds: Schema.optionalKey(categoryIds),\n});\n\nexport const blogOutput = Schema.Struct({\n id: uuid,\n name: Schema.String,\n slug: Schema.String,\n description: Schema.String,\n locale: Schema.String,\n accentColor: Schema.String,\n customCss: Schema.String,\n publicUrl: nullable(Schema.String),\n createdAt: isoDateTime,\n updatedAt: isoDateTime,\n});\n\nexport const publicBlogOutput = Schema.Struct({\n id: uuid,\n name: Schema.String,\n slug: Schema.String,\n description: Schema.String,\n locale: Schema.String,\n accentColor: Schema.String,\n publicUrl: nullable(Schema.String),\n createdAt: isoDateTime,\n updatedAt: isoDateTime,\n});\n\nexport const publicPostOutput = Schema.Struct({\n id: uuid,\n slug: Schema.String,\n title: Schema.String,\n excerpt: Schema.String,\n contentMarkdown: Schema.String,\n contentHtml: Schema.String,\n coverImageUrl: nullable(Schema.String),\n coverImageAlt: nullable(Schema.String),\n status: postStatus,\n locale: Schema.String,\n featured: Schema.Boolean,\n publishedAt: nullable(isoDateTime),\n updatedAt: isoDateTime,\n readingMinutes: Schema.Number,\n seoTitle: nullable(Schema.String),\n seoDescription: nullable(Schema.String),\n canonicalUrl: nullable(Schema.String),\n author: authorOutput,\n categories: Schema.Array(categoryOutput),\n});\n\nexport const publicPostPage = Schema.Struct({\n blog: publicBlogOutput,\n posts: Schema.Array(publicPostOutput),\n categories: Schema.Array(categoryOutput),\n pagination: Schema.Struct({\n page: Schema.Int,\n pageSize: Schema.Int,\n hasMore: Schema.Boolean,\n }),\n});\n\nexport const publicPostResult = Schema.Struct({\n blog: publicBlogOutput,\n post: publicPostOutput,\n});\n\nexport const paginatedPosts = Schema.Struct({\n items: Schema.Array(postOutput),\n total: Schema.Int,\n page: Schema.Int,\n pageSize: Schema.Int,\n});\n\nexport type PostStatus = typeof postStatus.Type;\nexport type Post = typeof postOutput.Type;\nexport type Blog = typeof blogOutput.Type;\nexport type PublicBlog = typeof publicBlogOutput.Type;\nexport type PublicAuthor = typeof authorOutput.Type;\nexport type PublicCategory = typeof categoryOutput.Type;\nexport type PublicPost = typeof publicPostOutput.Type;\nexport type PublicPostPage = typeof publicPostPage.Type;\nexport type PublicPostResult = typeof publicPostResult.Type;\nexport type PostCreateInput = typeof postCreateInput.Type;\nexport type PostCreateEncodedInput = typeof postCreateInput.Encoded;\nexport type PostUpdateInput = typeof postUpdateInput.Type;\nexport type PostUpdateEncodedInput = typeof postUpdateInput.Encoded;\nexport type PaginatedPosts = typeof paginatedPosts.Type;\n","import { Schema } from \"effect\";\nimport {\n HttpApi,\n HttpApiEndpoint,\n HttpApiGroup,\n HttpApiSchema,\n OpenApi,\n} from \"effect/unstable/httpapi\";\nimport {\n blogOutput,\n paginatedPosts,\n postCreateInput,\n postOutput,\n postStatus,\n postUpdateInput,\n} from \"./schemas.ts\";\n\nexport class ApiInputRejected extends Schema.TaggedError<ApiInputRejected>()(\n \"ApiInputRejected\",\n { message: Schema.String },\n { httpApiStatus: 400 },\n) {}\n\nexport class ApiAuthenticationFailed extends Schema.TaggedError<ApiAuthenticationFailed>()(\n \"ApiAuthenticationFailed\",\n { message: Schema.String },\n { httpApiStatus: 401 },\n) {}\n\nexport class ApiAccessDenied extends Schema.TaggedError<ApiAccessDenied>()(\n \"ApiAccessDenied\",\n { message: Schema.String },\n { httpApiStatus: 403 },\n) {}\n\nexport class ApiPostNotFound extends Schema.TaggedError<ApiPostNotFound>()(\n \"ApiPostNotFound\",\n { message: Schema.String },\n { httpApiStatus: 404 },\n) {}\n\nexport class ApiUnavailable extends Schema.TaggedError<ApiUnavailable>()(\n \"ApiUnavailable\",\n { message: Schema.String },\n { httpApiStatus: 500 },\n) {}\n\nexport const apiErrors = [\n ApiInputRejected,\n ApiAuthenticationFailed,\n ApiAccessDenied,\n ApiPostNotFound,\n ApiUnavailable,\n] as const;\n\nconst uuid = Schema.String.check(Schema.isUUID());\nconst pageNumber = Schema.NumberFromString.pipe(\n Schema.check(Schema.isInt(), Schema.isGreaterThanOrEqualTo(1)),\n);\nconst pageSize = Schema.NumberFromString.pipe(\n Schema.check(\n Schema.isInt(),\n Schema.isGreaterThanOrEqualTo(1),\n Schema.isLessThanOrEqualTo(100),\n ),\n);\n\nconst health = HttpApiGroup.make(\"health\").add(\n HttpApiEndpoint.get(\"check\", \"/health\", {\n success: Schema.Struct({\n status: Schema.Literal(\"ok\"),\n version: Schema.String,\n }),\n error: ApiUnavailable,\n }).annotate(OpenApi.Summary, \"Database readiness probe\"),\n);\n\nconst blogs = HttpApiGroup.make(\"blogs\").add(\n HttpApiEndpoint.get(\"list\", \"/blogs\", {\n success: Schema.Array(blogOutput),\n error: apiErrors,\n }).annotate(OpenApi.Summary, \"List blogs\"),\n);\n\nconst posts = HttpApiGroup.make(\"posts\")\n .add(\n HttpApiEndpoint.get(\"list\", \"/posts\", {\n query: {\n blog: Schema.optionalKey(Schema.String),\n search: Schema.optionalKey(Schema.String),\n status: Schema.optionalKey(postStatus),\n page: Schema.optionalKey(pageNumber),\n pageSize: Schema.optionalKey(pageSize),\n },\n success: paginatedPosts,\n error: apiErrors,\n }).annotate(OpenApi.Summary, \"List posts\"),\n )\n .add(\n HttpApiEndpoint.get(\"get\", \"/posts/:id\", {\n params: { id: uuid },\n success: postOutput,\n error: apiErrors,\n }).annotate(OpenApi.Summary, \"Get a post\"),\n )\n .add(\n HttpApiEndpoint.post(\"create\", \"/posts\", {\n payload: postCreateInput,\n success: postOutput.pipe(HttpApiSchema.status(200)),\n error: apiErrors,\n }).annotate(OpenApi.Summary, \"Create a post\"),\n )\n .add(\n HttpApiEndpoint.patch(\"update\", \"/posts/:id\", {\n params: { id: uuid },\n payload: postUpdateInput,\n success: postOutput,\n error: apiErrors,\n }).annotate(OpenApi.Summary, \"Update a post\"),\n )\n .add(\n HttpApiEndpoint.delete(\"archive\", \"/posts/:id\", {\n params: { id: uuid },\n success: Schema.Struct({ ok: Schema.Literal(true) }),\n error: apiErrors,\n }).annotate(OpenApi.Summary, \"Archive a post\"),\n );\n\nexport const api = HttpApi.make(\"ProsewireApi\")\n .add(health, blogs, posts)\n .prefix(\"/api/v1\")\n .annotate(OpenApi.Title, \"Prosewire private API\")\n .annotate(OpenApi.Version, \"1.0.0\");\n\n/** @deprecated Use `api`. Kept as a source-compatible migration alias. */\nexport const contract = api;\nexport type Contract = typeof api;\n","import { Schema } from \"effect\";\nimport {\n ApiInputRejected,\n ApiPostNotFound,\n} from \"./router.ts\";\nimport {\n postCreateInput,\n postStatus,\n postUpdateInput,\n type PostCreateInput,\n type PostStatus,\n type PostUpdateInput,\n} from \"./schemas.ts\";\n\nconst uuid = Schema.String.check(Schema.isUUID());\nconst pageNumber = Schema.NumberFromString.pipe(\n Schema.check(Schema.isInt(), Schema.isGreaterThanOrEqualTo(1)),\n);\nconst pageSize = Schema.NumberFromString.pipe(\n Schema.check(\n Schema.isInt(),\n Schema.isGreaterThanOrEqualTo(1),\n Schema.isLessThanOrEqualTo(100),\n ),\n);\n\nexport interface PostListRequest {\n readonly blog?: string | undefined;\n readonly search?: string | undefined;\n readonly status?: PostStatus | undefined;\n readonly page: number;\n readonly pageSize: number;\n}\n\nexport type PrivateApiRequest =\n | { readonly _tag: \"Health\" }\n | { readonly _tag: \"ListBlogs\" }\n | { readonly _tag: \"ListPosts\"; readonly input: PostListRequest }\n | { readonly _tag: \"GetPost\"; readonly id: string }\n | { readonly _tag: \"CreatePost\"; readonly input: PostCreateInput }\n | {\n readonly _tag: \"UpdatePost\";\n readonly id: string;\n readonly input: PostUpdateInput;\n }\n | { readonly _tag: \"ArchivePost\"; readonly id: string };\n\nasync function decode<S extends Schema.ConstraintDecoder<unknown>>(\n schema: S,\n value: unknown,\n message: string,\n): Promise<S[\"Type\"]> {\n try {\n return await Schema.decodeUnknownPromise(schema)(value);\n } catch {\n throw new ApiInputRejected({ message });\n }\n}\n\nasync function json(request: Request): Promise<unknown> {\n try {\n return await request.json();\n } catch {\n throw new ApiInputRejected({ message: \"Invalid JSON request body\" });\n }\n}\n\nasync function identifier(pathname: string): Promise<string | undefined> {\n const match = /^\\/api\\/v1\\/posts\\/([^/]+)$/.exec(pathname);\n if (!match?.[1]) return undefined;\n let value: string;\n try {\n value = decodeURIComponent(match[1]);\n } catch {\n throw new ApiInputRejected({ message: \"Invalid post id\" });\n }\n return decode(uuid, value, \"Invalid post id\");\n}\n\nexport async function decodePrivateApiRequest(\n request: Request,\n): Promise<PrivateApiRequest> {\n const { pathname, searchParams } = new URL(request.url);\n if (request.method === \"GET\" && pathname === \"/api/v1/health\") {\n return { _tag: \"Health\" };\n }\n if (request.method === \"GET\" && pathname === \"/api/v1/blogs\") {\n return { _tag: \"ListBlogs\" };\n }\n if (request.method === \"GET\" && pathname === \"/api/v1/posts\") {\n const statusValue = searchParams.get(\"status\");\n return {\n _tag: \"ListPosts\",\n input: {\n ...(searchParams.has(\"blog\")\n ? { blog: searchParams.get(\"blog\") ?? undefined }\n : {}),\n ...(searchParams.has(\"search\")\n ? { search: searchParams.get(\"search\") ?? undefined }\n : {}),\n ...(statusValue === null\n ? {}\n : {\n status: await decode(\n postStatus,\n statusValue,\n \"Invalid post status\",\n ),\n }),\n page: searchParams.has(\"page\")\n ? await decode(\n pageNumber,\n searchParams.get(\"page\"),\n \"Invalid pagination parameters\",\n )\n : 1,\n pageSize: searchParams.has(\"pageSize\")\n ? await decode(\n pageSize,\n searchParams.get(\"pageSize\"),\n \"Invalid pagination parameters\",\n )\n : 20,\n },\n };\n }\n\n const id = await identifier(pathname);\n if (id && request.method === \"GET\") return { _tag: \"GetPost\", id };\n if (pathname === \"/api/v1/posts\" && request.method === \"POST\") {\n return {\n _tag: \"CreatePost\",\n input: await decode(\n postCreateInput,\n await json(request),\n \"Invalid post input\",\n ),\n };\n }\n if (id && request.method === \"PATCH\") {\n return {\n _tag: \"UpdatePost\",\n id,\n input: await decode(\n postUpdateInput,\n await json(request),\n \"Invalid post update\",\n ),\n };\n }\n if (id && request.method === \"DELETE\") return { _tag: \"ArchivePost\", id };\n throw new ApiPostNotFound({ message: \"API route not found\" });\n}\n\nexport * as PrivateApiTransport from \"./transport.ts\";\n","import {\n api,\n type PostCreateEncodedInput,\n type PostCreateInput,\n type PostStatus,\n type PostUpdateInput,\n type PublicBlog,\n type PublicAuthor,\n type PublicCategory,\n type PublicPost,\n type PublicPostPage,\n type PublicPostResult,\n publicPostPage,\n publicPostResult,\n} from \"@prosewire/contract\";\nimport { Effect, Schema } from \"effect\";\nimport {\n FetchHttpClient,\n HttpClient,\n HttpClientRequest,\n} from \"effect/unstable/http\";\nimport { HttpApiClient } from \"effect/unstable/httpapi\";\n\nexport interface ProsewireClientOptions {\n /** Base URL of a Prosewire deployment, e.g. https://blog.example.com. */\n baseUrl: string;\n /** Private API key. Public rendered/raw endpoints do not need one. */\n apiKey?: string;\n fetch?: typeof fetch;\n}\n\nexport interface PrivatePostListInput {\n readonly blog?: string;\n readonly search?: string;\n readonly status?: PostStatus;\n readonly page?: number;\n readonly pageSize?: number;\n}\n\nfunction normalizedCreateInput(input: PostCreateEncodedInput): PostCreateInput {\n return {\n ...input,\n contentMarkdown: input.contentMarkdown ?? \"\",\n status: input.status ?? \"draft\",\n locale: input.locale ?? \"en\",\n featured: input.featured ?? false,\n categoryIds: input.categoryIds ?? [],\n };\n}\n\nexport function createEffectClient(options: ProsewireClientOptions) {\n const baseUrl = options.baseUrl.replace(/\\/$/, \"\");\n const generated = Effect.runSync(\n HttpApiClient.make(api, {\n baseUrl,\n transformClient: options.apiKey\n ? HttpClient.mapRequest(\n HttpClientRequest.bearerToken(options.apiKey),\n )\n : undefined,\n }).pipe(Effect.provide(FetchHttpClient.layer)),\n );\n const provideFetch = <A, E, R>(effect: Effect.Effect<A, E, R>) =>\n effect.pipe(\n Effect.provideService(\n FetchHttpClient.Fetch,\n options.fetch ?? globalThis.fetch,\n ),\n );\n\n return {\n health: () => provideFetch(generated.health.check()),\n blogs: {\n list: () => provideFetch(generated.blogs.list()),\n },\n posts: {\n list: (input: PrivatePostListInput = {}) =>\n provideFetch(generated.posts.list({ query: input })),\n get: (input: { readonly params: { readonly id: string } }) =>\n provideFetch(generated.posts.get(input)),\n create: (input: PostCreateEncodedInput) =>\n provideFetch(\n generated.posts.create({ payload: normalizedCreateInput(input) }),\n ),\n update: (input: {\n readonly params: { readonly id: string };\n readonly body: PostUpdateInput;\n }) =>\n provideFetch(\n generated.posts.update({\n params: input.params,\n payload: input.body,\n }),\n ),\n archive: (input: { readonly params: { readonly id: string } }) =>\n provideFetch(generated.posts.archive(input)),\n },\n };\n}\n\nexport type EffectClient = ReturnType<typeof createEffectClient>;\n\nexport function createClient(options: ProsewireClientOptions) {\n const client = createEffectClient(options);\n return {\n health: () => Effect.runPromise(client.health()),\n blogs: {\n list: () => Effect.runPromise(client.blogs.list()),\n },\n posts: {\n list: (input: PrivatePostListInput = {}) =>\n Effect.runPromise(client.posts.list(input)),\n get: (input: { readonly params: { readonly id: string } }) =>\n Effect.runPromise(client.posts.get(input)),\n create: (input: PostCreateEncodedInput) =>\n Effect.runPromise(client.posts.create(input)),\n update: (input: {\n readonly params: { readonly id: string };\n readonly body: PostUpdateInput;\n }) => Effect.runPromise(client.posts.update(input)),\n archive: (input: { readonly params: { readonly id: string } }) =>\n Effect.runPromise(client.posts.archive(input)),\n },\n };\n}\n\nexport type Client = ReturnType<typeof createClient>;\n\nexport type {\n PublicAuthor,\n PublicBlog,\n PublicCategory,\n PublicPost,\n PublicPostPage,\n PublicPostResult,\n};\n\nexport interface PublicListInput {\n search?: string;\n category?: string;\n page?: number;\n pageSize?: number;\n /** @deprecated Use pageSize. */\n limit?: number;\n}\n\nexport interface PublicContentClient {\n listPosts(input?: PublicListInput): Promise<PublicPostPage>;\n getPost(slug: string): Promise<PublicPostResult>;\n getRendered(path?: string): Promise<string>;\n}\n\nasync function decodeResponse<S extends Schema.ConstraintDecoder<unknown>>(\n schema: S,\n response: Response,\n): Promise<S[\"Type\"]> {\n return Schema.decodeUnknownPromise(schema)(await response.json());\n}\n\nexport function createPublicClient(\n options: Pick<ProsewireClientOptions, \"baseUrl\" | \"fetch\"> & { blog: string },\n): PublicContentClient {\n const request = options.fetch ?? fetch;\n const base = options.baseUrl.replace(/\\/$/, \"\");\n const blog = encodeURIComponent(options.blog);\n return {\n async listPosts(input = {}) {\n const query = new URLSearchParams();\n if (input.search) query.set(\"search\", input.search);\n if (input.category) query.set(\"category\", input.category);\n if (input.page) query.set(\"page\", String(input.page));\n if (input.pageSize) query.set(\"pageSize\", String(input.pageSize));\n if (input.limit) query.set(\"limit\", String(input.limit));\n const suffix = query.size ? `?${query.toString()}` : \"\";\n const response = await request(`${base}/api/public/${blog}/posts${suffix}`);\n if (!response.ok) throw new Error(`Prosewire request failed (${String(response.status)})`);\n return decodeResponse(publicPostPage, response);\n },\n async getPost(slug) {\n const response = await request(`${base}/api/public/${blog}/posts/${encodeURIComponent(slug)}`);\n if (!response.ok) throw new Error(`Prosewire request failed (${String(response.status)})`);\n return decodeResponse(publicPostResult, response);\n },\n async getRendered(path = \"\") {\n const encodedPath = path.replace(/^\\//, \"\").split(\"/\").filter(Boolean).map(encodeURIComponent).join(\"/\");\n const response = await request(`${base}/api/rendered/${blog}/${encodedPath}`);\n if (!response.ok) throw new Error(`Prosewire request failed (${String(response.status)})`);\n return response.text();\n },\n };\n}\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,77 @@
1
+ {
2
+ "name": "@prosewire/sdk",
3
+ "version": "0.2.0",
4
+ "license": "Apache-2.0",
5
+ "type": "module",
6
+ "description": "Typed client for the Prosewire content API.",
7
+ "keywords": [
8
+ "prosewire",
9
+ "publishing",
10
+ "cms",
11
+ "typescript"
12
+ ],
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "https://github.com/prosewire/prosewire.git",
16
+ "directory": "packages/sdk"
17
+ },
18
+ "homepage": "https://github.com/prosewire/prosewire#readme",
19
+ "bugs": {
20
+ "url": "https://github.com/prosewire/prosewire/issues"
21
+ },
22
+ "engines": {
23
+ "node": ">=24"
24
+ },
25
+ "main": "./dist/index.mjs",
26
+ "module": "./dist/index.mjs",
27
+ "types": "./dist/index.d.mts",
28
+ "exports": {
29
+ ".": {
30
+ "types": "./dist/index.d.mts",
31
+ "import": "./dist/index.mjs",
32
+ "default": "./dist/index.mjs"
33
+ }
34
+ },
35
+ "files": [
36
+ "dist",
37
+ "README.md",
38
+ "CHANGELOG.md"
39
+ ],
40
+ "publishConfig": {
41
+ "access": "public",
42
+ "provenance": true
43
+ },
44
+ "dependencies": {
45
+ "effect": "4.0.0-rc.110"
46
+ },
47
+ "devDependencies": {
48
+ "@types/node": "^26.2.0",
49
+ "tsdown": "^0.22.0",
50
+ "typescript": "npm:@typescript/typescript6@^6.0.2",
51
+ "vitest": "^4.1.11",
52
+ "@prosewire/contract": "0.0.0",
53
+ "@prosewire/config": "0.0.0"
54
+ },
55
+ "tsdown": {
56
+ "dts": {
57
+ "eager": true
58
+ },
59
+ "deps": {
60
+ "alwaysBundle": [
61
+ "@prosewire/contract"
62
+ ],
63
+ "dts": {
64
+ "alwaysBundle": [
65
+ "@prosewire/contract"
66
+ ]
67
+ }
68
+ }
69
+ },
70
+ "scripts": {
71
+ "build": "tsdown",
72
+ "lint": "biome lint src",
73
+ "typecheck": "tsc --noEmit",
74
+ "test": "vitest run",
75
+ "test:coverage": "vitest run --coverage"
76
+ }
77
+ }