@dockstat/outline-sync 1.1.3 → 1.2.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/README.md +170 -188
- package/dist/index.js +13562 -0
- package/package.json +15 -39
- package/LICENSE +0 -373
- package/dist/cli.js +0 -40
package/README.md
CHANGED
|
@@ -1,271 +1,253 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Outline Sync
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
Designed for multi-collection pipelines.
|
|
5
|
-
Features:
|
|
3
|
+
Bidirectional sync for Outline wiki to local folders with CI/CD support.
|
|
6
4
|
|
|
7
|
-
|
|
8
|
-
* Multi-collection support (`--collection` repeatable)
|
|
9
|
-
* Folder-based default storage (each page → `<slug>/README.md`, children inherit folders)
|
|
10
|
-
* Per-collection mapping file for custom paths
|
|
11
|
-
* Config-driven: `configs/outline-sync.json`, `<collection>.config.json`, `<collection>.pages.json`
|
|
12
|
-
* Whitespace/newline-agnostic diffs (formatting-only changes are ignored)
|
|
13
|
-
* Uses Git commit time when available (falls back to fs mtime)
|
|
14
|
-
* Dry-run mode, backups of overwritten files
|
|
5
|
+
## Installation
|
|
15
6
|
|
|
16
|
-
|
|
7
|
+
```bash
|
|
8
|
+
bun install
|
|
9
|
+
bun run build
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Configuration
|
|
17
13
|
|
|
18
|
-
|
|
14
|
+
### Option 1: Config File (Recommended)
|
|
19
15
|
|
|
20
|
-
|
|
16
|
+
Create `outline-sync.config.json`:
|
|
21
17
|
|
|
22
18
|
```bash
|
|
23
|
-
|
|
19
|
+
outline-sync init
|
|
24
20
|
```
|
|
25
21
|
|
|
26
|
-
|
|
22
|
+
Then edit the generated file:
|
|
27
23
|
|
|
28
|
-
|
|
24
|
+
```json
|
|
25
|
+
{
|
|
26
|
+
"url": "https://your-outline.com",
|
|
27
|
+
"token": "your_api_token",
|
|
28
|
+
"outputDir": "./outline-docs",
|
|
29
|
+
"customPaths": {
|
|
30
|
+
"doc-id-abc123": "../../README.md",
|
|
31
|
+
"doc-id-xyz789": "custom/important-doc.md"
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**Custom Paths:**
|
|
37
|
+
- Document IDs can be found in the Outline URL or via the API
|
|
38
|
+
- Paths starting with `..` are relative to current working directory
|
|
39
|
+
- Other paths are relative to `outputDir`
|
|
29
40
|
|
|
30
|
-
|
|
41
|
+
**Finding Document IDs:**
|
|
42
|
+
1. Open document in Outline
|
|
43
|
+
2. Check URL: `https://outline.com/doc/my-document-abc123` (ID is `abc123`)
|
|
44
|
+
3. Or run initial sync and check frontmatter in generated files
|
|
31
45
|
|
|
32
|
-
|
|
46
|
+
### Option 2: Environment Variables
|
|
33
47
|
|
|
34
48
|
```bash
|
|
35
|
-
export
|
|
49
|
+
export OUTLINE_URL=https://your-outline.com
|
|
50
|
+
export OUTLINE_TOKEN=your_api_token
|
|
51
|
+
export OUTLINE_OUTPUT_DIR=./outline-docs
|
|
36
52
|
```
|
|
37
53
|
|
|
38
|
-
|
|
54
|
+
### Option 3: CLI Arguments
|
|
39
55
|
|
|
40
|
-
|
|
41
|
-
bunx @dockstat/outline-sync setup
|
|
42
|
-
```
|
|
56
|
+
Pass configuration via command line (takes precedence over other methods).
|
|
43
57
|
|
|
44
|
-
|
|
58
|
+
## Usage
|
|
45
59
|
|
|
46
|
-
|
|
47
|
-
bunx @dockstat/outline-sync init --collection="COLLECTION_UUID"
|
|
48
|
-
# or multiple:
|
|
49
|
-
bunx @dockstat/outline-sync init --collection="id1" --collection="id2"
|
|
50
|
-
```
|
|
60
|
+
### Commands
|
|
51
61
|
|
|
52
|
-
|
|
62
|
+
**Initialize config file:**
|
|
53
63
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
* `docs/...` — markdown files saved folder-based (`<slug>/README.md`)
|
|
64
|
+
```bash
|
|
65
|
+
outline-sync init
|
|
66
|
+
```
|
|
58
67
|
|
|
59
|
-
|
|
68
|
+
**One-time sync (down only):**
|
|
60
69
|
|
|
61
70
|
```bash
|
|
62
|
-
|
|
71
|
+
outline-sync sync
|
|
72
|
+
# or with config file
|
|
73
|
+
outline-sync sync --config custom-config.json
|
|
63
74
|
```
|
|
64
75
|
|
|
65
|
-
|
|
76
|
+
**Watch mode (bidirectional):**
|
|
66
77
|
|
|
67
78
|
```bash
|
|
68
|
-
|
|
69
|
-
bunx @dockstat/outline-sync pull --collection="COLLECTION_UUID"
|
|
70
|
-
bunx @dockstat/outline-sync push --collection="COLLECTION_UUID"
|
|
79
|
+
outline-sync watch
|
|
71
80
|
```
|
|
72
81
|
|
|
73
|
-
|
|
82
|
+
**CI/CD mode:**
|
|
74
83
|
|
|
75
84
|
```bash
|
|
76
|
-
|
|
77
|
-
--collection="id-one" --collection="id-two" \
|
|
78
|
-
--dry-run
|
|
85
|
+
outline-sync ci
|
|
79
86
|
```
|
|
80
87
|
|
|
81
|
-
|
|
88
|
+
## API Reference (CLI Commands)
|
|
82
89
|
|
|
83
|
-
|
|
90
|
+
### `outline-sync init`
|
|
84
91
|
|
|
85
|
-
|
|
92
|
+
Creates a sample `outline-sync.config.json` configuration file in the current directory.
|
|
86
93
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
Commands:
|
|
92
|
-
setup - interactive setup (list & add a collection)
|
|
93
|
-
list-collections - print the collections visible to the API key
|
|
94
|
-
init --collection=ID - bootstrap pages.json + markdown for collection (repeatable)
|
|
95
|
-
pull --collection=ID - pull remote changes into local files (repeatable)
|
|
96
|
-
push --collection=ID - push local changes to remote (repeatable)
|
|
97
|
-
sync --collection=ID - bidirectional sync (timestamp-based) (repeatable)
|
|
98
|
-
|
|
99
|
-
Flags:
|
|
100
|
-
--collection=ID Repeatable; run command for multiple collection ids
|
|
101
|
-
--dry-run Preview actions (no writes to Outline or disk)
|
|
102
|
-
--api-key="..." Provide Outline API key (overrides env var)
|
|
103
|
-
--base-url="..." Custom Outline base URL (overrides default)
|
|
104
|
-
--help, -h
|
|
94
|
+
**Example:**
|
|
95
|
+
```bash
|
|
96
|
+
outline-sync init
|
|
105
97
|
```
|
|
106
98
|
|
|
107
|
-
|
|
99
|
+
### `outline-sync sync [options]`
|
|
108
100
|
|
|
109
|
-
|
|
101
|
+
Performs a one-time synchronization from your Outline wiki to your local folder. This command only pulls changes from Outline.
|
|
110
102
|
|
|
111
|
-
|
|
103
|
+
**Options:**
|
|
112
104
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
105
|
+
- `--url <url>`: The URL of your Outline instance. Can also be set via `OUTLINE_URL` env var or config file.
|
|
106
|
+
- `--token <token>`: Your Outline API token. Can also be set via `OUTLINE_TOKEN` env var or config file.
|
|
107
|
+
- `--output <dir>`: The local directory where documents will be stored. Default: `./outline-docs`
|
|
108
|
+
- `--config <path>`: Path to config file. Default: `./outline-sync.config.json`
|
|
109
|
+
|
|
110
|
+
**Example:**
|
|
111
|
+
```bash
|
|
112
|
+
outline-sync sync --url https://my.outline.app --token <YOUR_TOKEN> --output ~/my-wiki
|
|
119
113
|
```
|
|
120
114
|
|
|
121
|
-
|
|
115
|
+
### `outline-sync watch [options]`
|
|
122
116
|
|
|
123
|
-
|
|
124
|
-
{
|
|
125
|
-
"collections": [
|
|
126
|
-
{
|
|
127
|
-
"id": "COLLECTION_UUID",
|
|
128
|
-
"name": "Support Docs",
|
|
129
|
-
"saveDir": "docs",
|
|
130
|
-
"pagesFile": "configs/COLLECTION_UUID.pages.json",
|
|
131
|
-
"configFile": "configs/COLLECTION_UUID.config.json"
|
|
132
|
-
}
|
|
133
|
-
]
|
|
134
|
-
}
|
|
135
|
-
```
|
|
117
|
+
Starts a persistent process that watches for changes in your local directory and syncs them to Outline, and also pulls new changes from Outline periodically. This enables bidirectional synchronization.
|
|
136
118
|
|
|
137
|
-
|
|
119
|
+
**Options:**
|
|
138
120
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
"mappings": [
|
|
144
|
-
{
|
|
145
|
-
"match": { "id": "doc-id-123" },
|
|
146
|
-
"path": "guides/setup/" // directory mapping → will place doc as guides/setup/README.md
|
|
147
|
-
},
|
|
148
|
-
{
|
|
149
|
-
"match": { "title": "API Reference" },
|
|
150
|
-
"path": "reference/README.md" // explicit filename mapping
|
|
151
|
-
}
|
|
152
|
-
]
|
|
153
|
-
}
|
|
154
|
-
```
|
|
121
|
+
- `--url <url>`: The URL of your Outline instance.
|
|
122
|
+
- `--token <token>`: Your Outline API token.
|
|
123
|
+
- `--output <dir>`: The local directory being watched. Default: `./outline-docs`
|
|
124
|
+
- `--config <path>`: Path to config file. Default: `./outline-sync.config.json`
|
|
155
125
|
|
|
156
|
-
|
|
126
|
+
**Example:**
|
|
127
|
+
```bash
|
|
128
|
+
outline-sync watch
|
|
129
|
+
```
|
|
157
130
|
|
|
158
|
-
|
|
159
|
-
* `path` can be:
|
|
131
|
+
### `outline-sync ci [options]`
|
|
160
132
|
|
|
161
|
-
|
|
162
|
-
* explicit file (`reference/README.md`) → used verbatim (relative to project root unless you give an absolute path),
|
|
163
|
-
* bare filename → placed under parent directory or `saveDir`.
|
|
133
|
+
Executes a CI/CD-friendly synchronization. This command first pulls all documents from Outline, then checks for any local changes in your configured output directory, and finally pushes those local changes back to Outline. Designed for automated environments.
|
|
164
134
|
|
|
165
|
-
|
|
135
|
+
**Options:**
|
|
166
136
|
|
|
167
|
-
|
|
137
|
+
- `--url <url>`: The URL of your Outline instance.
|
|
138
|
+
- `--token <token>`: Your Outline API token.
|
|
139
|
+
- `--output <dir>`: The local directory to synchronize. Default: `./outline-docs`
|
|
140
|
+
- `--config <path>`: Path to config file. Default: `./outline-sync.config.json`
|
|
168
141
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
"pages": [
|
|
173
|
-
{
|
|
174
|
-
"title": "Product",
|
|
175
|
-
"file": "docs/product/README.md",
|
|
176
|
-
"id": "doc-product-id",
|
|
177
|
-
"children": [
|
|
178
|
-
{
|
|
179
|
-
"title": "Getting Started",
|
|
180
|
-
"file": "docs/product/getting-started/README.md",
|
|
181
|
-
"id": "doc-getting-started-id",
|
|
182
|
-
"children": []
|
|
183
|
-
}
|
|
184
|
-
]
|
|
185
|
-
}
|
|
186
|
-
]
|
|
187
|
-
}
|
|
142
|
+
**Example:**
|
|
143
|
+
```bash
|
|
144
|
+
outline-sync ci --output ./project-docs
|
|
188
145
|
```
|
|
189
146
|
|
|
190
|
-
`pages.json` is updated when new remote documents are created (IDs get written back).
|
|
191
|
-
|
|
192
147
|
---
|
|
193
148
|
|
|
194
|
-
|
|
149
|
+
## Examples
|
|
195
150
|
|
|
196
|
-
|
|
197
|
-
* For `sync` (default bidirectional flow): the *newer* version wins (remote.updatedAt vs local timestamp). The tool **ignores whitespace/newline-only differences** when deciding whether content actually differs — if the only difference is formatting, no update is performed.
|
|
198
|
-
* For `pull`: remote always wins and overwrites the local file if content differs (ignoring whitespace).
|
|
199
|
-
* For `push`: local always wins; remote is updated if content differs (ignoring whitespace).
|
|
200
|
-
* When writing to existing local files, a backup is created: `path/to/file.md.outline-sync.bak.<timestamp>`.
|
|
151
|
+
### Example 1: Root README
|
|
201
152
|
|
|
202
|
-
|
|
153
|
+
Place a specific document as your project's main README:
|
|
203
154
|
|
|
204
|
-
|
|
155
|
+
```json
|
|
156
|
+
{
|
|
157
|
+
"customPaths": {
|
|
158
|
+
"doc-abc123": "../../README.md"
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
```
|
|
205
162
|
|
|
206
|
-
|
|
163
|
+
### Example 2: Mixed Structure
|
|
207
164
|
|
|
208
|
-
|
|
165
|
+
Combine auto-organized docs with custom locations:
|
|
209
166
|
|
|
210
|
-
```
|
|
211
|
-
|
|
167
|
+
```json
|
|
168
|
+
{
|
|
169
|
+
"outputDir": "./docs",
|
|
170
|
+
"customPaths": {
|
|
171
|
+
"doc-home": "../../README.md",
|
|
172
|
+
"doc-api": "../../API.md",
|
|
173
|
+
"doc-contrib": "../../CONTRIBUTING.md"
|
|
174
|
+
}
|
|
175
|
+
}
|
|
212
176
|
```
|
|
213
177
|
|
|
214
|
-
|
|
178
|
+
Other documents without custom paths will be organized in `./docs` by collection.
|
|
215
179
|
|
|
216
|
-
|
|
180
|
+
### Example 3: Getting Document IDs
|
|
217
181
|
|
|
218
|
-
|
|
182
|
+
After first sync, check the frontmatter:
|
|
219
183
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
184
|
+
````markdown
|
|
185
|
+
---
|
|
186
|
+
id: abc123def456
|
|
187
|
+
title: My Document
|
|
188
|
+
collectionId: xyz789
|
|
189
|
+
parentDocumentId: null
|
|
190
|
+
updatedAt: '2024-01-15T10:30:00Z'
|
|
191
|
+
urlId: my-document-abc123
|
|
192
|
+
---
|
|
223
193
|
|
|
224
|
-
|
|
225
|
-
docs/product/README.md
|
|
226
|
-
docs/product/getting-started/README.md
|
|
227
|
-
docs/product/getting-started/install/README.md
|
|
194
|
+
Document content here...
|
|
228
195
|
```
|
|
229
196
|
|
|
230
|
-
|
|
197
|
+
Use the `id` field in your `customPaths` configuration.
|
|
231
198
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
# Advanced notes
|
|
199
|
+
## Features
|
|
235
200
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
201
|
+
- ✅ Sync Outline → Local
|
|
202
|
+
- ✅ Sync Local → Outline
|
|
203
|
+
- ✅ Each doc in own folder with README.md
|
|
204
|
+
- ✅ Custom path mapping for specific documents
|
|
205
|
+
- ✅ Frontmatter metadata preservation
|
|
206
|
+
- ✅ CI/CD integration
|
|
207
|
+
- ✅ File watching
|
|
242
208
|
|
|
243
|
-
|
|
209
|
+
## CI/CD Integration
|
|
244
210
|
|
|
245
|
-
|
|
211
|
+
### GitHub Actions
|
|
246
212
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
* Permissions / writing files: make sure the process has write permissions for `docs/` and `configs/`.
|
|
250
|
-
* Large collections: the Outline API is paginated (the client already pages with limit=100). If you hit rate limits, re-run with fewer collections at a time or add retries in your CI.
|
|
213
|
+
```yaml
|
|
214
|
+
name: Outline Sync
|
|
251
215
|
|
|
252
|
-
|
|
216
|
+
on:
|
|
217
|
+
push:
|
|
218
|
+
branches: [main]
|
|
219
|
+
schedule:
|
|
220
|
+
- cron: "0 */6 * * *" # Every 6 hours
|
|
253
221
|
|
|
254
|
-
|
|
222
|
+
jobs:
|
|
223
|
+
sync:
|
|
224
|
+
runs-on: ubuntu-latest
|
|
225
|
+
steps:
|
|
226
|
+
- uses: actions/checkout@v4
|
|
227
|
+
- uses: oven-sh/setup-bun@v1
|
|
228
|
+
- run: bun install
|
|
229
|
+
- run: bun run ci
|
|
230
|
+
env:
|
|
231
|
+
OUTLINE_URL: ${{ secrets.OUTLINE_URL }}
|
|
232
|
+
OUTLINE_TOKEN: ${{ secrets.OUTLINE_TOKEN }}
|
|
233
|
+
- uses: stefanzweifel/git-auto-commit-action@v5
|
|
234
|
+
with:
|
|
235
|
+
commit_message: "docs: sync from Outline"
|
|
236
|
+
```
|
|
255
237
|
|
|
256
|
-
|
|
238
|
+
Store `outline-sync.config.json` in your repo (without sensitive tokens):
|
|
257
239
|
|
|
258
|
-
|
|
240
|
+
```json
|
|
241
|
+
{
|
|
242
|
+
"outputDir": "./docs",
|
|
243
|
+
"customPaths": {
|
|
244
|
+
"doc-abc123": "../../README.md"
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
```
|
|
259
248
|
|
|
260
|
-
|
|
261
|
-
* parallel collection sync with a `--concurrent` flag
|
|
262
|
-
* a `--api-key-file` option to read secrets from a file
|
|
263
|
-
* richer conflict resolution (merge or interactive prompts)
|
|
249
|
+
Tokens can be passed via environment variables in CI.
|
|
264
250
|
|
|
265
|
-
|
|
251
|
+
## License
|
|
266
252
|
|
|
267
|
-
|
|
268
|
-
# run CLI against a local checkout
|
|
269
|
-
bun run bin/cli.ts setup
|
|
270
|
-
bun run bin/cli.ts init --collection="..."
|
|
271
|
-
```
|
|
253
|
+
MIT
|