kizlo 0.7.0 → 0.8.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 (85) hide show
  1. package/dist/category/error.js +14 -0
  2. package/dist/category/index.js +77 -0
  3. package/dist/category/schema.js +40 -0
  4. package/dist/category/utils.js +20 -0
  5. package/dist/cli/banner.js +1 -1
  6. package/dist/cli/commands/_setup.js +342 -0
  7. package/dist/cli/commands/create.js +152 -0
  8. package/dist/cli/commands/dev.js +1 -1
  9. package/dist/cli/commands/init.js +53 -300
  10. package/dist/cli/index.js +2 -1
  11. package/dist/cli/presets/generated/templates.js +59 -0
  12. package/dist/cli/presets/nextjs.js +3 -95
  13. package/dist/cli/presets/patch.js +133 -0
  14. package/dist/cli/presets/template.js +36 -0
  15. package/dist/comment/index.js +4 -4
  16. package/dist/context.d.ts +25 -8
  17. package/dist/context.js +15 -5
  18. package/dist/email/service.d.ts +4 -3
  19. package/dist/email/service.js +4 -4
  20. package/dist/index.d.ts +15 -11
  21. package/dist/index.js +10 -4
  22. package/dist/integrations/nextjs/metadata.js +6 -3
  23. package/dist/integrations/nextjs/sitemap.d.ts +8 -7
  24. package/dist/integrations/nextjs/sitemap.js +3 -3
  25. package/dist/menu/index.js +19 -14
  26. package/dist/menu/schema.d.ts +14 -0
  27. package/dist/menu/schema.js +35 -40
  28. package/dist/menu/utils.js +23 -14
  29. package/dist/nextjs/server.d.ts +2 -1
  30. package/dist/nextjs/server.js +2 -1
  31. package/dist/package.js +1 -1
  32. package/dist/page/error.js +20 -0
  33. package/dist/page/index.js +128 -0
  34. package/dist/page/schema.js +75 -0
  35. package/dist/page/utils.js +43 -0
  36. package/dist/post/error.js +4 -14
  37. package/dist/post/index.js +17 -9
  38. package/dist/post/schema.js +37 -66
  39. package/dist/post/utils.js +27 -24
  40. package/dist/router.d.ts +1006 -185
  41. package/dist/router.js +6 -0
  42. package/dist/seo/index.js +7 -44
  43. package/dist/seo/schema.d.ts +10 -6
  44. package/dist/seo/schema.js +7 -5
  45. package/dist/seo/sitemap.d.ts +9 -1
  46. package/dist/seo/sitemap.js +17 -1
  47. package/dist/seo/types.d.ts +17 -20
  48. package/dist/seo/utils.js +9 -7
  49. package/dist/settings/index.js +27 -24
  50. package/dist/settings/service.d.ts +14 -13
  51. package/dist/settings/service.interface.d.ts +2 -2
  52. package/dist/settings/service.js +9 -9
  53. package/dist/shared/middleware.d.ts +4 -4
  54. package/dist/shared/procedure.d.ts +6 -7
  55. package/dist/tag/error.js +14 -0
  56. package/dist/tag/index.js +76 -0
  57. package/dist/tag/schema.js +38 -0
  58. package/dist/tag/utils.js +19 -0
  59. package/dist/taxonomy/service.js +48 -0
  60. package/dist/test/fixtures.d.ts +1 -1
  61. package/dist/test/fixtures.js +1 -1
  62. package/dist/webhook/index.d.ts +2 -2
  63. package/dist/wordpress/category/service.d.ts +28 -0
  64. package/dist/wordpress/category/service.js +55 -0
  65. package/dist/wordpress/category/types.d.ts +120 -0
  66. package/dist/wordpress/category/types.js +15 -0
  67. package/dist/wordpress/comment/service.d.ts +1 -1
  68. package/dist/wordpress/index.d.ts +9 -4
  69. package/dist/wordpress/menu/items/types.d.ts +7 -4
  70. package/dist/wordpress/menu/items/types.js +22 -0
  71. package/dist/wordpress/page/service.d.ts +28 -0
  72. package/dist/wordpress/page/service.js +55 -0
  73. package/dist/wordpress/page/types.d.ts +270 -0
  74. package/dist/wordpress/page/types.js +27 -0
  75. package/dist/wordpress/post/types.d.ts +9 -5
  76. package/dist/wordpress/post/types.js +41 -0
  77. package/dist/wordpress/service.d.ts +7 -1
  78. package/dist/wordpress/service.js +6 -0
  79. package/dist/wordpress/tag/service.d.ts +28 -0
  80. package/dist/wordpress/tag/service.js +55 -0
  81. package/dist/wordpress/tag/types.d.ts +113 -0
  82. package/dist/wordpress/tag/types.js +15 -0
  83. package/package.json +5 -3
  84. package/dist/service.d.ts +0 -19
  85. package/dist/service.js +0 -20
@@ -1,8 +1,8 @@
1
1
  import { compare } from "../shared/crypto.js";
2
2
  import { createProcedure } from "../shared/procedure.js";
3
+ import { parseIdentifier } from "../shared/identifier.js";
3
4
  import { deserializeListMetadata } from "../shared/serialize.js";
4
5
  import { getPostTypeService } from "../post-type/service.js";
5
- import { parseIdentifier } from "../shared/identifier.js";
6
6
  import { GET_POST_ERROR_MAP, LIST_POST_ERROR_MAP } from "./error.js";
7
7
  import { ListPostInput, Post, PostList, RetrievePostInput } from "./schema.js";
8
8
  import { deserializePost } from "./utils.js";
@@ -21,7 +21,7 @@ const POST_ROUTER_MAP = {
21
21
  output: Post,
22
22
  errors: GET_POST_ERROR_MAP
23
23
  }, async ({ input, context, errors }) => {
24
- const postType = getPostTypeService("post", context.service.wordpress);
24
+ const postType = getPostTypeService("post", context.wordpress);
25
25
  if (input.query?.previewToken) {
26
26
  const result = await context.verifyPreviewToken(input.query.previewToken);
27
27
  if (!result) throw errors.POST_NOT_FOUND();
@@ -30,6 +30,8 @@ const POST_ROUTER_MAP = {
30
30
  value: result.id
31
31
  });
32
32
  if (response$1.error) switch (response$1.error.code) {
33
+ case "invalid_post_type":
34
+ case "post_type_not_found":
33
35
  case "rest_post_invalid_id": throw errors.POST_NOT_FOUND();
34
36
  case "rest_post_incorrect_password": throw errors.POST_PASSWORD_INVALID();
35
37
  default:
@@ -42,12 +44,14 @@ const POST_ROUTER_MAP = {
42
44
  return deserializePost({
43
45
  ...response$1.data,
44
46
  password: ""
45
- });
47
+ }, { preview: true });
46
48
  }
47
49
  const identifier = parseIdentifier(input.params.identifier);
48
50
  if (!identifier) throw errors.POST_NOT_FOUND();
49
51
  const response = await postType.get(identifier);
50
52
  if (response.error) switch (response.error.code) {
53
+ case "invalid_post_type":
54
+ case "post_type_not_found":
51
55
  case "rest_post_invalid_id": throw errors.POST_NOT_FOUND();
52
56
  case "rest_post_incorrect_password": throw errors.POST_PASSWORD_INVALID();
53
57
  default:
@@ -58,6 +62,7 @@ const POST_ROUTER_MAP = {
58
62
  throw errors.INTERNAL_SERVER_ERROR();
59
63
  }
60
64
  const data = response.data;
65
+ if (data.status !== "publish") throw errors.POST_NOT_FOUND();
61
66
  if (input.query?.password && data.password) {
62
67
  if (!await compare(input.query.password, data.password)) throw errors.POST_PASSWORD_INVALID();
63
68
  return deserializePost({
@@ -75,20 +80,25 @@ const POST_ROUTER_MAP = {
75
80
  output: PostList,
76
81
  errors: LIST_POST_ERROR_MAP
77
82
  }, async ({ input, context, errors }) => {
78
- const response = await getPostTypeService("post", context.service.wordpress).list({
83
+ const q = input.query;
84
+ const postType = getPostTypeService("post", context.wordpress);
85
+ const orderby = q?.orderby === "relevance" && !q?.search || q?.orderby === "include" && q?.include === void 0 ? void 0 : q?.orderby;
86
+ const response = await postType.list({
79
87
  context: "edit",
80
88
  status: "publish",
81
89
  after: input.query?.after,
82
90
  author: input.query?.author,
83
91
  author_exclude: input.query?.authorExclude,
84
92
  before: input.query?.before,
93
+ modified_after: input.query?.modifiedAfter,
94
+ modified_before: input.query?.modifiedBefore,
85
95
  categories: input.query?.categories,
86
96
  categories_exclude: input.query?.categoriesExclude,
87
97
  exclude: input.query?.exclude,
88
98
  include: input.query?.include,
89
99
  offset: input.query?.offset,
90
100
  order: input.query?.order,
91
- orderby: input.query?.orderby,
101
+ orderby,
92
102
  page: input.query?.page,
93
103
  per_page: input.query?.perPage,
94
104
  search: input.query?.search,
@@ -101,20 +111,18 @@ const POST_ROUTER_MAP = {
101
111
  });
102
112
  if (response.error) switch (response.error.code) {
103
113
  case "rest_post_invalid_page_number": throw errors.POST_INVALID_PAGE();
104
- case "rest_no_search_term_defined": throw errors.POST_SEARCH_REQUIRED();
105
- case "rest_orderby_include_missing_include": throw errors.POST_ORDERBY_INCLUDE_MISSING();
106
114
  default:
107
115
  context.logger.error("List posts unhandled error", response.error, { code: response.error.code });
108
116
  throw errors.INTERNAL_SERVER_ERROR();
109
117
  }
110
- const list = context.service.wordpress.resolveList({
118
+ const list = context.wordpress.resolveList({
111
119
  data: response.data,
112
120
  headers: response.headers,
113
121
  searchParams: input.query
114
122
  });
115
123
  return {
116
124
  meta: deserializeListMetadata(list.meta),
117
- items: list.items.map(deserializePost)
125
+ items: list.items.map((item) => deserializePost(item))
118
126
  };
119
127
  })
120
128
  };
@@ -1,46 +1,16 @@
1
1
  import { IdentifierInput, ListMetadata, ListOrder, Media } from "../shared/schema.js";
2
+ import { WP_POST_FORMATS, WP_POST_ORDER_BYES, WP_POST_STATUSES, WP_POST_TAX_RELATIONS } from "../wordpress/post/types.js";
2
3
  import { Seo } from "../seo/schema.js";
3
- import { BooleanLike, Metadata, NumberLike, arrayable } from "@kizlo/shared";
4
+ import { BooleanLike, Metadata, NumberLike, arrayable, lenient } from "@kizlo/shared";
4
5
  import z from "zod/v4";
5
6
 
6
7
  //#region src/post/schema.ts
7
- const POST_TYPE_FORMATS = [
8
- "standard",
9
- "aside",
10
- "chat",
11
- "gallery",
12
- "link",
13
- "image",
14
- "quote",
15
- "status",
16
- "video",
17
- "audio"
18
- ];
19
- const PostTypeFormat = z.enum(POST_TYPE_FORMATS);
20
- const POST_STATUSES = [
21
- "publish",
22
- "future",
23
- "draft",
24
- "pending",
25
- "private"
26
- ];
27
- const PostStatus = z.enum(POST_STATUSES);
28
- const POST_COMMENT_STATUSES = [
29
- "approved",
30
- "hold",
31
- "spam",
32
- "trash"
33
- ];
34
- const PostCommentStatus = z.enum(POST_COMMENT_STATUSES);
35
- const POST_COMMENT_TYPES = [
36
- "comment",
37
- "pingback",
38
- "trackback"
39
- ];
40
- const PostCommentType = z.enum(POST_COMMENT_TYPES);
8
+ const PostTypeFormat = z.enum(WP_POST_FORMATS);
9
+ const PostStatus = z.enum(WP_POST_STATUSES).exclude(["trash"]);
41
10
  const PostAuthorRef = z.object({
42
11
  id: z.number(),
43
12
  name: z.string(),
13
+ slug: z.string(),
44
14
  avatar: Media.nullable()
45
15
  });
46
16
  const PostCategoryRef = z.object({
@@ -56,11 +26,15 @@ const PostTagRef = z.object({
56
26
  const Post = z.object({
57
27
  id: z.number(),
58
28
  slug: z.string(),
29
+ url: z.string().nullable(),
30
+ parent: z.number().nullable(),
59
31
  title: z.string().nullable(),
60
32
  content: z.string().nullable(),
61
33
  excerpt: z.string().nullable(),
62
34
  commentsEnabled: z.boolean(),
63
35
  protected: z.boolean(),
36
+ preview: z.boolean(),
37
+ status: PostStatus,
64
38
  format: PostTypeFormat,
65
39
  sticky: z.boolean(),
66
40
  author: PostAuthorRef.nullable(),
@@ -81,39 +55,36 @@ const PostList = z.object({
81
55
  items: z.array(Post),
82
56
  meta: ListMetadata
83
57
  });
84
- const POST_ORDER_BYES = [
85
- "author",
86
- "date",
87
- "id",
88
- "include",
89
- "parent",
90
- "relevance",
91
- "slug",
92
- "include_slugs",
93
- "title"
58
+ const PostOrderBy = z.enum(WP_POST_ORDER_BYES);
59
+ const POST_SEARCH_COLUMNS = [
60
+ "post_title",
61
+ "post_content",
62
+ "post_excerpt"
94
63
  ];
95
- const PostOrderBy = z.enum(POST_ORDER_BYES);
64
+ const PostSearchColumn = z.enum(POST_SEARCH_COLUMNS);
96
65
  const ListPostInput = z.object({
97
- page: NumberLike.optional(),
98
- perPage: NumberLike.optional(),
99
- search: z.string().optional(),
100
- after: z.string().optional(),
101
- before: z.string().optional(),
102
- author: arrayable(NumberLike).optional(),
103
- authorExclude: arrayable(NumberLike).optional(),
104
- exclude: arrayable(NumberLike).optional(),
105
- include: arrayable(NumberLike).optional(),
106
- offset: NumberLike.optional(),
107
- order: ListOrder.optional(),
108
- orderby: PostOrderBy.optional(),
109
- searchColumns: z.array(z.string()).optional(),
110
- slug: arrayable(z.string()).optional(),
111
- taxRelation: z.enum(["AND", "OR"]).optional(),
112
- categories: arrayable(NumberLike).optional(),
113
- categoriesExclude: arrayable(NumberLike).optional(),
114
- tags: arrayable(NumberLike).optional(),
115
- tagsExclude: arrayable(NumberLike).optional(),
116
- sticky: BooleanLike.optional()
66
+ page: NumberLike.pipe(z.number().int().min(1)).catch(1).optional(),
67
+ perPage: lenient(NumberLike.pipe(z.number().int().min(1).max(100))),
68
+ search: lenient(z.string()),
69
+ after: lenient(z.string()),
70
+ before: lenient(z.string()),
71
+ modifiedAfter: lenient(z.string()),
72
+ modifiedBefore: lenient(z.string()),
73
+ author: lenient(arrayable(NumberLike)),
74
+ authorExclude: lenient(arrayable(NumberLike)),
75
+ exclude: lenient(arrayable(NumberLike)),
76
+ include: lenient(arrayable(NumberLike)),
77
+ offset: lenient(NumberLike.pipe(z.number().int().min(0))),
78
+ order: lenient(ListOrder),
79
+ orderby: lenient(PostOrderBy),
80
+ searchColumns: lenient(z.array(PostSearchColumn)),
81
+ slug: lenient(arrayable(z.string())),
82
+ taxRelation: lenient(z.enum(WP_POST_TAX_RELATIONS)),
83
+ categories: lenient(arrayable(NumberLike)),
84
+ categoriesExclude: lenient(arrayable(NumberLike)),
85
+ tags: lenient(arrayable(NumberLike)),
86
+ tagsExclude: lenient(arrayable(NumberLike)),
87
+ sticky: lenient(BooleanLike)
117
88
  });
118
89
 
119
90
  //#endregion
@@ -1,39 +1,42 @@
1
1
  import { deserializeSeo } from "../seo/utils.js";
2
- import { stringifiedMetaRecord } from "@kizlo/shared";
2
+ import { resolveWpTimestamp, stringifiedMetaRecord } from "@kizlo/shared";
3
3
 
4
4
  //#region src/post/utils.ts
5
- function deserializePost(data) {
5
+ function deserializePost(data, options) {
6
+ const locked = data.password.length > 0;
7
+ const kizlo = data.kizlo;
8
+ const title = data.title.rendered;
6
9
  return {
7
10
  id: data.id,
8
- title: data.title.rendered,
9
- content: !data.password.length ? data.content?.rendered ?? null : null,
10
- excerpt: !data.password.length ? data.excerpt.rendered : null,
11
- protected: !!data.password.length,
12
- featuredMedia: data.kizlo?.featured_media ? {
13
- id: data.kizlo.featured_media.id,
14
- alt: data.kizlo.featured_media.alt,
15
- name: data.title.rendered,
16
- src: data.kizlo.featured_media.url
17
- } : null,
11
+ url: kizlo.url ?? null,
12
+ parent: data.parent ?? null,
13
+ title: title.length > 0 ? title : null,
14
+ content: locked ? null : data.content?.rendered ?? null,
15
+ excerpt: locked ? null : data.excerpt?.rendered ?? null,
16
+ protected: locked,
17
+ preview: options?.preview ?? false,
18
+ status: data.status === "trash" ? "draft" : data.status,
19
+ featuredMedia: kizlo.featured_media ?? null,
18
20
  commentsEnabled: data.comment_status === "open",
19
21
  slug: data.slug,
20
22
  sticky: data.sticky ?? false,
21
- tags: data.kizlo.tags ?? [],
22
- categories: data.kizlo.categories ?? [],
23
- author: data.kizlo.author ? {
24
- id: data.kizlo.author.id,
25
- name: data.kizlo.author.name,
26
- avatar: data.kizlo.author.avatar_url ? {
23
+ tags: kizlo.tags ?? [],
24
+ categories: kizlo.categories ?? [],
25
+ author: kizlo.author ? {
26
+ id: kizlo.author.id,
27
+ name: kizlo.author.name,
28
+ slug: kizlo.author.slug,
29
+ avatar: kizlo.author.avatar_url ? {
27
30
  id: 0,
28
- alt: data.kizlo.author.name,
29
- name: data.kizlo.author.name,
30
- src: data.kizlo.author.avatar_url
31
+ alt: kizlo.author.name,
32
+ name: kizlo.author.name,
33
+ src: kizlo.author.avatar_url
31
34
  } : null
32
35
  } : null,
33
36
  format: data.format ?? "standard",
34
- seo: data.kizlo.seo ? deserializeSeo(data.kizlo.seo) : null,
35
- createdAt: new Date(data.date ?? "").getTime(),
36
- updatedAt: new Date(data.modified ?? "").getTime(),
37
+ seo: kizlo.seo ? deserializeSeo(kizlo.seo) : null,
38
+ createdAt: resolveWpTimestamp(data.date_gmt) ?? resolveWpTimestamp(data.modified_gmt) ?? 0,
39
+ updatedAt: resolveWpTimestamp(data.modified_gmt) ?? 0,
37
40
  meta: stringifiedMetaRecord(data.meta ?? {})
38
41
  };
39
42
  }