@conduction/nextcloud-vue 0.1.0-beta.1 → 0.1.0-beta.11

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 (208) hide show
  1. package/README.md +226 -0
  2. package/css/index.css +5 -0
  3. package/dist/nextcloud-vue.cjs.js +79416 -7715
  4. package/dist/nextcloud-vue.cjs.js.map +1 -1
  5. package/dist/nextcloud-vue.css +3583 -504
  6. package/dist/nextcloud-vue.esm.js +79343 -7692
  7. package/dist/nextcloud-vue.esm.js.map +1 -1
  8. package/l10n/en.json +164 -0
  9. package/l10n/nl.json +164 -0
  10. package/package.json +104 -63
  11. package/src/components/CnActionsBar/CnActionsBar.vue +254 -0
  12. package/src/components/CnActionsBar/index.js +1 -0
  13. package/src/components/CnAdvancedFormDialog/CnAdvancedFormDialog.vue +570 -0
  14. package/src/components/CnAdvancedFormDialog/CnDataTab.vue +217 -0
  15. package/src/components/CnAdvancedFormDialog/CnMetadataTab.vue +121 -0
  16. package/src/components/CnAdvancedFormDialog/CnPropertiesTab.vue +422 -0
  17. package/src/components/CnAdvancedFormDialog/CnPropertyValueCell.vue +247 -0
  18. package/src/components/CnAdvancedFormDialog/index.js +1 -0
  19. package/src/components/CnCard/CnCard.vue +415 -0
  20. package/src/components/CnCard/index.js +1 -0
  21. package/src/components/CnCardGrid/CnCardGrid.vue +156 -152
  22. package/src/components/CnCardGrid/index.js +1 -1
  23. package/src/components/CnCellRenderer/CnCellRenderer.vue +132 -132
  24. package/src/components/CnCellRenderer/index.js +1 -1
  25. package/src/components/CnChartWidget/CnChartWidget.vue +346 -0
  26. package/src/components/CnChartWidget/index.js +1 -0
  27. package/src/components/CnConfigurationCard/CnConfigurationCard.vue +77 -77
  28. package/src/components/CnConfigurationCard/index.js +1 -1
  29. package/src/components/CnContextMenu/CnContextMenu.vue +142 -0
  30. package/src/components/CnContextMenu/index.js +1 -0
  31. package/src/components/CnCopyDialog/CnCopyDialog.vue +266 -0
  32. package/src/components/CnCopyDialog/index.js +1 -0
  33. package/src/components/CnDashboardGrid/CnDashboardGrid.vue +229 -0
  34. package/src/components/CnDashboardGrid/index.js +1 -0
  35. package/src/components/CnDashboardPage/CnDashboardPage.vue +397 -0
  36. package/src/components/CnDashboardPage/index.js +1 -0
  37. package/src/components/CnDataTable/CnDataTable.vue +362 -354
  38. package/src/components/CnDataTable/index.js +1 -1
  39. package/src/components/CnDeleteDialog/CnDeleteDialog.vue +177 -0
  40. package/src/components/CnDeleteDialog/index.js +1 -0
  41. package/src/components/CnDetailCard/CnDetailCard.vue +225 -0
  42. package/src/components/CnDetailCard/index.js +1 -0
  43. package/src/components/CnDetailGrid/CnDetailGrid.vue +256 -0
  44. package/src/components/CnDetailGrid/index.js +1 -0
  45. package/src/components/CnDetailPage/CnDetailPage.vue +432 -0
  46. package/src/components/CnDetailPage/index.js +1 -0
  47. package/src/components/CnFacetSidebar/CnFacetSidebar.vue +234 -223
  48. package/src/components/CnFacetSidebar/index.js +1 -1
  49. package/src/components/CnFilterBar/CnFilterBar.vue +153 -152
  50. package/src/components/CnFilterBar/index.js +1 -1
  51. package/src/components/CnFormDialog/CnFormDialog.vue +1047 -0
  52. package/src/components/CnFormDialog/index.js +1 -0
  53. package/src/components/CnIcon/CnIcon.vue +89 -0
  54. package/src/components/CnIcon/index.js +1 -0
  55. package/src/components/CnIndexPage/CnIndexPage.vue +980 -682
  56. package/src/components/CnIndexPage/index.js +1 -1
  57. package/src/components/CnIndexSidebar/CnIndexSidebar.vue +536 -0
  58. package/src/components/CnIndexSidebar/index.js +1 -0
  59. package/src/components/CnInfoWidget/CnInfoWidget.vue +219 -0
  60. package/src/components/CnInfoWidget/index.js +1 -0
  61. package/src/components/CnItemCard/CnItemCard.vue +134 -0
  62. package/src/components/CnItemCard/index.js +1 -0
  63. package/src/components/CnJsonViewer/CnJsonViewer.vue +312 -0
  64. package/src/components/CnJsonViewer/index.js +1 -0
  65. package/src/components/CnKpiGrid/CnKpiGrid.vue +93 -89
  66. package/src/components/CnKpiGrid/index.js +1 -1
  67. package/src/components/CnMassActionBar/CnMassActionBar.vue +161 -160
  68. package/src/components/CnMassActionBar/index.js +1 -1
  69. package/src/components/CnMassCopyDialog/CnMassCopyDialog.vue +327 -320
  70. package/src/components/CnMassCopyDialog/index.js +1 -1
  71. package/src/components/CnMassDeleteDialog/CnMassDeleteDialog.vue +245 -238
  72. package/src/components/CnMassDeleteDialog/index.js +1 -1
  73. package/src/components/CnMassExportDialog/CnMassExportDialog.vue +191 -190
  74. package/src/components/CnMassExportDialog/index.js +1 -1
  75. package/src/components/CnMassImportDialog/CnMassImportDialog.vue +494 -491
  76. package/src/components/CnMassImportDialog/index.js +1 -1
  77. package/src/components/CnNoteCard/CnNoteCard.vue +149 -0
  78. package/src/components/CnNoteCard/index.js +1 -0
  79. package/src/components/CnNotesCard/CnNotesCard.vue +416 -0
  80. package/src/components/CnNotesCard/index.js +1 -0
  81. package/src/components/CnObjectCard/CnObjectCard.vue +294 -292
  82. package/src/components/CnObjectCard/index.js +1 -1
  83. package/src/components/CnObjectDataWidget/CnObjectDataWidget.vue +854 -0
  84. package/src/components/CnObjectDataWidget/index.js +1 -0
  85. package/src/components/CnObjectMetadataWidget/CnObjectMetadataWidget.vue +289 -0
  86. package/src/components/CnObjectMetadataWidget/index.js +1 -0
  87. package/src/components/CnObjectSidebar/CnAuditTrailTab.vue +369 -0
  88. package/src/components/CnObjectSidebar/CnFilesTab.vue +287 -0
  89. package/src/components/CnObjectSidebar/CnNotesTab.vue +250 -0
  90. package/src/components/CnObjectSidebar/CnObjectSidebar.vue +255 -0
  91. package/src/components/CnObjectSidebar/CnTagsTab.vue +259 -0
  92. package/src/components/CnObjectSidebar/CnTasksTab.vue +483 -0
  93. package/src/components/CnObjectSidebar/index.js +6 -0
  94. package/src/components/CnPageHeader/CnPageHeader.vue +61 -0
  95. package/src/components/CnPageHeader/index.js +1 -0
  96. package/src/components/CnPagination/CnPagination.vue +253 -252
  97. package/src/components/CnPagination/index.js +1 -1
  98. package/src/components/CnProgressBar/CnProgressBar.vue +262 -0
  99. package/src/components/CnProgressBar/index.js +1 -0
  100. package/src/components/CnRegisterMapping/CnRegisterMapping.vue +793 -0
  101. package/src/components/CnRegisterMapping/index.js +1 -0
  102. package/src/components/CnRowActions/CnRowActions.vue +95 -73
  103. package/src/components/CnRowActions/index.js +1 -1
  104. package/src/components/CnSchemaFormDialog/CnSchemaConfigurationTab.vue +226 -0
  105. package/src/components/CnSchemaFormDialog/CnSchemaFormDialog.vue +788 -0
  106. package/src/components/CnSchemaFormDialog/CnSchemaPropertiesTab.vue +305 -0
  107. package/src/components/CnSchemaFormDialog/CnSchemaPropertyActions.vue +1398 -0
  108. package/src/components/CnSchemaFormDialog/CnSchemaSecurityTab.vue +236 -0
  109. package/src/components/CnSchemaFormDialog/index.js +1 -0
  110. package/src/components/CnSettingsCard/CnSettingsCard.vue +92 -92
  111. package/src/components/CnSettingsCard/index.js +1 -1
  112. package/src/components/CnSettingsSection/CnSettingsSection.vue +267 -266
  113. package/src/components/CnSettingsSection/index.js +1 -1
  114. package/src/components/CnStatsBlock/CnStatsBlock.vue +437 -366
  115. package/src/components/CnStatsBlock/index.js +1 -1
  116. package/src/components/CnStatsPanel/CnStatsPanel.vue +321 -0
  117. package/src/components/CnStatsPanel/index.js +1 -0
  118. package/src/components/CnStatusBadge/CnStatusBadge.vue +90 -77
  119. package/src/components/CnStatusBadge/index.js +1 -1
  120. package/src/components/CnTabbedFormDialog/CnTabbedFormDialog.vue +545 -0
  121. package/src/components/CnTabbedFormDialog/index.js +1 -0
  122. package/src/components/CnTableWidget/CnTableWidget.vue +333 -0
  123. package/src/components/CnTableWidget/index.js +1 -0
  124. package/src/components/CnTasksCard/CnTasksCard.vue +374 -0
  125. package/src/components/CnTasksCard/index.js +1 -0
  126. package/src/components/CnTileWidget/CnTileWidget.vue +159 -0
  127. package/src/components/CnTileWidget/index.js +1 -0
  128. package/src/components/CnTimelineStages/CnTimelineStages.vue +294 -0
  129. package/src/components/CnTimelineStages/index.js +1 -0
  130. package/src/components/CnUserActionMenu/CnUserActionMenu.vue +436 -0
  131. package/src/components/CnUserActionMenu/index.js +1 -0
  132. package/src/components/CnVersionInfoCard/CnVersionInfoCard.vue +313 -312
  133. package/src/components/CnVersionInfoCard/index.js +1 -1
  134. package/src/components/CnWidgetRenderer/CnWidgetRenderer.vue +180 -0
  135. package/src/components/CnWidgetRenderer/index.js +1 -0
  136. package/src/components/CnWidgetWrapper/CnWidgetWrapper.vue +248 -0
  137. package/src/components/CnWidgetWrapper/index.js +1 -0
  138. package/src/components/index.js +57 -25
  139. package/src/composables/index.js +5 -3
  140. package/src/composables/useContextMenu.js +126 -0
  141. package/src/composables/useDashboardView.js +286 -0
  142. package/src/composables/useDetailView.js +290 -132
  143. package/src/composables/useListView.js +364 -153
  144. package/src/composables/useSubResource.js +142 -142
  145. package/src/constants/metadata.js +30 -0
  146. package/src/css/CnSchemaFormDialog.css +546 -0
  147. package/src/css/__sample_nextcloud_tokens.css +110 -0
  148. package/src/css/actions-bar.css +54 -0
  149. package/src/css/badge.css +83 -51
  150. package/src/css/card.css +129 -128
  151. package/src/css/context-menu.css +20 -0
  152. package/src/css/dashboard.css +70 -0
  153. package/src/css/detail-page.css +235 -0
  154. package/src/css/detail.css +68 -68
  155. package/src/css/index-page.css +44 -0
  156. package/src/css/index-sidebar.css +193 -0
  157. package/src/css/index.css +17 -8
  158. package/src/css/layout.css +90 -90
  159. package/src/css/page-header.css +35 -0
  160. package/src/css/pagination.css +72 -72
  161. package/src/css/table.css +142 -143
  162. package/src/css/timeline-stages.css +220 -0
  163. package/src/css/utilities.css +46 -46
  164. package/src/index.js +95 -50
  165. package/src/l10n/index.js +12 -0
  166. package/src/mixins/gridLayout.js +118 -0
  167. package/src/store/createCrudStore.d.ts +350 -0
  168. package/src/store/createCrudStore.js +413 -0
  169. package/src/store/createSubResourcePlugin.js +125 -135
  170. package/src/store/index.js +4 -3
  171. package/src/store/pluginMerge.js +55 -0
  172. package/src/store/plugins/auditTrails.js +357 -17
  173. package/src/store/plugins/files.js +250 -186
  174. package/src/store/plugins/index.js +8 -4
  175. package/src/store/plugins/lifecycle.js +180 -180
  176. package/src/store/plugins/logs.d.ts +22 -0
  177. package/src/store/plugins/logs.js +172 -0
  178. package/src/store/plugins/registerMapping.js +195 -0
  179. package/src/store/plugins/relations.js +68 -68
  180. package/src/store/plugins/search.js +385 -0
  181. package/src/store/plugins/selection.js +104 -0
  182. package/src/store/useObjectStore.js +793 -625
  183. package/src/types/auditTrail.d.ts +32 -32
  184. package/src/types/file.d.ts +23 -23
  185. package/src/types/index.d.ts +67 -35
  186. package/src/types/notification.d.ts +36 -36
  187. package/src/types/object.d.ts +40 -40
  188. package/src/types/organisation.d.ts +41 -41
  189. package/src/types/register.d.ts +25 -25
  190. package/src/types/schema.d.ts +39 -39
  191. package/src/types/shared.d.ts +79 -79
  192. package/src/types/source.d.ts +14 -14
  193. package/src/types/task.d.ts +31 -31
  194. package/src/utils/errors.js +96 -96
  195. package/src/utils/getTheme.js +9 -0
  196. package/src/utils/headers.js +80 -44
  197. package/src/utils/id.js +13 -0
  198. package/src/utils/index.js +4 -3
  199. package/src/utils/schema.js +423 -287
  200. package/src/utils/widgetVisibility.js +162 -0
  201. package/src/components/CnDetailViewLayout/CnDetailViewLayout.vue +0 -88
  202. package/src/components/CnDetailViewLayout/index.js +0 -1
  203. package/src/components/CnEmptyState/CnEmptyState.vue +0 -78
  204. package/src/components/CnEmptyState/index.js +0 -1
  205. package/src/components/CnListViewLayout/CnListViewLayout.vue +0 -80
  206. package/src/components/CnListViewLayout/index.js +0 -1
  207. package/src/components/CnViewModeToggle/CnViewModeToggle.vue +0 -77
  208. package/src/components/CnViewModeToggle/index.js +0 -1
@@ -0,0 +1,350 @@
1
+ /**
2
+ * Hand-written type definitions for `createCrudStore` (implementation is in
3
+ * `createCrudStore.js`). The library ships as JavaScript, but this file gives
4
+ * TypeScript consumers full entity inference, feature-flag gating, and
5
+ * `extend` merging with correct `this` typing.
6
+ *
7
+ * Design notes:
8
+ * - `const Id extends string` / `const F extends Features` preserves literal
9
+ * types so `features: { loading: true }` flows `true` through the
10
+ * conditional types without requiring `as const` at the call site.
11
+ * Requires TypeScript 5.0+.
12
+ * - Entity inference: if `config.entity` is a class constructor, `T` is the
13
+ * instance type. Otherwise `T` falls back to `unknown` unless the caller
14
+ * passes it explicitly via the second overload.
15
+ * - `ThisType<...>` inside `extend.actions` / `extend.getters` makes `this`
16
+ * resolve to the fully-merged store (state + getters + base actions +
17
+ * extended actions), matching Pinia's own runtime semantics.
18
+ * - `Omit<BaseActions<T>, keyof ExtActions>` implements override precedence:
19
+ * an extend action with the same name as a base action replaces it.
20
+ */
21
+
22
+ import type { StoreDefinition, _GettersTree } from 'pinia'
23
+
24
+ // ─────────────────────────────────────────────────────────────────────────────
25
+ // Utility types
26
+ // ─────────────────────────────────────────────────────────────────────────────
27
+
28
+ /**
29
+ * Forces TypeScript to eagerly evaluate an intersection of types into a
30
+ * single flat object shape. Purely a hover/tooltip ergonomics helper —
31
+ * semantically identical to the input.
32
+ *
33
+ * Without this, VSCode's quick-info tooltip shows `StoreDefinition<...,
34
+ * FullState<Source, ...> & ..., ..., MergedActions<...>>` with the aliases
35
+ * left unexpanded, making it hard to see which properties the store has.
36
+ * With this, hover shows `{ item: Source | null; list: Source[]; ... }`
37
+ * directly.
38
+ */
39
+ export type Prettify<T> = { [K in keyof T]: T[K] } & {}
40
+
41
+ /**
42
+ * A class constructor accepting raw data (e.g. `new Source(data)`).
43
+ */
44
+ export type EntityClass<T> = new (data: any) => T
45
+
46
+ /**
47
+ * Extract the instance type from an entity-class config field.
48
+ * Falls back to `unknown` when no class is provided.
49
+ */
50
+ export type InferEntity<E> =
51
+ E extends EntityClass<infer T> ? T :
52
+ E extends null | undefined ? unknown :
53
+ unknown
54
+
55
+ // ─────────────────────────────────────────────────────────────────────────────
56
+ // Feature flags
57
+ // ─────────────────────────────────────────────────────────────────────────────
58
+
59
+ /**
60
+ * Optional behavioral toggles. When a flag is set, the factory adds the
61
+ * corresponding state fields, getters, and actions to the store.
62
+ */
63
+ export interface Features {
64
+ /** Add `loading` / `error` state plus the `isLoading` / `getError` getters. */
65
+ loading?: boolean
66
+ /** Add `viewMode` state, the `getViewMode` getter, and a `setViewMode(mode)` action. */
67
+ viewMode?: boolean
68
+ }
69
+
70
+ export type LoadingState<F> = F extends { loading: true } ? { loading: boolean; error: string | null } : {}
71
+ export type ViewModeState<F> = F extends { viewMode: true } ? { viewMode: string } : {}
72
+
73
+ // Getter trees are declared as `(state) => value` and Pinia exposes them on
74
+ // the store as `.name: value`. We declare them as getter functions so the
75
+ // `StoreDefinition<..., Getters, ...>` return-type mapping kicks in.
76
+ export type LoadingGetters<F> = F extends { loading: true }
77
+ ? {
78
+ isLoading: (state: { loading: boolean }) => boolean
79
+ getError: (state: { error: string | null }) => string | null
80
+ }
81
+ : {}
82
+ export type ViewModeGetters<F> = F extends { viewMode: true }
83
+ ? { getViewMode: (state: { viewMode: string }) => string }
84
+ : {}
85
+
86
+ export type ViewModeActions<F> = F extends { viewMode: true } ? { setViewMode(mode: string): void } : {}
87
+
88
+ // ─────────────────────────────────────────────────────────────────────────────
89
+ // Base state, getters and actions
90
+ // ─────────────────────────────────────────────────────────────────────────────
91
+
92
+ /**
93
+ * State shape every store receives by default, independent of features and
94
+ * extensions. Feature-specific fields (`loading`, `error`, `viewMode`) and
95
+ * anything contributed by `extend.state` / plugins are added on top.
96
+ */
97
+ export interface BaseState<T> {
98
+ /** The currently active/selected item, or `null` when nothing is selected. */
99
+ item: T | null
100
+ /** The full list of items as last returned by `refreshList`. */
101
+ list: T[]
102
+ /** Active filter criteria (merged via `setFilters`). */
103
+ filters: Record<string, unknown>
104
+ /** Current pagination position. `limit` defaults to 20. */
105
+ pagination: { page: number; limit: number }
106
+ /**
107
+ * Internal, runtime-resolved configuration exposed so extend actions and
108
+ * plugins can build URLs, clean fields, or instantiate the entity class
109
+ * without re-reading user config.
110
+ */
111
+ _options: {
112
+ /** The raw endpoint segment supplied to the factory (e.g. `'sources'`). */
113
+ endpoint: string
114
+ /** Fields stripped by `cleanForSave` before POST/PUT. */
115
+ cleanFields: readonly string[]
116
+ /** Fully-qualified base URL for this store's REST endpoint, already `prefixUrl`-normalized. */
117
+ baseApiUrl: string
118
+ /** Entity class constructor, or `null` when the store returns raw data. */
119
+ entity: EntityClass<T> | null
120
+ }
121
+ }
122
+
123
+ /**
124
+ * Actions available on every store regardless of configuration. Extend
125
+ * actions with the same name replace these (see `MergedActions`).
126
+ */
127
+ export interface BaseActions<T> {
128
+ /** Set the active item. Wraps in the configured Entity class when present; pass `null` to clear. */
129
+ setItem(data: T | Partial<T> | null): void
130
+ /** Replace the item list. Maps each entry through the Entity class when configured. */
131
+ setList(data: Array<T | Partial<T>>): void
132
+ /** Set `pagination.page` and `pagination.limit`. `limit` defaults to 20. */
133
+ setPagination(page: number, limit?: number): void
134
+ /** Merge filter key/value pairs into the current `filters` object. */
135
+ setFilters(filters: Record<string, unknown>): void
136
+ /** GET the list endpoint. Optional `search` is appended as `?_search=`; `soft=true` skips the loading toggle. */
137
+ refreshList(search?: string | null, soft?: boolean): Promise<{ response: Response; data: T[] }>
138
+ /** GET `/:id`, set it as the active item, and return the raw response data. */
139
+ getOne(id: string | number): Promise<T>
140
+ /** DELETE `/:id`, refresh the list, and clear the active item. */
141
+ deleteOne(idOrItem: string | number | { id: string | number }): Promise<{ response: Response }>
142
+ /** POST or PUT the item depending on whether it has an `id`, then refresh the list. */
143
+ save(item: Partial<T>): Promise<{ response: Response; data: T }>
144
+ /** Return a copy of `item` with `cleanFields` stripped, suitable for POST/PUT bodies. */
145
+ cleanForSave(item: T | Partial<T>): Partial<T>
146
+ }
147
+
148
+ /**
149
+ * Action merge rule:
150
+ * - Base actions not overridden by the extend block are preserved.
151
+ * - Actions declared in `extend.actions` replace base actions of the same name.
152
+ * - `viewMode` feature action is appended when the flag is set.
153
+ * - Plugin-contributed actions are reachable via the loose index signature
154
+ * on `PluginActionContribution` below (typed as `any`-returning callables).
155
+ */
156
+ export type PluginActionContribution = { [key: string]: (...args: any[]) => any }
157
+
158
+ export type MergedActions<T, ExtActions, F> =
159
+ Omit<BaseActions<T>, keyof ExtActions> & ExtActions & ViewModeActions<F> & PluginActionContribution
160
+
161
+ // ─────────────────────────────────────────────────────────────────────────────
162
+ // Full store shape (state + getters + actions) used inside ThisType<...>
163
+ // ─────────────────────────────────────────────────────────────────────────────
164
+
165
+ // Plugins contribute arbitrary state, getters, and actions at runtime. We spread
166
+ // a loose index signature into the resolved store shape so plugin-contributed
167
+ // members are reachable via dot access without `as any`. The index signature
168
+ // returns `any` (not `unknown`) so callable plugin actions (`store.refreshLogs()`)
169
+ // type-check without an intermediate cast — trade-off is that typos on
170
+ // plugin-contributed members are not caught. Plugins needing strict typing
171
+ // should ship their own `.d.ts` augmenting the specific store.
172
+ export type PluginContribution = { [key: string]: any }
173
+
174
+ export type FullState<T, ExtState, F> =
175
+ BaseState<T> & ExtState & LoadingState<F> & ViewModeState<F> & PluginContribution
176
+
177
+ export type FullGetters<ExtGetters, F> =
178
+ ExtGetters & LoadingGetters<F> & ViewModeGetters<F>
179
+
180
+ export type StoreThis<T, ExtState, ExtGetters, ExtActions, F> =
181
+ FullState<T, ExtState, F> &
182
+ // Getters are callable-free on the Pinia store instance — accessed as properties.
183
+ // We narrow each getter declaration to its return type so `this.myGetter` is typed.
184
+ { [K in keyof ExtGetters]: ExtGetters[K] extends (state: any) => infer R ? R : never } &
185
+ LoadingGetters<F> & ViewModeGetters<F> &
186
+ MergedActions<T, ExtActions, F>
187
+
188
+ // ─────────────────────────────────────────────────────────────────────────────
189
+ // Plugins
190
+ // ─────────────────────────────────────────────────────────────────────────────
191
+
192
+ /**
193
+ * A plugin definition. Merged into the store at creation time:
194
+ * state is spread into store state, getters into getters, actions into actions.
195
+ *
196
+ * Merge precedence: base actions → plugin actions → extend.actions.
197
+ *
198
+ * Plugin-contributed properties are loosely typed on the resulting store
199
+ * (they appear as unknown state / any-returning actions). Consumers needing
200
+ * strict types on plugin output should augment the store's types at the
201
+ * call site, or use a plugin that ships a dedicated `.d.ts` with the shape.
202
+ *
203
+ * If `setup` is provided, it is invoked once per store instance the first
204
+ * time `useStore()` resolves it. Use this to register
205
+ * `store.$onAction` / `store.$subscribe` observers that react to base or
206
+ * other plugin actions without having to override them.
207
+ */
208
+ export interface CrudPlugin {
209
+ /** Unique plugin identifier; used by `clearAllSubResources` and for debugging. */
210
+ name: string
211
+ /** State factory returning the state fields this plugin contributes. */
212
+ state?: () => Record<string, unknown>
213
+ /** Getters this plugin contributes — each receives the store state. */
214
+ getters?: Record<string, (state: any) => unknown>
215
+ /** Actions this plugin contributes. May override a base action with the same name. */
216
+ actions?: Record<string, (...args: any[]) => any>
217
+ /**
218
+ * Optional lifecycle hook run once per store instance, the first time
219
+ * `useStore()` resolves it. Typically used to register
220
+ * `store.$onAction` / `store.$subscribe` subscribers so the plugin can
221
+ * react to base or other-plugin actions without overriding them.
222
+ */
223
+ setup?: (store: any) => void
224
+ }
225
+
226
+ export interface PluginContrib {
227
+ [key: string]: unknown
228
+ }
229
+
230
+ // ─────────────────────────────────────────────────────────────────────────────
231
+ // Config & extend shapes
232
+ // ─────────────────────────────────────────────────────────────────────────────
233
+
234
+ /**
235
+ * Domain-specific additions layered on top of the base store. Merged last,
236
+ * so `extend` can still override anything a plugin contributed.
237
+ */
238
+ export interface ExtendConfig<
239
+ T,
240
+ ExtState extends Record<string, unknown>,
241
+ ExtGetters extends _GettersTree<BaseState<T> & ExtState>,
242
+ ExtActions extends Record<string, (...args: any[]) => any>,
243
+ F extends Features,
244
+ > {
245
+ /** State factory returning extra state properties merged into the store. */
246
+ state?: () => ExtState
247
+ /** Extra getters, or overrides of base/plugin getters with the same name. */
248
+ getters?: ExtGetters & ThisType<StoreThis<T, ExtState, ExtGetters, ExtActions, F>>
249
+ /** Extra actions, or overrides of base/plugin actions with the same name. */
250
+ actions?: ExtActions & ThisType<StoreThis<T, ExtState, ExtGetters, ExtActions, F>>
251
+ }
252
+
253
+ /**
254
+ * Full configuration object accepted by `createCrudStore`. Mirrors the
255
+ * runtime options documented in `createCrudStore.js`.
256
+ */
257
+ export interface CrudConfig<
258
+ T,
259
+ ExtState extends Record<string, unknown>,
260
+ ExtGetters extends _GettersTree<BaseState<T> & ExtState>,
261
+ ExtActions extends Record<string, (...args: any[]) => any>,
262
+ F extends Features,
263
+ Entity = EntityClass<T> | null | undefined,
264
+ > {
265
+ /** API resource path segment appended to `baseUrl` (e.g. `'sources'`). Required. */
266
+ endpoint: string
267
+ /** API base URL before the endpoint. Defaults to `'/apps/openregister/api'`. */
268
+ baseUrl?: string
269
+ /** Entity class constructor used to wrap raw API data; pass `null` for raw data. */
270
+ entity?: Entity
271
+ /** Fields stripped from items before POST/PUT. Defaults to `['id','uuid','created','updated']`. */
272
+ cleanFields?: readonly string[]
273
+ /** Feature flags enabling optional state/getters/actions. See `Features`. */
274
+ features?: F
275
+ /**
276
+ * Custom parser for `refreshList`'s JSON response body. Called with the
277
+ * store as `this`, so it can also perform side-effects (e.g. storing
278
+ * pagination info). Must return an array of items. Default:
279
+ * `(json) => json.results`.
280
+ */
281
+ parseListResponse?: (this: StoreThis<T, ExtState, ExtGetters, ExtActions, F>, json: unknown) => T[] | Array<Partial<T>>
282
+ /**
283
+ * Plugin definitions merged into the store. Same shape as object-store
284
+ * plugins (`{ name, state?, getters?, actions?, setup? }`). Merge order
285
+ * is base → plugins → extend.
286
+ */
287
+ plugins?: readonly CrudPlugin[]
288
+ /** Extra state/getters/actions merged on top of base and plugin contributions. */
289
+ extend?: ExtendConfig<T, ExtState, ExtGetters, ExtActions, F>
290
+ }
291
+
292
+ // ─────────────────────────────────────────────────────────────────────────────
293
+ // The factory — overloaded
294
+ // ─────────────────────────────────────────────────────────────────────────────
295
+
296
+ /**
297
+ * Overload 1 — entity inference.
298
+ *
299
+ * Provide `config.entity` as a class constructor; `T` is inferred as the
300
+ * instance type:
301
+ *
302
+ * ```ts
303
+ * const useSourceStore = createCrudStore('source', {
304
+ * endpoint: 'sources',
305
+ * entity: Source, // T = Source
306
+ * features: { loading: true },
307
+ * })
308
+ * ```
309
+ */
310
+ export function createCrudStore<
311
+ Entity extends EntityClass<any>,
312
+ const Id extends string = string,
313
+ const F extends Features = {},
314
+ ExtState extends Record<string, unknown> = {},
315
+ ExtGetters extends _GettersTree<BaseState<InferEntity<Entity>> & ExtState> = {},
316
+ ExtActions extends Record<string, (...args: any[]) => any> = {},
317
+ >(
318
+ name: Id,
319
+ config: CrudConfig<InferEntity<Entity>, ExtState, ExtGetters, ExtActions, F, Entity>,
320
+ ): StoreDefinition<
321
+ Id,
322
+ Prettify<FullState<InferEntity<Entity>, ExtState, F>>,
323
+ Prettify<FullGetters<ExtGetters, F>>,
324
+ Prettify<MergedActions<InferEntity<Entity>, ExtActions, F>>
325
+ >
326
+
327
+ /**
328
+ * Overload 2 — explicit `T` for raw-data stores (no entity class).
329
+ *
330
+ * ```ts
331
+ * interface LogShape { id: number; message: string }
332
+ * const useLogStore = createCrudStore<'log', LogShape>('log', { endpoint: 'logs' })
333
+ * ```
334
+ */
335
+ export function createCrudStore<
336
+ const Id extends string,
337
+ T,
338
+ const F extends Features = {},
339
+ ExtState extends Record<string, unknown> = {},
340
+ ExtGetters extends _GettersTree<BaseState<T> & ExtState> = {},
341
+ ExtActions extends Record<string, (...args: any[]) => any> = {},
342
+ >(
343
+ name: Id,
344
+ config: CrudConfig<T, ExtState, ExtGetters, ExtActions, F, null | undefined>,
345
+ ): StoreDefinition<
346
+ Id,
347
+ FullState<T, ExtState, F>,
348
+ FullGetters<ExtGetters, F>,
349
+ MergedActions<T, ExtActions, F>
350
+ >