@arcforgelabs/flow 2026.10.21 → 2026.10.23
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.
- package/README.md +2 -1
- package/VISION.md +40 -9
- package/npm-shrinkwrap.json +2 -414
- package/package.json +6 -1
- package/server/app.js +7 -0
- package/server/core/links.js +166 -0
- package/server/core/outbox.js +129 -0
- package/server/core/queue.js +142 -0
- package/server/core/review.js +92 -0
- package/server/core/secrets.js +74 -0
- package/server/db/migrations/0005_data_spine.sql +99 -0
- package/server/db/migrations/0006_prior_links.sql +18 -0
- package/server/db/migrations/0007_integration_settings.sql +23 -0
- package/server/db/migrations/meta/0005_snapshot.json +2145 -0
- package/server/db/migrations/meta/0006_snapshot.json +2306 -0
- package/server/db/migrations/meta/0007_snapshot.json +2473 -0
- package/server/db/migrations/meta/_journal.json +21 -0
- package/server/db/schema.js +187 -1
- package/server/import/at-start.js +69 -1
- package/server/index.js +28 -8
- package/server/integrations/index.js +9 -3
- package/server/integrations/port.js +101 -9
- package/server/integrations/seazona/index.js +25 -3
- package/server/integrations/setup.js +234 -0
- package/server/integrations/xero/client.js +13 -0
- package/server/integrations/xero/import.js +116 -0
- package/server/integrations/xero/index.js +45 -5
- package/server/integrations/xero/migrations/0004_xero_mirror.sql +96 -0
- package/server/integrations/xero/migrations/meta/_journal.json +7 -0
- package/server/integrations/xero/mirror.js +295 -0
- package/server/integrations/xero/routes.js +26 -1
- package/server/integrations/xero/settings.js +8 -0
- package/server/ui/app-page.js +1 -1
- package/server/ui/app.js +142 -0
- package/server/ui/routes.js +9 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Flow
|
|
2
2
|
|
|
3
|
-
Flow is invoicing, bill
|
|
3
|
+
Flow is invoicing, bill approval and a financial dashboard for labs that make
|
|
4
4
|
work to order, first for dental labs. Seazona (the lab's case system) is a
|
|
5
5
|
bundled integration, and Xero is an optional one. See `VISION.md`.
|
|
6
6
|
|
|
@@ -32,6 +32,7 @@ run a lab.
|
|
|
32
32
|
| `LICENSE` | MIT licence |
|
|
33
33
|
| `docs/DESIGN.md` | The design systems (theme families), how pages and Clerk's components take them, and the screens |
|
|
34
34
|
| `docs/DATA_MODEL.md` | The PostgreSQL records, the rules the database holds, and how to change the schema |
|
|
35
|
+
| `docs/DATA_SPINE.md` | The design of the tables and jobs every integration shares: mirror, identity map, job queue, outbox, review queue |
|
|
35
36
|
| `docs/RELEASING.md` | Versions and channels, the release workflows, how to cut and roll back a release, and the one-time setup |
|
|
36
37
|
| `docs/SELF_HOSTING.md` | Running a Flow release with Docker, Node or Replit, the update notice, and Clerk sign-in |
|
|
37
38
|
| `docs/REPLIT.md` | A Replit workspace of this repository that follows a release channel (`FLOW_DEPLOY_REF`) |
|
package/VISION.md
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
# Flow — Vision
|
|
2
2
|
|
|
3
|
-
Flow is invoicing, bill
|
|
4
|
-
work to order, first for dental labs.
|
|
3
|
+
Flow is invoicing, bill approval and a financial dashboard for a lab that
|
|
4
|
+
makes work to order, first for dental labs. It is a complete application with
|
|
5
|
+
its own database. It is not a sync engine between other products.
|
|
5
6
|
|
|
6
7
|
It is for the person who bills the work and pays the suppliers. Finished feels
|
|
7
8
|
like this: completed cases become invoices they check and send, supplier bills
|
|
8
|
-
|
|
9
|
+
are reviewed and approved, and one dashboard shows cash, what is owed to the
|
|
9
10
|
lab, what the lab owes, and the GST for the BAS period. Every invoice a
|
|
10
11
|
customer was sent can be found again, exactly as it was sent.
|
|
11
12
|
|
|
@@ -13,8 +14,10 @@ Flow is open source so any lab can run its own installation.
|
|
|
13
14
|
|
|
14
15
|
## The core and its integrations
|
|
15
16
|
|
|
16
|
-
The core is invoices, bills, payments, contacts, the price list
|
|
17
|
-
dashboard.
|
|
17
|
+
The core is invoices, bills, payments, credit notes, contacts, the price list,
|
|
18
|
+
the jobs it bills, approvals and the dashboard. The core holds its own copy of
|
|
19
|
+
every record it shows, so it works with no integration connected and an owner
|
|
20
|
+
can build reports and features on its data.
|
|
18
21
|
|
|
19
22
|
Everything outside the core is an integration behind one contract (the
|
|
20
23
|
integration port):
|
|
@@ -25,15 +28,43 @@ integration port):
|
|
|
25
28
|
- **Xero** is optional. Its adapter sends issued invoices and approved bills
|
|
26
29
|
to the owner's own Xero organisation and reads payments back.
|
|
27
30
|
|
|
28
|
-
Adding an integration never changes the core.
|
|
31
|
+
Adding an integration never changes the core. Every integration uses the same
|
|
32
|
+
data spine (`docs/DATA_SPINE.md`): its records come into a mirror, get a Flow
|
|
33
|
+
identity, and become core records; Flow's writes leave through an outbox; a
|
|
34
|
+
conflict goes to one review queue; one job queue runs the work.
|
|
29
35
|
|
|
30
36
|
## Standing decisions
|
|
31
37
|
|
|
32
38
|
### Why does Flow keep its own records?
|
|
33
39
|
|
|
34
|
-
Flow is the store of record for the invoices
|
|
35
|
-
|
|
36
|
-
|
|
40
|
+
Flow is the store of record for the invoices it issues. Xero gets a copy and
|
|
41
|
+
owns bank reconciliation. A lab without Xero still has complete, correct
|
|
42
|
+
records.
|
|
43
|
+
|
|
44
|
+
Flow also keeps a read-only copy of the accounting history from before it
|
|
45
|
+
was installed (#54), so its reports and its dashboard cover years, not only
|
|
46
|
+
the days since install.
|
|
47
|
+
|
|
48
|
+
### Why does Flow hold its data instead of passing it through?
|
|
49
|
+
|
|
50
|
+
An app that only passes records from one system to another cannot answer
|
|
51
|
+
questions about them, cannot show history, and breaks when one side is down.
|
|
52
|
+
Flow stores what each integration reports, links it to its own records, and
|
|
53
|
+
acts from its own database. Sync is how the data arrives and leaves. It is
|
|
54
|
+
not the product.
|
|
55
|
+
|
|
56
|
+
### Who wins when two systems disagree?
|
|
57
|
+
|
|
58
|
+
The case system, Flow and the accounting system each own their own records,
|
|
59
|
+
and the data moves both ways. Flow records which system each change came
|
|
60
|
+
from. When two systems disagree, Flow never overwrites one silently: it opens
|
|
61
|
+
an item in the review queue for a person.
|
|
62
|
+
|
|
63
|
+
### Why are approvals in Flow?
|
|
64
|
+
|
|
65
|
+
The person who bills checks work before it leaves Flow. Writes to the
|
|
66
|
+
accounting system are drafts, and a person approves them. An approval is a
|
|
67
|
+
record in Flow with who, when and what they saw.
|
|
37
68
|
|
|
38
69
|
### Why is a sent invoice never changed?
|
|
39
70
|
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arcforgelabs/flow",
|
|
3
|
-
"version": "2026.10.
|
|
3
|
+
"version": "2026.10.23",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@arcforgelabs/flow",
|
|
9
|
-
"version": "2026.10.
|
|
9
|
+
"version": "2026.10.23",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@clerk/backend": "3.23.2",
|
|
@@ -95,418 +95,6 @@
|
|
|
95
95
|
"source-map-support": "^0.5.21"
|
|
96
96
|
}
|
|
97
97
|
},
|
|
98
|
-
"node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/android-arm": {
|
|
99
|
-
"version": "0.18.20",
|
|
100
|
-
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz",
|
|
101
|
-
"integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==",
|
|
102
|
-
"cpu": [
|
|
103
|
-
"arm"
|
|
104
|
-
],
|
|
105
|
-
"dev": true,
|
|
106
|
-
"license": "MIT",
|
|
107
|
-
"optional": true,
|
|
108
|
-
"os": [
|
|
109
|
-
"android"
|
|
110
|
-
],
|
|
111
|
-
"engines": {
|
|
112
|
-
"node": ">=12"
|
|
113
|
-
}
|
|
114
|
-
},
|
|
115
|
-
"node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/android-arm64": {
|
|
116
|
-
"version": "0.18.20",
|
|
117
|
-
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz",
|
|
118
|
-
"integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==",
|
|
119
|
-
"cpu": [
|
|
120
|
-
"arm64"
|
|
121
|
-
],
|
|
122
|
-
"dev": true,
|
|
123
|
-
"license": "MIT",
|
|
124
|
-
"optional": true,
|
|
125
|
-
"os": [
|
|
126
|
-
"android"
|
|
127
|
-
],
|
|
128
|
-
"engines": {
|
|
129
|
-
"node": ">=12"
|
|
130
|
-
}
|
|
131
|
-
},
|
|
132
|
-
"node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/android-x64": {
|
|
133
|
-
"version": "0.18.20",
|
|
134
|
-
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz",
|
|
135
|
-
"integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==",
|
|
136
|
-
"cpu": [
|
|
137
|
-
"x64"
|
|
138
|
-
],
|
|
139
|
-
"dev": true,
|
|
140
|
-
"license": "MIT",
|
|
141
|
-
"optional": true,
|
|
142
|
-
"os": [
|
|
143
|
-
"android"
|
|
144
|
-
],
|
|
145
|
-
"engines": {
|
|
146
|
-
"node": ">=12"
|
|
147
|
-
}
|
|
148
|
-
},
|
|
149
|
-
"node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/darwin-arm64": {
|
|
150
|
-
"version": "0.18.20",
|
|
151
|
-
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz",
|
|
152
|
-
"integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==",
|
|
153
|
-
"cpu": [
|
|
154
|
-
"arm64"
|
|
155
|
-
],
|
|
156
|
-
"dev": true,
|
|
157
|
-
"license": "MIT",
|
|
158
|
-
"optional": true,
|
|
159
|
-
"os": [
|
|
160
|
-
"darwin"
|
|
161
|
-
],
|
|
162
|
-
"engines": {
|
|
163
|
-
"node": ">=12"
|
|
164
|
-
}
|
|
165
|
-
},
|
|
166
|
-
"node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/darwin-x64": {
|
|
167
|
-
"version": "0.18.20",
|
|
168
|
-
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz",
|
|
169
|
-
"integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==",
|
|
170
|
-
"cpu": [
|
|
171
|
-
"x64"
|
|
172
|
-
],
|
|
173
|
-
"dev": true,
|
|
174
|
-
"license": "MIT",
|
|
175
|
-
"optional": true,
|
|
176
|
-
"os": [
|
|
177
|
-
"darwin"
|
|
178
|
-
],
|
|
179
|
-
"engines": {
|
|
180
|
-
"node": ">=12"
|
|
181
|
-
}
|
|
182
|
-
},
|
|
183
|
-
"node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/freebsd-arm64": {
|
|
184
|
-
"version": "0.18.20",
|
|
185
|
-
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz",
|
|
186
|
-
"integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==",
|
|
187
|
-
"cpu": [
|
|
188
|
-
"arm64"
|
|
189
|
-
],
|
|
190
|
-
"dev": true,
|
|
191
|
-
"license": "MIT",
|
|
192
|
-
"optional": true,
|
|
193
|
-
"os": [
|
|
194
|
-
"freebsd"
|
|
195
|
-
],
|
|
196
|
-
"engines": {
|
|
197
|
-
"node": ">=12"
|
|
198
|
-
}
|
|
199
|
-
},
|
|
200
|
-
"node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/freebsd-x64": {
|
|
201
|
-
"version": "0.18.20",
|
|
202
|
-
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz",
|
|
203
|
-
"integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==",
|
|
204
|
-
"cpu": [
|
|
205
|
-
"x64"
|
|
206
|
-
],
|
|
207
|
-
"dev": true,
|
|
208
|
-
"license": "MIT",
|
|
209
|
-
"optional": true,
|
|
210
|
-
"os": [
|
|
211
|
-
"freebsd"
|
|
212
|
-
],
|
|
213
|
-
"engines": {
|
|
214
|
-
"node": ">=12"
|
|
215
|
-
}
|
|
216
|
-
},
|
|
217
|
-
"node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-arm": {
|
|
218
|
-
"version": "0.18.20",
|
|
219
|
-
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz",
|
|
220
|
-
"integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==",
|
|
221
|
-
"cpu": [
|
|
222
|
-
"arm"
|
|
223
|
-
],
|
|
224
|
-
"dev": true,
|
|
225
|
-
"license": "MIT",
|
|
226
|
-
"optional": true,
|
|
227
|
-
"os": [
|
|
228
|
-
"linux"
|
|
229
|
-
],
|
|
230
|
-
"engines": {
|
|
231
|
-
"node": ">=12"
|
|
232
|
-
}
|
|
233
|
-
},
|
|
234
|
-
"node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-arm64": {
|
|
235
|
-
"version": "0.18.20",
|
|
236
|
-
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz",
|
|
237
|
-
"integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==",
|
|
238
|
-
"cpu": [
|
|
239
|
-
"arm64"
|
|
240
|
-
],
|
|
241
|
-
"dev": true,
|
|
242
|
-
"license": "MIT",
|
|
243
|
-
"optional": true,
|
|
244
|
-
"os": [
|
|
245
|
-
"linux"
|
|
246
|
-
],
|
|
247
|
-
"engines": {
|
|
248
|
-
"node": ">=12"
|
|
249
|
-
}
|
|
250
|
-
},
|
|
251
|
-
"node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-ia32": {
|
|
252
|
-
"version": "0.18.20",
|
|
253
|
-
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz",
|
|
254
|
-
"integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==",
|
|
255
|
-
"cpu": [
|
|
256
|
-
"ia32"
|
|
257
|
-
],
|
|
258
|
-
"dev": true,
|
|
259
|
-
"license": "MIT",
|
|
260
|
-
"optional": true,
|
|
261
|
-
"os": [
|
|
262
|
-
"linux"
|
|
263
|
-
],
|
|
264
|
-
"engines": {
|
|
265
|
-
"node": ">=12"
|
|
266
|
-
}
|
|
267
|
-
},
|
|
268
|
-
"node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-loong64": {
|
|
269
|
-
"version": "0.18.20",
|
|
270
|
-
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz",
|
|
271
|
-
"integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==",
|
|
272
|
-
"cpu": [
|
|
273
|
-
"loong64"
|
|
274
|
-
],
|
|
275
|
-
"dev": true,
|
|
276
|
-
"license": "MIT",
|
|
277
|
-
"optional": true,
|
|
278
|
-
"os": [
|
|
279
|
-
"linux"
|
|
280
|
-
],
|
|
281
|
-
"engines": {
|
|
282
|
-
"node": ">=12"
|
|
283
|
-
}
|
|
284
|
-
},
|
|
285
|
-
"node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-mips64el": {
|
|
286
|
-
"version": "0.18.20",
|
|
287
|
-
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz",
|
|
288
|
-
"integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==",
|
|
289
|
-
"cpu": [
|
|
290
|
-
"mips64el"
|
|
291
|
-
],
|
|
292
|
-
"dev": true,
|
|
293
|
-
"license": "MIT",
|
|
294
|
-
"optional": true,
|
|
295
|
-
"os": [
|
|
296
|
-
"linux"
|
|
297
|
-
],
|
|
298
|
-
"engines": {
|
|
299
|
-
"node": ">=12"
|
|
300
|
-
}
|
|
301
|
-
},
|
|
302
|
-
"node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-ppc64": {
|
|
303
|
-
"version": "0.18.20",
|
|
304
|
-
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz",
|
|
305
|
-
"integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==",
|
|
306
|
-
"cpu": [
|
|
307
|
-
"ppc64"
|
|
308
|
-
],
|
|
309
|
-
"dev": true,
|
|
310
|
-
"license": "MIT",
|
|
311
|
-
"optional": true,
|
|
312
|
-
"os": [
|
|
313
|
-
"linux"
|
|
314
|
-
],
|
|
315
|
-
"engines": {
|
|
316
|
-
"node": ">=12"
|
|
317
|
-
}
|
|
318
|
-
},
|
|
319
|
-
"node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-riscv64": {
|
|
320
|
-
"version": "0.18.20",
|
|
321
|
-
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz",
|
|
322
|
-
"integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==",
|
|
323
|
-
"cpu": [
|
|
324
|
-
"riscv64"
|
|
325
|
-
],
|
|
326
|
-
"dev": true,
|
|
327
|
-
"license": "MIT",
|
|
328
|
-
"optional": true,
|
|
329
|
-
"os": [
|
|
330
|
-
"linux"
|
|
331
|
-
],
|
|
332
|
-
"engines": {
|
|
333
|
-
"node": ">=12"
|
|
334
|
-
}
|
|
335
|
-
},
|
|
336
|
-
"node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-s390x": {
|
|
337
|
-
"version": "0.18.20",
|
|
338
|
-
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz",
|
|
339
|
-
"integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==",
|
|
340
|
-
"cpu": [
|
|
341
|
-
"s390x"
|
|
342
|
-
],
|
|
343
|
-
"dev": true,
|
|
344
|
-
"license": "MIT",
|
|
345
|
-
"optional": true,
|
|
346
|
-
"os": [
|
|
347
|
-
"linux"
|
|
348
|
-
],
|
|
349
|
-
"engines": {
|
|
350
|
-
"node": ">=12"
|
|
351
|
-
}
|
|
352
|
-
},
|
|
353
|
-
"node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-x64": {
|
|
354
|
-
"version": "0.18.20",
|
|
355
|
-
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz",
|
|
356
|
-
"integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==",
|
|
357
|
-
"cpu": [
|
|
358
|
-
"x64"
|
|
359
|
-
],
|
|
360
|
-
"dev": true,
|
|
361
|
-
"license": "MIT",
|
|
362
|
-
"optional": true,
|
|
363
|
-
"os": [
|
|
364
|
-
"linux"
|
|
365
|
-
],
|
|
366
|
-
"engines": {
|
|
367
|
-
"node": ">=12"
|
|
368
|
-
}
|
|
369
|
-
},
|
|
370
|
-
"node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/netbsd-x64": {
|
|
371
|
-
"version": "0.18.20",
|
|
372
|
-
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz",
|
|
373
|
-
"integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==",
|
|
374
|
-
"cpu": [
|
|
375
|
-
"x64"
|
|
376
|
-
],
|
|
377
|
-
"dev": true,
|
|
378
|
-
"license": "MIT",
|
|
379
|
-
"optional": true,
|
|
380
|
-
"os": [
|
|
381
|
-
"netbsd"
|
|
382
|
-
],
|
|
383
|
-
"engines": {
|
|
384
|
-
"node": ">=12"
|
|
385
|
-
}
|
|
386
|
-
},
|
|
387
|
-
"node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/openbsd-x64": {
|
|
388
|
-
"version": "0.18.20",
|
|
389
|
-
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz",
|
|
390
|
-
"integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==",
|
|
391
|
-
"cpu": [
|
|
392
|
-
"x64"
|
|
393
|
-
],
|
|
394
|
-
"dev": true,
|
|
395
|
-
"license": "MIT",
|
|
396
|
-
"optional": true,
|
|
397
|
-
"os": [
|
|
398
|
-
"openbsd"
|
|
399
|
-
],
|
|
400
|
-
"engines": {
|
|
401
|
-
"node": ">=12"
|
|
402
|
-
}
|
|
403
|
-
},
|
|
404
|
-
"node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/sunos-x64": {
|
|
405
|
-
"version": "0.18.20",
|
|
406
|
-
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz",
|
|
407
|
-
"integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==",
|
|
408
|
-
"cpu": [
|
|
409
|
-
"x64"
|
|
410
|
-
],
|
|
411
|
-
"dev": true,
|
|
412
|
-
"license": "MIT",
|
|
413
|
-
"optional": true,
|
|
414
|
-
"os": [
|
|
415
|
-
"sunos"
|
|
416
|
-
],
|
|
417
|
-
"engines": {
|
|
418
|
-
"node": ">=12"
|
|
419
|
-
}
|
|
420
|
-
},
|
|
421
|
-
"node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/win32-arm64": {
|
|
422
|
-
"version": "0.18.20",
|
|
423
|
-
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz",
|
|
424
|
-
"integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==",
|
|
425
|
-
"cpu": [
|
|
426
|
-
"arm64"
|
|
427
|
-
],
|
|
428
|
-
"dev": true,
|
|
429
|
-
"license": "MIT",
|
|
430
|
-
"optional": true,
|
|
431
|
-
"os": [
|
|
432
|
-
"win32"
|
|
433
|
-
],
|
|
434
|
-
"engines": {
|
|
435
|
-
"node": ">=12"
|
|
436
|
-
}
|
|
437
|
-
},
|
|
438
|
-
"node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/win32-ia32": {
|
|
439
|
-
"version": "0.18.20",
|
|
440
|
-
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz",
|
|
441
|
-
"integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==",
|
|
442
|
-
"cpu": [
|
|
443
|
-
"ia32"
|
|
444
|
-
],
|
|
445
|
-
"dev": true,
|
|
446
|
-
"license": "MIT",
|
|
447
|
-
"optional": true,
|
|
448
|
-
"os": [
|
|
449
|
-
"win32"
|
|
450
|
-
],
|
|
451
|
-
"engines": {
|
|
452
|
-
"node": ">=12"
|
|
453
|
-
}
|
|
454
|
-
},
|
|
455
|
-
"node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/win32-x64": {
|
|
456
|
-
"version": "0.18.20",
|
|
457
|
-
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz",
|
|
458
|
-
"integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==",
|
|
459
|
-
"cpu": [
|
|
460
|
-
"x64"
|
|
461
|
-
],
|
|
462
|
-
"dev": true,
|
|
463
|
-
"license": "MIT",
|
|
464
|
-
"optional": true,
|
|
465
|
-
"os": [
|
|
466
|
-
"win32"
|
|
467
|
-
],
|
|
468
|
-
"engines": {
|
|
469
|
-
"node": ">=12"
|
|
470
|
-
}
|
|
471
|
-
},
|
|
472
|
-
"node_modules/@esbuild-kit/core-utils/node_modules/esbuild": {
|
|
473
|
-
"version": "0.18.20",
|
|
474
|
-
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz",
|
|
475
|
-
"integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==",
|
|
476
|
-
"dev": true,
|
|
477
|
-
"hasInstallScript": true,
|
|
478
|
-
"license": "MIT",
|
|
479
|
-
"bin": {
|
|
480
|
-
"esbuild": "bin/esbuild"
|
|
481
|
-
},
|
|
482
|
-
"engines": {
|
|
483
|
-
"node": ">=12"
|
|
484
|
-
},
|
|
485
|
-
"optionalDependencies": {
|
|
486
|
-
"@esbuild/android-arm": "0.18.20",
|
|
487
|
-
"@esbuild/android-arm64": "0.18.20",
|
|
488
|
-
"@esbuild/android-x64": "0.18.20",
|
|
489
|
-
"@esbuild/darwin-arm64": "0.18.20",
|
|
490
|
-
"@esbuild/darwin-x64": "0.18.20",
|
|
491
|
-
"@esbuild/freebsd-arm64": "0.18.20",
|
|
492
|
-
"@esbuild/freebsd-x64": "0.18.20",
|
|
493
|
-
"@esbuild/linux-arm": "0.18.20",
|
|
494
|
-
"@esbuild/linux-arm64": "0.18.20",
|
|
495
|
-
"@esbuild/linux-ia32": "0.18.20",
|
|
496
|
-
"@esbuild/linux-loong64": "0.18.20",
|
|
497
|
-
"@esbuild/linux-mips64el": "0.18.20",
|
|
498
|
-
"@esbuild/linux-ppc64": "0.18.20",
|
|
499
|
-
"@esbuild/linux-riscv64": "0.18.20",
|
|
500
|
-
"@esbuild/linux-s390x": "0.18.20",
|
|
501
|
-
"@esbuild/linux-x64": "0.18.20",
|
|
502
|
-
"@esbuild/netbsd-x64": "0.18.20",
|
|
503
|
-
"@esbuild/openbsd-x64": "0.18.20",
|
|
504
|
-
"@esbuild/sunos-x64": "0.18.20",
|
|
505
|
-
"@esbuild/win32-arm64": "0.18.20",
|
|
506
|
-
"@esbuild/win32-ia32": "0.18.20",
|
|
507
|
-
"@esbuild/win32-x64": "0.18.20"
|
|
508
|
-
}
|
|
509
|
-
},
|
|
510
98
|
"node_modules/@esbuild-kit/esm-loader": {
|
|
511
99
|
"version": "2.6.5",
|
|
512
100
|
"resolved": "https://registry.npmjs.org/@esbuild-kit/esm-loader/-/esm-loader-2.6.5.tgz",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arcforgelabs/flow",
|
|
3
|
-
"version": "2026.10.
|
|
3
|
+
"version": "2026.10.23",
|
|
4
4
|
"description": "Invoicing, bill entry and a financial dashboard for labs, with Seazona and Xero integrations.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -52,5 +52,10 @@
|
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"drizzle-kit": "0.31.11"
|
|
55
|
+
},
|
|
56
|
+
"overrides": {
|
|
57
|
+
"@esbuild-kit/core-utils": {
|
|
58
|
+
"esbuild": "0.25.12"
|
|
59
|
+
}
|
|
55
60
|
}
|
|
56
61
|
}
|
package/server/app.js
CHANGED
|
@@ -3,6 +3,7 @@ import { createConnectorApi } from './api/connector.js';
|
|
|
3
3
|
import { createSignInRouter } from './auth/routes.js';
|
|
4
4
|
import { deployedBuildStatus } from './deployed-build.js';
|
|
5
5
|
import { integrationsHealth } from './integrations/health.js';
|
|
6
|
+
import { createSetupRouter } from './integrations/setup.js';
|
|
6
7
|
import { rateLimit } from './rate-limit.js';
|
|
7
8
|
import { DEFAULT_FAMILY } from './theme/themes.js';
|
|
8
9
|
import { messagePage } from './ui/page.js';
|
|
@@ -30,6 +31,7 @@ export function createApp({
|
|
|
30
31
|
auth = null,
|
|
31
32
|
updates = null,
|
|
32
33
|
integrations = null,
|
|
34
|
+
secrets = null,
|
|
33
35
|
trustProxy = false,
|
|
34
36
|
rateLimitPerMinute = 120,
|
|
35
37
|
signInRateLimitPerMinute = 30,
|
|
@@ -93,6 +95,11 @@ export function createApp({
|
|
|
93
95
|
// An adapter's own pages (such as the end of connecting Xero) use
|
|
94
96
|
// `messagePage` so they look like the rest of Flow.
|
|
95
97
|
const page = (options) => messagePage({ ...options, defaultFamily });
|
|
98
|
+
// Settings, Integrations: an owner turns integrations on and enters their
|
|
99
|
+
// settings (server/integrations/setup.js).
|
|
100
|
+
if (integrations && database && auth?.personAuth) {
|
|
101
|
+
app.use('/api/integrations', createSetupRouter({ db: database.db, registry: integrations, personAuth: auth.personAuth, secrets, log }));
|
|
102
|
+
}
|
|
96
103
|
for (const { path, handler } of integrations?.routes({ db: database?.db ?? null, personAuth: auth?.personAuth ?? null, log, messagePage: page }) ?? []) {
|
|
97
104
|
app.use(path, handler);
|
|
98
105
|
}
|