@jtfmumm/patchwork-standalone-frame 0.4.1 → 0.4.3
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 +138 -89
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,25 +2,146 @@
|
|
|
2
2
|
|
|
3
3
|
A standalone frame for patchwork tools. Provides repo setup, doc history, top bar UI, sharing modals, and optional keyhive access control.
|
|
4
4
|
|
|
5
|
-
## Quick start
|
|
5
|
+
## Quick start
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Scaffold a new project:
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
```
|
|
10
|
+
pnpm create @jtfmumm/patchwork-standalone
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
This prompts for your tool name, automerge URL, sync server, and mode (legacy or keyhive), then generates a ready-to-run project. After scaffolding:
|
|
10
14
|
|
|
11
|
-
|
|
12
|
-
-
|
|
15
|
+
```
|
|
16
|
+
cd my-standalone-app
|
|
17
|
+
pnpm install
|
|
18
|
+
pnpm build
|
|
19
|
+
```
|
|
13
20
|
|
|
14
|
-
|
|
21
|
+
For development:
|
|
15
22
|
|
|
16
23
|
```
|
|
17
|
-
|
|
18
|
-
|
|
24
|
+
pnpm dev
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## How it works
|
|
28
|
+
|
|
29
|
+
The standalone frame takes a patchwork tool and wraps it in an app shell with document management. You need three packages:
|
|
30
|
+
|
|
31
|
+
- **`@jtfmumm/patchwork-standalone-frame`**: the frame itself
|
|
32
|
+
- **`@jtfmumm/automerge-deps`**: fetches tool modules from a sync server at build time
|
|
33
|
+
- **`@jtfmumm/patchwork-standalone-vite`**: Vite plugin handling build configuration
|
|
34
|
+
|
|
35
|
+
Tools are published as automerge FolderDocs. `automerge-deps install` downloads them into `node_modules/` so they work like normal dependencies.
|
|
36
|
+
|
|
37
|
+
## API
|
|
38
|
+
|
|
39
|
+
### `mountStandaloneApp(root, toolOrPlugins, config?)`
|
|
40
|
+
|
|
41
|
+
Mounts the standalone frame into a DOM element.
|
|
42
|
+
|
|
43
|
+
- **`root`**: the HTML element to mount into
|
|
44
|
+
- **`toolOrPlugins`**: either a `ToolRegistration<D>` object or a `Plugin<D>[]` array (patchwork plugin convention)
|
|
45
|
+
- **`config`**: optional `StandaloneFrameConfig`
|
|
46
|
+
|
|
47
|
+
### Plugin convention
|
|
48
|
+
|
|
49
|
+
Tools that export a `plugins` array with `patchwork:tool` and `patchwork:datatype` entries can be passed directly:
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
import { plugins } from "my-tool";
|
|
53
|
+
mountStandaloneApp(root, plugins);
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### ToolRegistration
|
|
57
|
+
|
|
58
|
+
For tools that don't use the plugin convention:
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
const myTool: ToolRegistration<MyDoc> = {
|
|
62
|
+
id: "my-tool",
|
|
63
|
+
name: "My Tool",
|
|
64
|
+
defaultTitle: "Untitled",
|
|
65
|
+
init: (doc, repo) => { /* initialize a blank document */ },
|
|
66
|
+
getTitle: (doc) => doc.title || "Untitled",
|
|
67
|
+
setTitle: (doc, title) => { doc.title = title; },
|
|
68
|
+
render: (handle, element) => { /* mount UI, return cleanup function */ },
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
mountStandaloneApp(root, myTool);
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Legacy mode
|
|
75
|
+
|
|
76
|
+
Pass `{ legacyMode: true, repo }` to use a plain automerge repo without keyhive. You construct and configure the repo yourself.
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
import { Repo } from "@automerge/automerge-repo";
|
|
80
|
+
import { IndexedDBStorageAdapter } from "@automerge/automerge-repo-storage-indexeddb";
|
|
81
|
+
import { WebSocketClientAdapter } from "@automerge/automerge-repo-network-websocket";
|
|
82
|
+
import { mountStandaloneApp } from "@jtfmumm/patchwork-standalone-frame";
|
|
83
|
+
import { plugins } from "my-tool";
|
|
84
|
+
|
|
85
|
+
const repo = new Repo({
|
|
86
|
+
storage: new IndexedDBStorageAdapter(),
|
|
87
|
+
network: [new WebSocketClientAdapter("wss://your-sync-server.example.com")],
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
const root = document.getElementById("root");
|
|
91
|
+
if (root) {
|
|
92
|
+
mountStandaloneApp(root, plugins, { legacyMode: true, repo });
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Keyhive mode (default)
|
|
97
|
+
|
|
98
|
+
When `legacyMode` is not set, the frame initializes keyhive automatically, including WASM loading, repo creation, and access control. You don't need to create a repo yourself.
|
|
99
|
+
|
|
100
|
+
Keyhive mode requires one additional dependency:
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
pnpm add @automerge/automerge-repo-keyhive
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Then your entry point is simpler, with no repo setup needed:
|
|
107
|
+
|
|
108
|
+
```typescript
|
|
109
|
+
import { mountStandaloneApp } from "@jtfmumm/patchwork-standalone-frame";
|
|
110
|
+
import { plugins } from "my-tool";
|
|
111
|
+
|
|
112
|
+
const root = document.getElementById("root");
|
|
113
|
+
if (root) {
|
|
114
|
+
mountStandaloneApp(root, plugins, {
|
|
115
|
+
syncUrl: "wss://your-keyhive-sync-server.example.com",
|
|
116
|
+
});
|
|
117
|
+
}
|
|
19
118
|
```
|
|
20
119
|
|
|
21
|
-
###
|
|
120
|
+
### Config options
|
|
121
|
+
|
|
122
|
+
| Option | Description |
|
|
123
|
+
|--------|-------------|
|
|
124
|
+
| `legacyMode` | Use plain automerge docs without keyhive. Default: `false` |
|
|
125
|
+
| `repo` | Pre-built repo for legacy mode. Required when `legacyMode` is `true` |
|
|
126
|
+
| `syncUrl` | WebSocket sync server URL for keyhive mode |
|
|
127
|
+
|
|
128
|
+
The sync server URL is resolved in this order:
|
|
129
|
+
|
|
130
|
+
1. `config.syncUrl`
|
|
131
|
+
2. `VITE_SYNC_URL` environment variable
|
|
132
|
+
3. `tool.syncUrl` from the registration
|
|
133
|
+
4. `ws://localhost:3030` (default)
|
|
134
|
+
|
|
135
|
+
## Manual setup
|
|
136
|
+
|
|
137
|
+
If you prefer to set up a project manually instead of using the scaffolder, here are the steps:
|
|
138
|
+
|
|
139
|
+
### 1. Create the project and install dependencies
|
|
22
140
|
|
|
23
141
|
```
|
|
142
|
+
mkdir my-standalone-app && cd my-standalone-app
|
|
143
|
+
pnpm init
|
|
144
|
+
|
|
24
145
|
pnpm add @jtfmumm/patchwork-standalone-frame \
|
|
25
146
|
@automerge/automerge @automerge/automerge-repo \
|
|
26
147
|
@automerge/automerge-repo-network-websocket \
|
|
@@ -30,7 +151,7 @@ pnpm add @jtfmumm/patchwork-standalone-frame \
|
|
|
30
151
|
pnpm add -D @jtfmumm/automerge-deps @jtfmumm/patchwork-standalone-vite vite
|
|
31
152
|
```
|
|
32
153
|
|
|
33
|
-
###
|
|
154
|
+
### 2. Configure automerge-deps
|
|
34
155
|
|
|
35
156
|
Create `automerge-deps.json` to specify the tool and sync server for fetching the tool:
|
|
36
157
|
|
|
@@ -43,17 +164,15 @@ Create `automerge-deps.json` to specify the tool and sync server for fetching th
|
|
|
43
164
|
}
|
|
44
165
|
```
|
|
45
166
|
|
|
46
|
-
###
|
|
167
|
+
### 3. Fetch the tool
|
|
47
168
|
|
|
48
169
|
```
|
|
49
170
|
npx automerge-deps install
|
|
50
171
|
```
|
|
51
172
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
### 5. Create the entry point
|
|
173
|
+
### 4. Create the entry point
|
|
55
174
|
|
|
56
|
-
**`src/main.ts`**
|
|
175
|
+
**`src/main.ts`** (legacy mode shown; see keyhive mode above for the alternative)
|
|
57
176
|
```typescript
|
|
58
177
|
import { Repo } from "@automerge/automerge-repo";
|
|
59
178
|
import { IndexedDBStorageAdapter } from "@automerge/automerge-repo-storage-indexeddb";
|
|
@@ -72,7 +191,7 @@ if (root) {
|
|
|
72
191
|
}
|
|
73
192
|
```
|
|
74
193
|
|
|
75
|
-
###
|
|
194
|
+
### 5. Create the HTML shell
|
|
76
195
|
|
|
77
196
|
**`index.html`**
|
|
78
197
|
```html
|
|
@@ -94,7 +213,7 @@ if (root) {
|
|
|
94
213
|
</html>
|
|
95
214
|
```
|
|
96
215
|
|
|
97
|
-
###
|
|
216
|
+
### 6. Configure Vite
|
|
98
217
|
|
|
99
218
|
**`vite.config.ts`**
|
|
100
219
|
```typescript
|
|
@@ -106,9 +225,7 @@ export default defineConfig({
|
|
|
106
225
|
});
|
|
107
226
|
```
|
|
108
227
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
### 8. Add scripts to package.json
|
|
228
|
+
### 7. Add scripts to package.json
|
|
112
229
|
|
|
113
230
|
```json
|
|
114
231
|
{
|
|
@@ -121,7 +238,7 @@ The `tools` option lists tool packages fetched by `automerge-deps`. This enables
|
|
|
121
238
|
}
|
|
122
239
|
```
|
|
123
240
|
|
|
124
|
-
###
|
|
241
|
+
### 8. Run
|
|
125
242
|
|
|
126
243
|
```
|
|
127
244
|
pnpm dev
|
|
@@ -133,71 +250,3 @@ For production builds:
|
|
|
133
250
|
pnpm build
|
|
134
251
|
pnpm preview
|
|
135
252
|
```
|
|
136
|
-
|
|
137
|
-
## API
|
|
138
|
-
|
|
139
|
-
### `mountStandaloneApp(root, toolOrPlugins, config?)`
|
|
140
|
-
|
|
141
|
-
Mounts the standalone frame into a DOM element.
|
|
142
|
-
|
|
143
|
-
- **`root`**: the HTML element to mount into
|
|
144
|
-
- **`toolOrPlugins`**: either a `ToolRegistration<D>` object or a `Plugin<D>[]` array (patchwork plugin convention)
|
|
145
|
-
- **`config`**: optional `StandaloneFrameConfig`
|
|
146
|
-
|
|
147
|
-
### ToolRegistration
|
|
148
|
-
|
|
149
|
-
For tools that don't use the patchwork plugin convention:
|
|
150
|
-
|
|
151
|
-
```typescript
|
|
152
|
-
const myTool: ToolRegistration<MyDoc> = {
|
|
153
|
-
id: "my-tool",
|
|
154
|
-
name: "My Tool",
|
|
155
|
-
defaultTitle: "Untitled",
|
|
156
|
-
init: (doc, repo) => { /* initialize a blank document */ },
|
|
157
|
-
getTitle: (doc) => doc.title || "Untitled",
|
|
158
|
-
setTitle: (doc, title) => { doc.title = title; },
|
|
159
|
-
render: (handle, element) => { /* mount UI, return cleanup function */ },
|
|
160
|
-
};
|
|
161
|
-
|
|
162
|
-
mountStandaloneApp(root, myTool);
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
### Plugin convention
|
|
166
|
-
|
|
167
|
-
Tools that export a `plugins` array with `patchwork:tool` and `patchwork:datatype` entries can be passed directly:
|
|
168
|
-
|
|
169
|
-
```typescript
|
|
170
|
-
import { plugins } from "my-tool";
|
|
171
|
-
mountStandaloneApp(root, plugins);
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
### Legacy mode
|
|
175
|
-
|
|
176
|
-
Pass `{ legacyMode: true, repo }` to use a plain automerge repo without keyhive. You construct and configure the repo yourself. This is the recommended approach for standalone deployments.
|
|
177
|
-
|
|
178
|
-
### Keyhive mode (default)
|
|
179
|
-
|
|
180
|
-
When `legacyMode` is not set, the frame initializes keyhive automatically, including WASM loading, repo creation, and access control.
|
|
181
|
-
|
|
182
|
-
```typescript
|
|
183
|
-
import { plugins } from "my-tool";
|
|
184
|
-
|
|
185
|
-
mountStandaloneApp(root, plugins, {
|
|
186
|
-
syncUrl: "wss://your-keyhive-sync-server.example.com",
|
|
187
|
-
});
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
### Config options
|
|
191
|
-
|
|
192
|
-
| Option | Description |
|
|
193
|
-
|--------|-------------|
|
|
194
|
-
| `legacyMode` | Use plain automerge docs without keyhive. Default: `false` |
|
|
195
|
-
| `repo` | Pre-built repo for legacy mode. Required when `legacyMode` is `true` |
|
|
196
|
-
| `syncUrl` | WebSocket sync server URL for keyhive mode |
|
|
197
|
-
|
|
198
|
-
The sync server URL is resolved in this order:
|
|
199
|
-
|
|
200
|
-
1. `config.syncUrl`
|
|
201
|
-
2. `VITE_SYNC_URL` environment variable
|
|
202
|
-
3. `tool.syncUrl` from the registration
|
|
203
|
-
4. `ws://localhost:3030` (default)
|
package/package.json
CHANGED