@postxl/generators 1.12.3 → 1.14.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 (195) hide show
  1. package/dist/backend-ai/ai.generator.d.ts +18 -0
  2. package/dist/backend-ai/ai.generator.js +174 -0
  3. package/dist/backend-ai/ai.generator.js.map +1 -0
  4. package/dist/backend-ai/generators/ai-agent-service.generator.d.ts +4 -0
  5. package/dist/backend-ai/generators/ai-agent-service.generator.js +264 -0
  6. package/dist/backend-ai/generators/ai-agent-service.generator.js.map +1 -0
  7. package/dist/backend-ai/generators/ai-cache-service.generator.d.ts +1 -0
  8. package/dist/backend-ai/generators/ai-cache-service.generator.js +110 -0
  9. package/dist/backend-ai/generators/ai-cache-service.generator.js.map +1 -0
  10. package/dist/backend-ai/generators/ai-config.generator.d.ts +1 -0
  11. package/dist/backend-ai/generators/ai-config.generator.js +27 -0
  12. package/dist/backend-ai/generators/ai-config.generator.js.map +1 -0
  13. package/dist/backend-ai/generators/ai-module.generator.d.ts +2 -0
  14. package/dist/backend-ai/generators/ai-module.generator.js +89 -0
  15. package/dist/backend-ai/generators/ai-module.generator.js.map +1 -0
  16. package/dist/backend-ai/generators/ai-route.generator.d.ts +1 -0
  17. package/dist/backend-ai/generators/ai-route.generator.js +29 -0
  18. package/dist/backend-ai/generators/ai-route.generator.js.map +1 -0
  19. package/dist/backend-ai/generators/ai-tools-service.generator.d.ts +4 -0
  20. package/dist/backend-ai/generators/ai-tools-service.generator.js +222 -0
  21. package/dist/backend-ai/generators/ai-tools-service.generator.js.map +1 -0
  22. package/dist/backend-ai/generators/model-provider-interface.generator.d.ts +1 -0
  23. package/dist/backend-ai/generators/model-provider-interface.generator.js +48 -0
  24. package/dist/backend-ai/generators/model-provider-interface.generator.js.map +1 -0
  25. package/dist/backend-ai/generators/openai-model-provider-service.generator.d.ts +1 -0
  26. package/dist/backend-ai/generators/openai-model-provider-service.generator.js +128 -0
  27. package/dist/backend-ai/generators/openai-model-provider-service.generator.js.map +1 -0
  28. package/dist/backend-ai/index.d.ts +4 -0
  29. package/dist/backend-ai/index.js +40 -0
  30. package/dist/backend-ai/index.js.map +1 -0
  31. package/dist/backend-authentication/generators/authentication-service.generator.js +1 -1
  32. package/dist/backend-core/backend.generator.js +0 -4
  33. package/dist/backend-core/backend.generator.js.map +1 -1
  34. package/dist/backend-core/generators/main.generator.js +4 -3
  35. package/dist/backend-core/generators/main.generator.js.map +1 -1
  36. package/dist/backend-core/modules/backend-module-xlport.generator.js +1 -1
  37. package/dist/backend-e2e/backend-e2e.generator.js +4 -4
  38. package/dist/backend-e2e/backend-e2e.generator.js.map +1 -1
  39. package/dist/backend-excel-io/excel-io.generator.d.ts +19 -0
  40. package/dist/backend-excel-io/excel-io.generator.js +106 -0
  41. package/dist/backend-excel-io/excel-io.generator.js.map +1 -0
  42. package/dist/backend-excel-io/generators/excel-io-service.generator.d.ts +9 -0
  43. package/dist/backend-excel-io/generators/excel-io-service.generator.js +680 -0
  44. package/dist/backend-excel-io/generators/excel-io-service.generator.js.map +1 -0
  45. package/dist/backend-excel-io/index.d.ts +2 -0
  46. package/dist/backend-excel-io/index.js +22 -0
  47. package/dist/backend-excel-io/index.js.map +1 -0
  48. package/dist/backend-excel-io/template/README.md +24 -0
  49. package/dist/backend-excel-io/template/excel-io.controller.ts +195 -0
  50. package/dist/backend-excel-io/template/excel-io.module.ts +17 -0
  51. package/dist/backend-import/generators/detect-delta/detect-delta-functions.generator.js +149 -14
  52. package/dist/backend-import/generators/detect-delta/detect-delta-functions.generator.js.map +1 -1
  53. package/dist/backend-import/generators/filter-error-rows.generator.d.ts +2 -0
  54. package/dist/backend-import/generators/filter-error-rows.generator.js +28 -0
  55. package/dist/backend-import/generators/filter-error-rows.generator.js.map +1 -0
  56. package/dist/backend-import/generators/import-service.generator.js +126 -2
  57. package/dist/backend-import/generators/import-service.generator.js.map +1 -1
  58. package/dist/backend-import/import.generator.js +2 -0
  59. package/dist/backend-import/import.generator.js.map +1 -1
  60. package/dist/backend-repositories/generators/model-repository.generator.js +17 -2
  61. package/dist/backend-repositories/generators/model-repository.generator.js.map +1 -1
  62. package/dist/backend-router-trpc/generators/app-routes.generator.js +8 -1
  63. package/dist/backend-router-trpc/generators/app-routes.generator.js.map +1 -1
  64. package/dist/backend-router-trpc/generators/excel-io-route.generator.d.ts +4 -0
  65. package/dist/backend-router-trpc/generators/excel-io-route.generator.js +35 -0
  66. package/dist/backend-router-trpc/generators/excel-io-route.generator.js.map +1 -0
  67. package/dist/backend-router-trpc/generators/trpc-plugin.generator.js +9 -0
  68. package/dist/backend-router-trpc/generators/trpc-plugin.generator.js.map +1 -1
  69. package/dist/backend-router-trpc/generators/trpc-router-module.generator.js +9 -1
  70. package/dist/backend-router-trpc/generators/trpc-router-module.generator.js.map +1 -1
  71. package/dist/backend-router-trpc/generators/trpc-shared.generator.js +16 -1
  72. package/dist/backend-router-trpc/generators/trpc-shared.generator.js.map +1 -1
  73. package/dist/backend-router-trpc/router-trpc.generator.d.ts +3 -1
  74. package/dist/backend-router-trpc/router-trpc.generator.js +6 -0
  75. package/dist/backend-router-trpc/router-trpc.generator.js.map +1 -1
  76. package/dist/backend-seed/seed.generator.js +10 -1
  77. package/dist/backend-seed/seed.generator.js.map +1 -1
  78. package/dist/base/base.generator.js +0 -4
  79. package/dist/base/base.generator.js.map +1 -1
  80. package/dist/base/template/scripts/setup.sh +9 -4
  81. package/dist/base/template/sonar-project.properties +9 -1
  82. package/dist/decoders/datamodel-decoder.generator.js +91 -1
  83. package/dist/decoders/datamodel-decoder.generator.js.map +1 -1
  84. package/dist/decoders/decoders.generator.d.ts +9 -0
  85. package/dist/decoders/decoders.generator.js +15 -0
  86. package/dist/decoders/decoders.generator.js.map +1 -1
  87. package/dist/devops/devops.generator.d.ts +5 -1
  88. package/dist/devops/devops.generator.js +5 -4
  89. package/dist/devops/devops.generator.js.map +1 -1
  90. package/dist/devops/generators/bitbucket-pipelines-yml.generator.js +1 -0
  91. package/dist/devops/generators/bitbucket-pipelines-yml.generator.js.map +1 -1
  92. package/dist/devops/generators/docker-compose-yml.generator.d.ts +1 -1
  93. package/dist/devops/generators/docker-compose-yml.generator.js +16 -1
  94. package/dist/devops/generators/docker-compose-yml.generator.js.map +1 -1
  95. package/dist/devops/generators/e2e-yml.generator.js +35 -10
  96. package/dist/devops/generators/e2e-yml.generator.js.map +1 -1
  97. package/dist/devops/generators/jenkinsfile.generator.js +25 -1
  98. package/dist/devops/generators/jenkinsfile.generator.js.map +1 -1
  99. package/dist/e2e/template/e2e/specs/example.spec.ts-snapshots/Navigate-to-homepage-and-take-snapshot-1-chromium-linux.png +0 -0
  100. package/dist/frontend-actions/actions.generator.d.ts +9 -0
  101. package/dist/frontend-actions/actions.generator.js +111 -0
  102. package/dist/frontend-actions/actions.generator.js.map +1 -0
  103. package/dist/frontend-actions/generators/ai-action-text.utils.generator.d.ts +1 -0
  104. package/dist/frontend-actions/generators/ai-action-text.utils.generator.js +52 -0
  105. package/dist/frontend-actions/generators/ai-action-text.utils.generator.js.map +1 -0
  106. package/dist/frontend-actions/generators/ai-assistant-store.generator.d.ts +1 -0
  107. package/dist/frontend-actions/generators/ai-assistant-store.generator.js +230 -0
  108. package/dist/frontend-actions/generators/ai-assistant-store.generator.js.map +1 -0
  109. package/dist/frontend-actions/generators/ai-sidebar-content.generator.d.ts +1 -0
  110. package/dist/frontend-actions/generators/ai-sidebar-content.generator.js +139 -0
  111. package/dist/frontend-actions/generators/ai-sidebar-content.generator.js.map +1 -0
  112. package/dist/frontend-actions/generators/ai-sidepane.generator.d.ts +1 -0
  113. package/dist/frontend-actions/generators/ai-sidepane.generator.js +98 -0
  114. package/dist/frontend-actions/generators/ai-sidepane.generator.js.map +1 -0
  115. package/dist/frontend-actions/generators/base-global-actions.generator.d.ts +1 -0
  116. package/dist/frontend-actions/generators/base-global-actions.generator.js +405 -0
  117. package/dist/frontend-actions/generators/base-global-actions.generator.js.map +1 -0
  118. package/dist/frontend-actions/generators/command-palette-action.generator.d.ts +1 -0
  119. package/dist/frontend-actions/generators/command-palette-action.generator.js +87 -0
  120. package/dist/frontend-actions/generators/command-palette-action.generator.js.map +1 -0
  121. package/dist/frontend-actions/generators/command-palette-store.generator.d.ts +1 -0
  122. package/dist/frontend-actions/generators/command-palette-store.generator.js +288 -0
  123. package/dist/frontend-actions/generators/command-palette-store.generator.js.map +1 -0
  124. package/dist/frontend-actions/generators/command-palette.generator.d.ts +5 -0
  125. package/dist/frontend-actions/generators/command-palette.generator.js +332 -0
  126. package/dist/frontend-actions/generators/command-palette.generator.js.map +1 -0
  127. package/dist/frontend-actions/generators/filter-utils.generator.d.ts +1 -0
  128. package/dist/frontend-actions/generators/filter-utils.generator.js +50 -0
  129. package/dist/frontend-actions/generators/filter-utils.generator.js.map +1 -0
  130. package/dist/frontend-actions/generators/sidepanel-toggle.generator.d.ts +1 -0
  131. package/dist/frontend-actions/generators/sidepanel-toggle.generator.js +37 -0
  132. package/dist/frontend-actions/generators/sidepanel-toggle.generator.js.map +1 -0
  133. package/dist/frontend-actions/index.d.ts +4 -0
  134. package/dist/frontend-actions/index.js +40 -0
  135. package/dist/frontend-actions/index.js.map +1 -0
  136. package/dist/frontend-admin/admin.generator.d.ts +5 -1
  137. package/dist/frontend-admin/admin.generator.js +36 -1
  138. package/dist/frontend-admin/admin.generator.js.map +1 -1
  139. package/dist/frontend-admin/generators/admin-global-actions.generator.d.ts +4 -0
  140. package/dist/frontend-admin/generators/admin-global-actions.generator.js +230 -0
  141. package/dist/frontend-admin/generators/admin-global-actions.generator.js.map +1 -0
  142. package/dist/frontend-admin/generators/admin-overview-page.generator.js +21 -1
  143. package/dist/frontend-admin/generators/admin-overview-page.generator.js.map +1 -1
  144. package/dist/frontend-admin/generators/admin-sidebar.generator.js +20 -0
  145. package/dist/frontend-admin/generators/admin-sidebar.generator.js.map +1 -1
  146. package/dist/frontend-admin/generators/detail-sidebar.generator.js +44 -32
  147. package/dist/frontend-admin/generators/detail-sidebar.generator.js.map +1 -1
  148. package/dist/frontend-admin/generators/excel-io-page.generator.d.ts +4 -0
  149. package/dist/frontend-admin/generators/excel-io-page.generator.js +258 -0
  150. package/dist/frontend-admin/generators/excel-io-page.generator.js.map +1 -0
  151. package/dist/frontend-admin/generators/import-review-page-result-stage.generator.d.ts +1 -0
  152. package/dist/frontend-admin/generators/import-review-page-result-stage.generator.js +104 -0
  153. package/dist/frontend-admin/generators/import-review-page-result-stage.generator.js.map +1 -0
  154. package/dist/frontend-admin/generators/import-review-page-review-stage.generator.d.ts +1 -0
  155. package/dist/frontend-admin/generators/import-review-page-review-stage.generator.js +1031 -0
  156. package/dist/frontend-admin/generators/import-review-page-review-stage.generator.js.map +1 -0
  157. package/dist/frontend-admin/generators/import-review-page-upload-stage.generator.d.ts +1 -0
  158. package/dist/frontend-admin/generators/import-review-page-upload-stage.generator.js +77 -0
  159. package/dist/frontend-admin/generators/import-review-page-upload-stage.generator.js.map +1 -0
  160. package/dist/frontend-admin/generators/import-review-page.generator.d.ts +7 -0
  161. package/dist/frontend-admin/generators/import-review-page.generator.js +180 -0
  162. package/dist/frontend-admin/generators/import-review-page.generator.js.map +1 -0
  163. package/dist/frontend-admin/generators/model-admin-page.generator.js +198 -60
  164. package/dist/frontend-admin/generators/model-admin-page.generator.js.map +1 -1
  165. package/dist/frontend-admin/utils.d.ts +1 -0
  166. package/dist/frontend-admin/utils.js +26 -33
  167. package/dist/frontend-admin/utils.js.map +1 -1
  168. package/dist/frontend-core/frontend.generator.js +1 -2
  169. package/dist/frontend-core/frontend.generator.js.map +1 -1
  170. package/dist/frontend-core/generators/tsconfig.generator.js +1 -0
  171. package/dist/frontend-core/generators/tsconfig.generator.js.map +1 -1
  172. package/dist/frontend-core/template/.env.example +3 -0
  173. package/dist/frontend-core/template/src/components/admin/excel-io-actions.tsx +64 -0
  174. package/dist/frontend-core/template/src/components/admin/table-view-panel.tsx +41 -3
  175. package/dist/frontend-core/template/src/components/ui/color-mode-toggle/color-mode-toggle.tsx +1 -1
  176. package/dist/frontend-core/template/src/hooks/use-excel-io.ts +137 -0
  177. package/dist/frontend-core/template/src/hooks/use-import-review.ts +143 -0
  178. package/dist/frontend-core/template/src/lib/color.ts +6 -3
  179. package/dist/frontend-core/template/src/lib/config.ts +3 -1
  180. package/dist/frontend-core/template/src/lib/excel-download.ts +28 -0
  181. package/dist/frontend-core/types/hook.d.ts +1 -1
  182. package/dist/frontend-tables/generators/model-table.generator.js +21 -13
  183. package/dist/frontend-tables/generators/model-table.generator.js.map +1 -1
  184. package/dist/generators.js +6 -0
  185. package/dist/generators.js.map +1 -1
  186. package/dist/index.d.ts +3 -0
  187. package/dist/index.js +11 -2
  188. package/dist/index.js.map +1 -1
  189. package/dist/seed-data/seed-data.generator.d.ts +3 -0
  190. package/dist/seed-data/seed-data.generator.js +45 -1
  191. package/dist/seed-data/seed-data.generator.js.map +1 -1
  192. package/dist/types/template/ai.types.ts +34 -0
  193. package/dist/types/types.generator.js +1 -0
  194. package/dist/types/types.generator.js.map +1 -1
  195. package/package.json +4 -4
@@ -0,0 +1,288 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateCommandPaletteStore = generateCommandPaletteStore;
4
+ function generateCommandPaletteStore() {
5
+ return `import { useMemo, useSyncExternalStore } from 'react'
6
+
7
+ import { CommandPaletteAction, CommandPaletteActionPage, CommandPaletteActionResult } from './command-palette-action'
8
+
9
+ type GroupedActions = {
10
+ group: string
11
+ actions: CommandPaletteAction[]
12
+ }
13
+
14
+ type CommandPaletteState = {
15
+ page: CommandPaletteActionPage
16
+ componentActions: CommandPaletteAction[]
17
+ globalActions: CommandPaletteAction[]
18
+ running: boolean
19
+ search: string
20
+ globalRenderer: ((component: React.FC | null) => void) | null
21
+ }
22
+
23
+ type CommandPaletteActions = {
24
+ find: (key: string) => CommandPaletteAction | undefined
25
+ back: () => void
26
+ reset: () => void
27
+ cancel: () => void
28
+ select: (key: string, signal: AbortSignal, query?: string, input?: unknown) => Promise<CommandPaletteActionResult>
29
+ registerPageActions: (page: CommandPaletteActionPage) => void
30
+ deregisterPageActions: () => void
31
+ registerComponentActions: (actions: CommandPaletteAction[]) => void
32
+ deregisterComponentActions: (actions: CommandPaletteAction[]) => void
33
+ registerGlobalActions: (...actions: CommandPaletteAction[]) => void
34
+ registerGlobalRenderer: (render: (component: React.FC | null) => void) => void
35
+ calculateAvailableLLMActions: () => CommandPaletteAction[]
36
+ }
37
+
38
+ type CommandPaletteStore = CommandPaletteState & { actions: CommandPaletteActions }
39
+
40
+ const listeners = new Set<() => void>()
41
+ const rootPage: CommandPaletteActionPage = { actions: [] }
42
+
43
+ const into = (back: CommandPaletteActionPage, page: CommandPaletteActionPage): CommandPaletteActionPage => ({
44
+ ...page,
45
+ back,
46
+ })
47
+
48
+ const subscribe = (listener: () => void) => {
49
+ listeners.add(listener)
50
+ return () => listeners.delete(listener)
51
+ }
52
+
53
+ const notify = () => {
54
+ for (const listener of listeners) {
55
+ listener()
56
+ }
57
+ }
58
+
59
+ const setStore = (update: Partial<CommandPaletteState>) => {
60
+ store = {
61
+ ...store,
62
+ ...update,
63
+ }
64
+ notify()
65
+ }
66
+
67
+ const createActions = (): CommandPaletteActions => ({
68
+ calculateAvailableLLMActions() {
69
+ const { page, componentActions, globalActions } = store
70
+ const isRoot = !page.back
71
+ const isVisibleToLLM = (action: CommandPaletteAction) => action.visibility === 'visible' || action.visibility === 'llm'
72
+ const all = [
73
+ ...page.actions.filter(isVisibleToLLM),
74
+ ...(isRoot ? componentActions.filter(isVisibleToLLM) : []),
75
+ ...globalActions.filter(isVisibleToLLM),
76
+ ]
77
+
78
+ const seen = new Set<string>()
79
+ return all.filter((action) => {
80
+ if (seen.has(action.key)) {
81
+ return false
82
+ }
83
+
84
+ seen.add(action.key)
85
+ return true
86
+ })
87
+ },
88
+
89
+ find(key: string) {
90
+ const { page, componentActions, globalActions } = store
91
+ const isRoot = !page.back
92
+
93
+ return (
94
+ page.actions.find((action) => action.key === key) ??
95
+ (isRoot ? componentActions.find((action) => action.key === key) : undefined) ??
96
+ globalActions.find((action) => action.key === key)
97
+ )
98
+ },
99
+
100
+ back() {
101
+ const { page } = store
102
+ if (page.back) {
103
+ setStore({ page: page.back })
104
+ }
105
+ },
106
+
107
+ reset() {
108
+ let next = store.page
109
+
110
+ while (next.back) {
111
+ next = next.back
112
+ }
113
+
114
+ setStore({ page: next })
115
+ },
116
+
117
+ cancel() {
118
+ const { globalRenderer } = store
119
+ globalRenderer?.(null)
120
+ setStore({ running: false })
121
+ },
122
+
123
+ async select(key, signal, query = '', input = undefined) {
124
+ const { page, componentActions, globalActions, globalRenderer, running: wasRunning } = store
125
+ const isRoot = !page.back
126
+
127
+ const action =
128
+ page.actions.find((candidate) => candidate.key === key) ??
129
+ (isRoot ? componentActions.find((candidate) => candidate.key === key) : undefined) ??
130
+ globalActions.find((candidate) => candidate.key === key)
131
+
132
+ if (!action) {
133
+ return { kind: 'close' }
134
+ }
135
+
136
+ setStore({ running: true })
137
+
138
+ try {
139
+ signal.throwIfAborted()
140
+ const result = await action.run(query, input, signal, globalRenderer ?? (() => null))
141
+
142
+ if (result.kind === 'page') {
143
+ setStore({ page: into(page, result) })
144
+ }
145
+
146
+ return result
147
+ } finally {
148
+ globalRenderer?.(null)
149
+ setStore({ running: wasRunning })
150
+ }
151
+ },
152
+
153
+ registerPageActions(page) {
154
+ setStore({ page })
155
+ },
156
+
157
+ deregisterPageActions() {
158
+ setStore({ page: rootPage })
159
+ },
160
+
161
+ registerComponentActions(actions) {
162
+ const incoming = new Set(actions.map((action) => action.key))
163
+ const componentActions = [...store.componentActions.filter((action) => !incoming.has(action.key)), ...actions]
164
+ setStore({ componentActions })
165
+ },
166
+
167
+ deregisterComponentActions(actions) {
168
+ const toRemove = new Set(actions.map((action) => action.key))
169
+ setStore({ componentActions: store.componentActions.filter((action) => !toRemove.has(action.key)) })
170
+ },
171
+
172
+ registerGlobalActions(...actions) {
173
+ const incoming = new Set(actions.map((action) => action.key))
174
+ const globalActions = [...store.globalActions.filter((action) => !incoming.has(action.key)), ...actions]
175
+ setStore({ globalActions })
176
+ },
177
+
178
+ registerGlobalRenderer(render) {
179
+ setStore({ globalRenderer: render })
180
+ },
181
+ })
182
+
183
+ let store: CommandPaletteStore = {
184
+ page: rootPage,
185
+ componentActions: [],
186
+ globalActions: [],
187
+ running: false,
188
+ search: '',
189
+ globalRenderer: null,
190
+ actions: {} as CommandPaletteActions,
191
+ }
192
+ store.actions = createActions()
193
+
194
+ export const useCommandPaletteState = <T>(selector: (state: CommandPaletteState) => T): T =>
195
+ useSyncExternalStore(subscribe, () => selector(store), () => selector(store))
196
+
197
+ export const useCommandPaletteActions = (): CommandPaletteActions =>
198
+ useSyncExternalStore(subscribe, () => store.actions, () => store.actions)
199
+
200
+ export const useCommandPaletteAvailableActions = (query: string): GroupedActions[] => {
201
+ const page = useCommandPaletteState((state) => state.page)
202
+ const componentActions = useCommandPaletteState((state) => state.componentActions)
203
+ const globalActions = useCommandPaletteState((state) => state.globalActions)
204
+
205
+ return useMemo(
206
+ () => calculateAvailableActions({ page, componentActions, globalActions, query }),
207
+ [page, componentActions, globalActions, query],
208
+ )
209
+ }
210
+
211
+ const calculateAvailableActions = ({
212
+ page,
213
+ componentActions,
214
+ globalActions,
215
+ query,
216
+ }: {
217
+ page: CommandPaletteActionPage
218
+ componentActions: CommandPaletteAction[]
219
+ globalActions: CommandPaletteAction[]
220
+ query: string
221
+ }): GroupedActions[] => {
222
+ const hasQuery = query.trim().length > 0
223
+ const isRoot = !page.back
224
+
225
+ const canBeShownToUser = (action: CommandPaletteAction) => action.visibility === 'visible' || action.visibility === 'user'
226
+
227
+ const actionByGroup = new Map<string, CommandPaletteAction[]>()
228
+ const ungrouped: CommandPaletteAction[] = []
229
+ const seen = new Set<string>()
230
+
231
+ for (const action of [...page.actions, ...(isRoot ? componentActions : [])]) {
232
+ if (!canBeShownToUser(action)) {
233
+ continue
234
+ }
235
+
236
+ if (seen.has(action.key)) {
237
+ continue
238
+ }
239
+
240
+ if (action.group) {
241
+ const existing = actionByGroup.get(action.group) ?? []
242
+ actionByGroup.set(action.group, [...existing, action])
243
+ } else {
244
+ ungrouped.push(action)
245
+ }
246
+
247
+ seen.add(action.key)
248
+ }
249
+
250
+ const result: GroupedActions[] = []
251
+
252
+ if (isRoot) {
253
+ const filteredGlobal = globalActions.filter((action) => canBeShownToUser(action) && !seen.has(action.key))
254
+ if (filteredGlobal.length > 0) {
255
+ result.push({ group: 'Global actions', actions: filteredGlobal })
256
+ }
257
+ }
258
+
259
+ if (ungrouped.length > 0) {
260
+ result.push({ group: 'On this page', actions: ungrouped })
261
+ }
262
+
263
+ for (const [group, actions] of actionByGroup.entries()) {
264
+ result.push({ group, actions })
265
+ }
266
+
267
+ if (!hasQuery) {
268
+ return result
269
+ }
270
+
271
+ const terms = query
272
+ .toLowerCase()
273
+ .split(/\\s+/)
274
+ .map((term) => term.trim())
275
+ .filter(Boolean)
276
+
277
+ const matches = (action: CommandPaletteAction) => {
278
+ const text = [action.label, ...(action.keywords ?? [])].join(' ').toLowerCase()
279
+ return terms.every((term) => text.includes(term))
280
+ }
281
+
282
+ return result
283
+ .map((group) => ({ ...group, actions: group.actions.filter(matches) }))
284
+ .filter((group) => group.actions.length > 0)
285
+ }
286
+ `;
287
+ }
288
+ //# sourceMappingURL=command-palette-store.generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-palette-store.generator.js","sourceRoot":"","sources":["../../../src/frontend-actions/generators/command-palette-store.generator.ts"],"names":[],"mappings":";;AAAA,kEA2RC;AA3RD,SAAgB,2BAA2B;IACzC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyRR,CAAA;AACD,CAAC"}
@@ -0,0 +1,5 @@
1
+ import * as Generator from '@postxl/generator';
2
+ import { WithFrontendActions } from '../actions.generator';
3
+ export declare function generateCommandPalette({ context }: {
4
+ context: WithFrontendActions<Generator.Context>;
5
+ }): string;
@@ -0,0 +1,332 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.generateCommandPalette = generateCommandPalette;
37
+ const Generator = __importStar(require("@postxl/generator"));
38
+ function generateCommandPalette({ context }) {
39
+ const imports = Generator.ImportGenerator.from(Generator.toFilePath('./command-palette.tsx'))
40
+ .addImport({
41
+ from: Generator.toPackageName('react'),
42
+ items: [
43
+ Generator.toClassName('Component'),
44
+ Generator.toTypeName('ErrorInfo'),
45
+ Generator.toTypeName('PropsWithChildren'),
46
+ Generator.toFunctionName('useCallback'),
47
+ Generator.toFunctionName('useDeferredValue'),
48
+ Generator.toFunctionName('useEffect'),
49
+ Generator.toFunctionName('useMemo'),
50
+ Generator.toFunctionName('useRef'),
51
+ Generator.toFunctionName('useState'),
52
+ ],
53
+ })
54
+ .addImport({
55
+ from: Generator.toPackageName('@postxl/ui-components'),
56
+ items: [
57
+ Generator.toFunctionName('CommandDialog'),
58
+ Generator.toFunctionName('CommandGroup'),
59
+ Generator.toFunctionName('CommandInput'),
60
+ Generator.toFunctionName('CommandItem'),
61
+ Generator.toFunctionName('CommandList'),
62
+ ],
63
+ })
64
+ .addImport({ from: Generator.toBackendModuleLocation('@lib/router'), items: [Generator.toConstantName('router')] });
65
+ for (const hook of context.frontendActions.globalActionHooks) {
66
+ imports.add(hook);
67
+ }
68
+ const hookCalls = context.frontendActions.globalActionHooks.map((hook) => ` ${hook.name}()`).join('\n');
69
+ return `
70
+ ${imports.generate()}
71
+
72
+ import {
73
+ useCommandPaletteActions,
74
+ useCommandPaletteAvailableActions,
75
+ useCommandPaletteState,
76
+ } from './command-palette-store'
77
+
78
+ type CommandPaletteErrorBoundaryState = {
79
+ hasError: boolean
80
+ }
81
+
82
+ class CommandPaletteErrorBoundary extends Component<PropsWithChildren, CommandPaletteErrorBoundaryState> {
83
+ public constructor(props: PropsWithChildren) {
84
+ super(props)
85
+ this.state = { hasError: false }
86
+ }
87
+
88
+ public static getDerivedStateFromError(): CommandPaletteErrorBoundaryState {
89
+ return { hasError: true }
90
+ }
91
+
92
+ public componentDidCatch(error: unknown, info: ErrorInfo) {
93
+ console.error('CommandPalette rendering failed:', error, info)
94
+ }
95
+
96
+ public render() {
97
+ if (this.state.hasError) {
98
+ return null
99
+ }
100
+
101
+ return this.props.children
102
+ }
103
+ }
104
+
105
+ export function CommandPalette() {
106
+ return (
107
+ <CommandPaletteErrorBoundary>
108
+ <CommandPaletteInner />
109
+ </CommandPaletteErrorBoundary>
110
+ )
111
+ }
112
+
113
+ function CommandPaletteInner() {
114
+ const { find, cancel, registerGlobalRenderer, deregisterPageActions } = useCommandPaletteActions()
115
+ const isRunning = useCommandPaletteState((state) => state.running)
116
+ const {
117
+ mode,
118
+ open,
119
+ value,
120
+ inputRef,
121
+ handleKeydown,
122
+ handleOpenChange: onOpenChange,
123
+ handleSelect,
124
+ handleValueChange,
125
+ } = useCommandPaletteInput()
126
+
127
+ const deferredValue = useDeferredValue(value)
128
+ const availableActions = useCommandPaletteAvailableActions(deferredValue)
129
+
130
+ ${hookCalls}
131
+
132
+ const suggestions = useMemo(() => {
133
+ if (mode.value === 'search') {
134
+ return []
135
+ }
136
+
137
+ return find(mode.key)?.suggestions ?? []
138
+ }, [mode, find])
139
+
140
+ const [CustomContent, setCustomContent] = useState<React.FC | null>(null)
141
+
142
+ const handleOpenChange = useCallback(
143
+ (isOpen: boolean) => {
144
+ if (!isOpen) {
145
+ cancel()
146
+ setCustomContent(null)
147
+ }
148
+
149
+ onOpenChange(isOpen)
150
+ },
151
+ [cancel, onOpenChange],
152
+ )
153
+
154
+ useEffect(() => {
155
+ registerGlobalRenderer((component) => setCustomContent(() => component))
156
+ }, [registerGlobalRenderer])
157
+
158
+ useEffect(() => {
159
+ const down = (event: KeyboardEvent) => {
160
+ if (event.key.toLowerCase() === 'k' && (event.metaKey || event.ctrlKey)) {
161
+ event.preventDefault()
162
+ handleOpenChange(true)
163
+ }
164
+
165
+ handleKeydown(event)
166
+ }
167
+
168
+ document.addEventListener('keydown', down)
169
+ return () => document.removeEventListener('keydown', down)
170
+ }, [handleKeydown, handleOpenChange])
171
+
172
+ useEffect(() => {
173
+ return router.subscribe('onBeforeRouteMount', () => {
174
+ deregisterPageActions()
175
+ })
176
+ }, [deregisterPageActions])
177
+
178
+ return (
179
+ <CommandDialog open={open} onOpenChange={handleOpenChange}>
180
+ <CommandInput
181
+ ref={inputRef}
182
+ value={value}
183
+ onValueChange={handleValueChange}
184
+ placeholder={mode.value === 'search' ? 'Type a command or search...' : 'Enter value...'}
185
+ />
186
+
187
+ {CustomContent ? (
188
+ <CustomContent />
189
+ ) : (
190
+ <CommandList>
191
+ {mode.value === 'input' &&
192
+ suggestions.map((suggestion) => (
193
+ <CommandItem key={suggestion} value={suggestion} onSelect={() => handleSelect(suggestion, 'input')}>
194
+ {suggestion}
195
+ </CommandItem>
196
+ ))}
197
+
198
+ {availableActions.map(({ group, actions }) => (
199
+ <CommandGroup key={group} heading={group}>
200
+ {actions.map((action) => (
201
+ <CommandItem
202
+ key={action.key}
203
+ value={action.key}
204
+ keywords={action.keywords}
205
+ onSelect={() => handleSelect(action.key, action.kind)}
206
+ >
207
+ {action.icon}
208
+ {action.label}
209
+ </CommandItem>
210
+ ))}
211
+ </CommandGroup>
212
+ ))}
213
+ </CommandList>
214
+ )}
215
+
216
+ {isRunning && <div className="px-3 py-2 text-sm text-muted-foreground">Running action...</div>}
217
+ </CommandDialog>
218
+ )
219
+ }
220
+
221
+ const useCommandPaletteInput = () => {
222
+ const { select, back, reset } = useCommandPaletteActions()
223
+
224
+ const didSelect = useRef(false)
225
+ const inputRef = useRef<HTMLInputElement | null>(null)
226
+ const abortRef = useRef<AbortController | null>(null)
227
+
228
+ const [open, setOpen] = useState(false)
229
+ const [value, setValue] = useState('')
230
+ const [mode, setMode] = useState<{ value: 'search' } | { value: 'input'; key: string }>({ value: 'search' })
231
+
232
+ const handleOpenChange = useCallback(
233
+ (isOpen: boolean) => {
234
+ setOpen(isOpen)
235
+
236
+ if (!isOpen) {
237
+ setValue('')
238
+ setMode({ value: 'search' })
239
+ reset()
240
+ abortRef.current?.abort()
241
+ }
242
+
243
+ if (isOpen) {
244
+ setTimeout(() => inputRef.current?.focus(), 75)
245
+ }
246
+ },
247
+ [reset],
248
+ )
249
+
250
+ const runAction = useCallback(
251
+ async (key: string, query = '', input: unknown = undefined) => {
252
+ abortRef.current = new AbortController()
253
+ const result = await select(key, abortRef.current.signal, query, input)
254
+ handleOpenChange(result.kind !== 'close')
255
+ setMode({ value: 'search' })
256
+ return result
257
+ },
258
+ [handleOpenChange, select],
259
+ )
260
+
261
+ const handleKeydown = useCallback(
262
+ (event: KeyboardEvent) => {
263
+ if (!open) {
264
+ return
265
+ }
266
+
267
+ if (event.key === 'Backspace' && value === '') {
268
+ if (mode.value === 'input') {
269
+ setMode({ value: 'search' })
270
+ return
271
+ }
272
+
273
+ back()
274
+ return
275
+ }
276
+
277
+ if (event.key === 'Escape') {
278
+ handleOpenChange(false)
279
+ return
280
+ }
281
+
282
+ if (event.key === 'Enter') {
283
+ event.preventDefault()
284
+
285
+ if (didSelect.current) {
286
+ didSelect.current = false
287
+ return
288
+ }
289
+
290
+ if (mode.value === 'input') {
291
+ void runAction(mode.key, value, { query: value })
292
+ return
293
+ }
294
+ }
295
+ },
296
+ [open, value, mode, back, handleOpenChange, runAction],
297
+ )
298
+
299
+ const handleSelect = useCallback(
300
+ (key: string, kind: 'command' | 'input') => {
301
+ didSelect.current = true
302
+
303
+ if (mode.value === 'search') {
304
+ if (kind === 'input') {
305
+ setValue('')
306
+ setMode({ value: 'input', key })
307
+ return
308
+ }
309
+
310
+ void runAction(key)
311
+ return
312
+ }
313
+
314
+ void runAction(mode.key, key, { query: key })
315
+ },
316
+ [mode, runAction],
317
+ )
318
+
319
+ return {
320
+ mode,
321
+ open,
322
+ value,
323
+ inputRef,
324
+ handleOpenChange,
325
+ handleKeydown,
326
+ handleSelect,
327
+ handleValueChange: setValue,
328
+ }
329
+ }
330
+ `;
331
+ }
332
+ //# sourceMappingURL=command-palette.generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-palette.generator.js","sourceRoot":"","sources":["../../../src/frontend-actions/generators/command-palette.generator.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIA,wDAwSC;AA5SD,6DAA8C;AAI9C,SAAgB,sBAAsB,CAAC,EAAE,OAAO,EAAuD;IACrG,MAAM,OAAO,GAAG,SAAS,CAAC,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,uBAAuB,CAAC,CAAC;SAC1F,SAAS,CAAC;QACT,IAAI,EAAE,SAAS,CAAC,aAAa,CAAC,OAAO,CAAC;QACtC,KAAK,EAAE;YACL,SAAS,CAAC,WAAW,CAAC,WAAW,CAAC;YAClC,SAAS,CAAC,UAAU,CAAC,WAAW,CAAC;YACjC,SAAS,CAAC,UAAU,CAAC,mBAAmB,CAAC;YACzC,SAAS,CAAC,cAAc,CAAC,aAAa,CAAC;YACvC,SAAS,CAAC,cAAc,CAAC,kBAAkB,CAAC;YAC5C,SAAS,CAAC,cAAc,CAAC,WAAW,CAAC;YACrC,SAAS,CAAC,cAAc,CAAC,SAAS,CAAC;YACnC,SAAS,CAAC,cAAc,CAAC,QAAQ,CAAC;YAClC,SAAS,CAAC,cAAc,CAAC,UAAU,CAAC;SACrC;KACF,CAAC;SACD,SAAS,CAAC;QACT,IAAI,EAAE,SAAS,CAAC,aAAa,CAAC,uBAAuB,CAAC;QACtD,KAAK,EAAE;YACL,SAAS,CAAC,cAAc,CAAC,eAAe,CAAC;YACzC,SAAS,CAAC,cAAc,CAAC,cAAc,CAAC;YACxC,SAAS,CAAC,cAAc,CAAC,cAAc,CAAC;YACxC,SAAS,CAAC,cAAc,CAAC,aAAa,CAAC;YACvC,SAAS,CAAC,cAAc,CAAC,aAAa,CAAC;SACxC;KACF,CAAC;SACD,SAAS,CAAC,EAAE,IAAI,EAAE,SAAS,CAAC,uBAAuB,CAAC,aAAa,CAAC,EAAE,KAAK,EAAE,CAAC,SAAS,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAA;IAErH,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,eAAe,CAAC,iBAAiB,EAAE,CAAC;QAC7D,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IACnB,CAAC;IAED,MAAM,SAAS,GAAG,OAAO,CAAC,eAAe,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAExG,OAAO;EACP,OAAO,CAAC,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4DlB,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwMV,CAAA;AACD,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function generateFilterUtils(): string;
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateFilterUtils = generateFilterUtils;
4
+ function generateFilterUtils() {
5
+ return `import { z } from 'zod'
6
+
7
+ export const stringFilterInputSchema = z.object({
8
+ values: z.array(z.string()).optional(),
9
+ contains: z.string().optional(),
10
+ startsWith: z.string().optional(),
11
+ endsWith: z.string().optional(),
12
+ exclude: z.string().optional(),
13
+ })
14
+
15
+ export const numberFilterInputSchema = z.object({
16
+ values: z.array(z.number()).optional(),
17
+ min: z.number().optional(),
18
+ max: z.number().optional(),
19
+ })
20
+
21
+ export const dateFilterInputSchema = z.object({
22
+ values: z.array(z.string()).optional(),
23
+ start: z.string().optional(),
24
+ end: z.string().optional(),
25
+ })
26
+
27
+ export const booleanFilterInputSchema = z.object({
28
+ values: z.array(z.boolean()).optional(),
29
+ })
30
+
31
+ export const parseBooleanQuery = (query: string): boolean[] | undefined => {
32
+ const normalized = query.trim().toLowerCase()
33
+ if (normalized === 'true') {
34
+ return [true]
35
+ }
36
+ if (normalized === 'false') {
37
+ return [false]
38
+ }
39
+ return undefined
40
+ }
41
+
42
+ export const toFilterActionLabel = (value: string): string =>
43
+ value
44
+ .replaceAll(/([A-Z])([A-Z][a-z])/g, '$1 $2')
45
+ .replaceAll(/([a-z])([A-Z])/g, '$1 $2')
46
+ .replaceAll(/[-_]+/g, ' ')
47
+ .replace(/^./, (char) => char.toUpperCase())
48
+ `;
49
+ }
50
+ //# sourceMappingURL=filter-utils.generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filter-utils.generator.js","sourceRoot":"","sources":["../../../src/frontend-actions/generators/filter-utils.generator.ts"],"names":[],"mappings":";;AAAA,kDA6CC;AA7CD,SAAgB,mBAAmB;IACjC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2CR,CAAA;AACD,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function generateSidepanelToggle(): string;