nextpress-core 1.0.3 → 2.0.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.
Files changed (211) hide show
  1. package/cli/install.js +27 -0
  2. package/{dist/acf-functions/core/acf-builder.js → lib/acf-functions/core/acf-builder.ts} +45 -17
  3. package/{dist/acf-functions/core/acf-component-autoloader.js → lib/acf-functions/core/acf-component-autoloader.ts} +13 -7
  4. package/{dist/acf-functions/core/acf-field-group-autoloader.js → lib/acf-functions/core/acf-field-group-autoloader.ts} +11 -5
  5. package/{dist/acf-functions/services/define-field-group.d.ts → lib/acf-functions/services/define-field-group.ts} +4 -1
  6. package/{dist/acf-functions/services/define-layout.d.ts → lib/acf-functions/services/define-layout.ts} +4 -1
  7. package/lib/acf-functions/services/map-fields/helpers/map-choice-object.ts +20 -0
  8. package/{dist/acf-functions/services/map-fields/map-fields.js → lib/acf-functions/services/map-fields/map-fields.ts} +128 -89
  9. package/{dist/acf-functions/types/acf-field-group.d.ts → lib/acf-functions/types/acf-field-group.ts} +49 -28
  10. package/lib/acf-functions/types/acf-field.ts +2853 -0
  11. package/lib/acf-functions/types/acf-layout.ts +22 -0
  12. package/lib/acf-functions/types/components/field-props.ts +189 -0
  13. package/{dist/acf-functions/types/components/nextpress-component.d.ts → lib/acf-functions/types/components/nextpress-component.ts} +4 -3
  14. package/lib/ambient.d.ts +16 -0
  15. package/{dist/entities/common.d.ts → lib/entities/common.ts} +6 -4
  16. package/{dist/entities/option/option.interface.d.ts → lib/entities/option/option.interface.ts} +3 -3
  17. package/{dist/entities/option/option.js → lib/entities/option/option.ts} +21 -14
  18. package/{dist/entities/post/post.interface.d.ts → lib/entities/post/post.interface.ts} +26 -21
  19. package/lib/entities/post/post.ts +209 -0
  20. package/{dist/entities/term/term.interface.d.ts → lib/entities/term/term.interface.ts} +3 -3
  21. package/lib/entities/term/term.ts +82 -0
  22. package/{dist/entities/user/user.interface.d.ts → lib/entities/user/user.interface.ts} +2 -1
  23. package/lib/entities/user/user.ts +86 -0
  24. package/{dist/globals/entity-loader/entity-loader-base.js → lib/globals/entity-loader/entity-loader-base.ts} +64 -10
  25. package/{dist/globals/entity-loader/entity-loader.interface.d.ts → lib/globals/entity-loader/entity-loader.ts} +2 -4
  26. package/lib/globals/entity-loader/option-loader.ts +56 -0
  27. package/lib/globals/entity-loader/post-loader.ts +60 -0
  28. package/lib/globals/entity-loader/term-loader.ts +60 -0
  29. package/lib/globals/entity-loader/user-loader.ts +61 -0
  30. package/lib/globals/get-field/get-field.ts +76 -0
  31. package/{dist/globals/globals.js → lib/globals/globals.ts} +8 -3
  32. package/{dist/globals/nextpress-config/nextpress-config.interface.d.ts → lib/globals/nextpress-config/nextpress-config.interface.ts} +10 -6
  33. package/lib/globals/nextpress-config/nextpress-config.ts +8 -0
  34. package/lib/globals/queried-object/queried-object.ts +124 -0
  35. package/{dist/repository/optionquery/option-query-args.d.ts → lib/repository/optionquery/option-query-args.ts} +5 -2
  36. package/lib/repository/optionquery/option-query.ts +29 -0
  37. package/{dist/repository/postquery/post-query-args.d.ts → lib/repository/postquery/post-query-args.ts} +10 -6
  38. package/lib/repository/postquery/post-query.ts +282 -0
  39. package/{dist/repository/termquery/term-query-args.d.ts → lib/repository/termquery/term-query-args.ts} +16 -6
  40. package/lib/repository/termquery/term-query.ts +244 -0
  41. package/{dist/repository/userquery/user-query-args.d.ts → lib/repository/userquery/user-query-args.ts} +19 -7
  42. package/{dist/repository/userquery/user-query.js → lib/repository/userquery/user-query.ts} +93 -76
  43. package/{dist/router/helpers.js → lib/router/helpers.ts} +4 -4
  44. package/{dist/router/nextpress-layout.js → lib/router/nextpress-layout.tsx} +28 -9
  45. package/{dist/router/routes/not-found-page.js → lib/router/nextpress-not-found-route.tsx} +7 -5
  46. package/{dist/router/nextpress-proxy.js → lib/router/nextpress-proxy.ts} +15 -3
  47. package/{dist/router/nextpress-static-params.js → lib/router/nextpress-static-params.ts} +17 -5
  48. package/{dist/router/router.js → lib/router/router.tsx} +29 -22
  49. package/{dist/router/routes/api/api-get-admin-bar.js → lib/router/routes/api/api-get-admin-bar.ts} +8 -6
  50. package/{dist/router/routes/api/api-get-draft-mode.js → lib/router/routes/api/api-get-draft-mode.ts} +15 -6
  51. package/{dist/router/routes/api/api-get-field-groups.js → lib/router/routes/api/api-get-field-groups.ts} +13 -8
  52. package/{dist/router/routes/api/api-post-revalidate.js → lib/router/routes/api/api-post-revalidate.ts} +6 -4
  53. package/{dist/router/routes/api/helpers.js → lib/router/routes/api/helpers.ts} +4 -3
  54. package/lib/router/routes/author-archive.tsx +75 -0
  55. package/lib/router/routes/post-index-page.tsx +58 -0
  56. package/lib/router/routes/singular-page.tsx +78 -0
  57. package/lib/router/routes/site-front-page.tsx +51 -0
  58. package/lib/router/routes/term-archive.tsx +93 -0
  59. package/{dist/router/types.d.ts → lib/router/types.ts} +4 -2
  60. package/{dist/services/get-menu.js → lib/services/get-menu.ts} +56 -32
  61. package/{dist/services/get-theme-mods.js → lib/services/get-theme-mods.ts} +6 -4
  62. package/{dist/services/metadata/get-blogname.js → lib/services/metadata/get-blogname.ts} +2 -2
  63. package/{dist/services/metadata/get-favicon-url.js → lib/services/metadata/get-favicon-url.ts} +5 -4
  64. package/{dist/services/metadata/get-language-attribute.js → lib/services/metadata/get-language-attribute.ts} +1 -1
  65. package/{dist/services/utilities/capitalise-first-letter.js → lib/services/utilities/capitalise-first-letter.ts} +2 -3
  66. package/{dist/services/utilities/esc-html.js → lib/services/utilities/esc-html.ts} +3 -1
  67. package/{dist/services/utilities/get-date-time-formatter.js → lib/services/utilities/get-date-time-formatter.ts} +16 -6
  68. package/{dist/services/utilities/kses-post.js → lib/services/utilities/kses-post.ts} +2 -1
  69. package/{dist/services/utilities/process-url.js → lib/services/utilities/process-url.ts} +4 -3
  70. package/{dist/template-heirarchy/_autoloader/template-autoloader.js → lib/template-heirarchy/_autoloader/template-autoloader.ts} +18 -9
  71. package/{dist/template-heirarchy/archive/archive.js → lib/template-heirarchy/archive/archive.tsx} +10 -7
  72. package/{dist/template-heirarchy/archive/author.js → lib/template-heirarchy/archive/author.tsx} +10 -7
  73. package/{dist/template-heirarchy/archive/category.js → lib/template-heirarchy/archive/category.tsx} +11 -7
  74. package/{dist/template-heirarchy/archive/posttypearchive.js → lib/template-heirarchy/archive/posttypearchive.tsx} +11 -8
  75. package/{dist/template-heirarchy/archive/tag.js → lib/template-heirarchy/archive/tag.tsx} +12 -7
  76. package/{dist/template-heirarchy/archive/taxonomy.js → lib/template-heirarchy/archive/taxonomy.tsx} +10 -7
  77. package/{dist/template-heirarchy/home/home.js → lib/template-heirarchy/home/home.tsx} +10 -7
  78. package/{dist/template-heirarchy/index.js → lib/template-heirarchy/index.tsx} +9 -5
  79. package/{dist/template-heirarchy/not-found.tsx/not-found.js → lib/template-heirarchy/not-found.tsx/not-found.tsx} +10 -7
  80. package/{dist/template-heirarchy/page/page.js → lib/template-heirarchy/page/page.tsx} +10 -7
  81. package/{dist/template-heirarchy/page/posttype.js → lib/template-heirarchy/page/posttype.tsx} +12 -8
  82. package/{dist/template-heirarchy/page/single.js → lib/template-heirarchy/page/single.tsx} +10 -7
  83. package/{dist/template-heirarchy/page/singular.js → lib/template-heirarchy/page/singular.tsx} +10 -7
  84. package/lib/ui/render-attachment-image.tsx +28 -0
  85. package/lib/ui/render-components.tsx +12 -0
  86. package/lib/ui/render-the-admin-bar.tsx +79 -0
  87. package/lib/ui/render-the-logo.tsx +24 -0
  88. package/{dist/wpdb/wpdb.interface.d.ts → lib/wpdb/wpdb.interface.ts} +20 -1
  89. package/{dist/wpdb/wpdb.js → lib/wpdb/wpdb.ts} +9 -5
  90. package/package.json +8 -15
  91. package/dist/acf-functions/core/acf-builder.d.ts +0 -51
  92. package/dist/acf-functions/core/acf-component-autoloader.d.ts +0 -11
  93. package/dist/acf-functions/core/acf-field-group-autoloader.d.ts +0 -10
  94. package/dist/acf-functions/field-props.d.ts +0 -196
  95. package/dist/acf-functions/field-props.js +0 -1
  96. package/dist/acf-functions/services/define-field-group.js +0 -10
  97. package/dist/acf-functions/services/define-layout.js +0 -10
  98. package/dist/acf-functions/services/map-fields/helpers/map-choice-object.d.ts +0 -2
  99. package/dist/acf-functions/services/map-fields/helpers/map-choice-object.js +0 -18
  100. package/dist/acf-functions/services/map-fields/map-fields.d.ts +0 -21
  101. package/dist/acf-functions/types/acf-field-group.js +0 -1
  102. package/dist/acf-functions/types/acf-field.d.ts +0 -2813
  103. package/dist/acf-functions/types/acf-field.js +0 -1
  104. package/dist/acf-functions/types/acf-layout.d.ts +0 -19
  105. package/dist/acf-functions/types/acf-layout.js +0 -1
  106. package/dist/acf-functions/types/acf-values.js +0 -1
  107. package/dist/acf-functions/types/components/field-props.d.ts +0 -196
  108. package/dist/acf-functions/types/components/field-props.js +0 -1
  109. package/dist/acf-functions/types/components/nextpress-component.js +0 -1
  110. package/dist/entities/common.js +0 -1
  111. package/dist/entities/option/option.d.ts +0 -19
  112. package/dist/entities/option/option.interface.js +0 -2
  113. package/dist/entities/post/post.d.ts +0 -50
  114. package/dist/entities/post/post.interface.js +0 -2
  115. package/dist/entities/post/post.js +0 -184
  116. package/dist/entities/term/term.d.ts +0 -28
  117. package/dist/entities/term/term.interface.js +0 -1
  118. package/dist/entities/term/term.js +0 -67
  119. package/dist/entities/user/user.d.ts +0 -27
  120. package/dist/entities/user/user.interface.js +0 -1
  121. package/dist/entities/user/user.js +0 -74
  122. package/dist/globals/entity-loader/entity-loader-base.d.ts +0 -65
  123. package/dist/globals/entity-loader/entity-loader.interface.js +0 -1
  124. package/dist/globals/entity-loader/option-loader.d.ts +0 -15
  125. package/dist/globals/entity-loader/option-loader.js +0 -31
  126. package/dist/globals/entity-loader/post-loader.d.ts +0 -21
  127. package/dist/globals/entity-loader/post-loader.js +0 -28
  128. package/dist/globals/entity-loader/term-loader.d.ts +0 -21
  129. package/dist/globals/entity-loader/term-loader.js +0 -28
  130. package/dist/globals/entity-loader/user-loader.d.ts +0 -21
  131. package/dist/globals/entity-loader/user-loader.js +0 -28
  132. package/dist/globals/get-field/get-field.d.ts +0 -18
  133. package/dist/globals/get-field/get-field.js +0 -44
  134. package/dist/globals/globals.d.ts +0 -18
  135. package/dist/globals/nextpress-config/nextpress-config.d.ts +0 -4
  136. package/dist/globals/nextpress-config/nextpress-config.interface.js +0 -1
  137. package/dist/globals/nextpress-config/nextpress-config.js +0 -2
  138. package/dist/globals/queried-object/queried-object.d.ts +0 -62
  139. package/dist/globals/queried-object/queried-object.js +0 -56
  140. package/dist/repository/optionquery/option-query-args.js +0 -1
  141. package/dist/repository/optionquery/option-query.d.ts +0 -12
  142. package/dist/repository/optionquery/option-query.js +0 -20
  143. package/dist/repository/postquery/post-query-args.js +0 -1
  144. package/dist/repository/postquery/post-query.d.ts +0 -12
  145. package/dist/repository/postquery/post-query.js +0 -272
  146. package/dist/repository/termquery/term-query-args.js +0 -1
  147. package/dist/repository/termquery/term-query.d.ts +0 -11
  148. package/dist/repository/termquery/term-query.js +0 -213
  149. package/dist/repository/userquery/user-query-args.js +0 -1
  150. package/dist/repository/userquery/user-query.d.ts +0 -12
  151. package/dist/router/helpers.d.ts +0 -14
  152. package/dist/router/nextpress-layout.d.ts +0 -11
  153. package/dist/router/nextpress-proxy.d.ts +0 -8
  154. package/dist/router/nextpress-static-params.d.ts +0 -9
  155. package/dist/router/router.d.ts +0 -23
  156. package/dist/router/routes/api/api-get-admin-bar.d.ts +0 -8
  157. package/dist/router/routes/api/api-get-draft-mode.d.ts +0 -8
  158. package/dist/router/routes/api/api-get-field-groups.d.ts +0 -7
  159. package/dist/router/routes/api/api-post-revalidate.d.ts +0 -7
  160. package/dist/router/routes/api/helpers.d.ts +0 -8
  161. package/dist/router/routes/author-archive.d.ts +0 -25
  162. package/dist/router/routes/author-archive.js +0 -49
  163. package/dist/router/routes/not-found-page.d.ts +0 -15
  164. package/dist/router/routes/post-index-page.d.ts +0 -25
  165. package/dist/router/routes/post-index-page.js +0 -33
  166. package/dist/router/routes/singular-page.d.ts +0 -29
  167. package/dist/router/routes/singular-page.js +0 -51
  168. package/dist/router/routes/site-front-page.d.ts +0 -27
  169. package/dist/router/routes/site-front-page.js +0 -26
  170. package/dist/router/routes/term-archive.d.ts +0 -29
  171. package/dist/router/routes/term-archive.js +0 -65
  172. package/dist/router/types.js +0 -1
  173. package/dist/services/get-menu.d.ts +0 -13
  174. package/dist/services/get-theme-mods.d.ts +0 -7
  175. package/dist/services/metadata/get-blogname.d.ts +0 -6
  176. package/dist/services/metadata/get-favicon-url.d.ts +0 -6
  177. package/dist/services/metadata/get-language-attribute.d.ts +0 -6
  178. package/dist/services/services.d.ts +0 -3
  179. package/dist/services/services.js +0 -3
  180. package/dist/services/utilities/capitalise-first-letter.d.ts +0 -7
  181. package/dist/services/utilities/esc-html.d.ts +0 -7
  182. package/dist/services/utilities/get-date-time-formatter.d.ts +0 -6
  183. package/dist/services/utilities/index.d.ts +0 -0
  184. package/dist/services/utilities/index.js +0 -1
  185. package/dist/services/utilities/kses-post.d.ts +0 -7
  186. package/dist/services/utilities/process-url.d.ts +0 -7
  187. package/dist/template-heirarchy/_autoloader/template-autoloader.d.ts +0 -9
  188. package/dist/template-heirarchy/archive/archive.d.ts +0 -16
  189. package/dist/template-heirarchy/archive/author.d.ts +0 -16
  190. package/dist/template-heirarchy/archive/category.d.ts +0 -16
  191. package/dist/template-heirarchy/archive/posttypearchive.d.ts +0 -24
  192. package/dist/template-heirarchy/archive/tag.d.ts +0 -16
  193. package/dist/template-heirarchy/archive/taxonomy.d.ts +0 -16
  194. package/dist/template-heirarchy/home/home.d.ts +0 -16
  195. package/dist/template-heirarchy/index.d.ts +0 -17
  196. package/dist/template-heirarchy/not-found.tsx/not-found.d.ts +0 -16
  197. package/dist/template-heirarchy/page/page.d.ts +0 -16
  198. package/dist/template-heirarchy/page/posttype.d.ts +0 -24
  199. package/dist/template-heirarchy/page/single.d.ts +0 -16
  200. package/dist/template-heirarchy/page/singular.d.ts +0 -16
  201. package/dist/ui/render-attachment-image.d.ts +0 -12
  202. package/dist/ui/render-attachment-image.js +0 -24
  203. package/dist/ui/render-components.d.ts +0 -9
  204. package/dist/ui/render-components.js +0 -7
  205. package/dist/ui/render-the-admin-bar.d.ts +0 -8
  206. package/dist/ui/render-the-admin-bar.js +0 -36
  207. package/dist/ui/render-the-logo.d.ts +0 -10
  208. package/dist/ui/render-the-logo.js +0 -16
  209. package/dist/wpdb/wpdb.d.ts +0 -3
  210. package/dist/wpdb/wpdb.interface.js +0 -5
  211. /package/{dist/acf-functions/types/acf-values.d.ts → lib/acf-functions/types/acf-values.ts} +0 -0
@@ -0,0 +1,22 @@
1
+ import { NextpressField, ACFField } from "./acf-field";
2
+
3
+ type TransformACFLayout<T> = T extends any
4
+ ? Omit<T, 'key' | 'sub_fields'> &
5
+ ('sub_fields' extends keyof T ? { sub_fields: NextpressField[] } : [])
6
+ : never;
7
+
8
+ /** ACF Layout without key constraints to allow key generation */
9
+ export type NextpressLayout = TransformACFLayout<ACFLayout>
10
+
11
+ /**
12
+ * Represents a layout within an ACF Flexible Content field.
13
+ */
14
+ export type ACFLayout = {
15
+ key: string,
16
+ name: string,
17
+ label: string,
18
+ display: 'table' | 'block' | 'row',
19
+ sub_fields: ACFField[],
20
+ min?: string,
21
+ max?: string
22
+ }
@@ -0,0 +1,189 @@
1
+ import { IPost } from "nextpress/entities/post/post.interface";
2
+ import { ITerm } from "nextpress/entities/term/term.interface";
3
+ import { IUser } from "nextpress/entities/user/user.interface";
4
+ import { JSX } from "react";
5
+
6
+ type GetFields<T> =
7
+ T extends { fields: readonly any[] } ? T['fields']
8
+ : T extends { sub_fields: readonly any[] } ? T['sub_fields']
9
+ : never;
10
+
11
+ /**
12
+ * Represents the properties passed to a Nextpress ACF component.
13
+ *
14
+ * @template T - The expected type of the mapped ACF fields.
15
+ */
16
+ export type FieldProps<LayoutT> =
17
+ LayoutT extends { fields: readonly any[] } | { sub_fields: readonly any[] }
18
+ ? ResolvedFields<GetFields<LayoutT>>
19
+ : never;
20
+
21
+ /**
22
+ * An array of ACF field configurations to a strongly-typed object representing the resolved data structure.
23
+ * It iterates over the array, using the `name` property of each field as the object key, and determines the expected value type using the `MapFieldType` utility.
24
+ *
25
+ * @template Fields - A readonly array of ACF field configuration objects.
26
+ */
27
+ type ResolvedFields<Fields extends readonly any[]> = {
28
+ [F in Fields[number] as F['name']]: MapFieldType<F>
29
+ };
30
+
31
+ /**
32
+ * Maps an array of ACF Flexible Content layouts to a union type representing the resolved layout blocks.
33
+ * For each layout, it checks for the presence of `fields` or `sub_fields`, and resolves to a specific object
34
+ * structure containing the layout's React component and its deeply resolved field content.
35
+ *
36
+ * @template Layouts - A readonly array of ACF Flexible Content layout configuration objects.
37
+ */
38
+ export type ResolvedFlexibleContent<Layouts extends readonly any[]> = {
39
+ [L in Layouts[number] as L['name']]: L extends { name: infer Name } & ({ fields: readonly any[] } | { sub_fields: readonly any[] })
40
+ ? {
41
+ Component: () => Promise<JSX.Element>,
42
+ content: ResolvedFields<GetFields<L>>
43
+ }[]
44
+ : never
45
+ }[Layouts[number]['name']];
46
+
47
+
48
+ type MapFieldType<Field> =
49
+ Field extends { type: 'color_picker' }
50
+ ? string | null
51
+ : Field extends { type: 'date_picker' }
52
+ ? string | null
53
+ : Field extends { type: 'date_time_picker' }
54
+ ? string | null
55
+ : Field extends { type: 'google_map' }
56
+ ? ACFGoogleMapsObject | null
57
+ : Field extends { type: 'icon_picker' }
58
+ ? Field extends { return_format: 'string' }
59
+ ? string | null
60
+ : Field extends { return_format: 'array' }
61
+ ? ACFIconObject | null
62
+ : ACFIconObject | null
63
+ : Field extends { type: 'time_picker' }
64
+ ? string | null
65
+ : Field extends { type: 'email' }
66
+ ? string | null
67
+ : Field extends { type: 'number' }
68
+ ? number | null
69
+ : Field extends { type: 'password' }
70
+ ? string | null
71
+ : Field extends { type: 'range' }
72
+ ? number | null
73
+ : Field extends { type: 'text' }
74
+ ? string | null
75
+ : Field extends { type: 'textarea' }
76
+ ? string | null
77
+ : Field extends { type: 'button_group' }
78
+ ? Field extends { return_format: 'array' }
79
+ ? ACFChoiceObject | null
80
+ : string | null
81
+ : Field extends { type: 'checkbox' }
82
+ ? Field extends { return_format: 'array' }
83
+ ? ACFChoiceObject[]
84
+ : string[]
85
+ : Field extends { type: 'radio' }
86
+ ? Field extends { return_format: 'array' }
87
+ ? ACFChoiceObject | null
88
+ : string | null
89
+ : Field extends { type: 'select' }
90
+ ? Field extends { multiple: 1 }
91
+ ? Field extends { return_format: 'array' }
92
+ ? ACFChoiceObject[]
93
+ : string[]
94
+ : Field extends { return_format: 'array' }
95
+ ? ACFChoiceObject | null
96
+ : string | null
97
+ : Field extends { type: 'true_false' }
98
+ ? boolean
99
+ : Field extends { type: 'file' }
100
+ ? number | null
101
+ : Field extends { type: 'gallery' }
102
+ ? number[]
103
+ : Field extends { type: 'image' }
104
+ ? number | null
105
+ : Field extends { type: 'oembed' }
106
+ ? string | null
107
+ : Field extends { type: 'wysiwyg' }
108
+ ? string | null
109
+ : Field extends { type: 'link' }
110
+ ? Field extends { return_format: 'url' }
111
+ ? string | null
112
+ : Field extends { return_format: 'array' }
113
+ ? ACFLinkObject | null
114
+ : ACFLinkObject
115
+ : Field extends { type: 'page_link' }
116
+ ? Field extends { multiple: 1 }
117
+ ? string[]
118
+ : string | null
119
+ : Field extends { type: 'post_object' }
120
+ ? Field extends { multiple: 1 }
121
+ ? Field extends { return_format: 'object' }
122
+ ? IPost[]
123
+ : number[]
124
+ : Field extends { return_format: 'object' }
125
+ ? IPost | null
126
+ : number | null
127
+ : Field extends { type: 'relationship' }
128
+ ? Field extends { return_format: 'object' }
129
+ ? IPost[] | null
130
+ : number[] | null
131
+ : Field extends { type: 'taxonomy' }
132
+ ? Field extends { multiple: 1 }
133
+ ? Field extends { return_format: 'object' }
134
+ ? ITerm[]
135
+ : number[]
136
+ : Field extends { return_format: 'object' }
137
+ ? ITerm | null
138
+ : number | null
139
+ : Field extends { type: 'user' }
140
+ ? Field extends { multiple: 1 }
141
+ ? Field extends { return_format: 'object' }
142
+ ? IUser[]
143
+ : number[]
144
+ : Field extends { return_format: 'object' }
145
+ ? IUser | null
146
+ : number | null
147
+ : Field extends { type: 'group' } & ({ fields: readonly any[] } | { sub_fields: readonly any[] })
148
+ ? ResolvedFields<GetFields<Field>> | null
149
+ : Field extends { type: 'repeater' } & ({ fields: readonly any[] } | { sub_fields: readonly any[] })
150
+ ? ResolvedFields<GetFields<Field>>[] | null
151
+ : Field extends { type: 'flexible_content'; layouts: readonly any[] }
152
+ ? ResolvedFlexibleContent<Field['layouts']> | null
153
+ : Field extends { fields: readonly any[] } | { sub_fields: readonly any[] }
154
+ ? ResolvedFields<GetFields<Field>>
155
+ : never;
156
+
157
+ export type ACFIconObject = {
158
+ type: string,
159
+ value: string
160
+ }
161
+
162
+ export type ACFLinkObject = {
163
+ title: string,
164
+ url: string,
165
+ target: string
166
+ }
167
+
168
+ export type ACFChoiceObject = {
169
+ label?: string
170
+ value?: string,
171
+ }
172
+
173
+ export type ACFGoogleMapsObject = {
174
+ address: string;
175
+ lat: string | number;
176
+ lng: string | number;
177
+ zoom: string | number;
178
+ place_id: string;
179
+ name: string;
180
+ street_number: string | number;
181
+ street_name: string;
182
+ street_name_short: string;
183
+ city: string;
184
+ state: string;
185
+ state_short: string;
186
+ post_code: string | number;
187
+ country: string;
188
+ country_short: string;
189
+ }
@@ -1,11 +1,12 @@
1
1
  import { JSX } from 'react';
2
2
  import { NextpressLayout } from '../acf-layout';
3
+
3
4
  /**
4
5
  * Represents a Next.js React component that consumes Nextpress ACF fields.
5
6
  *
6
7
  * @template T - The expected type of the mapped ACF fields.
7
8
  */
8
9
  export type NextpressComponent = {
9
- layout: NextpressLayout;
10
- Component: () => Promise<JSX.Element>;
11
- };
10
+ layout: NextpressLayout
11
+ Component: () => Promise<JSX.Element>
12
+ }
@@ -0,0 +1,16 @@
1
+ declare module '@/nextpress.config' {
2
+ type NextpressConfig = import('nextpress/globals/nextpress-config/nextpress-config.interface').NextpressConfig;
3
+
4
+ export const nextpressConfig: NextpressConfig
5
+ }
6
+
7
+ declare module '@/fonts' {
8
+ type NextFont = import('next/dist/compiled/@next/font').NextFont;
9
+
10
+ const fonts: NextFont[];
11
+ export default fonts;
12
+ }
13
+
14
+ declare module '@/app/_templates/layout' {
15
+ export const LayoutTemplate: ({ children }: Readonly<{children: import('react').React.ReactNode}>) => Promise<import('react').JSX.Element>;
16
+ }
@@ -3,17 +3,19 @@
3
3
  */
4
4
  export interface IPath {
5
5
  /** Nextpress path to entity. */
6
- path: string;
6
+ path: string
7
7
  }
8
+
8
9
  /**
9
10
  * Array of field key-value pairs.
10
11
  */
11
12
  export type Fields = {
12
13
  /** Field key. */
13
- key: string;
14
+ key: string,
14
15
  /** Field value. */
15
- value: string;
16
+ value: string
16
17
  }[];
18
+
17
19
  /**
18
20
  * Represents entity that can provide ACF fields.
19
21
  */
@@ -24,5 +26,5 @@ export interface IFieldLocation {
24
26
  * @param {string} name - Field name prefix to search for.
25
27
  * @returns {Promise<Fields>} Promise resolving to array of fields.
26
28
  */
27
- getFields: (name: string) => Promise<Fields>;
29
+ getFields: (name: string) => Promise<Fields>
28
30
  }
@@ -1,7 +1,7 @@
1
1
  import { Selectable } from "kysely";
2
- import { WpOption } from "../../wpdb/wpdb.interface";
2
+ import { WpOption } from "nextpress/wpdb/wpdb.interface";
3
+
3
4
  /**
4
5
  * Represents option entity.
5
6
  */
6
- export interface IOption extends Omit<Selectable<WpOption>, 'autoload'> {
7
- }
7
+ export interface IOption extends Omit<Selectable<WpOption>, 'autoload'> {};
@@ -1,36 +1,43 @@
1
- import { wpdb } from "@/wpdb/wpdb";
1
+ import { wpdb } from "nextpress/wpdb/wpdb";
2
+ import { IOption } from "./option.interface";
3
+
2
4
  /**
3
5
  * Implementation of IOption entity.
4
6
  */
5
- export class Option {
6
- constructor(optionId) {
7
- this.optionId = optionId;
8
- }
9
- ;
7
+ export class Option implements IOption
8
+ {
9
+ constructor(public optionId: number) {};
10
+
11
+ /** Raw option data from database. */
12
+ private optionData?: Record<string, any>;
13
+
10
14
  /**
11
15
  * Retrieves array of Option instances by IDs.
12
16
  *
13
17
  * @param {number[]} ids - Array of option IDs to retrieve.
14
18
  * @returns {Promise<Option[]>} Promise resolving to array of Option instances.
15
19
  */
16
- static async get(ids) {
20
+ static async get(ids: number[]): Promise<Option[]> {
17
21
  ids = ids.filter(Boolean);
18
- if (!ids || !ids.length)
19
- return [];
22
+ if (!ids || !ids.length) return [];
23
+
20
24
  const optionData = await wpdb
21
25
  .selectFrom('wpOptions')
22
26
  .where('optionId', 'in', ids)
23
27
  .select(['optionId', 'optionName', 'optionValue'])
24
28
  .execute();
29
+
25
30
  const optionDataMap = new Map(optionData.map(option => [Number(option.optionId), option]));
31
+
26
32
  return ids.map(id => {
27
33
  const instance = new Option(id);
34
+
28
35
  instance.optionData = optionDataMap.get(id);
36
+
29
37
  return instance;
30
- });
38
+ })
31
39
  }
32
- get optionName() { var _a, _b; return (_b = (_a = this.optionData) === null || _a === void 0 ? void 0 : _a['optionName']) !== null && _b !== void 0 ? _b : ''; }
33
- ;
34
- get optionValue() { var _a, _b; return (_b = (_a = this.optionData) === null || _a === void 0 ? void 0 : _a['optionValue']) !== null && _b !== void 0 ? _b : ''; }
35
- ;
40
+
41
+ get optionName(): string { return this.optionData?.['optionName'] ?? ''};
42
+ get optionValue(): string { return this.optionData?.['optionValue'] ?? ''};
36
43
  }
@@ -1,67 +1,72 @@
1
1
  import { Selectable } from "kysely";
2
- import { WpPost } from "../../wpdb/wpdb.interface";
3
2
  import { IFieldLocation, IPath } from "../common";
3
+ import { WpPost } from "nextpress/wpdb/wpdb.interface";
4
+
4
5
  /**
5
6
  * Attributes for post attachment images.
6
7
  */
7
8
  export type PostImageAttributes = {
8
9
  /** Image source URL. */
9
- src?: string;
10
+ src?: string,
10
11
  /** Image alternative text. */
11
- alt?: string;
12
+ alt?: string,
12
13
  /** Image height. */
13
- height?: number;
14
+ height?: number,
14
15
  /** Image width. */
15
- width?: number;
16
- };
16
+ width?: number,
17
+ }
18
+
17
19
  /**
18
20
  * Attributes for nav menu items.
19
21
  */
20
22
  export type MenuItemAttributes = {
21
23
  /** Menu item label. */
22
- label: string;
24
+ label: string,
23
25
  /** Menu item type. */
24
- type: 'custom' | 'post_type' | 'taxonomy';
26
+ type: 'custom' | 'post_type' | 'taxonomy',
25
27
  /** Parent menu item ID. */
26
- parentId: number;
28
+ parentId: number,
27
29
  /** Target object ID. */
28
- objectId: number;
30
+ objectId: number,
29
31
  /** Menu item URL. */
30
- url: string;
31
- };
32
+ url: string,
33
+ }
34
+
32
35
  /**
33
36
  * Base post properties.
34
37
  */
35
- export interface IBasePost extends Selectable<WpPost> {
36
- }
38
+ export interface IBasePost extends Selectable<WpPost> {}
39
+
37
40
  /**
38
41
  * Page post properties.
39
42
  */
40
- export interface IPagePost extends IBasePost, IPath {
41
- }
43
+ export interface IPagePost extends IBasePost, IPath {}
44
+
42
45
  /**
43
46
  * Standard post properties.
44
47
  */
45
48
  export interface IPostPost extends IBasePost, IPath {
46
49
  /** Featured image attachment ID. */
47
- thumbnailId: number;
50
+ thumbnailId: number,
48
51
  }
52
+
49
53
  /**
50
54
  * Attachment post properties.
51
55
  */
52
56
  export interface IAttachmentPost extends IBasePost {
53
57
  /** Image attributes. */
54
- imageAttributes: PostImageAttributes;
58
+ imageAttributes: PostImageAttributes,
55
59
  }
60
+
56
61
  /**
57
62
  * Menu item properties.
58
63
  */
59
64
  export interface IMenuItem extends IBasePost {
60
65
  /** Menu item attributes. */
61
- menuItemAttributes: MenuItemAttributes | null;
66
+ menuItemAttributes: MenuItemAttributes | null
62
67
  }
68
+
63
69
  /**
64
70
  * Comprehensive post entity encompassing all post types.
65
71
  */
66
- export interface IPost extends IBasePost, IPagePost, IPostPost, IAttachmentPost, IMenuItem, IFieldLocation {
67
- }
72
+ export interface IPost extends IBasePost, IPagePost, IPostPost, IAttachmentPost, IMenuItem, IFieldLocation {};
@@ -0,0 +1,209 @@
1
+ import { unserialize } from "php-serialize";
2
+ import { Fields } from "../common";
3
+ import { IPost, PostImageAttributes, MenuItemAttributes } from "./post.interface";
4
+ import { processURL } from "nextpress/services/utilities/process-url";
5
+ import { wpdb } from "nextpress/wpdb/wpdb";
6
+
7
+ const excerptLength = nextpressConfig.excerptLength ?? 55;
8
+
9
+ /**
10
+ * Implementation of IPost entity.
11
+ */
12
+ export class Post implements IPost {
13
+ constructor(public ID: number) { }
14
+
15
+ /** Raw post data from database. */
16
+ private postData?: Record<string, any>;
17
+ /** Map of post meta key-value pairs. */
18
+ private metaMap?: Map<string, string>;
19
+
20
+ /**
21
+ * Retrieves array of Post instances by IDs.
22
+ *
23
+ * @param {number[]} ids - Array of post IDs to retrieve.
24
+ * @returns {Promise<Post[]>} Promise resolving to array of Post instances.
25
+ */
26
+ static async get(ids: number[]): Promise<Post[]> {
27
+ ids = ids.filter(Boolean);
28
+ if (!ids || !ids.length) return [];
29
+
30
+ const postsData = await wpdb
31
+ .selectFrom('wpPosts')
32
+ .where('ID', 'in', ids)
33
+ .selectAll()
34
+ .execute();
35
+
36
+ const metaData = await wpdb
37
+ .selectFrom('wpPostmeta')
38
+ .where('postId', 'in', ids)
39
+ .where('metaKey', 'in', [
40
+ '_nextpress_path',
41
+ '_thumbnail_id',
42
+ '_wp_attachment_image_alt',
43
+ '_wp_attachment_metadata',
44
+ '_menu_item_type',
45
+ '_menu_item_object_id',
46
+ '_menu_item_url',
47
+ '_menu_item_menu_item_parent'
48
+ ])
49
+ .select(['postId', 'metaKey', 'metaValue'])
50
+ .execute();
51
+
52
+ const metaByPostId = new Map<number, Map<string, string>>();
53
+ for (const row of metaData) {
54
+ const postId = Number(row.postId);
55
+ if (!metaByPostId.has(postId)) {
56
+ metaByPostId.set(postId, new Map());
57
+ }
58
+ metaByPostId.get(postId)?.set(row.metaKey || '', row.metaValue || '');
59
+ }
60
+
61
+ const postDataMap = new Map(postsData.map(post => [Number(post.ID), post]));
62
+
63
+ return ids.map(id => {
64
+ const instance = new Post(id);
65
+
66
+ instance.postData = postDataMap.get(id);
67
+ instance.metaMap = metaByPostId.get(id) || new Map<string, string>();
68
+
69
+ postLoader.prime([instance.thumbnailId]);
70
+
71
+ return instance;
72
+ });
73
+ }
74
+
75
+ get path(): string {
76
+ return this.metaMap?.get('_nextpress_path') ?? '';
77
+ }
78
+
79
+ get thumbnailId(): number {
80
+ const val = this.metaMap?.get('_thumbnail_id');
81
+ return val ? Number(val) : 0;
82
+ }
83
+
84
+ private _imageAttributes?: PostImageAttributes;
85
+ get imageAttributes(): PostImageAttributes {
86
+ if (this._imageAttributes !== undefined) return this._imageAttributes;
87
+ if (!this.metaMap) return {};
88
+
89
+ const alt = this.metaMap.get('_wp_attachment_image_alt') ?? '';
90
+ const rawMetadata = this.metaMap.get('_wp_attachment_metadata');
91
+
92
+ if (!rawMetadata && !alt) {
93
+ this._imageAttributes = {};
94
+ return this._imageAttributes;
95
+ }
96
+
97
+ const guid = this.guid;
98
+ const index = guid.indexOf('/wp-content');
99
+ const path = index !== -1 ? guid.slice(index) : guid;
100
+ const srcPath = `${process.env.WP_SERVICE_URL}${path}`;
101
+
102
+ try {
103
+ const metadata: { height?: string; width?: string } = unserialize(rawMetadata ?? 'a:0:{}');
104
+ this._imageAttributes = {
105
+ src: srcPath,
106
+ alt: alt,
107
+ height: metadata.height ? Number(metadata.height) : undefined,
108
+ width: metadata.width ? Number(metadata.width) : undefined
109
+ };
110
+ } catch (error: any) {
111
+ console.warn('Error while getting post: Could not unserialize php: ', error.message);
112
+ this._imageAttributes = {};
113
+ }
114
+
115
+ return this._imageAttributes;
116
+ }
117
+
118
+ private _menuItemAttributes?: MenuItemAttributes | null
119
+ get menuItemAttributes(): MenuItemAttributes | null {
120
+ if (this._menuItemAttributes !== undefined) return this._menuItemAttributes;
121
+ if (!this.metaMap) return null;
122
+
123
+ const typeMeta = this.metaMap.get('_menu_item_type');
124
+ const type = ['custom', 'post_type', 'taxonomy'].includes(typeMeta ?? '')
125
+ ? typeMeta as 'custom' | 'post_type' | 'taxonomy'
126
+ : undefined;
127
+
128
+ let url;
129
+ let objectId;
130
+ if (type === 'custom') {
131
+ const urlMeta = this.metaMap.get('_menu_item_url');
132
+ url = urlMeta ? processURL(urlMeta) : '';
133
+ } else {
134
+ objectId = Number(this.metaMap.get('_menu_item_object_id'));
135
+ }
136
+
137
+ const parentId = Number(this.metaMap.get('_menu_item_menu_item_parent')) ?? 0;
138
+
139
+ const label = this.postTitle ?? '';
140
+
141
+ return {
142
+ label,
143
+ type: type ?? 'custom',
144
+ parentId,
145
+ objectId: objectId ?? 0,
146
+ url: url ?? ''
147
+ }
148
+ }
149
+
150
+ private _postExcerpt?: string
151
+ get postExcerpt(): string {
152
+ if (this._postExcerpt !== undefined) return this._postExcerpt;
153
+ const excerpt = this.postData?.['postExcerpt'] ?? '';
154
+
155
+ if (excerpt) return excerpt;
156
+
157
+ const postContent = this.postContent;
158
+ if (!postContent) return '';
159
+
160
+ const plainText = postContent
161
+ .replace(/<[^>]+>/g, ' ') // Strip HTML tags
162
+ .replace(/\s+/g, ' ') // Normalize multiple spaces into a single space
163
+ .trim();
164
+
165
+ const words = plainText.split(' ');
166
+ if (words.length > (excerptLength)) {
167
+ return words.slice(0, excerptLength).join(' ') + '...';
168
+ }
169
+
170
+ this._postExcerpt = plainText;
171
+ return this._postExcerpt;
172
+ }
173
+
174
+ get commentCount(): number { return this.postData?.['commentCount'] ?? 0; }
175
+ get commentStatus(): string { return this.postData?.['commentStatus'] ?? 'closed'; }
176
+ get guid(): string { return this.postData?.['guid'] ?? ''; }
177
+ get menuOrder(): number { return this.postData?.['menuOrder'] ?? 0; }
178
+ get pinged(): string { return this.postData?.['pinged'] ?? ''; }
179
+ get pingStatus(): string { return this.postData?.['pingStatus'] ?? 'closed'; }
180
+ get postAuthor(): number { return this.postData?.['postAuthor'] ?? 0; }
181
+ get postContent(): string { return this.postData?.['postContent'] ?? ''; }
182
+ get postContentFiltered(): string { return this.postData?.['postContentFiltered'] ?? ''; }
183
+ get postDate(): Date { return this.postData?.['postDate'] ?? new Date(); }
184
+ get postDateGmt(): Date { return this.postData?.['postDateGmt'] ?? new Date(); }
185
+ get postMimeType(): string { return this.postData?.['postMimeType'] ?? ''; }
186
+ get postModified(): Date { return this.postData?.['postModified'] ?? new Date(); }
187
+ get postModifiedGmt(): Date { return this.postData?.['postModifiedGmt'] ?? new Date(); }
188
+ get postName(): string { return this.postData?.['postName'] ?? ''; }
189
+ get postParent(): number { return this.postData?.['postParent'] ?? 0; }
190
+ get postPassword(): string { return this.postData?.['postPassword'] ?? ''; }
191
+ get postStatus(): string { return this.postData?.['postStatus'] ?? 'draft'; }
192
+ get postTitle(): string { return this.postData?.['postTitle'] ?? ''; }
193
+ get postType(): string { return this.postData?.['postType'] ?? 'post'; }
194
+ get toPing(): string { return this.postData?.['toPing'] ?? ''; }
195
+
196
+ async getFields(name: string): Promise<Fields> {
197
+ const meta = await wpdb
198
+ .selectFrom('wpPostmeta')
199
+ .where('metaKey', 'like', `${name}%`)
200
+ .where('postId', '=', this.ID)
201
+ .select(['metaKey', 'metaValue'])
202
+ .execute();
203
+
204
+ return meta.map(m => ({
205
+ key: m.metaKey || '',
206
+ value: m.metaValue || ''
207
+ }));
208
+ }
209
+ }
@@ -1,8 +1,8 @@
1
1
  import { Selectable } from "kysely";
2
- import { WpTerm, WpTermTaxonomy } from "../../wpdb/wpdb.interface";
3
2
  import { IPath } from "../common";
3
+ import { WpTerm, WpTermTaxonomy } from "nextpress/wpdb/wpdb.interface";
4
+
4
5
  /**
5
6
  * Represents term entity.
6
7
  */
7
- export interface ITerm extends Selectable<WpTerm>, Selectable<WpTermTaxonomy>, IPath {
8
- }
8
+ export interface ITerm extends Selectable<WpTerm>, Selectable<WpTermTaxonomy>, IPath {}