@adonis-agora/collaboration 0.7.4 → 0.9.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 +96 -0
- package/README.md +1 -0
- package/dist/commands/collaboration_prune.d.ts +25 -0
- package/dist/commands/collaboration_prune.d.ts.map +1 -0
- package/dist/commands/collaboration_prune.js +59 -0
- package/dist/commands/collaboration_prune.js.map +1 -0
- package/dist/commands/commands.json +1 -1
- package/dist/configure.d.ts +1 -1
- package/dist/configure.js +1 -1
- package/dist/providers/collaboration_provider.d.ts.map +1 -1
- package/dist/providers/collaboration_provider.js +5 -2
- package/dist/providers/collaboration_provider.js.map +1 -1
- package/dist/src/collaboration_manager.d.ts +20 -1
- package/dist/src/collaboration_manager.d.ts.map +1 -1
- package/dist/src/collaboration_manager.js +28 -3
- package/dist/src/collaboration_manager.js.map +1 -1
- package/dist/src/documents.d.ts +3 -3
- package/dist/src/documents.d.ts.map +1 -1
- package/dist/src/documents.js.map +1 -1
- package/dist/src/drivers/automerge/automerge_driver.d.ts.map +1 -1
- package/dist/src/drivers/automerge/automerge_driver.js +24 -0
- package/dist/src/drivers/automerge/automerge_driver.js.map +1 -1
- package/dist/src/drivers/yjs/yjs_driver.d.ts.map +1 -1
- package/dist/src/drivers/yjs/yjs_driver.js +17 -2
- package/dist/src/drivers/yjs/yjs_driver.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/routes.d.ts.map +1 -1
- package/dist/src/routes.js +104 -36
- package/dist/src/routes.js.map +1 -1
- package/dist/src/storage/file_system_storage.d.ts +4 -1
- package/dist/src/storage/file_system_storage.d.ts.map +1 -1
- package/dist/src/storage/file_system_storage.js +42 -1
- package/dist/src/storage/file_system_storage.js.map +1 -1
- package/dist/src/storage/in_memory_storage.d.ts +2 -1
- package/dist/src/storage/in_memory_storage.d.ts.map +1 -1
- package/dist/src/storage/in_memory_storage.js +17 -0
- package/dist/src/storage/in_memory_storage.js.map +1 -1
- package/dist/src/storage/lucid_storage.d.ts +16 -6
- package/dist/src/storage/lucid_storage.d.ts.map +1 -1
- package/dist/src/storage/lucid_storage.js +102 -35
- package/dist/src/storage/lucid_storage.js.map +1 -1
- package/dist/src/storage/shared.d.ts +17 -0
- package/dist/src/storage/shared.d.ts.map +1 -0
- package/dist/src/storage/shared.js +21 -0
- package/dist/src/storage/shared.js.map +1 -0
- package/dist/src/types.d.ts +17 -0
- package/dist/src/types.d.ts.map +1 -1
- package/dist/stubs/collaboration/migrations/collab_comments.stub +4 -4
- package/dist/stubs/collaboration/migrations/collab_documents.stub +5 -5
- package/dist/stubs/collaboration/migrations/collab_versions.stub +9 -7
- package/package.json +19 -14
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,101 @@
|
|
|
1
1
|
# @adonis-agora/collaboration
|
|
2
2
|
|
|
3
|
+
## 0.9.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 16b8f4e: Add version retention to the library instead of the docs: `pruneVersions` on the storage SPI, `collaboration:prune` on the CLI.
|
|
8
|
+
|
|
9
|
+
**The API.** `CollaborationStorage` gains
|
|
10
|
+
`pruneVersions({ keep, docName?, dryRun? }): Promise<number>` — delete all but the `keep` most
|
|
11
|
+
recent versions and return how many went. `keep` is counted **per document**, so a document
|
|
12
|
+
versioned every minute never evicts the history of one versioned twice a year; `docName` narrows
|
|
13
|
+
the run to one document and `dryRun` counts without deleting. `keep: 0` deletes every version,
|
|
14
|
+
while a negative, fractional or `NaN` `keep` throws instead of silently wiping the history the
|
|
15
|
+
caller meant to keep. Implemented in all three built-in storages, and exposed on the manager as
|
|
16
|
+
`collaboration.current.pruneVersions({ keep })` for scheduling it from code.
|
|
17
|
+
|
|
18
|
+
**The command.** `node ace collaboration:prune --keep=20 [--doc=<name>] [--dry-run]` prints how
|
|
19
|
+
many versions it removed. The docs previously told you to run a hand-written
|
|
20
|
+
`DELETE FROM collab_versions` for this; they no longer do.
|
|
21
|
+
|
|
22
|
+
**Fixes found by running the Lucid storage against a real Postgres** (a new
|
|
23
|
+
`pnpm test:integration` suite boots a throwaway container and runs the _published_ migrations):
|
|
24
|
+
|
|
25
|
+
- `LucidStorage` could not insert anything through a real Lucid connection. `db.connection().from(table)`
|
|
26
|
+
returns the SELECT builder, which has no `insert()` — so saving a document, a version or a comment
|
|
27
|
+
threw `insert is not a function`. The three insert paths now use `.table(...)`, which is the insert
|
|
28
|
+
builder on both Lucid and knex.
|
|
29
|
+
- The lazy `CREATE TABLE IF NOT EXISTS` bootstrap crashed on any app that had run the published
|
|
30
|
+
migrations: knex skips the table but still emits its `CREATE INDEX`, which fails with
|
|
31
|
+
`relation "collab_comments_doc_name_space_index" already exists`. Existing tables are now left
|
|
32
|
+
alone.
|
|
33
|
+
|
|
34
|
+
**Custom storages** must implement `pruneVersions` — the custom-storage guide documents the
|
|
35
|
+
per-document contract, including the worked example.
|
|
36
|
+
|
|
37
|
+
### Patch Changes
|
|
38
|
+
|
|
39
|
+
- 0a8550a: **fix(lucid): lazy resolve db facade to avoid boot-time race**
|
|
40
|
+
|
|
41
|
+
The static `import dbFacade from '@adonisjs/lucid/services/db'` evaluated the
|
|
42
|
+
module before the Lucid provider had registered the facade, so `dbFacade` was
|
|
43
|
+
`undefined` and every `LucidStorage` operation crashed with
|
|
44
|
+
`Cannot read properties of undefined (reading 'connection')`.
|
|
45
|
+
|
|
46
|
+
Replaced the static import with a dynamic `import()` inside `knex()`, cached
|
|
47
|
+
in a static field. The first call to any storage method (e.g. `saveDocument`,
|
|
48
|
+
`loadDocument`) resolves the facade lazily — by then the app is fully booted
|
|
49
|
+
and the facade is available.
|
|
50
|
+
|
|
51
|
+
The constructor still accepts an optional `db` argument for tests that provide
|
|
52
|
+
a mocked or real connection directly.
|
|
53
|
+
|
|
54
|
+
## 0.8.0
|
|
55
|
+
|
|
56
|
+
### Minor Changes
|
|
57
|
+
|
|
58
|
+
- 4f4a622: Enforce the document permissions, fix the wiring that made declared documents a no-op, and rewrite the docs.
|
|
59
|
+
|
|
60
|
+
**Permissions are now enforced, not just reported.** `canWrite: false` makes the sync connection
|
|
61
|
+
read-only (Hocuspocus connection config on Yjs, dropped inbound messages on Automerge) — the client
|
|
62
|
+
still receives every edit, its own are ignored. The built-in REST routes resolve the caller and
|
|
63
|
+
check the matching permission before touching anything: `canRead` to read comments, versions and
|
|
64
|
+
state; `canWrite` to create or restore a version; `canComment` to write a comment. A comment is
|
|
65
|
+
attributed to the authenticated user, and a `userId` in the request body is ignored.
|
|
66
|
+
|
|
67
|
+
Apps mounting these routes without auth middleware will now get `401` instead of unauthenticated
|
|
68
|
+
access — set `routes.middleware`.
|
|
69
|
+
|
|
70
|
+
**Fixes:**
|
|
71
|
+
|
|
72
|
+
- `config.documents` was never forwarded from the provider to the manager, so every `defineDocument`
|
|
73
|
+
declaration was silently ignored — per-document `engine` and `authorize` never applied. The REST
|
|
74
|
+
token endpoint also used only the global `authorize`, which bypassed per-document rules entirely
|
|
75
|
+
on the edge engines.
|
|
76
|
+
- The published migrations created a different schema from the one `LucidStorage` queries
|
|
77
|
+
(`document_name` vs `doc_name`, no `state` column), so running them broke every read.
|
|
78
|
+
- `LucidStorage` discarded version snapshots and `loadVersionSnapshot` returned the current
|
|
79
|
+
document, making `restoreVersion` and `diffVersions` silent no-ops.
|
|
80
|
+
- `lucidStorage()` defaulted to a hard-coded connection name; it now falls back to the app's default
|
|
81
|
+
connection.
|
|
82
|
+
|
|
83
|
+
**Client:** `useAwareness` also returns the `awareness` channel, which is what Tiptap's
|
|
84
|
+
`CollaborationCursor` needs to publish the local caret.
|
|
85
|
+
|
|
86
|
+
### Patch Changes
|
|
87
|
+
|
|
88
|
+
- d6e162e: **fix(yjs): seed persisted documents via `onLoadDocument`**
|
|
89
|
+
|
|
90
|
+
The YjsDriver wired `onStoreDocument` (persist) but never `onLoadDocument`. Without
|
|
91
|
+
that hook Hocuspocus creates an **empty in-memory Y.Doc on every connection**, so a
|
|
92
|
+
previously saved document always came back blank to clients (and got overwritten on
|
|
93
|
+
the next save). A whiteboard/text doc that was saved would reopen vazio/empty on reload.
|
|
94
|
+
|
|
95
|
+
`onLoadDocument` now loads the stored state via the configured storage and seeds the
|
|
96
|
+
doc before serving it (no-op when nothing was persisted yet). Added a regression test
|
|
97
|
+
(`yjs_driver_persist.spec.ts`) covering both paths.
|
|
98
|
+
|
|
3
99
|
## 0.2.0
|
|
4
100
|
|
|
5
101
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -85,6 +85,7 @@ The transport is chosen automatically from the engine reported by `GET /collabor
|
|
|
85
85
|
### Commands
|
|
86
86
|
|
|
87
87
|
- `collaboration:init` — scaffolds the documents directory, base migrations (when a database is configured) and the PartyKit worker (`--engine=partykit`)
|
|
88
|
+
- `collaboration:prune --keep=20 [--doc=<name>] [--dry-run]` — deletes all but the N most recent versions of each document (same call as `collaboration.pruneVersions({ keep })`)
|
|
88
89
|
- `make:collab-document <name>` — generates shared document types in `app/collaboration/documents/` (spaces + allowed anchor kinds), importable by the frontend
|
|
89
90
|
|
|
90
91
|
Commands are registered automatically by `configure`; manual setups need `commands: ['@adonis-agora/collaboration/commands']` in `adonisrc.ts`.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { BaseCommand } from '@adonisjs/core/ace';
|
|
2
|
+
/**
|
|
3
|
+
* `node ace collaboration:prune --keep=20`
|
|
4
|
+
*
|
|
5
|
+
* Applies a retention policy to the version history: keeps the `--keep` most
|
|
6
|
+
* recent versions of **each** document and deletes the rest. `keep` is per
|
|
7
|
+
* document, so a document versioned every minute never evicts the history of
|
|
8
|
+
* one versioned twice a year.
|
|
9
|
+
*
|
|
10
|
+
* There is no automatic retention in the library — run this from cron or a
|
|
11
|
+
* scheduler at whatever interval your version rate justifies. The same call
|
|
12
|
+
* from code is `collaboration.current.pruneVersions({ keep })`.
|
|
13
|
+
*/
|
|
14
|
+
export default class CollaborationPrune extends BaseCommand {
|
|
15
|
+
static commandName: string;
|
|
16
|
+
static description: string;
|
|
17
|
+
static options: {
|
|
18
|
+
startApp: boolean;
|
|
19
|
+
};
|
|
20
|
+
keep?: number;
|
|
21
|
+
doc?: string;
|
|
22
|
+
dryRun?: boolean;
|
|
23
|
+
run(): Promise<void>;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=collaboration_prune.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collaboration_prune.d.ts","sourceRoot":"","sources":["../../commands/collaboration_prune.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAS,MAAM,oBAAoB,CAAC;AAGxD;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,OAAO,OAAO,kBAAmB,SAAQ,WAAW;IACzD,OAAgB,WAAW,SAAyB;IACpD,OAAgB,WAAW,SAAgE;IAC3F,OAAgB,OAAO;;MAAsB;IAGrC,IAAI,CAAC,EAAE,MAAM,CAAC;IAGd,GAAG,CAAC,EAAE,MAAM,CAAC;IAGb,MAAM,CAAC,EAAE,OAAO,CAAC;IAEV,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CA4BpC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { BaseCommand, flags } from '@adonisjs/core/ace';
|
|
8
|
+
import { CollaborationManager } from '../src/collaboration_manager.js';
|
|
9
|
+
/**
|
|
10
|
+
* `node ace collaboration:prune --keep=20`
|
|
11
|
+
*
|
|
12
|
+
* Applies a retention policy to the version history: keeps the `--keep` most
|
|
13
|
+
* recent versions of **each** document and deletes the rest. `keep` is per
|
|
14
|
+
* document, so a document versioned every minute never evicts the history of
|
|
15
|
+
* one versioned twice a year.
|
|
16
|
+
*
|
|
17
|
+
* There is no automatic retention in the library — run this from cron or a
|
|
18
|
+
* scheduler at whatever interval your version rate justifies. The same call
|
|
19
|
+
* from code is `collaboration.current.pruneVersions({ keep })`.
|
|
20
|
+
*/
|
|
21
|
+
export default class CollaborationPrune extends BaseCommand {
|
|
22
|
+
static commandName = 'collaboration:prune';
|
|
23
|
+
static description = 'Delete all but the N most recent versions of each document';
|
|
24
|
+
static options = { startApp: true };
|
|
25
|
+
async run() {
|
|
26
|
+
const keep = this.keep ?? 20;
|
|
27
|
+
const manager = await this.app.container.make(CollaborationManager);
|
|
28
|
+
let removed;
|
|
29
|
+
try {
|
|
30
|
+
removed = await manager.pruneVersions({
|
|
31
|
+
keep,
|
|
32
|
+
...(this.doc ? { docName: this.doc } : {}),
|
|
33
|
+
...(this.dryRun ? { dryRun: true } : {}),
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
this.logger.error(error instanceof Error ? error.message : String(error));
|
|
38
|
+
this.exitCode = 1;
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const scope = this.doc ? `document '${this.doc}'` : 'all documents';
|
|
42
|
+
if (this.dryRun) {
|
|
43
|
+
this.logger.info(`dry run: ${removed} version(s) would be deleted from ${scope}, keeping ${keep} per document`);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
this.logger.action(`prune ${scope}`).succeeded();
|
|
47
|
+
this.logger.success(`${removed} version(s) deleted, keeping ${keep} per document.`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
__decorate([
|
|
51
|
+
flags.number({ description: 'Versions to keep per document (default 20)' })
|
|
52
|
+
], CollaborationPrune.prototype, "keep", void 0);
|
|
53
|
+
__decorate([
|
|
54
|
+
flags.string({ description: 'Prune a single document instead of every one' })
|
|
55
|
+
], CollaborationPrune.prototype, "doc", void 0);
|
|
56
|
+
__decorate([
|
|
57
|
+
flags.boolean({ description: 'Report what would be deleted without deleting anything' })
|
|
58
|
+
], CollaborationPrune.prototype, "dryRun", void 0);
|
|
59
|
+
//# sourceMappingURL=collaboration_prune.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collaboration_prune.js","sourceRoot":"","sources":["../../commands/collaboration_prune.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAEvE;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,OAAO,OAAO,kBAAmB,SAAQ,WAAW;IACzD,MAAM,CAAU,WAAW,GAAG,qBAAqB,CAAC;IACpD,MAAM,CAAU,WAAW,GAAG,4DAA4D,CAAC;IAC3F,MAAM,CAAU,OAAO,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAWpC,KAAK,CAAC,GAAG;QAChB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAEpE,IAAI,OAAe,CAAC;QACpB,IAAI,CAAC;YACH,OAAO,GAAG,MAAM,OAAO,CAAC,aAAa,CAAC;gBACpC,IAAI;gBACJ,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC1C,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACzC,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YAC1E,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;YAClB,OAAO;QACT,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,aAAa,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,eAAe,CAAC;QACpE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,YAAY,OAAO,qCAAqC,KAAK,aAAa,IAAI,eAAe,CAC9F,CAAC;YACF,OAAO;QACT,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,KAAK,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC;QACjD,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,OAAO,gCAAgC,IAAI,gBAAgB,CAAC,CAAC;IACtF,CAAC;;AAnCO;IADP,KAAK,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,4CAA4C,EAAE,CAAC;gDACtD;AAGd;IADP,KAAK,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,8CAA8C,EAAE,CAAC;+CACzD;AAGb;IADP,KAAK,CAAC,OAAO,CAAC,EAAE,WAAW,EAAE,wDAAwD,EAAE,CAAC;kDAChE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"commands":[{"commandName":"collaboration:init","description":"Scaffold base directories, migrations and (optionally) the PartyKit worker","help":"","namespace":"collaboration","aliases":[],"flags":[{"name":"engine","flagName":"engine","required":false,"type":"string","description":"Sync engine (yjs | automerge | partykit) — defaults to the one in config"}],"args":[],"options":{"startApp":true},"filePath":"collaboration_init.js"},{"commandName":"make:collab-document","description":"Make shared types for a collaborative document (spaces + anchors)","help":"","namespace":"make","aliases":[],"flags":[{"name":"anchors","flagName":"anchors","required":false,"type":"string","description":"Allowed anchor kinds as a comma-separated list (text-range,canvas-object,timestamp)"},{"name":"spaces","flagName":"spaces","required":false,"type":"string","description":"Document spaces as a comma-separated list (default 'text')"}],"args":[{"name":"name","argumentName":"name","required":true,"description":"Collaborative document name (e.g. researches/writing)","type":"string"}],"options":{"startApp":true,"allowUnknownFlags":true},"filePath":"make_collab_document.js"}],"version":1}
|
|
1
|
+
{"commands":[{"commandName":"collaboration:init","description":"Scaffold base directories, migrations and (optionally) the PartyKit worker","help":"","namespace":"collaboration","aliases":[],"flags":[{"name":"engine","flagName":"engine","required":false,"type":"string","description":"Sync engine (yjs | automerge | partykit) — defaults to the one in config"}],"args":[],"options":{"startApp":true},"filePath":"collaboration_init.js"},{"commandName":"collaboration:prune","description":"Delete all but the N most recent versions of each document","help":"","namespace":"collaboration","aliases":[],"flags":[{"name":"keep","flagName":"keep","required":false,"type":"number","description":"Versions to keep per document (default 20)"},{"name":"doc","flagName":"doc","required":false,"type":"string","description":"Prune a single document instead of every one"},{"name":"dryRun","flagName":"dry-run","required":false,"type":"boolean","description":"Report what would be deleted without deleting anything"}],"args":[],"options":{"startApp":true},"filePath":"collaboration_prune.js"},{"commandName":"make:collab-document","description":"Make shared types for a collaborative document (spaces + anchors)","help":"","namespace":"make","aliases":[],"flags":[{"name":"anchors","flagName":"anchors","required":false,"type":"string","description":"Allowed anchor kinds as a comma-separated list (text-range,canvas-object,timestamp)"},{"name":"spaces","flagName":"spaces","required":false,"type":"string","description":"Document spaces as a comma-separated list (default 'text')"}],"args":[{"name":"name","argumentName":"name","required":true,"description":"Collaborative document name (e.g. researches/writing)","type":"string"}],"options":{"startApp":true,"allowUnknownFlags":true},"filePath":"make_collab_document.js"}],"version":1}
|
package/dist/configure.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import type Configure from '@adonisjs/core/commands/configure';
|
|
|
4
4
|
*
|
|
5
5
|
* 1. registers the collaboration service provider in `adonisrc.ts`;
|
|
6
6
|
* 2. registers the ace commands barrel (`collaboration:init`,
|
|
7
|
-
* `make:collab-document`);
|
|
7
|
+
* `collaboration:prune`, `make:collab-document`);
|
|
8
8
|
* 3. publishes `config/collaboration.ts` (engine, path, redis, authorize,
|
|
9
9
|
* storage).
|
|
10
10
|
*/
|
package/dist/configure.js
CHANGED
|
@@ -4,7 +4,7 @@ import { stubsRoot } from './stubs/main.js';
|
|
|
4
4
|
*
|
|
5
5
|
* 1. registers the collaboration service provider in `adonisrc.ts`;
|
|
6
6
|
* 2. registers the ace commands barrel (`collaboration:init`,
|
|
7
|
-
* `make:collab-document`);
|
|
7
|
+
* `collaboration:prune`, `make:collab-document`);
|
|
8
8
|
* 3. publishes `config/collaboration.ts` (engine, path, redis, authorize,
|
|
9
9
|
* storage).
|
|
10
10
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collaboration_provider.d.ts","sourceRoot":"","sources":["../../providers/collaboration_provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAQ/D;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,OAAO,OAAO,4BAA4B;IAGnC,SAAS,CAAC,GAAG,EAAE,kBAAkB;IAF7C,OAAO,CAAC,MAAM,CAAC,CAAyB;gBAElB,GAAG,EAAE,kBAAkB;IAE7C,QAAQ;
|
|
1
|
+
{"version":3,"file":"collaboration_provider.d.ts","sourceRoot":"","sources":["../../providers/collaboration_provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAQ/D;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,OAAO,OAAO,4BAA4B;IAGnC,SAAS,CAAC,GAAG,EAAE,kBAAkB;IAF7C,OAAO,CAAC,MAAM,CAAC,CAAyB;gBAElB,GAAG,EAAE,kBAAkB;IAE7C,QAAQ;IA8BF,KAAK;IAiDL,QAAQ;CAIf"}
|
|
@@ -34,6 +34,7 @@ export default class CollaborationServiceProvider {
|
|
|
34
34
|
const managerConfig = {
|
|
35
35
|
engine: config.engine ?? 'yjs',
|
|
36
36
|
...(config.engineFor ? { engineFor: config.engineFor } : {}),
|
|
37
|
+
...(config.documents ? { documents: config.documents } : {}),
|
|
37
38
|
...(config.authorize ? { authorize: config.authorize } : {}),
|
|
38
39
|
path: config.path ?? '/collaboration',
|
|
39
40
|
debounce: config.debounce ?? 2000,
|
|
@@ -75,8 +76,10 @@ export default class CollaborationServiceProvider {
|
|
|
75
76
|
runtimeOptions.middleware = routes.middleware;
|
|
76
77
|
if (routes?.resolveUser !== undefined)
|
|
77
78
|
runtimeOptions.resolveUser = routes.resolveUser;
|
|
78
|
-
|
|
79
|
-
|
|
79
|
+
// The token endpoint must resolve permissions exactly like the WebSocket
|
|
80
|
+
// handshake does — through the manager, so declared documents' own
|
|
81
|
+
// `authorize` applies and an unmatched document still fails closed.
|
|
82
|
+
runtimeOptions.authorize = (ctx, docName) => manager.authorize(ctx, docName);
|
|
80
83
|
await collaborationRoutes(router, runtimeOptions);
|
|
81
84
|
}
|
|
82
85
|
async shutdown() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collaboration_provider.js","sourceRoot":"","sources":["../../providers/collaboration_provider.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAEvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAEzE;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,OAAO,OAAO,4BAA4B;IAGzB;IAFd,MAAM,CAA0B;IAExC,YAAsB,GAAuB;QAAvB,QAAG,GAAH,GAAG,CAAoB;IAAG,CAAC;IAEjD,QAAQ;QACN,+FAA+F;QAC/F,0FAA0F;QAC1F,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAEvB,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAyB,eAAe,CAAC,CAAC;QAC5E,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QAErB,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,SAAS,CAAC,oBAAoB,EAAE,GAAG,EAAE;
|
|
1
|
+
{"version":3,"file":"collaboration_provider.js","sourceRoot":"","sources":["../../providers/collaboration_provider.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,7 +4,8 @@ import { PartyKitDriver } from './drivers/partykit/partykit_driver.js';
|
|
|
4
4
|
import { YjsDriver } from './drivers/yjs/yjs_driver.js';
|
|
5
5
|
import { CommentService } from './services/comment_service.js';
|
|
6
6
|
import { type PresenceMember, PresenceService, type PresenceStore } from './services/presence_service.js';
|
|
7
|
-
import type {
|
|
7
|
+
import type { CollabConnectionContext, CollabPermission } from './types.js';
|
|
8
|
+
import type { CollabDiffSummary, CollabVersion, CollaborationConfig, CollaborationEngine, PruneVersionsOptions } from './types.js';
|
|
8
9
|
/**
|
|
9
10
|
* Library facade. Each document resolves to an engine (per-doc via
|
|
10
11
|
* `config.engineFor`, default `config.engine`) and a driver instance per
|
|
@@ -23,6 +24,15 @@ export declare class CollaborationManager {
|
|
|
23
24
|
engineFor({ docName }: {
|
|
24
25
|
docName: string;
|
|
25
26
|
}): Promise<CollaborationEngine>;
|
|
27
|
+
/**
|
|
28
|
+
* Resolved authorization for a document: the declared document's own
|
|
29
|
+
* `authorize` when one matches, else the global `authorize`, else deny.
|
|
30
|
+
*
|
|
31
|
+
* Public because the permission seam has to hold on both paths — the
|
|
32
|
+
* WebSocket handshake AND the REST token endpoint issue credentials, and
|
|
33
|
+
* both must resolve the rule the same way.
|
|
34
|
+
*/
|
|
35
|
+
authorize(ctx: CollabConnectionContext, docName: string): Promise<CollabPermission>;
|
|
26
36
|
get engine(): string;
|
|
27
37
|
/** Attaches the WebSocket(s) to the Adonis HTTP server. No-op on edge. */
|
|
28
38
|
attach(server: import('node:http').Server): Promise<void>;
|
|
@@ -55,6 +65,15 @@ export declare class CollaborationManager {
|
|
|
55
65
|
docName: string;
|
|
56
66
|
state: Uint8Array;
|
|
57
67
|
}): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* Deletes all but the `keep` most recent versions of each document, and
|
|
70
|
+
* returns how many were removed. `keep` is per document — a busy document
|
|
71
|
+
* never evicts another one's history.
|
|
72
|
+
*
|
|
73
|
+
* Meant for a scheduled job; `node ace collaboration:prune` is the same
|
|
74
|
+
* call from the CLI.
|
|
75
|
+
*/
|
|
76
|
+
pruneVersions({ keep, docName, dryRun }: PruneVersionsOptions): Promise<number>;
|
|
58
77
|
/** Online members of a document (across all instances, when Redis set). */
|
|
59
78
|
listPresence({ docName }: {
|
|
60
79
|
docName: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collaboration_manager.d.ts","sourceRoot":"","sources":["../../src/collaboration_manager.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAA2B,MAAM,aAAa,CAAC;AAChF,OAAO,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAC1E,OAAO,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAEvE,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EACL,KAAK,cAAc,EACnB,eAAe,EACf,KAAK,aAAa,EACnB,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"collaboration_manager.d.ts","sourceRoot":"","sources":["../../src/collaboration_manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -47,8 +47,15 @@ export class CollaborationManager {
|
|
|
47
47
|
}
|
|
48
48
|
return null;
|
|
49
49
|
}
|
|
50
|
-
/**
|
|
51
|
-
|
|
50
|
+
/**
|
|
51
|
+
* Resolved authorization for a document: the declared document's own
|
|
52
|
+
* `authorize` when one matches, else the global `authorize`, else deny.
|
|
53
|
+
*
|
|
54
|
+
* Public because the permission seam has to hold on both paths — the
|
|
55
|
+
* WebSocket handshake AND the REST token endpoint issue credentials, and
|
|
56
|
+
* both must resolve the rule the same way.
|
|
57
|
+
*/
|
|
58
|
+
async authorize(ctx, docName) {
|
|
52
59
|
const declared = this.#documentFor(docName);
|
|
53
60
|
if (declared?.declaration.authorize) {
|
|
54
61
|
return declared.declaration.authorize(ctx, { docName, params: declared.params });
|
|
@@ -69,7 +76,7 @@ export class CollaborationManager {
|
|
|
69
76
|
});
|
|
70
77
|
}
|
|
71
78
|
const shared = {
|
|
72
|
-
authorize: (ctx, docName) => this
|
|
79
|
+
authorize: (ctx, docName) => this.authorize(ctx, docName),
|
|
73
80
|
...(storage ? { storage } : {}),
|
|
74
81
|
...(this.config.path !== undefined ? { path: this.config.path } : {}),
|
|
75
82
|
...(this.config.debounce !== undefined ? { debounce: this.config.debounce } : {}),
|
|
@@ -128,6 +135,24 @@ export class CollaborationManager {
|
|
|
128
135
|
}
|
|
129
136
|
await this.config.storage.saveDocument(docName, state);
|
|
130
137
|
}
|
|
138
|
+
/**
|
|
139
|
+
* Deletes all but the `keep` most recent versions of each document, and
|
|
140
|
+
* returns how many were removed. `keep` is per document — a busy document
|
|
141
|
+
* never evicts another one's history.
|
|
142
|
+
*
|
|
143
|
+
* Meant for a scheduled job; `node ace collaboration:prune` is the same
|
|
144
|
+
* call from the CLI.
|
|
145
|
+
*/
|
|
146
|
+
async pruneVersions({ keep, docName, dryRun }) {
|
|
147
|
+
if (!this.config.storage) {
|
|
148
|
+
throw new Error('[@adonis-agora/collaboration] pruneVersions requires a storage backend — configure storage in config/collaboration.ts');
|
|
149
|
+
}
|
|
150
|
+
return this.config.storage.pruneVersions({
|
|
151
|
+
keep,
|
|
152
|
+
...(docName !== undefined ? { docName } : {}),
|
|
153
|
+
...(dryRun !== undefined ? { dryRun } : {}),
|
|
154
|
+
});
|
|
155
|
+
}
|
|
131
156
|
/** Online members of a document (across all instances, when Redis set). */
|
|
132
157
|
async listPresence({ docName }) {
|
|
133
158
|
return this.presence?.list(docName) ?? [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collaboration_manager.js","sourceRoot":"","sources":["../../src/collaboration_manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAEtD,OAAO,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAC1E,OAAO,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AACvE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAEL,eAAe,GAEhB,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"collaboration_manager.js","sourceRoot":"","sources":["../../src/collaboration_manager.ts"],"names":[],"mappings":"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"}
|
package/dist/src/documents.d.ts
CHANGED
|
@@ -9,10 +9,10 @@ import type { CollabConnectionContext, CollabPermission, CollaborationEngine } f
|
|
|
9
9
|
* @example
|
|
10
10
|
* // config/collaboration.ts
|
|
11
11
|
* documents: {
|
|
12
|
-
* 'researches/:id/writing': defineDocument({
|
|
12
|
+
* 'researches/:id/writing': defineDocument<{ id: string }>({
|
|
13
13
|
* engine: 'yjs',
|
|
14
|
-
* async authorize(ctx, {
|
|
15
|
-
* const research = await findAccessibleResearch(ctx.userId, id)
|
|
14
|
+
* async authorize(ctx, { docName, params }) {
|
|
15
|
+
* const research = await findAccessibleResearch(ctx.userId, params.id)
|
|
16
16
|
* return research
|
|
17
17
|
* ? { canRead: true, canWrite: true, canComment: true }
|
|
18
18
|
* : { canRead: false, canWrite: false, canComment: false }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"documents.d.ts","sourceRoot":"","sources":["../../src/documents.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEjG;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,yBAAyB,
|
|
1
|
+
{"version":3,"file":"documents.d.ts","sourceRoot":"","sources":["../../src/documents.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEjG;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,yBAAyB,CACxC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAEzD,iEAAiE;IACjE,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B;;;;OAIG;IACH,SAAS,CAAC,EAAE,CACV,GAAG,EAAE,uBAAuB,EAC5B,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,CAAC,CAAA;KAAE,KACjC,OAAO,CAAC,gBAAgB,CAAC,CAAC;CAChC;AAED,wBAAgB,cAAc,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACtF,WAAW,EAAE,yBAAyB,CAAC,CAAC,CAAC,GACxC,yBAAyB,CAAC,CAAC,CAAC,CAE9B;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,GACd,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAe/B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"documents.js","sourceRoot":"","sources":["../../src/documents.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"documents.js","sourceRoot":"","sources":["../../src/documents.ts"],"names":[],"mappings":"AAuCA,MAAM,UAAU,cAAc,CAC5B,WAAyC;IAEzC,OAAO,WAAW,CAAC;AACrB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAClC,OAAe,EACf,OAAe;IAEf,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACjC,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAClC,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAEhD,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC;QAClD,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAE,CAAC;QAC3B,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACzB,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,CAAE,CAAC;QACzC,CAAC;aAAM,IAAI,IAAI,KAAK,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;YAClC,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"automerge_driver.d.ts","sourceRoot":"","sources":["../../../../src/drivers/automerge/automerge_driver.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AACpF,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAwB,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"automerge_driver.d.ts","sourceRoot":"","sources":["../../../../src/drivers/automerge/automerge_driver.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AACpF,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAwB,MAAM,gBAAgB,CAAC;AA4B7F,qBAAa,eAAgB,YAAW,mBAAmB;IACzD,QAAQ,CAAC,MAAM,eAAe;IAE9B,OAAO,CAAC,KAAK,CAA2B;IACxC,OAAO,CAAC,GAAG,CAAC,CAAkB;IAC9B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA0B;IAClD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuB;IAC/C,OAAO,CAAC,aAAa,CAAoD;gBAE7D,OAAO,EAAE,uBAAuB;YAK9B,QAAQ;IActB,OAAO,CAAC,SAAS;IAQX,MAAM,CAAC,MAAM,EAAE,OAAO,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YA4DjD,mBAAmB;IAkBjC,OAAO,CAAC,gBAAgB;IAclB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAKtD,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAMvD,+DAA+D;IACzD,aAAa,CACjB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,KAAK,EAAE,MAAM,GAAG,IAAI,GACnB,OAAO,CAAC,aAAa,CAAC;IAgBnB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAIvD,cAAc,CAClB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAAG,IAAI,GACzB,OAAO,CAAC,IAAI,CAAC;IAoBV,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAenF,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAM7B"}
|
|
@@ -3,6 +3,22 @@ import { next as ANext } from '@automerge/automerge';
|
|
|
3
3
|
import { WebSocketServer } from 'ws';
|
|
4
4
|
import { createVersionMetadata, seqVersions } from '../../versioning.js';
|
|
5
5
|
import { lineDiff, resolveStorage } from '../shared.js';
|
|
6
|
+
/**
|
|
7
|
+
* Automerge driver.
|
|
8
|
+
*
|
|
9
|
+
* Automerge has NATIVE version control: every change generates a hash and
|
|
10
|
+
* the full history lives inside the doc itself (`Automerge.getHistory`).
|
|
11
|
+
* `createVersion` here is just a marker (label + hash heads) — the content
|
|
12
|
+
* between versions is already in the doc. `restoreVersion` brings the doc
|
|
13
|
+
* back to the version's heads via a compensating change (non-destructive).
|
|
14
|
+
*
|
|
15
|
+
* Transport: clients speak Automerge's binary protocol
|
|
16
|
+
* (@automerge/automerge-repo-network-websocket on the client). On the server
|
|
17
|
+
* we use an in-memory DocHandle + simple per-room broadcast; for horizontal
|
|
18
|
+
* scaling, updates are re-broadcast via Redis pub/sub (same philosophy as transmit).
|
|
19
|
+
*/
|
|
20
|
+
/** Connections whose permission denied canWrite — their updates are dropped. */
|
|
21
|
+
const readOnlyClients = new WeakSet();
|
|
6
22
|
export class AutomergeDriver {
|
|
7
23
|
engine = 'automerge';
|
|
8
24
|
rooms = new Map();
|
|
@@ -62,13 +78,21 @@ export class AutomergeDriver {
|
|
|
62
78
|
}
|
|
63
79
|
const room = await this.loadRoom(docName);
|
|
64
80
|
room.clients.add(ws);
|
|
81
|
+
if (!permission.canWrite)
|
|
82
|
+
readOnlyClients.add(ws);
|
|
65
83
|
// Sends the full state to the new client.
|
|
66
84
|
ws.send(A.save(room.text));
|
|
67
85
|
ws.on('message', (data) => {
|
|
86
|
+
// A read-only connection still receives every update; its own are
|
|
87
|
+
// dropped. Enforced here because the client cannot be trusted to
|
|
88
|
+
// respect a permission it was merely told about.
|
|
89
|
+
if (readOnlyClients.has(ws))
|
|
90
|
+
return;
|
|
68
91
|
void this.handleClientMessage(docName, data, ws);
|
|
69
92
|
});
|
|
70
93
|
ws.on('close', () => {
|
|
71
94
|
room.clients.delete(ws);
|
|
95
|
+
readOnlyClients.delete(ws);
|
|
72
96
|
});
|
|
73
97
|
}
|
|
74
98
|
catch {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"automerge_driver.js","sourceRoot":"","sources":["../../../../src/drivers/automerge/automerge_driver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,sBAAsB,CAAC;AAC1C,OAAO,EAAE,IAAI,IAAI,KAAK,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,IAAI,CAAC;AAIrC,OAAO,EAAE,qBAAqB,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACzE,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"automerge_driver.js","sourceRoot":"","sources":["../../../../src/drivers/automerge/automerge_driver.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"yjs_driver.d.ts","sourceRoot":"","sources":["../../../../src/drivers/yjs/yjs_driver.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"yjs_driver.d.ts","sourceRoot":"","sources":["../../../../src/drivers/yjs/yjs_driver.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AACpF,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAwB,MAAM,gBAAgB,CAAC;AAsB7F,qBAAa,SAAU,YAAW,mBAAmB;IACnD,QAAQ,CAAC,MAAM,SAAS;IAExB,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,GAAG,CAAC,CAAkB;IAC9B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA0B;IAClD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuB;gBAEnC,OAAO,EAAE,uBAAuB;IA8D5C,OAAO,CAAC,OAAO;IAKf,OAAO,CAAC,OAAO;YAQD,SAAS;IAQjB,MAAM,CAAC,MAAM,EAAE,OAAO,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBzD,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAStD,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAajD,aAAa,CACjB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,KAAK,EAAE,MAAM,GAAG,IAAI,GACnB,OAAO,CAAC,aAAa,CAAC;IASnB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAIvD,cAAc,CAClB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GAAG,IAAI,GACxB,OAAO,CAAC,IAAI,CAAC;IAgBV,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;YAY3E,YAAY;IAMpB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAU7B"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Hocuspocus } from '@hocuspocus/server';
|
|
1
|
+
import { Hocuspocus, } from '@hocuspocus/server';
|
|
2
2
|
import { TiptapTransformer } from '@hocuspocus/transformer';
|
|
3
3
|
import { WebSocketServer } from 'ws';
|
|
4
4
|
import * as Y from 'yjs';
|
|
@@ -33,7 +33,7 @@ export class YjsDriver {
|
|
|
33
33
|
// the driver instance.
|
|
34
34
|
const storage = this.storage;
|
|
35
35
|
this.hocuspocus = new Hocuspocus({
|
|
36
|
-
async onAuthenticate({ documentName, token }) {
|
|
36
|
+
async onAuthenticate({ documentName, token, connectionConfig }) {
|
|
37
37
|
const ctx = parseLegacyToken(token);
|
|
38
38
|
if (!ctx)
|
|
39
39
|
throw new Error('invalid token');
|
|
@@ -41,6 +41,10 @@ export class YjsDriver {
|
|
|
41
41
|
if (!permission.canRead) {
|
|
42
42
|
throw new Error('no access to this document');
|
|
43
43
|
}
|
|
44
|
+
// canWrite has to bind the connection itself: a client that is only
|
|
45
|
+
// told it may not write can simply not ask. Hocuspocus drops inbound
|
|
46
|
+
// updates on a read-only connection while still syncing outbound.
|
|
47
|
+
connectionConfig.readOnly = !permission.canWrite;
|
|
44
48
|
},
|
|
45
49
|
async onConnect({ documentName, requestParameters }) {
|
|
46
50
|
const token = requestParameters.get('token');
|
|
@@ -60,6 +64,17 @@ export class YjsDriver {
|
|
|
60
64
|
await options.presence.leave(documentName, userId);
|
|
61
65
|
}
|
|
62
66
|
},
|
|
67
|
+
// Seed each in-memory doc from the persisted state: without this hook the
|
|
68
|
+
// Hocuspocus doc starts EMPTY on every connection, so a previously saved
|
|
69
|
+
// document comes back blank to clients (and is then overwritten on save).
|
|
70
|
+
async onLoadDocument({ documentName }) {
|
|
71
|
+
const stored = await storage.loadDocument(documentName);
|
|
72
|
+
if (stored?.state && stored.state.byteLength > 0) {
|
|
73
|
+
const doc = new Y.Doc();
|
|
74
|
+
Y.applyUpdate(doc, stored.state);
|
|
75
|
+
return { document: doc };
|
|
76
|
+
}
|
|
77
|
+
},
|
|
63
78
|
async onStoreDocument({ documentName, document }) {
|
|
64
79
|
await storage.saveDocument(documentName, Y.encodeStateAsUpdate(document));
|
|
65
80
|
},
|