betterstart-cli 0.0.104 → 0.0.105

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 (140) hide show
  1. package/dist/cli.js +6416 -5203
  2. package/dist/cli.js.map +1 -1
  3. package/package.json +1 -1
  4. package/dist/assets/adapters/next/templates/renderers/commands/init/banner-art.ts +0 -7
  5. package/dist/assets/adapters/next/templates/renderers/commands/init/verify-database-reachable.ts +0 -30
  6. package/dist/assets/adapters/next/templates/renderers/commands/seed/build-seed-script.ts +0 -171
  7. package/dist/assets/adapters/next/templates/renderers/generators/actions/action-helpers/build-authorship-alias-block.ts +0 -4
  8. package/dist/assets/adapters/next/templates/renderers/generators/actions/action-helpers/build-authorship-data-fields.ts +0 -4
  9. package/dist/assets/adapters/next/templates/renderers/generators/actions/action-helpers/build-format-action-date-source.ts +0 -18
  10. package/dist/assets/adapters/next/templates/renderers/generators/actions/action-helpers/build-read-select-option-type.ts +0 -6
  11. package/dist/assets/adapters/next/templates/renderers/generators/actions/action-helpers/build-relationship-data-types.ts +0 -25
  12. package/dist/assets/adapters/next/templates/renderers/generators/actions/action-helpers/build-result-mapping.ts +0 -62
  13. package/dist/assets/adapters/next/templates/renderers/generators/actions/action-helpers/generate-populate-list-rels-function.ts +0 -50
  14. package/dist/assets/adapters/next/templates/renderers/generators/actions/entity-file-contents/build-restore-many-to-many-statements.ts +0 -27
  15. package/dist/assets/adapters/next/templates/renderers/generators/actions/entity-file-contents/build-select-option-types.ts +0 -37
  16. package/dist/assets/adapters/next/templates/renderers/generators/actions/entity-file-contents/gen-bulk-sort-order-content.ts +0 -93
  17. package/dist/assets/adapters/next/templates/renderers/generators/actions/entity-file-contents/gen-create-content.ts +0 -157
  18. package/dist/assets/adapters/next/templates/renderers/generators/actions/entity-file-contents/gen-create-select-option-content.ts +0 -134
  19. package/dist/assets/adapters/next/templates/renderers/generators/actions/entity-file-contents/gen-delete-bulk-content.ts +0 -85
  20. package/dist/assets/adapters/next/templates/renderers/generators/actions/entity-file-contents/gen-delete-content.ts +0 -66
  21. package/dist/assets/adapters/next/templates/renderers/generators/actions/entity-file-contents/gen-distinct-files.ts +0 -45
  22. package/dist/assets/adapters/next/templates/renderers/generators/actions/entity-file-contents/gen-get-by-id-content.ts +0 -55
  23. package/dist/assets/adapters/next/templates/renderers/generators/actions/entity-file-contents/gen-get-by-slug-content.ts +0 -55
  24. package/dist/assets/adapters/next/templates/renderers/generators/actions/entity-file-contents/gen-get-plural-content.ts +0 -106
  25. package/dist/assets/adapters/next/templates/renderers/generators/actions/entity-file-contents/gen-get-select-options-content.ts +0 -55
  26. package/dist/assets/adapters/next/templates/renderers/generators/actions/entity-file-contents/gen-get-versions-content.ts +0 -19
  27. package/dist/assets/adapters/next/templates/renderers/generators/actions/entity-file-contents/gen-m2m-files.ts +0 -151
  28. package/dist/assets/adapters/next/templates/renderers/generators/actions/entity-file-contents/gen-restore-content.ts +0 -123
  29. package/dist/assets/adapters/next/templates/renderers/generators/actions/entity-file-contents/gen-update-content.ts +0 -187
  30. package/dist/assets/adapters/next/templates/renderers/generators/actions/entity-file-contents/generate-resolve-media-function.ts +0 -40
  31. package/dist/assets/adapters/next/templates/renderers/generators/actions/entity-file-contents/generate-slug-helpers.ts +0 -73
  32. package/dist/assets/adapters/next/templates/renderers/generators/actions/entity-file-contents/generate-version-snapshot-helpers.ts +0 -104
  33. package/dist/assets/adapters/next/templates/renderers/generators/actions/lifecycle-hook-emissions/lifecycle-context.ts +0 -22
  34. package/dist/assets/adapters/next/templates/renderers/generators/actions/lifecycle-hook-emissions/lifecycle-hook-import.ts +0 -4
  35. package/dist/assets/adapters/next/templates/renderers/generators/actions/markdown-renderer.ts +0 -411
  36. package/dist/assets/adapters/next/templates/renderers/generators/actions/select-fields-resolver.ts +0 -99
  37. package/dist/assets/adapters/next/templates/renderers/generators/actions/single-actions/generate-single-actions.ts +0 -292
  38. package/dist/assets/adapters/next/templates/renderers/generators/columns/column-defs/generate-authorship-value.ts +0 -8
  39. package/dist/assets/adapters/next/templates/renderers/generators/columns/column-defs/generate-column-def.ts +0 -297
  40. package/dist/assets/adapters/next/templates/renderers/generators/columns/column-defs/generate-first-column-def.ts +0 -483
  41. package/dist/assets/adapters/next/templates/renderers/generators/columns/column-defs/generate-image-cell-media.ts +0 -38
  42. package/dist/assets/adapters/next/templates/renderers/generators/columns/column-defs/generate-image-element.ts +0 -22
  43. package/dist/assets/adapters/next/templates/renderers/generators/columns/column-defs/generate-relationship-label.ts +0 -26
  44. package/dist/assets/adapters/next/templates/renderers/generators/columns/column-defs/generate-select-label.ts +0 -17
  45. package/dist/assets/adapters/next/templates/renderers/generators/columns/custom-cell.ts +0 -24
  46. package/dist/assets/adapters/next/templates/renderers/generators/columns/generate-columns.ts +0 -55
  47. package/dist/assets/adapters/next/templates/renderers/generators/create-page.ts +0 -16
  48. package/dist/assets/adapters/next/templates/renderers/generators/database/generate-database.ts +0 -5
  49. package/dist/assets/adapters/next/templates/renderers/generators/database/generate-junction-table.ts +0 -27
  50. package/dist/assets/adapters/next/templates/renderers/generators/database/generate-select-options-table.ts +0 -35
  51. package/dist/assets/adapters/next/templates/renderers/generators/database/generate-table-definition.ts +0 -25
  52. package/dist/assets/adapters/next/templates/renderers/generators/dev-mode-integration/build-entity-dev-mode-snippets.ts +0 -180
  53. package/dist/assets/adapters/next/templates/renderers/generators/dev-mode-integration/build-form-dev-mode-snippets.ts +0 -97
  54. package/dist/assets/adapters/next/templates/renderers/generators/dev-mode-integration/build-single-dev-mode-snippets.ts +0 -60
  55. package/dist/assets/adapters/next/templates/renderers/generators/dev-mode-integration/create-dev-mode-integration-artifact.ts +0 -89
  56. package/dist/assets/adapters/next/templates/renderers/generators/dev-mode-integration/lifecycle-hook-code.ts +0 -55
  57. package/dist/assets/adapters/next/templates/renderers/generators/edit-page.ts +0 -33
  58. package/dist/assets/adapters/next/templates/renderers/generators/email-template/generate-email-template.ts +0 -248
  59. package/dist/assets/adapters/next/templates/renderers/generators/email-template/generate-field-value.ts +0 -31
  60. package/dist/assets/adapters/next/templates/renderers/generators/emitted-helpers.ts +0 -16
  61. package/dist/assets/adapters/next/templates/renderers/generators/form/field-jsx/generate-icon-postfix.ts +0 -27
  62. package/dist/assets/adapters/next/templates/renderers/generators/form/field-jsx/render-boolean-field.ts +0 -47
  63. package/dist/assets/adapters/next/templates/renderers/generators/form/field-jsx/render-creatable-select-field.ts +0 -122
  64. package/dist/assets/adapters/next/templates/renderers/generators/form/field-jsx/render-date-field.ts +0 -47
  65. package/dist/assets/adapters/next/templates/renderers/generators/form/field-jsx/render-default-field.ts +0 -53
  66. package/dist/assets/adapters/next/templates/renderers/generators/form/field-jsx/render-gallery-field.ts +0 -46
  67. package/dist/assets/adapters/next/templates/renderers/generators/form/field-jsx/render-group-field.ts +0 -16
  68. package/dist/assets/adapters/next/templates/renderers/generators/form/field-jsx/render-icon-field.ts +0 -31
  69. package/dist/assets/adapters/next/templates/renderers/generators/form/field-jsx/render-markdown-field.ts +0 -50
  70. package/dist/assets/adapters/next/templates/renderers/generators/form/field-jsx/render-media-field.ts +0 -47
  71. package/dist/assets/adapters/next/templates/renderers/generators/form/field-jsx/render-multi-relationship-field.ts +0 -91
  72. package/dist/assets/adapters/next/templates/renderers/generators/form/field-jsx/render-multi-select-field.ts +0 -219
  73. package/dist/assets/adapters/next/templates/renderers/generators/form/field-jsx/render-number-field.ts +0 -48
  74. package/dist/assets/adapters/next/templates/renderers/generators/form/field-jsx/render-richtext-field.ts +0 -50
  75. package/dist/assets/adapters/next/templates/renderers/generators/form/field-jsx/render-select-field.ts +0 -61
  76. package/dist/assets/adapters/next/templates/renderers/generators/form/field-jsx/render-separator-field.ts +0 -16
  77. package/dist/assets/adapters/next/templates/renderers/generators/form/field-jsx/render-single-relationship-field.ts +0 -93
  78. package/dist/assets/adapters/next/templates/renderers/generators/form/field-jsx/render-textarea-field.ts +0 -53
  79. package/dist/assets/adapters/next/templates/renderers/generators/form/field-jsx-nested/render-list-field.ts +0 -163
  80. package/dist/assets/adapters/next/templates/renderers/generators/form/field-jsx-nested/render-nested-field.ts +0 -164
  81. package/dist/assets/adapters/next/templates/renderers/generators/form/field-jsx-nested/render-nested-object-list-field.ts +0 -59
  82. package/dist/assets/adapters/next/templates/renderers/generators/form/field-jsx-nested/render-text-input-field.ts +0 -27
  83. package/dist/assets/adapters/next/templates/renderers/generators/form/form-entity/generate-form.ts +0 -822
  84. package/dist/assets/adapters/next/templates/renderers/generators/form/form-shared/build-default-value-from-sync-functions.ts +0 -41
  85. package/dist/assets/adapters/next/templates/renderers/generators/form/form-shared/build-ui-imports.ts +0 -58
  86. package/dist/assets/adapters/next/templates/renderers/generators/form/form-shared/generate-default-value.ts +0 -67
  87. package/dist/assets/adapters/next/templates/renderers/generators/form/form-shared/generate-nested-list-default-value.ts +0 -13
  88. package/dist/assets/adapters/next/templates/renderers/generators/form/form-shared/label-with-description.ts +0 -14
  89. package/dist/assets/adapters/next/templates/renderers/generators/form/form-shared/render-tabs-trigger.ts +0 -18
  90. package/dist/assets/adapters/next/templates/renderers/generators/form/form-shared/select-read-values-expression.ts +0 -21
  91. package/dist/assets/adapters/next/templates/renderers/generators/form/form-single/build-group-creatable-select-handlers.ts +0 -67
  92. package/dist/assets/adapters/next/templates/renderers/generators/form/form-single/build-group-creatable-select-state.ts +0 -29
  93. package/dist/assets/adapters/next/templates/renderers/generators/form/form-single/build-group-field-array-hooks.ts +0 -13
  94. package/dist/assets/adapters/next/templates/renderers/generators/form/form-single/build-group-fields-jsx.ts +0 -30
  95. package/dist/assets/adapters/next/templates/renderers/generators/form/form-single/generate-card-component.ts +0 -129
  96. package/dist/assets/adapters/next/templates/renderers/generators/form/form-single/generate-single-form.ts +0 -66
  97. package/dist/assets/adapters/next/templates/renderers/generators/form-admin/admin-columns/generate-column-def.ts +0 -72
  98. package/dist/assets/adapters/next/templates/renderers/generators/form-admin/admin-columns/generate-columns.ts +0 -89
  99. package/dist/assets/adapters/next/templates/renderers/generators/form-admin/admin-page/generate-page.ts +0 -23
  100. package/dist/assets/adapters/next/templates/renderers/generators/form-admin/admin-page-content.ts +0 -246
  101. package/dist/assets/adapters/next/templates/renderers/generators/form-admin/admin-submission-drawer.ts +0 -216
  102. package/dist/assets/adapters/next/templates/renderers/generators/form-admin/admin-table.ts +0 -273
  103. package/dist/assets/adapters/next/templates/renderers/generators/form-pipeline/form-actions/exclusive-date-upper-bound-helper.ts +0 -11
  104. package/dist/assets/adapters/next/templates/renderers/generators/form-pipeline/form-actions/generate-form-actions.ts +0 -505
  105. package/dist/assets/adapters/next/templates/renderers/generators/form-pipeline/form-component-multistep/build-component-source.ts +0 -197
  106. package/dist/assets/adapters/next/templates/renderers/generators/form-pipeline/form-component-shared/build-field-error-helper.ts +0 -16
  107. package/dist/assets/adapters/next/templates/renderers/generators/form-pipeline/form-component-shared/error-message-line.ts +0 -13
  108. package/dist/assets/adapters/next/templates/renderers/generators/form-pipeline/form-component-shared/generate-field-jsx.ts +0 -226
  109. package/dist/assets/adapters/next/templates/renderers/generators/form-pipeline/form-component-shared/generate-file-upload-field-jsx.ts +0 -41
  110. package/dist/assets/adapters/next/templates/renderers/generators/form-pipeline/form-component-shared/generate-list-field-jsx.ts +0 -160
  111. package/dist/assets/adapters/next/templates/renderers/generators/form-pipeline/form-component-shared/generate-multiselect-field-jsx.ts +0 -40
  112. package/dist/assets/adapters/next/templates/renderers/generators/form-pipeline/form-component-shared/generate-number-field-jsx.ts +0 -41
  113. package/dist/assets/adapters/next/templates/renderers/generators/form-pipeline/form-component-shared/generate-text-field-jsx.ts +0 -39
  114. package/dist/assets/adapters/next/templates/renderers/generators/form-pipeline/form-component-shared/label-with-description-line.ts +0 -14
  115. package/dist/assets/adapters/next/templates/renderers/generators/form-pipeline/form-component-single/build-single-step-form-component-source.ts +0 -100
  116. package/dist/assets/adapters/next/templates/renderers/generators/form-pipeline/form-database.ts +0 -29
  117. package/dist/assets/adapters/next/templates/renderers/generators/form-pipeline/form-hook.ts +0 -142
  118. package/dist/assets/adapters/next/templates/renderers/generators/hook/generate-hook.ts +0 -169
  119. package/dist/assets/adapters/next/templates/renderers/generators/hook/generate-single-hook.ts +0 -30
  120. package/dist/assets/adapters/next/templates/renderers/generators/navigation-extract.ts +0 -19
  121. package/dist/assets/adapters/next/templates/renderers/generators/page-content/generate-page-content.ts +0 -419
  122. package/dist/assets/adapters/next/templates/renderers/generators/page.ts +0 -24
  123. package/dist/assets/adapters/next/templates/renderers/generators/row-actions-emitters/build-delete-dialog-source.ts +0 -108
  124. package/dist/assets/adapters/next/templates/renderers/generators/row-actions-emitters/build-row-actions-source.ts +0 -61
  125. package/dist/assets/adapters/next/templates/renderers/generators/single-page.ts +0 -59
  126. package/dist/assets/adapters/next/templates/renderers/generators/sortable-header/build-sort-label-expr.ts +0 -9
  127. package/dist/assets/adapters/next/templates/renderers/generators/sortable-header/build-sortable-header-button-jsx.ts +0 -20
  128. package/dist/assets/adapters/next/templates/renderers/generators/sortable-header/build-sortable-header-def.ts +0 -14
  129. package/dist/assets/adapters/next/templates/renderers/generators/table.ts +0 -284
  130. package/dist/assets/adapters/next/templates/renderers/generators/thankyou-email-template.ts +0 -110
  131. package/dist/assets/adapters/next/templates/renderers/generators/webhook-events/render-extract.ts +0 -14
  132. package/dist/assets/adapters/next/templates/renderers/init/scaffolders/next-config/create-next-config-template.ts +0 -48
  133. package/dist/assets/adapters/next/templates/renderers/init/scaffolders/tailwind/admin-shadow-input-utility.ts +0 -9
  134. package/dist/assets/adapters/next/templates/renderers/init/scaffolders/tailwind/admin-theme-block.ts +0 -42
  135. package/dist/assets/adapters/next/templates/renderers/init/templates/app/admin.ts +0 -12
  136. package/dist/assets/adapters/next/templates/renderers/integration-runtime/render-core-email-provider.ts +0 -27
  137. package/dist/assets/adapters/next/templates/renderers/integration-runtime/render-core-storage-provider.ts +0 -27
  138. package/dist/assets/adapters/next/templates/renderers/snapshots/barrels/render-db-barrel.ts +0 -8
  139. package/dist/assets/adapters/next/templates/renderers/snapshots/barrels/render-navigation-barrel.ts +0 -63
  140. package/dist/assets/adapters/next/templates/renderers/snapshots/barrels/render-webhook-events-barrel.ts +0 -16
@@ -1,505 +0,0 @@
1
- export function renderFormActionsSearchTemplate({ map }: { map: string }): string {
2
- return ` const search = filters?.search
3
- if (search && typeof search === 'string' && search.trim()) {
4
- const searchTerm = \`%\${search.trim().toLowerCase()}%\`
5
- conditions.push(
6
- or(
7
- ${map}
8
- )
9
- )
10
- }
11
- `
12
- }
13
-
14
- export function renderFormActionsComponentTemplate({
15
- pascal,
16
- dataFields,
17
- formName,
18
- idPlaceholder
19
- }: {
20
- pascal: string
21
- dataFields: string
22
- formName: string
23
- idPlaceholder: string
24
- }): string {
25
- return `export interface ${pascal}SubmissionData {
26
- id: string
27
- ${dataFields}
28
- ipAddress: string | null
29
- userAgent: string | null
30
- submittedAt: string
31
- createdAt: string
32
- updatedAt: string
33
- }
34
-
35
- export interface ${pascal}SubmissionsResponse {
36
- submissions: ${pascal}SubmissionData[]
37
- total: number
38
- }
39
-
40
- export interface Get${pascal}SubmissionsFilters {
41
- search?: string
42
- submittedAtFrom?: string
43
- submittedAtTo?: string
44
- limit?: number
45
- offset?: number
46
- orderBy?: string
47
- orderDirection?: 'asc' | 'desc'
48
- }
49
-
50
- export interface Create${pascal}SubmissionInput {
51
- ${dataFields}
52
- ipAddress?: string
53
- userAgent?: string
54
- }
55
-
56
- export interface Create${pascal}SubmissionResult {
57
- success: boolean
58
- error?: string
59
- submission?: ${pascal}SubmissionData
60
- }
61
-
62
- export interface Delete${pascal}SubmissionResult {
63
- success: boolean
64
- error?: string
65
- count?: number
66
- }
67
-
68
- export const CACHE_TAG = '${formName}:submissions:all'
69
- export const CACHE_TAG_BY_ID = (id: string) => \`${formName}:submissions:id:${idPlaceholder}\`
70
- `
71
- }
72
-
73
- export function renderFormActionsServerActionTemplate({
74
- sort,
75
- tableName,
76
- cacheReadImport,
77
- pascal,
78
- exclusiveDateUpperBoundSource,
79
- sortableColumnsMap,
80
- cacheLifeLine,
81
- searchBlock,
82
- formName
83
- }: {
84
- sort: string
85
- tableName: string
86
- cacheReadImport: string
87
- pascal: string
88
- exclusiveDateUpperBoundSource: string
89
- sortableColumnsMap: string
90
- cacheLifeLine: string
91
- searchBlock: string
92
- formName: string
93
- }): string {
94
- return `'use server'
95
-
96
- import { ${sort} } from 'drizzle-orm'
97
- import db from '@admin/db'
98
- import { ${tableName} } from '@admin/db/schema'
99
- ${cacheReadImport}
100
- import { CACHE_TAG } from './types'
101
- import type {
102
- Get${pascal}SubmissionsFilters,
103
- ${pascal}SubmissionsResponse,
104
- ${pascal}SubmissionData
105
- } from './types'
106
-
107
- ${exclusiveDateUpperBoundSource}
108
-
109
- const SORTABLE_COLUMNS = {
110
- ${sortableColumnsMap}
111
- } as const
112
-
113
- export async function get${pascal}Submissions(
114
- filters?: Get${pascal}SubmissionsFilters
115
- ): Promise<${pascal}SubmissionsResponse> {
116
- 'use cache'${cacheLifeLine}
117
- cacheTag(CACHE_TAG)
118
-
119
- try {
120
- const conditions = []
121
- ${searchBlock} if (filters?.submittedAtFrom) {
122
- conditions.push(gte(${tableName}.submittedAt, filters.submittedAtFrom))
123
- }
124
- const submittedAtExclusiveTo = getExclusiveDateUpperBound(filters?.submittedAtTo)
125
- if (submittedAtExclusiveTo) {
126
- conditions.push(lt(${tableName}.submittedAt, submittedAtExclusiveTo))
127
- }
128
-
129
- const query = db.select().from(${tableName})
130
-
131
- const sortColumn = filters?.orderBy && filters.orderBy in SORTABLE_COLUMNS
132
- ? SORTABLE_COLUMNS[filters.orderBy as keyof typeof SORTABLE_COLUMNS]
133
- : ${tableName}.submittedAt
134
- const sortFn =
135
- filters?.orderBy && filters.orderBy in SORTABLE_COLUMNS
136
- ? filters.orderDirection === 'desc'
137
- ? desc
138
- : asc
139
- : desc
140
- const orderClause = sortFn(sortColumn)
141
-
142
- const orderedQuery = conditions.length > 0
143
- ? query.where(and(...conditions)).orderBy(orderClause)
144
- : query.orderBy(orderClause)
145
-
146
- const limit = filters?.limit
147
- const offset = filters?.offset
148
- const isPaginated = typeof limit === 'number' && limit > 0
149
- let results: unknown[]
150
- if (isPaginated) {
151
- const paginatedQuery = typeof offset === 'number' && offset > 0
152
- ? orderedQuery.limit(limit).offset(offset)
153
- : orderedQuery.limit(limit)
154
- results = await paginatedQuery
155
- } else {
156
- results = await orderedQuery
157
- }
158
-
159
- const total = isPaginated
160
- ? Number(
161
- (
162
- await db
163
- .select({ count: sql\`count(*)\` })
164
- .from(${tableName})
165
- .where(conditions.length > 0 ? and(...conditions) : undefined)
166
- )[0]?.count ?? 0
167
- )
168
- : results.length
169
-
170
- return {
171
- submissions: results as ${pascal}SubmissionData[],
172
- total
173
- }
174
- } catch (error) {
175
- console.error('Error fetching ${formName} submissions:', error)
176
- throw new Error('Failed to fetch ${formName} submissions')
177
- }
178
- }
179
- `
180
- }
181
-
182
- export function renderFormActionsServerActionDetailsTemplate({
183
- tableName,
184
- cacheReadImport,
185
- pascal,
186
- cacheLifeLine,
187
- formName
188
- }: {
189
- tableName: string
190
- cacheReadImport: string
191
- pascal: string
192
- cacheLifeLine: string
193
- formName: string
194
- }): string {
195
- return `'use server'
196
-
197
- import { eq } from 'drizzle-orm'
198
- import db from '@admin/db'
199
- import { ${tableName} } from '@admin/db/schema'
200
- ${cacheReadImport}
201
- import { CACHE_TAG, CACHE_TAG_BY_ID } from './types'
202
- import type { ${pascal}SubmissionData } from './types'
203
-
204
- export async function get${pascal}Submission(id: string): Promise<${pascal}SubmissionData | null> {
205
- 'use cache'${cacheLifeLine}
206
- cacheTag(CACHE_TAG_BY_ID(id))
207
- cacheTag(CACHE_TAG)
208
-
209
- try {
210
- const [submission] = await db
211
- .select()
212
- .from(${tableName})
213
- .where(eq(${tableName}.id, id))
214
- .limit(1)
215
- return (submission as ${pascal}SubmissionData) ?? null
216
- } catch (error) {
217
- console.error(\`Error fetching ${formName} submission \${id}:\`, error)
218
- throw new Error('Failed to fetch ${formName} submission')
219
- }
220
- }
221
- `
222
- }
223
-
224
- export function renderFormActionsServerActionLabelTemplate({
225
- tableName,
226
- cacheInvalidationFn,
227
- mailchimpImport,
228
- lifecycleHookImport,
229
- pascal,
230
- createLifecycleContext,
231
- beforeHook,
232
- validation,
233
- formSettingsKey,
234
- schemaNotificationFallback,
235
- formName,
236
- schemaLabel,
237
- submitterEmailFieldNull,
238
- mailchimpCall,
239
- createResultLifecycleContext,
240
- afterHook
241
- }: {
242
- tableName: string
243
- cacheInvalidationFn: string
244
- mailchimpImport: string
245
- lifecycleHookImport: string
246
- pascal: string
247
- createLifecycleContext: string
248
- beforeHook: string
249
- validation: string
250
- formSettingsKey: string
251
- schemaNotificationFallback: string
252
- formName: string
253
- schemaLabel: string
254
- submitterEmailFieldNull: string
255
- mailchimpCall: string
256
- createResultLifecycleContext: string
257
- afterHook: string
258
- }): string {
259
- return `'use server'
260
-
261
- import { getSession } from '@admin/auth/middleware'
262
- import db from '@admin/db'
263
- import { ${tableName} } from '@admin/db/schema'
264
- import { getFormSettings } from '@admin/actions/forms'
265
- import { sendFormEmails } from '@admin/actions/email/send-form-emails'
266
- import { getTouchedFieldNames } from '@admin/utils/audit/get-touched-field-names'
267
- import { ${cacheInvalidationFn} } from 'next/cache'
268
- ${mailchimpImport}
269
- import { CACHE_TAG, CACHE_TAG_BY_ID } from './types'
270
- ${lifecycleHookImport}
271
- import type { Create${pascal}SubmissionInput, Create${pascal}SubmissionResult, ${pascal}SubmissionData } from './types'
272
-
273
- export async function create${pascal}Submission(
274
- data: Create${pascal}SubmissionInput
275
- ): Promise<Create${pascal}SubmissionResult> {
276
- try {
277
- const session = await getSession()
278
- const now = new Date().toISOString()
279
- const auditRequestMetadata = await getAuditRequestMetadata()
280
- const changedFields = getTouchedFieldNames(data as unknown as Record<string, unknown>)
281
- const lifecycleContext = ${createLifecycleContext}
282
- ${beforeHook}
283
-
284
- ${validation}
285
-
286
- const [submission] = await db
287
- .insert(${tableName})
288
- .values({
289
- ...data,
290
- submittedAt: now
291
- })
292
- .returning()
293
- const created${pascal}Submission = submission as ${pascal}SubmissionData
294
-
295
- const settings = await getFormSettings('${formSettingsKey}')
296
- const notificationEmails = settings?.notificationEmails
297
- ? settings.notificationEmails.split(',').map((e: string) => e.trim()).filter(Boolean)
298
- : ${schemaNotificationFallback}
299
-
300
- await sendFormEmails({
301
- formName: '${formName}',
302
- formLabel: '${schemaLabel}',
303
- notificationEmails,
304
- submitterEmail: ${submitterEmailFieldNull},
305
- submissionData: { ...data },
306
- submittedAt: created${pascal}Submission.submittedAt,
307
- })${mailchimpCall}
308
-
309
- ${cacheInvalidationFn}(CACHE_TAG)
310
- ${cacheInvalidationFn}(CACHE_TAG_BY_ID(created${pascal}Submission.id))
311
- const created${pascal}SubmissionContext = ${createResultLifecycleContext}
312
- ${afterHook}
313
-
314
- return {
315
- success: true,
316
- submission: created${pascal}Submission
317
- }
318
- } catch (error) {
319
- console.error('Error creating ${formName} submission:', error)
320
- return {
321
- success: false,
322
- error: error instanceof Error ? error.message : 'Failed to create ${formName} submission'
323
- }
324
- }
325
- }
326
- `
327
- }
328
-
329
- export function renderFormActionsServerActionBeforeDeleteTemplate({
330
- tableName,
331
- cacheInvalidationFn,
332
- lifecycleHookImport,
333
- pascal,
334
- deleteLifecycleContext,
335
- beforeHook,
336
- afterHook,
337
- formName
338
- }: {
339
- tableName: string
340
- cacheInvalidationFn: string
341
- lifecycleHookImport: string
342
- pascal: string
343
- deleteLifecycleContext: string
344
- beforeHook: string
345
- afterHook: string
346
- formName: string
347
- }): string {
348
- return `'use server'
349
-
350
- import { getSession } from '@admin/auth/middleware'
351
- import { eq } from 'drizzle-orm'
352
- import db from '@admin/db'
353
- import { ${tableName} } from '@admin/db/schema'
354
- import { ${cacheInvalidationFn} } from 'next/cache'
355
- import { CACHE_TAG, CACHE_TAG_BY_ID } from './types'
356
- ${lifecycleHookImport}
357
- import type { Delete${pascal}SubmissionResult } from './types'
358
-
359
- export async function delete${pascal}Submission(id: string): Promise<Delete${pascal}SubmissionResult> {
360
- try {
361
- const session = await getSession()
362
- const now = new Date().toISOString()
363
- const auditRequestMetadata = await getAuditRequestMetadata()
364
- const lifecycleContext = ${deleteLifecycleContext}
365
- ${beforeHook}
366
-
367
- await db.delete(${tableName}).where(eq(${tableName}.id, id))
368
- ${cacheInvalidationFn}(CACHE_TAG)
369
- ${cacheInvalidationFn}(CACHE_TAG_BY_ID(id))
370
- ${afterHook}
371
- return { success: true }
372
- } catch (error) {
373
- console.error(\`Error deleting ${formName} submission \${id}:\`, error)
374
- return {
375
- success: false,
376
- error: error instanceof Error ? error.message : 'Failed to delete ${formName} submission'
377
- }
378
- }
379
- }
380
- `
381
- }
382
-
383
- export function renderFormActionsServerActionBeforeDeleteBranchTemplate({
384
- tableName,
385
- cacheInvalidationFn,
386
- lifecycleHookImport,
387
- pascal,
388
- deleteLifecycleContext,
389
- beforeHook,
390
- afterHook,
391
- formName
392
- }: {
393
- tableName: string
394
- cacheInvalidationFn: string
395
- lifecycleHookImport: string
396
- pascal: string
397
- deleteLifecycleContext: string
398
- beforeHook: string
399
- afterHook: string
400
- formName: string
401
- }): string {
402
- return `'use server'
403
-
404
- import { getSession } from '@admin/auth/middleware'
405
- import { eq, or } from 'drizzle-orm'
406
- import db from '@admin/db'
407
- import { ${tableName} } from '@admin/db/schema'
408
- import { ${cacheInvalidationFn} } from 'next/cache'
409
- import { CACHE_TAG, CACHE_TAG_BY_ID } from './types'
410
- ${lifecycleHookImport}
411
- import type { Delete${pascal}SubmissionResult } from './types'
412
-
413
- export async function deleteBulk${pascal}Submissions(ids: string[]): Promise<Delete${pascal}SubmissionResult> {
414
- try {
415
- if (ids.length === 0) return { success: true, count: 0 }
416
- const session = await getSession()
417
- const now = new Date().toISOString()
418
- const auditRequestMetadata = await getAuditRequestMetadata()
419
- const lifecycleContexts = ids.map((id) => (${deleteLifecycleContext}))
420
-
421
- for (const lifecycleContext of lifecycleContexts) {
422
- ${beforeHook}
423
- }
424
-
425
- await db.delete(${tableName}).where(
426
- or(...ids.map(id => eq(${tableName}.id, id)))
427
- )
428
- ${cacheInvalidationFn}(CACHE_TAG)
429
- for (const id of ids) {
430
- ${cacheInvalidationFn}(CACHE_TAG_BY_ID(id))
431
- }
432
- for (const lifecycleContext of lifecycleContexts) {
433
- ${afterHook}
434
- }
435
- return { success: true, count: ids.length }
436
- } catch (error) {
437
- console.error(\`Error bulk deleting ${formName} submissions:\`, error)
438
- return {
439
- success: false,
440
- error: error instanceof Error ? error.message : 'Failed to bulk delete ${formName} submissions'
441
- }
442
- }
443
- }
444
- `
445
- }
446
-
447
- export function renderFormActionsServerActionDetailsBranchTemplate({
448
- pascal,
449
- kebab
450
- }: {
451
- pascal: string
452
- kebab: string
453
- }): string {
454
- return `'use server'
455
-
456
- import { get${pascal}Submissions } from './get-${kebab}-submissions'
457
-
458
- import { EXCLUSIVE_DATE_UPPER_BOUND_SOURCE } from '@cli-constants/generators.js'
459
- import { SEARCHABLE_FORM_FIELD_TYPES, SORTABLE_FORM_FIELD_TYPES } from '@cli-constants/schema-codegen.js'
460
- export async function export${pascal}SubmissionsCSV(): Promise<string> {
461
- const { submissions } = await get${pascal}Submissions()
462
- if (submissions.length === 0) return ''
463
- const headers = Object.keys(submissions[0]).join(',')
464
- const rows = submissions.map((sub) =>
465
- Object.values(sub)
466
- .map((val: unknown) => {
467
- if (val === null || val === undefined) return ''
468
- const str = String(val)
469
- if (str.includes(',') || str.includes('"') || str.includes('\\n')) {
470
- return \`"\${str.replace(/"/g, '""')}"\`
471
- }
472
- return str
473
- })
474
- .join(',')
475
- )
476
- return [headers, ...rows].join('\\n')
477
- }
478
- `
479
- }
480
-
481
- export function renderFormActionsContentTemplate({
482
- pascal,
483
- kebab,
484
- exportBarrelLine
485
- }: {
486
- pascal: string
487
- kebab: string
488
- exportBarrelLine: string
489
- }): string {
490
- return `export type {
491
- ${pascal}SubmissionData,
492
- ${pascal}SubmissionsResponse,
493
- Get${pascal}SubmissionsFilters,
494
- Create${pascal}SubmissionInput,
495
- Create${pascal}SubmissionResult,
496
- Delete${pascal}SubmissionResult
497
- } from './types'
498
- export { get${pascal}Submissions } from './get-${kebab}-submissions'
499
- export { get${pascal}Submission } from './get-${kebab}-submission'
500
- export { create${pascal}Submission } from './create-${kebab}-submission'
501
- export { delete${pascal}Submission } from './delete-${kebab}-submission'
502
- export { deleteBulk${pascal}Submissions } from './delete-bulk-${kebab}-submissions'${exportBarrelLine}
503
- export { CACHE_TAG, CACHE_TAG_BY_ID } from './types'
504
- `
505
- }
@@ -1,197 +0,0 @@
1
- export function renderBuildComponentSourceContentTemplate({
2
- pPascal
3
- }: {
4
- pPascal: string
5
- }): string {
6
- return ` <NuqsAdapter>
7
- <React.Suspense fallback={null}>
8
- <${pPascal}FormInner />
9
- </React.Suspense>
10
- </NuqsAdapter>`
11
- }
12
-
13
- export function renderBuildComponentSourceGeneratedFunctionTemplate({
14
- pPascal,
15
- providerOpen
16
- }: {
17
- pPascal: string
18
- providerOpen: string
19
- }): string {
20
- return `\nexport function ${pPascal}Form() {
21
- return (
22
- ${providerOpen}
23
- )
24
- }\n`
25
- }
26
-
27
- export function renderBuildComponentSourceClientModuleTemplate({
28
- pHasListFieldsTrash2,
29
- pRhfImport,
30
- pPascal,
31
- pActionImportPath,
32
- pZodFields,
33
- fieldErrorHelper,
34
- pStepsConst,
35
- pDefaults,
36
- pFieldArraySetup,
37
- pWatchSetup,
38
- pSuccessHandler,
39
- pSuccessMessage,
40
- pStepContentBlocks,
41
- pSubmitText,
42
- exportWrapper
43
- }: {
44
- pHasListFieldsTrash2: string
45
- pRhfImport: string
46
- pPascal: string
47
- pActionImportPath: string
48
- pZodFields: string
49
- fieldErrorHelper: string
50
- pStepsConst: string
51
- pDefaults: string
52
- pFieldArraySetup: string
53
- pWatchSetup: string
54
- pSuccessHandler: string
55
- pSuccessMessage: string
56
- pStepContentBlocks: string
57
- pSubmitText: string
58
- exportWrapper: string
59
- }): string {
60
- return `'use client'
61
-
62
- import * as React from 'react'
63
- import { standardSchemaResolver } from '@hookform/resolvers/standard-schema'
64
- import { ChevronLeft, ChevronRight${pHasListFieldsTrash2} } from 'lucide-react'
65
- import { createParser, useQueryState } from 'nuqs'
66
- import { NuqsAdapter } from 'nuqs/adapters/next/app'
67
- ${pRhfImport}
68
- import { z } from 'zod/v3'
69
- import { create${pPascal}Submission } from '@admin/actions/${pActionImportPath}'
70
-
71
- const formSchema = z.object({
72
- ${pZodFields}
73
- })
74
-
75
- type FormValues = z.infer<typeof formSchema>
76
- ${fieldErrorHelper}
77
-
78
- ${pStepsConst}
79
-
80
- const stepParser = createParser({
81
- parse(value) {
82
- if (!/^\\d+$/.test(value)) {
83
- return null
84
- }
85
- const step = Number.parseInt(value, 10)
86
- if (!Number.isInteger(step) || step < 0 || step >= STEPS.length) {
87
- return null
88
- }
89
- return step
90
- },
91
- serialize(value) {
92
- return String(value)
93
- }
94
- }).withDefault(0)
95
-
96
- function ${pPascal}FormInner() {
97
- const [currentStep, setCurrentStep] = useQueryState('step', stepParser)
98
- const [submitted, setSubmitted] = React.useState(false)
99
- const [submitting, startSubmitTransition] = React.useTransition()
100
-
101
- const form = useForm<FormValues>({
102
- resolver: standardSchemaResolver(formSchema),
103
- defaultValues: {
104
- ${pDefaults}
105
- },
106
- })
107
-
108
- ${pFieldArraySetup}${pWatchSetup}
109
- async function handleNext() {
110
- const stepFields = STEPS[currentStep].fields as (keyof FormValues)[]
111
- const isValid = await form.trigger(stepFields, { shouldFocus: true })
112
- if (isValid) {
113
- setCurrentStep(currentStep + 1)
114
- }
115
- }
116
-
117
- function handleBack() {
118
- setCurrentStep(currentStep - 1)
119
- }
120
-
121
- function onSubmit(values: FormValues) {
122
- startSubmitTransition(async () => {
123
- try {
124
- const result = await create${pPascal}Submission(values)
125
- if (result.success) {
126
- ${pSuccessHandler}
127
- } else {
128
- form.setError('root', { message: result.error || 'Something went wrong' })
129
- }
130
- } catch {
131
- form.setError('root', { message: 'Something went wrong. Please try again.' })
132
- }
133
- })
134
- }
135
-
136
- if (submitted) {
137
- return (
138
- <div className="rounded-sm border p-6 text-center">
139
- <h3 className="text-lg font-semibold">Thank you!</h3>
140
- <p className="mt-2 text-muted-foreground">${pSuccessMessage}</p>
141
- </div>
142
- )
143
- }
144
-
145
- return (
146
- <form onSubmit={(event) => event.preventDefault()} className="space-y-8">
147
- <div>
148
- <h3 className="text-lg font-semibold">{STEPS[currentStep].label}</h3>
149
- {'description' in STEPS[currentStep] && STEPS[currentStep].description && (
150
- <p className="text-sm text-muted-foreground mt-1">{STEPS[currentStep].description}</p>
151
- )}
152
- </div>
153
-
154
- <div key={currentStep} className="animate-in fade-in duration-300 space-y-6">
155
- ${pStepContentBlocks}
156
- </div>
157
-
158
- {form.formState.errors.root && (
159
- <p className="text-sm text-destructive">{form.formState.errors.root.message}</p>
160
- )}
161
-
162
- <div className="flex justify-between">
163
- <button
164
- type="button"
165
- onClick={handleBack}
166
- disabled={currentStep === 0}
167
- className="inline-flex h-9 items-center justify-center rounded-md border border-input bg-background px-4 py-2 text-sm font-medium shadow-xs transition-colors hover:bg-accent hover:text-accent-foreground disabled:pointer-events-none disabled:opacity-50"
168
- >
169
- <ChevronLeft className="size-4" />
170
- Back
171
- </button>
172
- {currentStep < STEPS.length - 1 ? (
173
- <button
174
- type="button"
175
- onClick={handleNext}
176
- className="inline-flex h-9 items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground shadow-xs transition-colors hover:bg-primary/90 disabled:pointer-events-none disabled:opacity-50"
177
- >
178
- Next
179
- <ChevronRight className="ml-2 size-4" />
180
- </button>
181
- ) : (
182
- <button
183
- type="button"
184
- disabled={submitting}
185
- aria-busy={submitting}
186
- onClick={() => form.handleSubmit(onSubmit)()}
187
- className="inline-flex h-9 items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground shadow-xs transition-colors hover:bg-primary/90 disabled:pointer-events-none disabled:opacity-50"
188
- >
189
- {submitting ? 'Submitting…' : ${pSubmitText}}
190
- </button>
191
- )}
192
- </div>
193
- </form>
194
- )
195
- }
196
- ${exportWrapper}`
197
- }
@@ -1,16 +0,0 @@
1
- export function renderBuildFieldErrorHelperSegmentTemplate(): string {
2
- return `function getFieldErrorMessage(errors: FieldErrors<FormValues>, path: string): string | undefined {
3
- let current: unknown = errors
4
- for (const segment of path.split('.')) {
5
- if (!current || typeof current !== 'object') {
6
- return undefined
7
- }
8
- current = (current as Record<string, unknown>)[segment]
9
- }
10
- if (current && typeof current === 'object' && 'message' in current) {
11
- const message = (current as { message?: unknown }).message
12
- return typeof message === 'string' ? message : undefined
13
- }
14
- return undefined
15
- }`
16
- }