@chelone/core 0.6.0 → 0.7.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 (242) hide show
  1. package/dist/assistant/assistant-session.d.ts +6 -0
  2. package/dist/assistant/assistant-session.js +204 -181
  3. package/dist/assistant/echo-transport.js +26 -29
  4. package/dist/assistant/http-transport.d.ts +10 -0
  5. package/dist/assistant/http-transport.js +98 -0
  6. package/dist/assistant/types.d.ts +1 -7
  7. package/dist/auth/access-control.d.ts +13 -5
  8. package/dist/auth/access-control.js +25 -21
  9. package/dist/auth/auth-options.d.ts +21 -17
  10. package/dist/auth/auth-options.js +80 -48
  11. package/dist/auth/permission-matrix.d.ts +12 -0
  12. package/dist/auth/permission-matrix.js +67 -0
  13. package/dist/auth/types.d.ts +14 -4
  14. package/dist/block-editor/block-document.d.ts +60 -0
  15. package/dist/block-editor/block-document.js +143 -0
  16. package/dist/block-editor/data-blocks.d.ts +63 -0
  17. package/dist/block-editor/data-blocks.js +117 -0
  18. package/dist/chart/chart-data.js +46 -44
  19. package/dist/command-menu/hotkey.js +58 -47
  20. package/dist/command-menu/recents.js +8 -11
  21. package/dist/command-menu/registry.d.ts +9 -5
  22. package/dist/command-menu/registry.js +36 -46
  23. package/dist/controller/calendar-dates.js +82 -113
  24. package/dist/controller/calendar-events.js +93 -88
  25. package/dist/controller/client-list-controller.d.ts +2 -2
  26. package/dist/controller/client-list-controller.js +251 -254
  27. package/dist/controller/data-table-columns.d.ts +2 -0
  28. package/dist/controller/data-table-columns.js +50 -56
  29. package/dist/controller/deep-equal.d.ts +1 -0
  30. package/dist/controller/deep-equal.js +14 -0
  31. package/dist/controller/filter-toggle.js +36 -44
  32. package/dist/controller/in-place-editor.d.ts +42 -0
  33. package/dist/controller/in-place-editor.js +42 -0
  34. package/dist/controller/infinite-list-controller.js +219 -189
  35. package/dist/controller/inspector.d.ts +49 -0
  36. package/dist/controller/inspector.js +64 -0
  37. package/dist/controller/job-monitor.d.ts +3 -4
  38. package/dist/controller/job-monitor.js +37 -47
  39. package/dist/controller/kanban-board.d.ts +2 -3
  40. package/dist/controller/kanban-board.js +43 -24
  41. package/dist/controller/list-controller.d.ts +5 -5
  42. package/dist/controller/list-controller.js +444 -400
  43. package/dist/controller/list-params.js +96 -87
  44. package/dist/controller/pivot-grid.js +89 -95
  45. package/dist/controller/prev-next.d.ts +2 -2
  46. package/dist/controller/prev-next.js +74 -54
  47. package/dist/controller/record-controllers.d.ts +14 -6
  48. package/dist/controller/record-controllers.js +288 -257
  49. package/dist/controller/record-diff.d.ts +21 -0
  50. package/dist/controller/record-diff.js +50 -0
  51. package/dist/controller/record-timeline.js +42 -30
  52. package/dist/controller/record-tree.js +57 -47
  53. package/dist/controller/record-workflow.d.ts +38 -16
  54. package/dist/controller/record-workflow.js +85 -64
  55. package/dist/controller/reference-many-controller.js +198 -192
  56. package/dist/controller/reference-one-controller.d.ts +1 -1
  57. package/dist/controller/reference-one-controller.js +63 -56
  58. package/dist/controller/saved-queries.js +104 -91
  59. package/dist/controller/translate-fallback.js +10 -6
  60. package/dist/csv/export.d.ts +2 -1
  61. package/dist/csv/export.js +43 -40
  62. package/dist/csv/import-controller.js +185 -169
  63. package/dist/csv/match-headers.js +29 -22
  64. package/dist/csv/parse-with.js +60 -54
  65. package/dist/csv/run-import.js +69 -72
  66. package/dist/csv/validate-rows.d.ts +1 -1
  67. package/dist/csv/validate-rows.js +65 -52
  68. package/dist/data/cache-ops.d.ts +5 -4
  69. package/dist/data/cache-ops.js +208 -188
  70. package/dist/data/combine-data-providers.js +25 -23
  71. package/dist/data/data-provider-log.d.ts +45 -0
  72. package/dist/data/data-provider-log.js +93 -0
  73. package/dist/data/errors.js +14 -10
  74. package/dist/data/fake-provider.d.ts +6 -3
  75. package/dist/data/fake-provider.js +129 -114
  76. package/dist/data/fetch-utils.js +61 -44
  77. package/dist/data/filter-branch.d.ts +5 -0
  78. package/dist/data/filter-branch.js +10 -0
  79. package/dist/data/get-many-aggregate.js +84 -76
  80. package/dist/data/http-error.js +17 -12
  81. package/dist/data/keys.js +50 -36
  82. package/dist/data/mutation-options.d.ts +14 -9
  83. package/dist/data/mutation-options.js +93 -109
  84. package/dist/data/query-options.js +73 -68
  85. package/dist/data/remove-empty.d.ts +3 -0
  86. package/dist/data/remove-empty.js +11 -0
  87. package/dist/data/undoable.d.ts +2 -2
  88. package/dist/data/undoable.js +190 -174
  89. package/dist/data/with-lifecycle-callbacks.d.ts +45 -17
  90. package/dist/data/with-lifecycle-callbacks.js +66 -52
  91. package/dist/environment/application-update-store.js +58 -55
  92. package/dist/environment/offline-store.js +21 -21
  93. package/dist/form/array-binding.d.ts +30 -11
  94. package/dist/form/array-binding.js +184 -166
  95. package/dist/form/choice-ids.d.ts +7 -0
  96. package/dist/form/choice-ids.js +11 -0
  97. package/dist/form/choices-controller.d.ts +3 -2
  98. package/dist/form/choices-controller.js +302 -275
  99. package/dist/form/date-format.d.ts +38 -0
  100. package/dist/form/date-format.js +89 -0
  101. package/dist/form/dirty-values.d.ts +2 -2
  102. package/dist/form/dirty-values.js +22 -11
  103. package/dist/form/duration.d.ts +22 -0
  104. package/dist/form/duration.js +49 -0
  105. package/dist/form/edit-create-form.d.ts +12 -5
  106. package/dist/form/edit-create-form.js +243 -188
  107. package/dist/form/event-value.d.ts +6 -0
  108. package/dist/form/event-value.js +17 -0
  109. package/dist/form/field-error.d.ts +14 -0
  110. package/dist/form/field-error.js +28 -0
  111. package/dist/form/field-name.d.ts +20 -0
  112. package/dist/form/field-name.js +6 -0
  113. package/dist/form/filter-form-values.js +63 -49
  114. package/dist/form/form-controller.d.ts +9 -1
  115. package/dist/form/form-controller.js +165 -160
  116. package/dist/form/form-groups.d.ts +4 -3
  117. package/dist/form/form-groups.js +79 -79
  118. package/dist/form/form-handle.d.ts +175 -0
  119. package/dist/form/form-handle.js +68 -0
  120. package/dist/form/input-binding.d.ts +56 -31
  121. package/dist/form/input-binding.js +169 -118
  122. package/dist/form/input-values.d.ts +130 -0
  123. package/dist/form/input-values.js +177 -0
  124. package/dist/form/json-text.js +51 -37
  125. package/dist/form/save-pipeline.d.ts +6 -8
  126. package/dist/form/save-pipeline.js +91 -82
  127. package/dist/form/set-form-values.d.ts +6 -0
  128. package/dist/form/set-form-values.js +10 -0
  129. package/dist/form/source.js +97 -65
  130. package/dist/form/text-of.d.ts +2 -0
  131. package/dist/form/text-of.js +7 -0
  132. package/dist/form/validators.d.ts +58 -19
  133. package/dist/form/validators.js +97 -71
  134. package/dist/geo/bbox.d.ts +5 -4
  135. package/dist/geo/bbox.js +69 -48
  136. package/dist/geo/bounds.d.ts +14 -3
  137. package/dist/geo/bounds.js +98 -68
  138. package/dist/geo/constraints.js +88 -93
  139. package/dist/geo/coordinates.js +31 -23
  140. package/dist/geo/editor.d.ts +13 -13
  141. package/dist/geo/editor.js +176 -153
  142. package/dist/geo/geocoding.d.ts +4 -4
  143. package/dist/geo/geocoding.js +38 -41
  144. package/dist/geo/geojson.d.ts +12 -74
  145. package/dist/geo/geojson.js +52 -40
  146. package/dist/geo/geometry-math.d.ts +4 -4
  147. package/dist/geo/geometry-math.js +100 -93
  148. package/dist/geo/index.d.ts +7 -6
  149. package/dist/geo/map-layers.d.ts +42 -7
  150. package/dist/geo/map-layers.js +88 -62
  151. package/dist/geo/map-style.js +31 -32
  152. package/dist/geo/messages.js +48 -45
  153. package/dist/geo/nominatim.js +88 -80
  154. package/dist/geo/osm-presets.d.ts +4 -3
  155. package/dist/geo/osm-presets.js +108 -86
  156. package/dist/geo/osm-tags.js +14 -12
  157. package/dist/geo/overpass.d.ts +14 -2
  158. package/dist/geo/overpass.js +83 -90
  159. package/dist/geo/shape-value.d.ts +9 -5
  160. package/dist/geo/shape-value.js +169 -146
  161. package/dist/geo/snap-to-roads.d.ts +3 -3
  162. package/dist/geo/snap-to-roads.js +55 -50
  163. package/dist/geo/throttle.js +36 -39
  164. package/dist/guards.d.ts +37 -0
  165. package/dist/guards.js +62 -0
  166. package/dist/i18n/default-messages.js +34 -29
  167. package/dist/i18n/english-messages.js +187 -189
  168. package/dist/i18n/i18n.d.ts +2 -2
  169. package/dist/i18n/i18n.js +47 -60
  170. package/dist/i18n/inflection.d.ts +34 -0
  171. package/dist/i18n/inflection.js +82 -0
  172. package/dist/i18n/messages.d.ts +10 -2
  173. package/dist/i18n/messages.js +17 -4
  174. package/dist/i18n/missing-keys.js +66 -62
  175. package/dist/i18n/translatable.d.ts +16 -1
  176. package/dist/i18n/translatable.js +40 -47
  177. package/dist/index.d.ts +71 -24
  178. package/dist/index.js +40 -288
  179. package/dist/json/deep-equal.d.ts +8 -0
  180. package/dist/json/deep-equal.js +24 -0
  181. package/dist/json/strip-json-comments.js +38 -42
  182. package/dist/noop.d.ts +2 -0
  183. package/dist/noop.js +4 -0
  184. package/dist/notification/error-message.d.ts +2 -0
  185. package/dist/notification/error-message.js +10 -0
  186. package/dist/notification/notification-store.d.ts +3 -2
  187. package/dist/notification/notification-store.js +41 -45
  188. package/dist/onboarding-tour/placement.js +63 -78
  189. package/dist/onboarding-tour/tour-controller.js +46 -54
  190. package/dist/realtime/add-events-for-mutations.js +75 -81
  191. package/dist/realtime/announce-lock.js +16 -13
  192. package/dist/realtime/broadcast-channel-transport.js +65 -59
  193. package/dist/realtime/copy-members.js +22 -14
  194. package/dist/realtime/in-memory-lock-provider.js +40 -48
  195. package/dist/realtime/live.js +95 -101
  196. package/dist/realtime/lock-options.js +16 -16
  197. package/dist/realtime/lock-session.js +91 -78
  198. package/dist/realtime/memory-transport.js +25 -25
  199. package/dist/realtime/presence.js +120 -122
  200. package/dist/realtime/realtime-data-provider.d.ts +10 -0
  201. package/dist/realtime/realtime-data-provider.js +45 -42
  202. package/dist/realtime/reconnect-backoff.js +17 -0
  203. package/dist/realtime/sse-transport.d.ts +31 -0
  204. package/dist/realtime/sse-transport.js +235 -0
  205. package/dist/realtime/status-store.js +23 -28
  206. package/dist/realtime/topic-hub.js +62 -71
  207. package/dist/realtime/topics.js +10 -12
  208. package/dist/realtime/types.js +10 -12
  209. package/dist/realtime/unread-count.js +21 -21
  210. package/dist/realtime/websocket-transport.d.ts +32 -0
  211. package/dist/realtime/websocket-transport.js +306 -0
  212. package/dist/resource/describe-resource.d.ts +2 -0
  213. package/dist/resource/describe-resource.js +232 -219
  214. package/dist/resource/get-at-path.js +29 -14
  215. package/dist/resource/identifier.d.ts +18 -0
  216. package/dist/resource/identifier.js +27 -0
  217. package/dist/resource/record.d.ts +4 -0
  218. package/dist/resource/record.js +10 -0
  219. package/dist/resource/register.d.ts +7 -0
  220. package/dist/resource/registry-store.d.ts +45 -15
  221. package/dist/resource/registry-store.js +67 -60
  222. package/dist/resource/registry.d.ts +10 -0
  223. package/dist/resource/registry.js +8 -4
  224. package/dist/resource/source-path.d.ts +16 -1
  225. package/dist/rich-text/rich-text-extras.d.ts +132 -0
  226. package/dist/rich-text/rich-text-extras.js +179 -0
  227. package/dist/rich-text/rich-text-image.d.ts +124 -0
  228. package/dist/rich-text/rich-text-image.js +163 -0
  229. package/dist/rich-text/rich-text.d.ts +6 -0
  230. package/dist/rich-text/rich-text.js +125 -88
  231. package/dist/router/location.d.ts +22 -4
  232. package/dist/router/location.js +41 -18
  233. package/dist/router/match.js +47 -39
  234. package/dist/router/paths.js +40 -34
  235. package/dist/router/record-from-location.d.ts +1 -1
  236. package/dist/router/record-from-location.js +25 -17
  237. package/dist/store/adapters.js +51 -55
  238. package/dist/store/micro-store.js +57 -59
  239. package/dist/store/shallow-equal.d.ts +12 -0
  240. package/dist/store/shallow-equal.js +20 -0
  241. package/dist/store/store.js +54 -57
  242. package/package.json +13 -11
@@ -2,174 +2,190 @@ import { createMicroStore } from "../store/micro-store.js";
2
2
  import { matchCsvHeaders } from "./match-headers.js";
3
3
  import { runCsvImport } from "./run-import.js";
4
4
  import { csvSchemaFields, validateCsvRows } from "./validate-rows.js";
5
- const STEPS = ["upload", "map", "preview", "commit"];
6
- const asError = (error) => error instanceof Error ? error : new Error(String(error));
5
+ // src/csv/import-controller.ts
6
+ var STEPS = [
7
+ "upload",
8
+ "map",
9
+ "preview",
10
+ "commit"
11
+ ];
12
+ var asError = (error) => error instanceof Error ? error : new Error(String(error));
7
13
  function createCsvImportController(options) {
8
- const fromSchema = csvSchemaFields(options.schema);
9
- const explicitFields = options.fields ?? fromSchema.fields;
10
- const requiredFields = options.requiredFields ?? (options.fields ? [] : fromSchema.required);
11
- const initialMapping = options.mapping ?? {};
12
- const initial = () => ({
13
- step: "upload",
14
- fileName: null,
15
- headers: [],
16
- rows: [],
17
- parseError: null,
18
- fields: explicitFields,
19
- requiredFields,
20
- mapping: initialMapping,
21
- validations: [],
22
- progress: { current: 0, total: 0 },
23
- status: "idle",
24
- report: null,
25
- error: null
26
- });
27
- const store = createMicroStore(initial());
28
- const state = () => store.getSnapshot();
29
- let mappingSettled = Object.keys(initialMapping).length > 0;
30
- let generation = 0;
31
- let busy = false;
32
- let created = false;
33
- let abort;
34
- const startImport = () => {
35
- const run = ++generation;
36
- const controller = new AbortController();
37
- abort = controller;
38
- const validations = state().validations;
39
- const total = validations.filter((v) => v.ok).length;
40
- store.setState({
41
- status: "running",
42
- progress: { current: 0, total },
43
- report: null,
44
- error: null
45
- });
46
- void (async () => {
47
- let report;
48
- try {
49
- report = await runCsvImport({
50
- dataProvider: options.dataProvider,
51
- resource: options.resource,
52
- validations,
53
- ...options.batchSize !== void 0 && {
54
- batchSize: options.batchSize
55
- },
56
- signal: controller.signal,
57
- onProgress: (progress) => {
58
- if (run === generation) store.setState({ progress });
59
- }
60
- });
61
- } catch (thrown) {
62
- if (run !== generation) return;
63
- const error = asError(thrown);
64
- store.setState({ status: "failed", error });
65
- options.onError?.(error);
66
- return;
67
- }
68
- if (run !== generation) return;
69
- if (report.created > 0) created = true;
70
- store.setState({ status: "done", report });
71
- options.onComplete?.(report);
72
- })();
73
- };
74
- const gate = (step) => {
75
- const s = state();
76
- switch (step) {
77
- case "upload":
78
- return s.rows.length > 0 && s.parseError === null;
79
- case "map":
80
- return s.requiredFields.every((field) => !!s.mapping[field]) && Object.values(s.mapping).some(Boolean);
81
- case "preview":
82
- return !created && s.validations.some((v) => v.ok);
83
- case "commit":
84
- return false;
85
- }
86
- };
87
- return {
88
- store,
89
- loadParsed(parsed, fileName) {
90
- if (state().status === "running" || busy) return;
91
- const first = parsed.errors[0];
92
- const parseError = first ? first.row === void 0 ? first.message : `Row ${first.row}: ${first.message}` : null;
93
- const fields = explicitFields.length > 0 ? explicitFields : parsed.headers;
94
- mappingSettled = Object.keys(initialMapping).length > 0;
95
- created = false;
96
- store.setState({
97
- ...initial(),
98
- fileName: fileName ?? null,
99
- headers: parsed.headers,
100
- rows: parseError === null ? parsed.rows : [],
101
- parseError,
102
- fields
103
- });
104
- },
105
- setMapping(field, header) {
106
- if (busy) return;
107
- mappingSettled = true;
108
- store.setState((prev) => ({
109
- mapping: { ...prev.mapping, [field]: header }
110
- }));
111
- },
112
- async next() {
113
- if (busy) return false;
114
- const s = state();
115
- if (s.status === "running") return false;
116
- const index = STEPS.indexOf(s.step);
117
- const target = STEPS[index + 1];
118
- if (!target || !gate(s.step)) return false;
119
- if (target === "map") {
120
- if (!mappingSettled) {
121
- mappingSettled = true;
122
- const mapping = explicitFields.length > 0 ? matchCsvHeaders(s.fields, s.headers) : Object.fromEntries(s.headers.map((h) => [h, h]));
123
- store.setState({ mapping });
124
- }
125
- store.setState({ step: "map" });
126
- } else if (target === "preview") {
127
- busy = true;
128
- const run = generation;
129
- try {
130
- const validations = await validateCsvRows(s.rows, {
131
- mapping: s.mapping,
132
- ...options.schema && { schema: options.schema },
133
- ...options.transform && { transform: options.transform }
134
- });
135
- if (run !== generation) return false;
136
- store.setState({ validations, step: "preview" });
137
- } finally {
138
- if (run === generation) busy = false;
139
- }
140
- } else {
141
- store.setState({ step: "commit" });
142
- startImport();
143
- }
144
- return true;
145
- },
146
- back() {
147
- const s = state();
148
- if (s.status === "running" || busy) return;
149
- const previous = STEPS[STEPS.indexOf(s.step) - 1];
150
- if (!previous) return;
151
- store.setState({
152
- step: previous,
153
- status: "idle",
154
- report: null,
155
- error: null,
156
- progress: { current: 0, total: 0 }
157
- });
158
- },
159
- cancel() {
160
- abort?.abort();
161
- },
162
- reset() {
163
- generation += 1;
164
- abort?.abort();
165
- abort = void 0;
166
- busy = false;
167
- created = false;
168
- mappingSettled = Object.keys(initialMapping).length > 0;
169
- store.setState(initial());
170
- }
171
- };
14
+ const fromSchema = csvSchemaFields(options.schema);
15
+ const explicitFields = options.fields ?? fromSchema.fields;
16
+ const requiredFields = options.requiredFields ?? (options.fields ? [] : fromSchema.required);
17
+ const initialMapping = options.mapping ?? {};
18
+ const initial = () => ({
19
+ step: "upload",
20
+ fileName: null,
21
+ headers: [],
22
+ rows: [],
23
+ parseError: null,
24
+ fields: explicitFields,
25
+ requiredFields,
26
+ mapping: initialMapping,
27
+ validations: [],
28
+ progress: {
29
+ current: 0,
30
+ total: 0
31
+ },
32
+ status: "idle",
33
+ report: null,
34
+ error: null
35
+ });
36
+ const store = createMicroStore(initial());
37
+ const state = () => store.getSnapshot();
38
+ let mappingSettled = Object.keys(initialMapping).length > 0;
39
+ let generation = 0;
40
+ let busy = false;
41
+ let created = false;
42
+ let abort;
43
+ const startImport = () => {
44
+ const run = ++generation;
45
+ const controller = new AbortController();
46
+ abort = controller;
47
+ const validations = state().validations;
48
+ const total = validations.filter((v) => v.ok).length;
49
+ store.setState({
50
+ status: "running",
51
+ progress: {
52
+ current: 0,
53
+ total
54
+ },
55
+ report: null,
56
+ error: null
57
+ });
58
+ (async () => {
59
+ let report;
60
+ try {
61
+ report = await runCsvImport({
62
+ dataProvider: options.dataProvider,
63
+ resource: options.resource,
64
+ validations,
65
+ ...options.batchSize !== void 0 && { batchSize: options.batchSize },
66
+ signal: controller.signal,
67
+ onProgress: (progress) => {
68
+ if (run === generation) store.setState({ progress });
69
+ }
70
+ });
71
+ } catch (thrown) {
72
+ if (run !== generation) return;
73
+ const error = asError(thrown);
74
+ store.setState({
75
+ status: "failed",
76
+ error
77
+ });
78
+ options.onError?.(error);
79
+ return;
80
+ }
81
+ if (run !== generation) return;
82
+ if (report.created > 0) created = true;
83
+ store.setState({
84
+ status: "done",
85
+ report
86
+ });
87
+ options.onComplete?.(report);
88
+ })();
89
+ };
90
+ const gate = (step) => {
91
+ const s = state();
92
+ switch (step) {
93
+ case "upload": return s.rows.length > 0 && s.parseError === null;
94
+ case "map": return s.requiredFields.every((field) => !!s.mapping[field]) && Object.values(s.mapping).some(Boolean);
95
+ case "preview": return !created && s.validations.some((v) => v.ok);
96
+ case "commit": return false;
97
+ }
98
+ };
99
+ return {
100
+ store,
101
+ loadParsed(parsed, fileName) {
102
+ if (state().status === "running" || busy) return;
103
+ const first = parsed.errors[0];
104
+ const parseError = first ? first.row === void 0 ? first.message : `Row ${first.row}: ${first.message}` : null;
105
+ const fields = explicitFields.length > 0 ? explicitFields : parsed.headers;
106
+ mappingSettled = Object.keys(initialMapping).length > 0;
107
+ created = false;
108
+ store.setState({
109
+ ...initial(),
110
+ fileName: fileName ?? null,
111
+ headers: parsed.headers,
112
+ rows: parseError === null ? parsed.rows : [],
113
+ parseError,
114
+ fields
115
+ });
116
+ },
117
+ setMapping(field, header) {
118
+ if (busy) return;
119
+ mappingSettled = true;
120
+ store.setState((prev) => ({ mapping: {
121
+ ...prev.mapping,
122
+ [field]: header
123
+ } }));
124
+ },
125
+ async next() {
126
+ if (busy) return false;
127
+ const s = state();
128
+ if (s.status === "running") return false;
129
+ const target = STEPS[STEPS.indexOf(s.step) + 1];
130
+ if (!target || !gate(s.step)) return false;
131
+ if (target === "map") {
132
+ if (!mappingSettled) {
133
+ mappingSettled = true;
134
+ const mapping = explicitFields.length > 0 ? matchCsvHeaders(s.fields, s.headers) : Object.fromEntries(s.headers.map((h) => [h, h]));
135
+ store.setState({ mapping });
136
+ }
137
+ store.setState({ step: "map" });
138
+ } else if (target === "preview") {
139
+ busy = true;
140
+ const run = generation;
141
+ try {
142
+ const validations = await validateCsvRows(s.rows, {
143
+ mapping: s.mapping,
144
+ ...options.schema && { schema: options.schema },
145
+ ...options.transform && { transform: options.transform }
146
+ });
147
+ if (run !== generation) return false;
148
+ store.setState({
149
+ validations,
150
+ step: "preview"
151
+ });
152
+ } finally {
153
+ if (run === generation) busy = false;
154
+ }
155
+ } else {
156
+ store.setState({ step: "commit" });
157
+ startImport();
158
+ }
159
+ return true;
160
+ },
161
+ back() {
162
+ const s = state();
163
+ if (s.status === "running" || busy) return;
164
+ const previous = STEPS[STEPS.indexOf(s.step) - 1];
165
+ if (!previous) return;
166
+ store.setState({
167
+ step: previous,
168
+ status: "idle",
169
+ report: null,
170
+ error: null,
171
+ progress: {
172
+ current: 0,
173
+ total: 0
174
+ }
175
+ });
176
+ },
177
+ cancel() {
178
+ abort?.abort();
179
+ },
180
+ reset() {
181
+ generation += 1;
182
+ abort?.abort();
183
+ abort = void 0;
184
+ busy = false;
185
+ created = false;
186
+ mappingSettled = Object.keys(initialMapping).length > 0;
187
+ store.setState(initial());
188
+ }
189
+ };
172
190
  }
173
- export {
174
- createCsvImportController
175
- };
191
+ export { createCsvImportController };
@@ -1,24 +1,31 @@
1
- const normalise = (name) => name.toLowerCase().replace(/[\s_-]+/g, "");
1
+ // src/csv/match-headers.ts
2
+ var normalise = (name) => name.toLowerCase().replace(/[\s_-]+/g, "");
3
+ /**
4
+ * Pairs each field with the CSV header it most likely names. Pass one takes an
5
+ * equal name, pass two a header that contains the field, pass three a header
6
+ * the field contains. A later match never takes a header an earlier one took.
7
+ */
2
8
  function matchCsvHeaders(fields, headers) {
3
- const free = headers.map((header) => ({ header, name: normalise(header) })).filter(({ name }) => name !== "");
4
- const result = /* @__PURE__ */ new Map();
5
- const pass = (matches) => {
6
- for (const field of fields) {
7
- if (result.has(field)) continue;
8
- const name = normalise(field);
9
- if (name === "") continue;
10
- const index = free.findIndex((entry) => matches(name, entry.name));
11
- const found = free[index];
12
- if (!found) continue;
13
- result.set(field, found.header);
14
- free.splice(index, 1);
15
- }
16
- };
17
- pass((field, header) => field === header);
18
- pass((field, header) => header.includes(field));
19
- pass((field, header) => field.includes(header));
20
- return Object.fromEntries(result);
9
+ const free = headers.map((header) => ({
10
+ header,
11
+ name: normalise(header)
12
+ })).filter(({ name }) => name !== "");
13
+ const result = /* @__PURE__ */ new Map();
14
+ const pass = (matches) => {
15
+ for (const field of fields) {
16
+ if (result.has(field)) continue;
17
+ const name = normalise(field);
18
+ if (name === "") continue;
19
+ const index = free.findIndex((entry) => matches(name, entry.name));
20
+ const found = free[index];
21
+ if (!found) continue;
22
+ result.set(field, found.header);
23
+ free.splice(index, 1);
24
+ }
25
+ };
26
+ pass((field, header) => field === header);
27
+ pass((field, header) => header.includes(field));
28
+ pass((field, header) => field.includes(header));
29
+ return Object.fromEntries(result);
21
30
  }
22
- export {
23
- matchCsvHeaders
24
- };
31
+ export { matchCsvHeaders };
@@ -1,58 +1,64 @@
1
- const OPTIONS = { header: false, skipEmptyLines: "greedy" };
2
- const IGNORED_CODES = /* @__PURE__ */ new Set(["UndetectableDelimiter"]);
1
+ // src/csv/parse-with.ts
2
+ var OPTIONS = {
3
+ header: false,
4
+ skipEmptyLines: "greedy"
5
+ };
6
+ var IGNORED_CODES = /* @__PURE__ */ new Set(["UndetectableDelimiter"]);
3
7
  function parseCsvWith(parser, text) {
4
- const result = parser.parse(text, OPTIONS);
5
- const body = text.replace(/^/, "");
6
- const [headerRow = [], ...records] = result.data;
7
- const headers = nameHeaders(headerRow);
8
- const rowOf = (error) => {
9
- if (error.row === void 0) return void 0;
10
- if (error.index === void 0) return error.row;
11
- const rows2 = parser.parse(body.slice(0, error.index), OPTIONS).data.length;
12
- return Math.max(rows2 - 1, 0);
13
- };
14
- const errors = [];
15
- for (const error of result.errors) {
16
- if (IGNORED_CODES.has(error.code)) continue;
17
- const { code, message } = error;
18
- const row = rowOf(error);
19
- errors.push(row === void 0 ? { code, message } : { code, row, message });
20
- }
21
- records.forEach((record, index) => {
22
- if (record.length === headers.length) return;
23
- const few = record.length < headers.length;
24
- errors.push({
25
- code: few ? "TooFewFields" : "TooManyFields",
26
- row: index + 1,
27
- message: `Too ${few ? "few" : "many"} fields: expected ${headers.length} fields but parsed ${record.length}`
28
- });
29
- });
30
- const rows = records.map(
31
- (record) => Object.fromEntries(
32
- headers.map((header, index) => [header, record[index] ?? ""])
33
- )
34
- );
35
- return { headers, rows, errors };
8
+ const result = parser.parse(text, OPTIONS);
9
+ const body = text.replace(/^/, "");
10
+ const [headerRow = [], ...records] = result.data;
11
+ const headers = nameHeaders(headerRow);
12
+ const rowOf = (error) => {
13
+ if (error.row === void 0) return void 0;
14
+ if (error.index === void 0) return error.row;
15
+ const rows = parser.parse(body.slice(0, error.index), OPTIONS).data.length;
16
+ return Math.max(rows - 1, 0);
17
+ };
18
+ const errors = [];
19
+ for (const error of result.errors) {
20
+ if (IGNORED_CODES.has(error.code)) continue;
21
+ const { code, message } = error;
22
+ const row = rowOf(error);
23
+ errors.push(row === void 0 ? {
24
+ code,
25
+ message
26
+ } : {
27
+ code,
28
+ row,
29
+ message
30
+ });
31
+ }
32
+ records.forEach((record, index) => {
33
+ if (record.length === headers.length) return;
34
+ const few = record.length < headers.length;
35
+ errors.push({
36
+ code: few ? "TooFewFields" : "TooManyFields",
37
+ row: index + 1,
38
+ message: `Too ${few ? "few" : "many"} fields: expected ${headers.length} fields but parsed ${record.length}`
39
+ });
40
+ });
41
+ return {
42
+ headers,
43
+ rows: records.map((record) => Object.fromEntries(headers.map((header, index) => [header, record[index] ?? ""]))),
44
+ errors
45
+ };
36
46
  }
37
47
  function nameHeaders(cells) {
38
- const trimmed = cells.map(
39
- (cell, index) => cell.trim() || `column_${index + 1}`
40
- );
41
- const taken = new Set(trimmed);
42
- const seen = /* @__PURE__ */ new Set();
43
- return trimmed.map((header) => {
44
- if (!seen.has(header)) {
45
- seen.add(header);
46
- return header;
47
- }
48
- let n = 1;
49
- while (taken.has(`${header}_${n}`)) n += 1;
50
- const renamed = `${header}_${n}`;
51
- taken.add(renamed);
52
- seen.add(renamed);
53
- return renamed;
54
- });
48
+ const trimmed = cells.map((cell, index) => cell.trim() || `column_${index + 1}`);
49
+ const taken = new Set(trimmed);
50
+ const seen = /* @__PURE__ */ new Set();
51
+ return trimmed.map((header) => {
52
+ if (!seen.has(header)) {
53
+ seen.add(header);
54
+ return header;
55
+ }
56
+ let n = 1;
57
+ while (taken.has(`${header}_${n}`)) n += 1;
58
+ const renamed = `${header}_${n}`;
59
+ taken.add(renamed);
60
+ seen.add(renamed);
61
+ return renamed;
62
+ });
55
63
  }
56
- export {
57
- parseCsvWith
58
- };
64
+ export { parseCsvWith };