@filelayer/core 0.3.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.
- package/CHANGELOG.md +338 -0
- package/LICENSE +202 -0
- package/MIGRATIONS.md +328 -0
- package/NOTICE +37 -0
- package/README.md +343 -0
- package/SEMANTICS.md +729 -0
- package/dist/authz.d.ts +524 -0
- package/dist/authz.d.ts.map +1 -0
- package/dist/authz.js +889 -0
- package/dist/authz.js.map +1 -0
- package/dist/db.d.ts +145 -0
- package/dist/db.d.ts.map +1 -0
- package/dist/db.js +217 -0
- package/dist/db.js.map +1 -0
- package/dist/delivery.d.ts +293 -0
- package/dist/delivery.d.ts.map +1 -0
- package/dist/delivery.js +519 -0
- package/dist/delivery.js.map +1 -0
- package/dist/errors.d.ts +16 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +21 -0
- package/dist/errors.js.map +1 -0
- package/dist/filelayer.d.ts +542 -0
- package/dist/filelayer.d.ts.map +1 -0
- package/dist/filelayer.js +1360 -0
- package/dist/filelayer.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/simple.d.ts +297 -0
- package/dist/simple.d.ts.map +1 -0
- package/dist/simple.js +492 -0
- package/dist/simple.js.map +1 -0
- package/dist/storage.d.ts +269 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +700 -0
- package/dist/storage.js.map +1 -0
- package/dist/store.d.ts +432 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +862 -0
- package/dist/store.js.map +1 -0
- package/package.json +77 -0
- package/schema.sql +1190 -0
- package/src/authz.ts +1398 -0
- package/src/db.ts +271 -0
- package/src/delivery.ts +737 -0
- package/src/errors.ts +24 -0
- package/src/filelayer.ts +1836 -0
- package/src/index.ts +7 -0
- package/src/simple.ts +666 -0
- package/src/storage.ts +917 -0
- package/src/store.ts +1072 -0
- package/test/delivery.test.ts +0 -0
- package/test/group-subjects.test.ts +1072 -0
- package/test/helpers.ts +65 -0
- package/test/listing.test.ts +689 -0
- package/test/local-s3.d.mts +33 -0
- package/test/local-s3.mjs +400 -0
- package/test/persistence.test.ts +953 -0
- package/test/regression.test.ts +619 -0
- package/test/s3-live.test.ts +322 -0
- package/test/security.test.ts +1652 -0
- package/test/semantics.test.ts +888 -0
- package/test/storage.test.ts +437 -0
- package/test/tiers.test.ts +432 -0
- package/test/vault-example.test.ts +302 -0
- package/tsconfig.build.json +29 -0
- package/tsconfig.json +19 -0
package/MIGRATIONS.md
ADDED
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
# Migrations and the compatibility promise
|
|
2
|
+
|
|
3
|
+
How schema changes reach you, what upgrading costs, and what we do and do not
|
|
4
|
+
promise before 1.0.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 1. The promise, stated narrowly
|
|
9
|
+
|
|
10
|
+
Filelayer is `0.x`. The version is `0.MINOR.PATCH` and it means:
|
|
11
|
+
|
|
12
|
+
| Change | Version bump | What you must do |
|
|
13
|
+
|---|---|---|
|
|
14
|
+
| Breaking API change, breaking schema change, or both | **MINOR** (`0.3.x` → `0.4.0`) | Read the entry in this file. Run its SQL. Possibly edit call sites. |
|
|
15
|
+
| Additive API, bug fix, doc fix, new optional column with a default | **PATCH** (`0.3.0` → `0.3.1`) | `npm update`. Nothing else. |
|
|
16
|
+
|
|
17
|
+
There is no long-term support branch, no backporting, and no deprecation period
|
|
18
|
+
before 1.0. A minor bump may remove a method in the same release that replaces
|
|
19
|
+
it. That is what `0.x` means and it is why this file exists: the compensation
|
|
20
|
+
for moving fast is that every break is written down, with the SQL, before it
|
|
21
|
+
ships.
|
|
22
|
+
|
|
23
|
+
At 1.0 this changes to ordinary semantic versioning, and schema changes become
|
|
24
|
+
additive-with-a-deprecation-window rather than replace-in-place.
|
|
25
|
+
|
|
26
|
+
**Nothing has been published to npm yet.** At the time of writing there are no
|
|
27
|
+
installs, so no migration in this file has ever been executed by anyone other
|
|
28
|
+
than us. Entry 1 below is written as if it had been, because the next one will
|
|
29
|
+
be.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## 2. How a schema change is delivered
|
|
34
|
+
|
|
35
|
+
There is no migration framework and there is not going to be one. Filelayer
|
|
36
|
+
owns a schema; your application owns a migration runner. Wrapping ours in a tool
|
|
37
|
+
that competes with yours would be the wrong kind of opinionated.
|
|
38
|
+
|
|
39
|
+
What we ship instead:
|
|
40
|
+
|
|
41
|
+
1. **`schema.sql` is the whole, current, canonical schema.** It is idempotent
|
|
42
|
+
only in the sense that it creates a database from nothing. It is not a
|
|
43
|
+
sequence of migrations and it will not upgrade an existing database.
|
|
44
|
+
Programmatic access, so a runner does not hardcode a path:
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
import { SCHEMA_PATH, loadSchemaSql } from '@filelayer/core';
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
2. **Every breaking schema change gets a numbered entry in this file** with the
|
|
51
|
+
forward SQL, written to be pasted into your own migration tool, plus what it
|
|
52
|
+
costs and what it breaks in the API.
|
|
53
|
+
|
|
54
|
+
3. **The version in `package.json` is the contract.** If your installed schema
|
|
55
|
+
was applied from `0.3.x`, entries above `0.3` apply to you in order.
|
|
56
|
+
|
|
57
|
+
### Recording which version your database is at
|
|
58
|
+
|
|
59
|
+
There is no `schema_version` table today, and that is a gap we are naming rather
|
|
60
|
+
than hiding: right now you have to know which release you applied. If you have
|
|
61
|
+
just deployed, record it yourself:
|
|
62
|
+
|
|
63
|
+
```sql
|
|
64
|
+
COMMENT ON SCHEMA public IS 'filelayer schema 0.3.0';
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
A real version table lands before 1.0.
|
|
68
|
+
|
|
69
|
+
### The order that is safe
|
|
70
|
+
|
|
71
|
+
Schema changes below are written to be applied **before** the new library
|
|
72
|
+
version is deployed, not after. Every one of them is designed so that the
|
|
73
|
+
previous library version keeps working against the new schema for the length of
|
|
74
|
+
a deploy — which means the safe sequence is always:
|
|
75
|
+
|
|
76
|
+
1. apply the SQL,
|
|
77
|
+
2. verify the old processes are still healthy,
|
|
78
|
+
3. roll the new library version out,
|
|
79
|
+
4. run any backfill the entry mentions.
|
|
80
|
+
|
|
81
|
+
Where an entry cannot honour that, it says so in bold at the top.
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## 3. Migrations
|
|
86
|
+
|
|
87
|
+
### Entry 1 — `0.2.x` → `0.3.0`: identifiers become per-project
|
|
88
|
+
|
|
89
|
+
**Breaking. Schema and API. This is a security fix; do not skip it.**
|
|
90
|
+
|
|
91
|
+
#### What was wrong
|
|
92
|
+
|
|
93
|
+
`org.external_id` and `actor.external_id` were **globally unique**. That is
|
|
94
|
+
correct for a library where each customer runs their own database, and it is a
|
|
95
|
+
cross-customer data breach the moment more than one application shares one.
|
|
96
|
+
|
|
97
|
+
The failure was not a collision error. It was a silent success:
|
|
98
|
+
|
|
99
|
+
- The identity resolver upserts a customer's own org id with
|
|
100
|
+
`INSERT ... ON CONFLICT (external_id) DO UPDATE ... RETURNING id`. Under a
|
|
101
|
+
global unique index, application B calling `put({ org: 'acme' })` did not get
|
|
102
|
+
an error — it got application A's org id, and then the resolver helpfully
|
|
103
|
+
added B's user to A's tenant as a `member`.
|
|
104
|
+
- Actor resolution had the same shape, so `as: 'alice'` in application B
|
|
105
|
+
resolved to application A's Alice.
|
|
106
|
+
|
|
107
|
+
A complete cross-tenant compromise, reachable from the most ergonomic entry
|
|
108
|
+
point in the library, requiring no attacker skill beyond picking a common org
|
|
109
|
+
name.
|
|
110
|
+
|
|
111
|
+
#### What changed
|
|
112
|
+
|
|
113
|
+
A scope above the tenant: the **project**, which is one customer application.
|
|
114
|
+
`external_id` is the customer's id space, so it is unique *within* a project and
|
|
115
|
+
meaningless across projects.
|
|
116
|
+
|
|
117
|
+
- New table `project`, plus a default project row
|
|
118
|
+
(`00000000-0000-0000-0000-0000000f11e1`) so that a single-application
|
|
119
|
+
deployment needs no project vocabulary at all.
|
|
120
|
+
- `org` and `actor` gain `project_id`, and their unique constraints become
|
|
121
|
+
`UNIQUE (project_id, external_id)`.
|
|
122
|
+
- Every table that can name an actor carries `project_id` under a composite
|
|
123
|
+
foreign key, so a cross-project membership, ownership, grant subject or grant
|
|
124
|
+
issuer is *unrepresentable* — the same standard cross-tenant access is held
|
|
125
|
+
to, one level up.
|
|
126
|
+
- `project_id` is **derived, never supplied**: a trigger overwrites whatever a
|
|
127
|
+
writer passed with the value read from the owning org.
|
|
128
|
+
|
|
129
|
+
#### The migration
|
|
130
|
+
|
|
131
|
+
For a deployment that has data. Every existing row lands in one project, which
|
|
132
|
+
is exactly what a pre-project deployment was.
|
|
133
|
+
|
|
134
|
+
```sql
|
|
135
|
+
BEGIN;
|
|
136
|
+
|
|
137
|
+
-- 1. The project table, and the default project every existing row belongs to.
|
|
138
|
+
CREATE TABLE project (
|
|
139
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
140
|
+
key text NOT NULL UNIQUE,
|
|
141
|
+
name text,
|
|
142
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
143
|
+
deleted_at timestamptz
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
INSERT INTO project (id, key, name)
|
|
147
|
+
VALUES ('00000000-0000-0000-0000-0000000f11e1',
|
|
148
|
+
'__filelayer_default_project__',
|
|
149
|
+
'Default project');
|
|
150
|
+
|
|
151
|
+
-- 2. Drop the global uniqueness that was the defect.
|
|
152
|
+
ALTER TABLE org DROP CONSTRAINT org_external_id_key;
|
|
153
|
+
ALTER TABLE actor DROP CONSTRAINT actor_external_id_key;
|
|
154
|
+
|
|
155
|
+
-- 3. Scope both id spaces to a project.
|
|
156
|
+
ALTER TABLE org ADD COLUMN project_id uuid NOT NULL
|
|
157
|
+
DEFAULT '00000000-0000-0000-0000-0000000f11e1'
|
|
158
|
+
REFERENCES project(id) ON DELETE CASCADE;
|
|
159
|
+
ALTER TABLE actor ADD COLUMN project_id uuid NOT NULL
|
|
160
|
+
DEFAULT '00000000-0000-0000-0000-0000000f11e1'
|
|
161
|
+
REFERENCES project(id) ON DELETE CASCADE;
|
|
162
|
+
|
|
163
|
+
ALTER TABLE org ADD CONSTRAINT org_project_external_key UNIQUE (project_id, external_id);
|
|
164
|
+
ALTER TABLE actor ADD CONSTRAINT actor_project_external_key UNIQUE (project_id, external_id);
|
|
165
|
+
|
|
166
|
+
-- 4. The composite keys that make a cross-project row unrepresentable.
|
|
167
|
+
ALTER TABLE org ADD CONSTRAINT org_id_project_key UNIQUE (id, project_id);
|
|
168
|
+
ALTER TABLE actor ADD CONSTRAINT actor_id_project_key UNIQUE (id, project_id);
|
|
169
|
+
|
|
170
|
+
COMMIT;
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Then apply, from the `0.3.0` `schema.sql`, in this order:
|
|
174
|
+
|
|
175
|
+
1. the `project_id` columns and composite foreign keys on `membership`, `file`
|
|
176
|
+
and `grant`;
|
|
177
|
+
2. the `project_from_org()` trigger function and its triggers;
|
|
178
|
+
3. the updated `grant_scope_is_live()` — it now also requires the owning
|
|
179
|
+
project to be live.
|
|
180
|
+
|
|
181
|
+
Copy those blocks verbatim from `schema.sql`; they are commented at the
|
|
182
|
+
constraint that enforces each property. Doing it by hand from this file would be
|
|
183
|
+
transcription, and transcription is how a security migration goes wrong.
|
|
184
|
+
|
|
185
|
+
#### If you would rather not migrate
|
|
186
|
+
|
|
187
|
+
There were no installs at `0.2.x`, so the supported answer is: **drop and
|
|
188
|
+
recreate.** If your data is disposable, that is one command and it is the path
|
|
189
|
+
we took.
|
|
190
|
+
|
|
191
|
+
#### What it costs
|
|
192
|
+
|
|
193
|
+
- Three new columns, three new unique indexes, one trigger per affected table.
|
|
194
|
+
Negligible at any size we can currently defend claims about.
|
|
195
|
+
- The composite foreign keys are validated on `ALTER TABLE`, which takes an
|
|
196
|
+
`ACCESS EXCLUSIVE` lock. On a large `grant` table, add them `NOT VALID` first
|
|
197
|
+
and `VALIDATE CONSTRAINT` afterwards.
|
|
198
|
+
|
|
199
|
+
#### What it breaks in the API
|
|
200
|
+
|
|
201
|
+
Nothing, for a single-application deployment. `Filelayer.quickstart()` and the
|
|
202
|
+
`fl.files` / `fl.orgs` / `fl.shares` facades resolve into the default project
|
|
203
|
+
and read exactly as before. If you run more than one application against one
|
|
204
|
+
database, you must name a project — and before this change you could not, which
|
|
205
|
+
was the whole problem.
|
|
206
|
+
|
|
207
|
+
#### The secondary effect worth knowing
|
|
208
|
+
|
|
209
|
+
Project scoping is also what bounds unauthenticated audit-chain growth. A caller
|
|
210
|
+
probing org ids can only reach a tenant chain inside a project they are already
|
|
211
|
+
authenticated for; probes at every other id land on the system chain. That turns
|
|
212
|
+
"any internet caller can degrade any tenant" into "an authenticated customer can
|
|
213
|
+
degrade their own tenant" — a quota question rather than a security one. Ingest
|
|
214
|
+
rate limiting is still required; see `SEMANTICS.md`.
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
### Entry 2 — `0.3.0` → `0.4.0`: group grant subjects (RFC-001)
|
|
219
|
+
|
|
220
|
+
#### What was missing
|
|
221
|
+
|
|
222
|
+
`grant_subject` was `actor | link | anonymous`. Org-wide access existed only as
|
|
223
|
+
`file.visibility = 'org'`, which applies only to the file's **own** org. So
|
|
224
|
+
"every member of *that* organization may read this file" had no representation
|
|
225
|
+
at all, and "all admins of this org" had none either. Both were being worked
|
|
226
|
+
around with per-user fan-out, which makes membership changes only *eventually*
|
|
227
|
+
consistent with access — the opposite of the property the product sells.
|
|
228
|
+
|
|
229
|
+
#### What changed
|
|
230
|
+
|
|
231
|
+
`grant_subject := actor | org | role | link | anonymous`, plus two columns on
|
|
232
|
+
`file_grant`. Resolution is a join against `membership`, never a
|
|
233
|
+
materialization. See `SEMANTICS.md` §1a and §7b.
|
|
234
|
+
|
|
235
|
+
**This is a breaking schema change and an additive API change.** No existing
|
|
236
|
+
call site changes; `ShareInput.subject` gains two variants and
|
|
237
|
+
`shares.create` gains `withOrg` / `minRole`.
|
|
238
|
+
|
|
239
|
+
#### The migration
|
|
240
|
+
|
|
241
|
+
```sql
|
|
242
|
+
BEGIN;
|
|
243
|
+
|
|
244
|
+
-- 1. Two new subject types. They must be added in breadth order for the
|
|
245
|
+
-- enum's declaration order to remain meaningful to a reader; nothing in
|
|
246
|
+
-- the code depends on it (the role threshold is generated from
|
|
247
|
+
-- ROLE_RANK in authz.ts, never from the enum's ordinals).
|
|
248
|
+
ALTER TYPE grant_subject ADD VALUE IF NOT EXISTS 'org' AFTER 'actor';
|
|
249
|
+
ALTER TYPE grant_subject ADD VALUE IF NOT EXISTS 'role' AFTER 'org';
|
|
250
|
+
|
|
251
|
+
COMMIT; -- an added enum value must commit before it can be used
|
|
252
|
+
|
|
253
|
+
BEGIN;
|
|
254
|
+
|
|
255
|
+
-- 2. The subject columns. Both nullable; every existing row is unaffected.
|
|
256
|
+
ALTER TABLE file_grant ADD COLUMN subject_org_id uuid;
|
|
257
|
+
ALTER TABLE file_grant ADD COLUMN subject_min_role org_role;
|
|
258
|
+
|
|
259
|
+
-- 3. I1/P8: the subject org must be in the same PROJECT as the file.
|
|
260
|
+
-- `project_id` is derived from the file's org by trigger, so this is
|
|
261
|
+
-- what makes a cross-project group grant unrepresentable.
|
|
262
|
+
-- NOT VALID first on a large table, then VALIDATE, to avoid holding
|
|
263
|
+
-- ACCESS EXCLUSIVE for the scan.
|
|
264
|
+
ALTER TABLE file_grant
|
|
265
|
+
ADD CONSTRAINT file_grant_subject_org_id_project_id_fkey
|
|
266
|
+
FOREIGN KEY (subject_org_id, project_id) REFERENCES org (id, project_id)
|
|
267
|
+
ON DELETE CASCADE NOT VALID;
|
|
268
|
+
ALTER TABLE file_grant VALIDATE CONSTRAINT file_grant_subject_org_id_project_id_fkey;
|
|
269
|
+
|
|
270
|
+
-- 4. Subject coherence, replaced wholesale. Copy the new constraint body
|
|
271
|
+
-- verbatim from schema.sql rather than transcribing it.
|
|
272
|
+
ALTER TABLE file_grant DROP CONSTRAINT grant_subject_coherent;
|
|
273
|
+
-- ...then the five-branch CHECK from schema.sql.
|
|
274
|
+
|
|
275
|
+
CREATE INDEX CONCURRENTLY grant_subject_org_idx ON file_grant (file_id, subject_org_id)
|
|
276
|
+
WHERE revoked_at IS NULL AND subject_org_id IS NOT NULL;
|
|
277
|
+
|
|
278
|
+
COMMIT;
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
Then replace, verbatim from the `0.4.0` `schema.sql`:
|
|
282
|
+
|
|
283
|
+
1. `grant_scope_is_live()` — it takes a fourth argument, `p_subject_org_id`, and
|
|
284
|
+
gains the I2 term. **Its five call sites must be updated together**:
|
|
285
|
+
`grant_is_live()` (twice), `live_grant_recursive` (twice) and
|
|
286
|
+
`consume_download()`. Missing one leaves a group grant alive after its
|
|
287
|
+
subject org is deleted.
|
|
288
|
+
2. `file_grant_attenuate()` — it gains the **I6** check, and its trigger's
|
|
289
|
+
`UPDATE OF` list gains the four subject columns. Without the trigger change,
|
|
290
|
+
a delegated grant can be widened to an entire organization by a second
|
|
291
|
+
`UPDATE` statement.
|
|
292
|
+
|
|
293
|
+
#### What it costs
|
|
294
|
+
|
|
295
|
+
Two nullable columns, one partial index, one foreign key. The added subject-org
|
|
296
|
+
liveness term costs **+6.5%** on an eight-deep grant lookup, and the two extra
|
|
297
|
+
columns account for a further low-single-digit percentage through row width.
|
|
298
|
+
A group-grant decision is **~1.9 ms** against **~1.3 ms** for an actor-grant
|
|
299
|
+
decision on PGlite — one extra query, one join, and **independent of the size of
|
|
300
|
+
the named org**: the figure is measured against a 200-member org holding two
|
|
301
|
+
grant rows in total. Reproduce the timings with `npm run dev:bench` from the
|
|
302
|
+
repository root of a clone.
|
|
303
|
+
|
|
304
|
+
Authorization via an **org role** is unchanged (0.61 ms before and after):
|
|
305
|
+
standing resolution reaches the role first and returns before the group lookup
|
|
306
|
+
is issued.
|
|
307
|
+
|
|
308
|
+
#### What it does not do
|
|
309
|
+
|
|
310
|
+
No custom groups, no nested orgs, no configurable inheritance, no deny rules.
|
|
311
|
+
`file.visibility = 'org'` is retained and is unchanged.
|
|
312
|
+
|
|
313
|
+
---
|
|
314
|
+
|
|
315
|
+
## 4. What is not covered here
|
|
316
|
+
|
|
317
|
+
- **Data migration between storage adapters.** Moving objects from one bucket to
|
|
318
|
+
another is outside the library. `file.storage_provider` and
|
|
319
|
+
`file.storage_key` form a unique pair and are half of an object's identity, so
|
|
320
|
+
changing `provider` on an existing deployment repoints every row at a store
|
|
321
|
+
that does not have the bytes. There is no supported path for this yet.
|
|
322
|
+
- **Downgrades.** None of the entries above has a reverse script. Restore from a
|
|
323
|
+
backup.
|
|
324
|
+
- **Audit chain rewriting.** By construction there is none: `audit_event` has
|
|
325
|
+
rules that make `UPDATE` and `DELETE` no-ops, and the chain is verified by
|
|
326
|
+
recomputation. A migration that needed to rewrite history would invalidate
|
|
327
|
+
every subsequent hash, and we would rather that be impossible than
|
|
328
|
+
documented.
|
package/NOTICE
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
Filelayer
|
|
2
|
+
Copyright 2026 Technology Pro Bono S.L.
|
|
3
|
+
|
|
4
|
+
This product includes software developed by the Filelayer project
|
|
5
|
+
(https://github.com/filelayer/filelayer).
|
|
6
|
+
|
|
7
|
+
Licensed under the Apache License, Version 2.0. See the LICENSE file in
|
|
8
|
+
this distribution, or http://www.apache.org/licenses/LICENSE-2.0.
|
|
9
|
+
|
|
10
|
+
--------------------------------------------------------------------------
|
|
11
|
+
THIRD-PARTY SOFTWARE (informational)
|
|
12
|
+
--------------------------------------------------------------------------
|
|
13
|
+
|
|
14
|
+
The following is recorded for the convenience of downstream redistributors
|
|
15
|
+
and anyone reviewing this distribution's licence obligations. It is
|
|
16
|
+
NOT a required attribution notice under Apache-2.0 section 4(d), and
|
|
17
|
+
redistributors of Filelayer do not inherit an obligation to reproduce it.
|
|
18
|
+
|
|
19
|
+
Filelayer has exactly one runtime dependency:
|
|
20
|
+
|
|
21
|
+
@electric-sql/pglite
|
|
22
|
+
PostgreSQL compiled to WebAssembly, used for the embedded database in
|
|
23
|
+
`Filelayer.quickstart()` and in the test suite.
|
|
24
|
+
Licensed under the Apache License, Version 2.0.
|
|
25
|
+
https://github.com/electric-sql/pglite
|
|
26
|
+
|
|
27
|
+
It is declared as a normal npm dependency and is installed from the
|
|
28
|
+
registry by the consumer. No part of it is vendored into, copied into, or
|
|
29
|
+
redistributed inside this repository or the published tarball, so this
|
|
30
|
+
distribution is not a Derivative Work of it. It ships no NOTICE file of
|
|
31
|
+
its own, so Apache-2.0 section 4(d) imposes no propagation requirement
|
|
32
|
+
even where a redistributor bundles it.
|
|
33
|
+
|
|
34
|
+
No other third-party code is vendored, copied or embedded in this
|
|
35
|
+
distribution. The comparison implementations under `benchmark/` are original
|
|
36
|
+
work written for this repository; they are not published to npm and are not
|
|
37
|
+
part of the distributed package.
|