@jtfmumm/patchwork-standalone-frame 0.2.0 → 0.3.1
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 +167 -17
- package/dist/index.d.ts +2 -0
- package/dist/index.js +462 -444
- package/dist/share-modal.d.ts +1 -1
- package/package.json +1 -1
- package/src/frame.tsx +1 -1
- package/src/index.ts +2 -0
- package/src/share-modal.tsx +64 -37
package/README.md
CHANGED
|
@@ -1,34 +1,184 @@
|
|
|
1
1
|
# @jtfmumm/patchwork-standalone-frame
|
|
2
2
|
|
|
3
|
-
A
|
|
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
|
-
##
|
|
5
|
+
## Quick start: standalone app from an automerge tool
|
|
6
6
|
|
|
7
|
+
This guide walks through building a standalone web app from a patchwork tool published as an automerge FolderDoc.
|
|
8
|
+
|
|
9
|
+
### Prerequisites
|
|
10
|
+
|
|
11
|
+
- Node.js 18+
|
|
12
|
+
- pnpm
|
|
13
|
+
|
|
14
|
+
### 1. Create the project
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
mkdir my-standalone-app && cd my-standalone-app
|
|
18
|
+
pnpm init
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### 2. Install dependencies
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
pnpm add @jtfmumm/patchwork-standalone-frame \
|
|
25
|
+
@automerge/automerge @automerge/automerge-repo \
|
|
26
|
+
@automerge/automerge-repo-network-websocket \
|
|
27
|
+
@automerge/automerge-repo-storage-indexeddb \
|
|
28
|
+
solid-js
|
|
29
|
+
|
|
30
|
+
pnpm add -D @jtfmumm/automerge-deps @jtfmumm/patchwork-standalone-vite vite
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### 3. Configure automerge-deps
|
|
34
|
+
|
|
35
|
+
Create `automerge-deps.json` to specify the tool and sync server:
|
|
36
|
+
|
|
37
|
+
```json
|
|
38
|
+
{
|
|
39
|
+
"syncServers": ["wss://your-sync-server.example.com"],
|
|
40
|
+
"dependencies": [
|
|
41
|
+
{ "name": "my-tool", "url": "automerge:<tool-url>" }
|
|
42
|
+
]
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### 4. Fetch the tool
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
npx automerge-deps install
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
This downloads the tool's FolderDoc from the sync server and writes it to `node_modules/my-tool/`.
|
|
53
|
+
|
|
54
|
+
### 5. Create the entry point
|
|
55
|
+
|
|
56
|
+
**`src/main.ts`**
|
|
57
|
+
```typescript
|
|
58
|
+
import { Repo } from "@automerge/automerge-repo";
|
|
59
|
+
import { IndexedDBStorageAdapter } from "@automerge/automerge-repo-storage-indexeddb";
|
|
60
|
+
import { BrowserWebSocketClientAdapter } from "@automerge/automerge-repo-network-websocket";
|
|
61
|
+
import { mountStandaloneApp } from "@jtfmumm/patchwork-standalone-frame";
|
|
62
|
+
import { plugins } from "my-tool";
|
|
63
|
+
|
|
64
|
+
const repo = new Repo({
|
|
65
|
+
storage: new IndexedDBStorageAdapter(),
|
|
66
|
+
network: [new BrowserWebSocketClientAdapter("wss://your-sync-server.example.com")],
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
const root = document.getElementById("root");
|
|
70
|
+
if (root) {
|
|
71
|
+
mountStandaloneApp(root, plugins, { legacyMode: true, repo });
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### 6. Create the HTML shell
|
|
76
|
+
|
|
77
|
+
**`index.html`**
|
|
78
|
+
```html
|
|
79
|
+
<!doctype html>
|
|
80
|
+
<html lang="en">
|
|
81
|
+
<head>
|
|
82
|
+
<meta charset="UTF-8" />
|
|
83
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
84
|
+
<title>My Tool</title>
|
|
85
|
+
<style>
|
|
86
|
+
* { margin: 0; padding: 0; }
|
|
87
|
+
html, body, #root { height: 100%; }
|
|
88
|
+
</style>
|
|
89
|
+
</head>
|
|
90
|
+
<body>
|
|
91
|
+
<div id="root"></div>
|
|
92
|
+
<script type="module" src="/src/main.ts"></script>
|
|
93
|
+
</body>
|
|
94
|
+
</html>
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### 7. Configure Vite
|
|
98
|
+
|
|
99
|
+
**`vite.config.ts`**
|
|
7
100
|
```typescript
|
|
8
|
-
import {
|
|
101
|
+
import { defineConfig } from "vite";
|
|
102
|
+
import { patchworkStandalone } from "@jtfmumm/patchwork-standalone-vite";
|
|
103
|
+
|
|
104
|
+
export default defineConfig({
|
|
105
|
+
plugins: [patchworkStandalone({ tools: ["my-tool"] })],
|
|
106
|
+
});
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
The `tools` option lists tool packages fetched by `automerge-deps`. This enables serving of the tool's code-split chunks during development.
|
|
110
|
+
|
|
111
|
+
### 8. Add scripts to package.json
|
|
112
|
+
|
|
113
|
+
```json
|
|
114
|
+
{
|
|
115
|
+
"scripts": {
|
|
116
|
+
"fetch-deps": "automerge-deps install",
|
|
117
|
+
"dev": "vite",
|
|
118
|
+
"build": "pnpm fetch-deps && vite build",
|
|
119
|
+
"preview": "vite preview"
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### 9. Run
|
|
125
|
+
|
|
126
|
+
```
|
|
127
|
+
pnpm dev
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
For production builds:
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
pnpm build
|
|
134
|
+
pnpm preview
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## API
|
|
9
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
|
|
10
152
|
const myTool: ToolRegistration<MyDoc> = {
|
|
11
|
-
id: "my-tool",
|
|
12
|
-
name: "My Tool",
|
|
13
|
-
defaultTitle: "Untitled",
|
|
14
|
-
init: (doc, repo) => {
|
|
15
|
-
// Initialize a blank document
|
|
16
|
-
},
|
|
153
|
+
id: "my-tool",
|
|
154
|
+
name: "My Tool",
|
|
155
|
+
defaultTitle: "Untitled",
|
|
156
|
+
init: (doc, repo) => { /* initialize a blank document */ },
|
|
17
157
|
getTitle: (doc) => doc.title || "Untitled",
|
|
18
158
|
setTitle: (doc, title) => { doc.title = title; },
|
|
19
|
-
|
|
20
|
-
render: (handle, element) => {
|
|
21
|
-
// Mount your UI into `element`, return a cleanup function
|
|
22
|
-
},
|
|
159
|
+
render: (handle, element) => { /* mount UI, return cleanup function */ },
|
|
23
160
|
};
|
|
24
161
|
|
|
25
|
-
|
|
26
|
-
if (root) mountStandaloneApp(root, myTool);
|
|
162
|
+
mountStandaloneApp(root, myTool);
|
|
27
163
|
```
|
|
28
164
|
|
|
29
|
-
|
|
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. The sync server URL is resolved in this order:
|
|
30
181
|
|
|
31
|
-
The sync server URL is resolved in this order:
|
|
32
182
|
1. `VITE_SYNC_URL` environment variable
|
|
33
183
|
2. `tool.syncUrl` from the registration
|
|
34
184
|
3. `ws://localhost:3030` (default)
|
package/dist/index.d.ts
CHANGED
|
@@ -34,6 +34,8 @@ export interface StandaloneFrameConfig {
|
|
|
34
34
|
legacyMode?: boolean;
|
|
35
35
|
/** Pre-built repo for legacy mode. Required when legacyMode is true. */
|
|
36
36
|
repo?: FrameRepo;
|
|
37
|
+
/** WebSocket sync server URL. Overrides tool.syncUrl. */
|
|
38
|
+
syncUrl?: string;
|
|
37
39
|
}
|
|
38
40
|
export interface PluginDescription {
|
|
39
41
|
id: string;
|