@dockstat/outline-sync 1.0.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 +217 -0
- package/dist/sync.d.ts +3 -0
- package/dist/sync.js +25 -0
- package/package.json +61 -0
package/README.md
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
# Outline ↔ Git Markdown Sync (Bun CLI)
|
|
2
|
+
|
|
3
|
+
A small Bun-based CLI that bi-directionally syncs a Git-backed Markdown tree with a **single** Outline collection.
|
|
4
|
+
|
|
5
|
+
Features:
|
|
6
|
+
|
|
7
|
+
* Two-way sync (newer wins): push local (git) → Outline; pull Outline → local.
|
|
8
|
+
* Prefer **git commit timestamp** for local change detection (falls back to `mtime`).
|
|
9
|
+
* Single collection only (manifest top-level `collectionId` or CLI / env override).
|
|
10
|
+
* `--init` to bootstrap `pages.json` + `docs/` from an existing collection.
|
|
11
|
+
* `--list-collections` to print available collections (id + name).
|
|
12
|
+
* `--dry-run` to preview actions without writing.
|
|
13
|
+
* Safe local backups before overwriting (`*.outline-sync.bak.<ts>`).
|
|
14
|
+
* Bun + TypeScript single-file CLI (`sync.ts`) — drop in repo root and run with Bun.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Table of contents
|
|
19
|
+
|
|
20
|
+
* # Quick start
|
|
21
|
+
* # Manifest (`pages.json`)
|
|
22
|
+
* # Commands / Flags
|
|
23
|
+
* # Init (bootstrap) flow
|
|
24
|
+
* # How sync decisions are made
|
|
25
|
+
* # CI integration example
|
|
26
|
+
* # Safety & backups
|
|
27
|
+
* # Troubleshooting
|
|
28
|
+
* # Extending / Roadmap
|
|
29
|
+
* # License
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
# Quick start
|
|
34
|
+
|
|
35
|
+
1. Install Bun: [https://bun.sh](https://bun.sh)
|
|
36
|
+
2. Place the provided `sync.ts` in your repository root.
|
|
37
|
+
3. Ensure you have a shell environment variable `OUTLINE_API_KEY` set to a valid Outline API key.
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
export OUTLINE_API_KEY="sk_live_..." # REQUIRED
|
|
41
|
+
# optional:
|
|
42
|
+
export OUTLINE_BASE_URL="https://app.getoutline.com"
|
|
43
|
+
export OUTLINE_COLLECTION_ID="COLLECTION_UUID" # optional runtime override
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
4. To bootstrap a manifest from an existing collection (recommended first run):
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
# list collections so you can pick the collection id
|
|
50
|
+
OUTLINE_API_KEY=sk_xxx bun run sync.ts --list-collections
|
|
51
|
+
|
|
52
|
+
# bootstrap files + pages.json from the collection
|
|
53
|
+
OUTLINE_API_KEY=sk_xxx bun run sync.ts --init --collection-id=COLLECTION_UUID
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
5. Review and commit `pages.json` and `docs/`:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
git add pages.json docs
|
|
60
|
+
git commit -m "chore: bootstrap Outline manifest"
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
6. Run normal sync:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
OUTLINE_API_KEY=sk_xxx bun run sync.ts
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Or preview only (no writes):
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
OUTLINE_API_KEY=sk_xxx bun run sync.ts --dry-run
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
# Manifest (`pages.json`)
|
|
78
|
+
|
|
79
|
+
`pages.json` defines the single collection and the page tree. Example:
|
|
80
|
+
|
|
81
|
+
```json
|
|
82
|
+
{
|
|
83
|
+
"collectionId": "YOUR_COLLECTION_UUID",
|
|
84
|
+
"pages": [
|
|
85
|
+
{
|
|
86
|
+
"title": "Home",
|
|
87
|
+
"file": "docs/home.md",
|
|
88
|
+
"id": null,
|
|
89
|
+
"children": [
|
|
90
|
+
{
|
|
91
|
+
"title": "Subpage",
|
|
92
|
+
"file": "docs/subpage.md",
|
|
93
|
+
"id": null,
|
|
94
|
+
"children": []
|
|
95
|
+
}
|
|
96
|
+
]
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"title": "About",
|
|
100
|
+
"file": "docs/about.md",
|
|
101
|
+
"id": null,
|
|
102
|
+
"children": []
|
|
103
|
+
}
|
|
104
|
+
]
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Fields:
|
|
109
|
+
|
|
110
|
+
* `collectionId`: The single Outline collection the sync will write to. Required (or must be provided at runtime).
|
|
111
|
+
* `title`: Outline document title.
|
|
112
|
+
* `file`: Relative path to the markdown file.
|
|
113
|
+
* `id`: Outline document id (UUID). Use `null` for documents not yet created; `--init` will populate ids when bootstrapping.
|
|
114
|
+
* `children`: nested pages.
|
|
115
|
+
|
|
116
|
+
**Important:** Only the top-level `collectionId` (manifest) or a runtime override (`--collection-id` / `OUTLINE_COLLECTION_ID`) is used. Per-page collection fields are ignored.
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
# Commands / Flags
|
|
121
|
+
|
|
122
|
+
* `--init` : Bootstrap `pages.json` + `docs/` from an existing Outline collection. Requires `--collection-id` (or `OUTLINE_COLLECTION_ID` env var).
|
|
123
|
+
* `--list-collections` : Print all collections you can access (id + name).
|
|
124
|
+
* `--collection-id=<ID>` : Override manifest collection id for this run (useful in CI).
|
|
125
|
+
* `--dry-run` : Preview actions without writing to Outline or local files.
|
|
126
|
+
* `--help` / `-h` : Show help.
|
|
127
|
+
|
|
128
|
+
Examples:
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
# list collections
|
|
132
|
+
OUTLINE_API_KEY=sk_xxx bun run sync.ts --list-collections
|
|
133
|
+
|
|
134
|
+
# init from collection
|
|
135
|
+
OUTLINE_API_KEY=sk_xxx bun run sync.ts --init --collection-id=abc-uuid
|
|
136
|
+
|
|
137
|
+
# normal sync
|
|
138
|
+
OUTLINE_API_KEY=sk_xxx bun run sync.ts
|
|
139
|
+
|
|
140
|
+
# dry-run preview
|
|
141
|
+
OUTLINE_API_KEY=sk_xxx bun run sync.ts --dry-run
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
# Init (bootstrap) flow
|
|
147
|
+
|
|
148
|
+
`--init` performs:
|
|
149
|
+
|
|
150
|
+
1. `collections.list` or `documents.list` to fetch documents from the collection.
|
|
151
|
+
2. Creates `docs/<slug>.md` files for each document (slugified title). If slugs collide, a short id suffix is appended.
|
|
152
|
+
3. Builds the parent/child tree and writes `pages.json` with each entry containing the Outline `id`.
|
|
153
|
+
4. If not using `--dry-run`, files and `pages.json` are written to disk. Review and commit them.
|
|
154
|
+
|
|
155
|
+
This is the recommended first step when adopting the tool for an existing Outline collection.
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
# How sync decisions are made
|
|
160
|
+
|
|
161
|
+
For each manifest page:
|
|
162
|
+
|
|
163
|
+
1. If local file exists, determine local timestamp:
|
|
164
|
+
|
|
165
|
+
* Prefer **git last commit timestamp** (`git log -1 --format=%ct -- <file>`).
|
|
166
|
+
* If not available, use filesystem `mtime`.
|
|
167
|
+
2. If `page.id` exists, fetch Outline metadata (`documents.info`) and read `updatedAt`.
|
|
168
|
+
3. Compare timestamps (500ms tolerance):
|
|
169
|
+
|
|
170
|
+
* `local > remote` → **push** local content to Outline (`documents.update`).
|
|
171
|
+
* `remote > local` → **pull** remote content and overwrite local file (creates backup).
|
|
172
|
+
* equal → **skip**.
|
|
173
|
+
4. If `page.id` is null → create doc in Outline (`documents.create`) under manifest collection and parent, then persist returned `id` into `pages.json`.
|
|
174
|
+
|
|
175
|
+
Note: Timestamp comparison uses git commit times where possible so that checkout/mtime changes don't cause accidental overrides.
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
# CI integration example
|
|
180
|
+
|
|
181
|
+
A typical CI step (safe):
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
# in CI, set OUTLINE_API_KEY as secret
|
|
185
|
+
bun run sync.ts --dry-run # preview what would change
|
|
186
|
+
bun run sync.ts # perform sync
|
|
187
|
+
git add pages.json
|
|
188
|
+
git commit -m "chore: outline sync update" || true
|
|
189
|
+
# optionally push — guard against CI loops
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Tip: Only commit when `pages.json` changed and be careful not to trigger infinite CI runs from the commit itself (e.g., detect CI and skip push).
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
# Safety & backups
|
|
197
|
+
|
|
198
|
+
* Before overwriting a local file, the script copies it to `file.outline-sync.bak.<timestamp>` (same directory).
|
|
199
|
+
* `--dry-run` mode prints actions without writing to Outline or disk.
|
|
200
|
+
* The tool writes `id`s back to `pages.json`; commit that file after `--init`.
|
|
201
|
+
* Basic retry/backoff is implemented for API rate-limits (429). For very large collections you may want to add stronger batching.
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
# Troubleshooting
|
|
206
|
+
|
|
207
|
+
* `ERROR: please set OUTLINE_API_KEY` — set `OUTLINE_API_KEY` env var.
|
|
208
|
+
* `Manifest pages.json not found` — run `--init --collection-id=<id>` to bootstrap.
|
|
209
|
+
* Duplicate pages after init: ensure you used the right collection; the tool does not attempt to dedupe across multiple collections.
|
|
210
|
+
* `git log` returns nothing for a file: file not committed; the script falls back to `mtime`.
|
|
211
|
+
* Hitting rate limits (429): rerun later or implement slower batching.
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
# License
|
|
216
|
+
|
|
217
|
+
MIT — use, modify and share.
|
package/dist/sync.d.ts
ADDED
package/dist/sync.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import j from"fs/promises";import{existsSync as Y}from"fs";import V from"path";var F="pages.json",R=process.argv.slice(2),M=process.env.OUTLINE_BASE_URL||null,D=process.env.OUTLINE_API_KEY||null,y=null,B=!1,A=!1,x=!1;for(let J of R)if(J.startsWith("--collection-id="))y=J.split("=")[1]||null;else if(J==="--dry-run")B=!0;else if(J==="--init")A=!0;else if(J==="--list-collections")x=!0;else if(J==="init")A=!0;else if(J==="list-collections")x=!0;else if(J==="--help"||J==="-h")C();else if(J.startsWith("--api-key="))D=J.split("=")[1]||null;else if(J.startsWith("--base-url="))M=J.split("=")[1]||null;if(!M)M="https://app.getoutline.com";var E={Authorization:`Bearer ${D}`,"Content-Type":"application/json"};function C(){console.log(`
|
|
3
|
+
Usage:
|
|
4
|
+
OUTLINE_API_KEY=... bun run sync.ts [options]
|
|
5
|
+
|
|
6
|
+
Options:
|
|
7
|
+
--init Bootstrap pages.json + markdown files from a collection
|
|
8
|
+
--collection-id=COL_ID Use this collection id (required with --init unless OUTLINE_COLLECTION_ID set)
|
|
9
|
+
--list-collections List collections you have access to (prints id + name)
|
|
10
|
+
--dry-run Print actions without writing anything
|
|
11
|
+
--help Show this help
|
|
12
|
+
Examples:
|
|
13
|
+
OUTLINE_API_KEY=... bun run sync.ts --list-collections
|
|
14
|
+
OUTLINE_API_KEY=... bun run sync.ts --init --collection-id=abc-uuid
|
|
15
|
+
OUTLINE_API_KEY=... bun run sync.ts # perform regular sync
|
|
16
|
+
OUTLINE_API_KEY=... bun run sync.ts --dry-run
|
|
17
|
+
`),process.exit(0)}var b=process.env.OUTLINE_COLLECTION_ID||null;function u(J){if(y)return y;if(b)return b;if(J)return J;throw new Error("No collection id found. Provide collectionId in pages.json, or set OUTLINE_COLLECTION_ID env var, or pass --collection-id=ID")}var L=(J)=>new Promise((Q)=>setTimeout(Q,J));function N(J){return J.toString().normalize("NFKD").replace(/[\u0300-\u036F]/g,"").toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/(^-|-$)+/g,"").slice(0,120)}function P(J){try{let Q=V.resolve(J),X=Bun.spawnSync(["git","log","-1","--format=%ct","--",Q],{cwd:process.cwd()});if(X.exitCode!==0)return null;let Z=new TextDecoder().decode(X.stdout).trim();if(!Z)return null;let $=Number(Z);if(Number.isNaN($))return null;return $*1000}catch{return null}}async function g(J){let Q=P(J);if(Q)return Q;return(await j.stat(J)).mtimeMs}async function _(J,Q){if(Y(J)){let X=`${J}.outline-sync.bak.${Date.now()}`;if(!B)await j.copyFile(J,X);console.log(`Backed up existing file to ${X}`)}else if(!B)await j.mkdir(V.dirname(J),{recursive:!0});if(!B)await j.writeFile(J,Q,"utf8");else console.log(`[dry-run] would write file ${J} (${Q.length} bytes)`)}async function v(J,Q,X=3){let Z=`${M}/api/${J}`;for(let $=0;$<X;$++)try{let G=await fetch(Z,{method:"POST",headers:E,body:JSON.stringify(Q)});if(G.status===429){let z=1000*($+1);console.warn(`Rate limited. Backing off ${z}ms`),await L(z);continue}let H=await G.json();if(!G.ok)throw console.error(`[Outline] ${G.status} ${J} payload=`,Q,"response=",H),new Error(`Outline API error ${G.status}: ${JSON.stringify(H)}`);return H}catch(G){if($===X-1)throw G;console.warn(`Request failed (attempt ${$+1}): ${G}. Retrying...`),await L(500*($+1))}throw new Error("outlineRequest: unreachable")}async function h(J){return(await v("documents.info",{id:J})).data??null}async function m(J,Q,X,Z){let $={title:J,text:Q,collectionId:X,parentDocumentId:Z||null,publish:!0};if(B)return console.log(`[dry-run] would create doc title="${J}" collection=${X} parent=${Z}`),{id:`dry-run-${Math.random().toString(36).slice(2,9)}`,title:J,text:Q,collectionId:X,parentDocumentId:Z};return(await v("documents.create",$)).data}async function I(J,Q,X){let Z={id:J,text:X,publish:!0};if(Q)Z.title=Q;if(B)return console.log(`[dry-run] would update doc id=${J} title=${Q}`),{id:J,title:Q,text:X};return(await v("documents.update",Z)).data}async function f(){let J=[],Q=0,X=100;while(!0)try{let $=(await v("collections.list",{offset:Q,limit:X})).data||[];for(let G of $)J.push({id:G.id,name:G.name});if($.length<X)break;Q+=$.length}catch(Z){if((Z?.message??"").includes("Pagination limit is too large")&&X!==100){console.warn("Outline API complained about limit; retrying with limit=100"),X=100;continue}throw Z}return J}async function r(J){let Q=[],X=0,Z=100;while(!0)try{let G=(await v("documents.list",{collectionId:J,offset:X,limit:Z})).data||[];for(let H of G)Q.push(H);if(G.length<Z)break;X+=G.length}catch($){if(($?.message??"").includes("Pagination limit is too large")&&Z!==100){console.warn("Outline API complained about limit; retrying with limit=100"),Z=100;continue}throw $}return Q}async function c(J,Q="docs"){let X=new Map,Z=new Set;for(let z of J){let w=N(z.title||"untitled"),k=`${w}.md`;if(Z.has(k)){let q=(z.id||"").slice(0,6),O=1,U=`${w}-${q}.md`;while(Z.has(U))O++,U=`${w}-${q}-${O}.md`;k=U}Z.add(k);let K=V.join(Q,k);X.set(z.id,K);let W=z.text??`# ${z.title}
|
|
18
|
+
|
|
19
|
+
`;if(!B)await j.mkdir(Q,{recursive:!0}),await j.writeFile(K,W,"utf8");else console.log(`[dry-run] would write ${K} (${W.length} bytes)`)}let $=new Map;for(let z of J)$.set(z.id,{title:z.title,file:X.get(z.id)||V.join(Q,`${N(z.title)}.md`),id:z.id,children:[],raw:z});let G=[];for(let z of $.values()){let w=z.raw||{},k=w.parentDocumentId??w.parentId??null;if(k&&$.has(k))$.get(k).children.push(z);else G.push(z)}function H(z){return{title:z.title,file:z.file,id:z.id,children:(z.children||[]).map(H)}}return G.map(H)}async function S(J,Q){if(B){console.log(`[dry-run] would persist manifest to ${Q}`);return}await j.writeFile(Q,`${JSON.stringify(J,null,2)}
|
|
20
|
+
`,"utf8")}async function p(J){if(!Y(J))throw new Error(`Manifest ${J} not found. Create ${J} with structure described in README.`);let Q=await j.readFile(J,"utf8");return JSON.parse(Q)}async function T(J,Q,X,Z,$){let G=Q.file,H=V.resolve(G),z=Y(H),w=0;if(z)try{w=await g(H)}catch(K){console.warn(`Couldn't stat file ${H}: ${K}`),w=0}if(Q.id){let K=null;try{K=await h(Q.id)}catch(W){console.error(`Failed to fetch Outline info for ${Q.title} (${Q.id}): ${W}`);return}if(!K)console.log(`Outline doc ${Q.id} not found - will create as new under collection ${$}.`),Q.id=null;else{let W=K.updatedAt?new Date(K.updatedAt).getTime():0;if(!z)console.log(`[PULL] Local file missing for "${Q.title}" -> fetching remote`),await _(H,K.text||"");else if(w>W+500){console.log(`[PUSH] Local newer for "${Q.title}" -> updating Outline`);try{let q=await j.readFile(H,"utf8");await I(Q.id,Q.title,q),console.log(` Updated Outline doc ${Q.id}`)}catch(q){console.error(` Failed to push ${Q.title}: ${q}`)}}else if(W>w+500){console.log(`[PULL] Outline newer for "${Q.title}" -> overwriting local file`);try{await _(H,K.text||""),console.log(` Wrote local file ${H}`)}catch(q){console.error(` Failed to write file ${H}: ${q}`)}}else console.log(`[SKIP] No changes for "${Q.title}"`)}}if(!Q.id){if(!Y(H))await j.mkdir(V.dirname(H),{recursive:!0}),await j.writeFile(H,`# ${Q.title}
|
|
21
|
+
|
|
22
|
+
`,"utf8"),console.log(`Created local placeholder file ${H}`);let K=await j.readFile(H,"utf8");try{let W=await m(Q.title,K,$,X);if(W?.id)Q.id=W.id,console.log(`Created Outline doc "${Q.title}" id=${Q.id} in collection ${$}`),await S(J,Z);else console.warn(`Create returned no id for "${Q.title}"`)}catch(W){console.error(`Failed to create Outline doc for "${Q.title}": ${W}`)}}let k=Q.id||X;if(Q.children?.length)for(let K of Q.children)await T(J,K,k,Z,$)}async function d(){if(x){console.log("Fetching collections...");try{let X=await f();for(let Z of X)console.log(`${Z.id} ${Z.name}`)}catch(X){console.error(`Failed to list collections: ${X}`)}return}if(A){let X=y||b;if(!X)console.error("Init requires a collection id. Provide with --collection-id=ID or set OUTLINE_COLLECTION_ID env var."),process.exit(1);console.log(`Bootstrapping manifest from collection ${X} (dry-run=${B})...`);try{let Z=await r(X);console.log(`Fetched ${Z.length} documents from Outline.`);let $=await c(Z,"docs");await S({collectionId:X,pages:$},F),console.log(`Wrote manifest to ${F} (pages saved into docs/).`)}catch(Z){console.error(`Init failed: ${Z}`)}return}if(!Y(F))console.error(`Manifest ${F} not found. Run with --init --collection-id=COLLECTION_ID to bootstrap.`),process.exit(1);let J=await p(F),Q=u(J.collectionId??null);if(console.log(`Syncing into single collection: ${Q}`),B)console.log("Running in dry-run mode; no destructive actions will be performed.");for(let X of J.pages)await T(J,X,null,V.resolve(F),Q);await S(J,V.resolve(F)),console.log("Sync complete.")}d();
|
|
23
|
+
|
|
24
|
+
//# debugId=50792B40EFF52C1C64756E2164756E21
|
|
25
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3luYy50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsKICAgICIvKipcbiAqIE91dGxpbmUgPD4gR2l0IE1hcmtkb3duIHR3by13YXkgc3luYyAoc2luZ2xlLWNvbGxlY3Rpb24pICsgaW5pdFxuICogLSBCdW4gcnVudGltZSAodXNlcyBCdW4uc3Bhd25TeW5jLCBnbG9iYWwgZmV0Y2gpXG4gKlxuICogTmV3IGZlYXR1cmVzOlxuICogIC0gLS1pbml0IDogYm9vdHN0cmFwIHBhZ2VzLmpzb24gKyBtYXJrZG93biBmaWxlcyBmcm9tIGFuIGV4aXN0aW5nIGNvbGxlY3Rpb25cbiAqICAtIC0tbGlzdC1jb2xsZWN0aW9ucyA6IHByaW50cyBjb2xsZWN0aW9ucyAoaWQgKyBuYW1lKVxuICpcbiAqIFVzYWdlOlxuICogIE9VVExJTkVfQVBJX0tFWT0uLi4gYnVuIHJ1biBzeW5jLnRzIC0taW5pdCAtLWNvbGxlY3Rpb24taWQ9Q09MTEVDVElPTl9VVUlEXG4gKiAgT1VUTElORV9BUElfS0VZPS4uLiBidW4gcnVuIHN5bmMudHMgLS1saXN0LWNvbGxlY3Rpb25zXG4gKiAgT1VUTElORV9BUElfS0VZPS4uLiBidW4gcnVuIHN5bmMudHMgICAgICAgICAgICAjIG5vcm1hbCBzeW5jXG4gKlxuICogTk9URTogaWYgeW91IHJ1biAtLWluaXQgd2l0aG91dCAtLWRyeS1ydW4gaXQgd2lsbCBhY3R1YWxseSB3cml0ZSBmaWxlcyAmIHBhZ2VzLmpzb25cbiAqL1xuXG5pbXBvcnQgZnMgZnJvbSBcIm5vZGU6ZnMvcHJvbWlzZXNcIjtcbmltcG9ydCB7IGV4aXN0c1N5bmMgfSBmcm9tIFwibm9kZTpmc1wiO1xuaW1wb3J0IHBhdGggZnJvbSBcIm5vZGU6cGF0aFwiO1xuXG50eXBlIFBhZ2VFbnRyeSA9IHtcbiAgdGl0bGU6IHN0cmluZztcbiAgZmlsZTogc3RyaW5nO1xuICBpZDogc3RyaW5nIHwgbnVsbDtcbiAgY2hpbGRyZW4/OiBQYWdlRW50cnlbXTtcbn07XG5cbnR5cGUgTWFuaWZlc3QgPSB7XG4gIGNvbGxlY3Rpb25JZDogc3RyaW5nO1xuICBwYWdlczogUGFnZUVudHJ5W107XG59O1xuXG5jb25zdCBNQU5JRkVTVCA9IFwicGFnZXMuanNvblwiO1xuXG5jb25zdCBhcmd2ID0gcHJvY2Vzcy5hcmd2LnNsaWNlKDIpO1xubGV0IEJBU0VfVVJMID0gcHJvY2Vzcy5lbnYuT1VUTElORV9CQVNFX1VSTCB8fCBudWxsO1xubGV0IEFQSV9LRVkgPSBwcm9jZXNzLmVudi5PVVRMSU5FX0FQSV9LRVkgfHwgbnVsbDtcbmxldCBDTElfQ09MTEVDVElPTl9PVkVSUklERTogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG5sZXQgRFJZX1JVTiA9IGZhbHNlO1xubGV0IERPX0lOSVQgPSBmYWxzZTtcbmxldCBMSVNUX0NPTExFQ1RJT05TID0gZmFsc2U7XG5cbmZvciAoY29uc3QgYSBvZiBhcmd2KSB7XG4gIGlmIChhLnN0YXJ0c1dpdGgoXCItLWNvbGxlY3Rpb24taWQ9XCIpKSB7XG4gICAgQ0xJX0NPTExFQ1RJT05fT1ZFUlJJREUgPSBhLnNwbGl0KFwiPVwiKVsxXSB8fCBudWxsO1xuICB9IGVsc2UgaWYgKGEgPT09IFwiLS1kcnktcnVuXCIpIHtcbiAgICBEUllfUlVOID0gdHJ1ZTtcbiAgfSBlbHNlIGlmIChhID09PSBcIi0taW5pdFwiKSB7XG4gICAgRE9fSU5JVCA9IHRydWU7XG4gIH0gZWxzZSBpZiAoYSA9PT0gXCItLWxpc3QtY29sbGVjdGlvbnNcIikge1xuICAgIExJU1RfQ09MTEVDVElPTlMgPSB0cnVlO1xuICB9IGVsc2UgaWYgKGEgPT09IFwiaW5pdFwiKSB7XG4gICAgRE9fSU5JVCA9IHRydWU7XG4gIH0gZWxzZSBpZiAoYSA9PT0gXCJsaXN0LWNvbGxlY3Rpb25zXCIpIHtcbiAgICBMSVNUX0NPTExFQ1RJT05TID0gdHJ1ZTtcbiAgfSBlbHNlIGlmIChhID09PSBcIi0taGVscFwiIHx8IGEgPT09IFwiLWhcIikge1xuICAgIHByaW50SGVscEFuZEV4aXQoKTtcbiAgfSBlbHNlIGlmIChhLnN0YXJ0c1dpdGgoXCItLWFwaS1rZXk9XCIpKSB7XG4gICAgQVBJX0tFWSA9IGEuc3BsaXQoXCI9XCIpWzFdIHx8IG51bGw7XG4gIH0gZWxzZSBpZiAoYS5zdGFydHNXaXRoKFwiLS1iYXNlLXVybD1cIikpIHtcbiAgICBCQVNFX1VSTCA9IGEuc3BsaXQoXCI9XCIpWzFdIHx8IG51bGw7XG4gIH0gZWxzZSB7XG4gICAgLy8gaWdub3JlIHVua25vd24sIGFsbG93IG90aGVyIGZsYWdzIGluIGZ1dHVyZVxuICB9XG59XG5cbmlmICghQkFTRV9VUkwpIHtcbiAgQkFTRV9VUkwgPSBcImh0dHBzOi8vYXBwLmdldG91dGxpbmUuY29tXCI7XG59XG5cbmNvbnN0IEhFQURFUlMgPSB7XG4gIEF1dGhvcml6YXRpb246IGBCZWFyZXIgJHtBUElfS0VZfWAsXG4gIFwiQ29udGVudC1UeXBlXCI6IFwiYXBwbGljYXRpb24vanNvblwiLFxufTtcblxuZnVuY3Rpb24gcHJpbnRIZWxwQW5kRXhpdCgpIHtcbiAgY29uc29sZS5sb2coYFxuVXNhZ2U6XG4gIE9VVExJTkVfQVBJX0tFWT0uLi4gYnVuIHJ1biBzeW5jLnRzIFtvcHRpb25zXVxuXG5PcHRpb25zOlxuICAtLWluaXQgICAgICAgICAgICAgICAgICAgICAgQm9vdHN0cmFwIHBhZ2VzLmpzb24gKyBtYXJrZG93biBmaWxlcyBmcm9tIGEgY29sbGVjdGlvblxuICAtLWNvbGxlY3Rpb24taWQ9Q09MX0lEICAgICAgVXNlIHRoaXMgY29sbGVjdGlvbiBpZCAocmVxdWlyZWQgd2l0aCAtLWluaXQgdW5sZXNzIE9VVExJTkVfQ09MTEVDVElPTl9JRCBzZXQpXG4gIC0tbGlzdC1jb2xsZWN0aW9ucyAgICAgICAgICBMaXN0IGNvbGxlY3Rpb25zIHlvdSBoYXZlIGFjY2VzcyB0byAocHJpbnRzIGlkICsgbmFtZSlcbiAgLS1kcnktcnVuICAgICAgICAgICAgICAgICAgIFByaW50IGFjdGlvbnMgd2l0aG91dCB3cml0aW5nIGFueXRoaW5nXG4gIC0taGVscCAgICAgICAgICAgICAgICAgICAgICBTaG93IHRoaXMgaGVscFxuRXhhbXBsZXM6XG4gIE9VVExJTkVfQVBJX0tFWT0uLi4gYnVuIHJ1biBzeW5jLnRzIC0tbGlzdC1jb2xsZWN0aW9uc1xuICBPVVRMSU5FX0FQSV9LRVk9Li4uIGJ1biBydW4gc3luYy50cyAtLWluaXQgLS1jb2xsZWN0aW9uLWlkPWFiYy11dWlkXG4gIE9VVExJTkVfQVBJX0tFWT0uLi4gYnVuIHJ1biBzeW5jLnRzICAgICAgICAgICAgICAgICAgIyBwZXJmb3JtIHJlZ3VsYXIgc3luY1xuICBPVVRMSU5FX0FQSV9LRVk9Li4uIGJ1biBydW4gc3luYy50cyAtLWRyeS1ydW5cbmApO1xuICBwcm9jZXNzLmV4aXQoMCk7XG59XG5cbmNvbnN0IEVOVl9DT0xMRUNUSU9OID0gcHJvY2Vzcy5lbnYuT1VUTElORV9DT0xMRUNUSU9OX0lEIHx8IG51bGw7XG5mdW5jdGlvbiByZXNvbHZlQ29sbGVjdGlvbklkKG1hbmlmZXN0Q29sbGVjdGlvbklkOiBzdHJpbmcgfCBudWxsKTogc3RyaW5nIHtcbiAgaWYgKENMSV9DT0xMRUNUSU9OX09WRVJSSURFKSByZXR1cm4gQ0xJX0NPTExFQ1RJT05fT1ZFUlJJREU7XG4gIGlmIChFTlZfQ09MTEVDVElPTikgcmV0dXJuIEVOVl9DT0xMRUNUSU9OO1xuICBpZiAobWFuaWZlc3RDb2xsZWN0aW9uSWQpIHJldHVybiBtYW5pZmVzdENvbGxlY3Rpb25JZDtcbiAgdGhyb3cgbmV3IEVycm9yKFxuICAgIFwiTm8gY29sbGVjdGlvbiBpZCBmb3VuZC4gUHJvdmlkZSBjb2xsZWN0aW9uSWQgaW4gcGFnZXMuanNvbiwgb3Igc2V0IE9VVExJTkVfQ09MTEVDVElPTl9JRCBlbnYgdmFyLCBvciBwYXNzIC0tY29sbGVjdGlvbi1pZD1JRFwiLFxuICApO1xufVxuXG5jb25zdCBzbGVlcCA9IChtczogbnVtYmVyKSA9PiBuZXcgUHJvbWlzZSgocikgPT4gc2V0VGltZW91dChyLCBtcykpO1xuXG5mdW5jdGlvbiBzbHVnaWZ5VGl0bGUodGl0bGU6IHN0cmluZykge1xuICByZXR1cm4gdGl0bGVcbiAgICAudG9TdHJpbmcoKVxuICAgIC5ub3JtYWxpemUoXCJORktEXCIpXG4gICAgLnJlcGxhY2UoL1tcXHUwMzAwLVxcdTAzNkZdL2csIFwiXCIpIC8vIHJlbW92ZSBkaWFjcml0aWNzXG4gICAgLnRvTG93ZXJDYXNlKClcbiAgICAucmVwbGFjZSgvW15hLXowLTldKy9nLCBcIi1cIilcbiAgICAucmVwbGFjZSgvKF4tfC0kKSsvZywgXCJcIilcbiAgICAuc2xpY2UoMCwgMTIwKTtcbn1cblxuZnVuY3Rpb24gZ2V0R2l0VGltZXN0YW1wTXMoZmlsZVBhdGg6IHN0cmluZyk6IG51bWJlciB8IG51bGwge1xuICB0cnkge1xuICAgIGNvbnN0IHJlc29sdmVkID0gcGF0aC5yZXNvbHZlKGZpbGVQYXRoKTtcbiAgICBjb25zdCBvdXQgPSBCdW4uc3Bhd25TeW5jKFxuICAgICAgW1wiZ2l0XCIsIFwibG9nXCIsIFwiLTFcIiwgXCItLWZvcm1hdD0lY3RcIiwgXCItLVwiLCByZXNvbHZlZF0sXG4gICAgICB7IGN3ZDogcHJvY2Vzcy5jd2QoKSB9LFxuICAgICk7XG4gICAgaWYgKG91dC5leGl0Q29kZSAhPT0gMCkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGNvbnN0IHR4dCA9IG5ldyBUZXh0RGVjb2RlcigpLmRlY29kZShvdXQuc3Rkb3V0KS50cmltKCk7XG4gICAgaWYgKCF0eHQpIHJldHVybiBudWxsO1xuICAgIGNvbnN0IHNlYyA9IE51bWJlcih0eHQpO1xuICAgIGlmIChOdW1iZXIuaXNOYU4oc2VjKSkgcmV0dXJuIG51bGw7XG4gICAgcmV0dXJuIHNlYyAqIDEwMDA7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiBudWxsO1xuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGdldExvY2FsVGltZXN0YW1wTXMoZmlsZVBhdGg6IHN0cmluZyk6IFByb21pc2U8bnVtYmVyPiB7XG4gIGNvbnN0IGdpdFRzID0gZ2V0R2l0VGltZXN0YW1wTXMoZmlsZVBhdGgpO1xuICBpZiAoZ2l0VHMpIHJldHVybiBnaXRUcztcbiAgY29uc3Qgc3QgPSBhd2FpdCBmcy5zdGF0KGZpbGVQYXRoKTtcbiAgcmV0dXJuIHN0Lm10aW1lTXM7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHNhZmVXcml0ZUZpbGUoZmlsZVBhdGg6IHN0cmluZywgY29udGVudDogc3RyaW5nKSB7XG4gIGlmIChleGlzdHNTeW5jKGZpbGVQYXRoKSkge1xuICAgIGNvbnN0IGJhayA9IGAke2ZpbGVQYXRofS5vdXRsaW5lLXN5bmMuYmFrLiR7RGF0ZS5ub3coKX1gO1xuICAgIGlmICghRFJZX1JVTikge1xuICAgICAgYXdhaXQgZnMuY29weUZpbGUoZmlsZVBhdGgsIGJhayk7XG4gICAgfVxuICAgIGNvbnNvbGUubG9nKGBCYWNrZWQgdXAgZXhpc3RpbmcgZmlsZSB0byAke2Jha31gKTtcbiAgfSBlbHNlIHtcbiAgICBpZiAoIURSWV9SVU4pIHtcbiAgICAgIGF3YWl0IGZzLm1rZGlyKHBhdGguZGlybmFtZShmaWxlUGF0aCksIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICAgIH1cbiAgfVxuICBpZiAoIURSWV9SVU4pIHtcbiAgICBhd2FpdCBmcy53cml0ZUZpbGUoZmlsZVBhdGgsIGNvbnRlbnQsIFwidXRmOFwiKTtcbiAgfSBlbHNlIHtcbiAgICBjb25zb2xlLmxvZyhcbiAgICAgIGBbZHJ5LXJ1bl0gd291bGQgd3JpdGUgZmlsZSAke2ZpbGVQYXRofSAoJHtjb250ZW50Lmxlbmd0aH0gYnl0ZXMpYCxcbiAgICApO1xuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIG91dGxpbmVSZXF1ZXN0KFxuICBlbmRwb2ludDogc3RyaW5nLFxuICBib2R5OiBhbnksXG4gIHJldHJpZXMgPSAzLFxuKTogUHJvbWlzZTxhbnk+IHtcbiAgY29uc3QgdXJsID0gYCR7QkFTRV9VUkx9L2FwaS8ke2VuZHBvaW50fWA7XG4gIGZvciAobGV0IGF0dGVtcHQgPSAwOyBhdHRlbXB0IDwgcmV0cmllczsgYXR0ZW1wdCsrKSB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IGZldGNoKHVybCwge1xuICAgICAgICBtZXRob2Q6IFwiUE9TVFwiLFxuICAgICAgICBoZWFkZXJzOiBIRUFERVJTLFxuICAgICAgICBib2R5OiBKU09OLnN0cmluZ2lmeShib2R5KSxcbiAgICAgIH0pO1xuICAgICAgaWYgKHJlcy5zdGF0dXMgPT09IDQyOSkge1xuICAgICAgICBjb25zdCBiYWNrb2ZmID0gMTAwMCAqIChhdHRlbXB0ICsgMSk7XG4gICAgICAgIGNvbnNvbGUud2FybihgUmF0ZSBsaW1pdGVkLiBCYWNraW5nIG9mZiAke2JhY2tvZmZ9bXNgKTtcbiAgICAgICAgYXdhaXQgc2xlZXAoYmFja29mZik7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgY29uc3QganNvbiA9IGF3YWl0IHJlcy5qc29uKCk7XG4gICAgICBpZiAoIXJlcy5vaykge1xuICAgICAgICBjb25zb2xlLmVycm9yKFxuICAgICAgICAgIGBbT3V0bGluZV0gJHtyZXMuc3RhdHVzfSAke2VuZHBvaW50fSBwYXlsb2FkPWAsXG4gICAgICAgICAgYm9keSxcbiAgICAgICAgICBcInJlc3BvbnNlPVwiLFxuICAgICAgICAgIGpzb24sXG4gICAgICAgICk7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgT3V0bGluZSBBUEkgZXJyb3IgJHtyZXMuc3RhdHVzfTogJHtKU09OLnN0cmluZ2lmeShqc29uKX1gLFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGpzb247XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBpZiAoYXR0ZW1wdCA9PT0gcmV0cmllcyAtIDEpIHRocm93IGVycjtcbiAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgYFJlcXVlc3QgZmFpbGVkIChhdHRlbXB0ICR7YXR0ZW1wdCArIDF9KTogJHtlcnJ9LiBSZXRyeWluZy4uLmAsXG4gICAgICApO1xuICAgICAgYXdhaXQgc2xlZXAoNTAwICogKGF0dGVtcHQgKyAxKSk7XG4gICAgfVxuICB9XG4gIHRocm93IG5ldyBFcnJvcihcIm91dGxpbmVSZXF1ZXN0OiB1bnJlYWNoYWJsZVwiKTtcbn1cblxuLyogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgQVBJIGhlbHBlcnMgZm9yIG5vcm1hbCBzeW5jXG4gICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICovXG5cbmFzeW5jIGZ1bmN0aW9uIGZldGNoT3V0bGluZUluZm8oZG9jdW1lbnRJZDogc3RyaW5nKSB7XG4gIGNvbnN0IHBheWxvYWQgPSB7IGlkOiBkb2N1bWVudElkIH07XG4gIGNvbnN0IGpzb24gPSBhd2FpdCBvdXRsaW5lUmVxdWVzdChcImRvY3VtZW50cy5pbmZvXCIsIHBheWxvYWQpO1xuICByZXR1cm4ganNvbi5kYXRhID8/IG51bGw7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGNyZWF0ZU91dGxpbmVEb2N1bWVudChcbiAgdGl0bGU6IHN0cmluZyxcbiAgdGV4dDogc3RyaW5nLFxuICBjb2xsZWN0aW9uSWQ6IHN0cmluZyxcbiAgcGFyZW50RG9jdW1lbnRJZDogc3RyaW5nIHwgbnVsbCxcbikge1xuICBjb25zdCBwYXlsb2FkID0ge1xuICAgIHRpdGxlLFxuICAgIHRleHQsXG4gICAgY29sbGVjdGlvbklkLFxuICAgIHBhcmVudERvY3VtZW50SWQ6IHBhcmVudERvY3VtZW50SWQgfHwgbnVsbCxcbiAgICBwdWJsaXNoOiB0cnVlLFxuICB9O1xuICBpZiAoRFJZX1JVTikge1xuICAgIGNvbnNvbGUubG9nKFxuICAgICAgYFtkcnktcnVuXSB3b3VsZCBjcmVhdGUgZG9jIHRpdGxlPVwiJHt0aXRsZX1cIiBjb2xsZWN0aW9uPSR7Y29sbGVjdGlvbklkfSBwYXJlbnQ9JHtwYXJlbnREb2N1bWVudElkfWAsXG4gICAgKTtcbiAgICByZXR1cm4ge1xuICAgICAgaWQ6IGBkcnktcnVuLSR7TWF0aC5yYW5kb20oKS50b1N0cmluZygzNikuc2xpY2UoMiwgOSl9YCxcbiAgICAgIHRpdGxlLFxuICAgICAgdGV4dCxcbiAgICAgIGNvbGxlY3Rpb25JZCxcbiAgICAgIHBhcmVudERvY3VtZW50SWQsXG4gICAgfTtcbiAgfVxuICBjb25zdCBqc29uID0gYXdhaXQgb3V0bGluZVJlcXVlc3QoXCJkb2N1bWVudHMuY3JlYXRlXCIsIHBheWxvYWQpO1xuICByZXR1cm4ganNvbi5kYXRhO1xufVxuXG5hc3luYyBmdW5jdGlvbiB1cGRhdGVPdXRsaW5lRG9jdW1lbnQoXG4gIGlkOiBzdHJpbmcsXG4gIHRpdGxlOiBzdHJpbmcgfCB1bmRlZmluZWQsXG4gIHRleHQ6IHN0cmluZyxcbikge1xuICBjb25zdCBwYXlsb2FkOiBhbnkgPSB7IGlkLCB0ZXh0LCBwdWJsaXNoOiB0cnVlIH07XG4gIGlmICh0aXRsZSkgcGF5bG9hZC50aXRsZSA9IHRpdGxlO1xuICBpZiAoRFJZX1JVTikge1xuICAgIGNvbnNvbGUubG9nKGBbZHJ5LXJ1bl0gd291bGQgdXBkYXRlIGRvYyBpZD0ke2lkfSB0aXRsZT0ke3RpdGxlfWApO1xuICAgIHJldHVybiB7IGlkLCB0aXRsZSwgdGV4dCB9O1xuICB9XG4gIGNvbnN0IGpzb24gPSBhd2FpdCBvdXRsaW5lUmVxdWVzdChcImRvY3VtZW50cy51cGRhdGVcIiwgcGF5bG9hZCk7XG4gIHJldHVybiBqc29uLmRhdGE7XG59XG5cbi8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgIEluaXQgaGVscGVyc1xuICAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqL1xuXG4vKipcbiAqIExpc3QgT3V0bGluZSBjb2xsZWN0aW9ucyAocGFnZWQpXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGxpc3RDb2xsZWN0aW9ucygpOiBQcm9taXNlPHsgaWQ6IHN0cmluZzsgbmFtZTogc3RyaW5nIH1bXT4ge1xuICBjb25zdCBvdXQ6IHsgaWQ6IHN0cmluZzsgbmFtZTogc3RyaW5nIH1bXSA9IFtdO1xuICBsZXQgb2Zmc2V0ID0gMDtcbiAgbGV0IGxpbWl0ID0gMTAwOyAvLyBPdXRsaW5lIG1heCBpcyAxMDBcbiAgd2hpbGUgKHRydWUpIHtcbiAgICB0cnkge1xuICAgICAgY29uc3QganNvbiA9IGF3YWl0IG91dGxpbmVSZXF1ZXN0KFwiY29sbGVjdGlvbnMubGlzdFwiLCB7IG9mZnNldCwgbGltaXQgfSk7XG4gICAgICBjb25zdCBkYXRhID0ganNvbi5kYXRhIHx8IFtdO1xuICAgICAgZm9yIChjb25zdCBjIG9mIGRhdGEpIG91dC5wdXNoKHsgaWQ6IGMuaWQsIG5hbWU6IGMubmFtZSB9KTtcbiAgICAgIGlmIChkYXRhLmxlbmd0aCA8IGxpbWl0KSBicmVhaztcbiAgICAgIG9mZnNldCArPSBkYXRhLmxlbmd0aDtcbiAgICB9IGNhdGNoIChlcnI6IGFueSkge1xuICAgICAgLy8gRGVmZW5zaXZlOiBpZiBBUEkgY29tcGxhaW5zIGFib3V0IGxpbWl0LCByZXRyeSBvbmNlIHdpdGggbGltaXQ9MTAwXG4gICAgICBjb25zdCBtc2cgPSBlcnI/Lm1lc3NhZ2UgPz8gXCJcIjtcbiAgICAgIGlmIChtc2cuaW5jbHVkZXMoXCJQYWdpbmF0aW9uIGxpbWl0IGlzIHRvbyBsYXJnZVwiKSAmJiBsaW1pdCAhPT0gMTAwKSB7XG4gICAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgICBcIk91dGxpbmUgQVBJIGNvbXBsYWluZWQgYWJvdXQgbGltaXQ7IHJldHJ5aW5nIHdpdGggbGltaXQ9MTAwXCIsXG4gICAgICAgICk7XG4gICAgICAgIGxpbWl0ID0gMTAwO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIHRocm93IGVycjtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIG91dDtcbn1cblxuLyoqXG4gKiBMaXN0IGFsbCBkb2N1bWVudHMgaW4gYSBjb2xsZWN0aW9uIChwYWdlZCkuXG4gKiBSZXR1cm5zIGFycmF5IG9mIGRvY3VtZW50cyB7IGlkLCB0aXRsZSwgdGV4dCwgcGFyZW50RG9jdW1lbnRJZCwgdXBkYXRlZEF0IH1cbiAqL1xuYXN5bmMgZnVuY3Rpb24gbGlzdERvY3VtZW50c0luQ29sbGVjdGlvbihjb2xsZWN0aW9uSWQ6IHN0cmluZyk6IFByb21pc2U8YW55W10+IHtcbiAgY29uc3Qgb3V0OiBhbnlbXSA9IFtdO1xuICBsZXQgb2Zmc2V0ID0gMDtcbiAgbGV0IGxpbWl0ID0gMTAwOyAvLyBtdXN0IGJlIDw9IDEwMCBwZXIgT3V0bGluZSBBUElcbiAgd2hpbGUgKHRydWUpIHtcbiAgICB0cnkge1xuICAgICAgY29uc3QganNvbiA9IGF3YWl0IG91dGxpbmVSZXF1ZXN0KFwiZG9jdW1lbnRzLmxpc3RcIiwge1xuICAgICAgICBjb2xsZWN0aW9uSWQsXG4gICAgICAgIG9mZnNldCxcbiAgICAgICAgbGltaXQsXG4gICAgICB9KTtcbiAgICAgIGNvbnN0IGRhdGEgPSBqc29uLmRhdGEgfHwgW107XG4gICAgICBmb3IgKGNvbnN0IGQgb2YgZGF0YSkgb3V0LnB1c2goZCk7XG4gICAgICBpZiAoZGF0YS5sZW5ndGggPCBsaW1pdCkgYnJlYWs7XG4gICAgICBvZmZzZXQgKz0gZGF0YS5sZW5ndGg7XG4gICAgfSBjYXRjaCAoZXJyOiBhbnkpIHtcbiAgICAgIGNvbnN0IG1zZyA9IGVycj8ubWVzc2FnZSA/PyBcIlwiO1xuICAgICAgaWYgKG1zZy5pbmNsdWRlcyhcIlBhZ2luYXRpb24gbGltaXQgaXMgdG9vIGxhcmdlXCIpICYmIGxpbWl0ICE9PSAxMDApIHtcbiAgICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICAgIFwiT3V0bGluZSBBUEkgY29tcGxhaW5lZCBhYm91dCBsaW1pdDsgcmV0cnlpbmcgd2l0aCBsaW1pdD0xMDBcIixcbiAgICAgICAgKTtcbiAgICAgICAgbGltaXQgPSAxMDA7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgdGhyb3cgZXJyO1xuICAgIH1cbiAgfVxuICByZXR1cm4gb3V0O1xufVxuXG4vKipcbiAqIFdyaXRlIGRvY3MgdG8gZGlzayBhbmQgcmV0dXJuIHBhZ2VzIGFycmF5ICh3aXRoIGZpbGUgcGF0aHMgc2V0KVxuICovXG5hc3luYyBmdW5jdGlvbiBtYXRlcmlhbGl6ZURvY3NUb0ZpbGVzKFxuICBkb2NzOiBhbnlbXSxcbiAgZGVzdERpciA9IFwiZG9jc1wiLFxuKTogUHJvbWlzZTxQYWdlRW50cnlbXT4ge1xuICAvLyBkb2NzIGlzIGZsYXQgYXJyYXkgd2l0aCBpZC90aXRsZS90ZXh0L3BhcmVudERvY3VtZW50SWQgKG9yIHBhcmVudElkKVxuICBjb25zdCBpZFRvRmlsZW5hbWUgPSBuZXcgTWFwPHN0cmluZywgc3RyaW5nPigpO1xuICBjb25zdCB1c2VkID0gbmV3IFNldDxzdHJpbmc+KCk7XG5cbiAgLy8gMSkgYXNzaWduIHVuaXF1ZSBmaWxlbmFtZXMgYW5kIHdyaXRlIGZpbGVzXG4gIGZvciAoY29uc3QgZCBvZiBkb2NzKSB7XG4gICAgY29uc3Qgc2x1ZyA9IHNsdWdpZnlUaXRsZShkLnRpdGxlIHx8IFwidW50aXRsZWRcIik7XG4gICAgbGV0IGNhbmRpZGF0ZSA9IGAke3NsdWd9Lm1kYDtcbiAgICAvLyBlbnN1cmUgdW5pcXVlbmVzc1xuICAgIGlmICh1c2VkLmhhcyhjYW5kaWRhdGUpKSB7XG4gICAgICBjb25zdCBzaG9ydCA9IChkLmlkIHx8IFwiXCIpLnNsaWNlKDAsIDYpO1xuICAgICAgbGV0IGkgPSAxO1xuICAgICAgbGV0IGF0dGVtcHQgPSBgJHtzbHVnfS0ke3Nob3J0fS5tZGA7XG4gICAgICB3aGlsZSAodXNlZC5oYXMoYXR0ZW1wdCkpIHtcbiAgICAgICAgaSsrO1xuICAgICAgICBhdHRlbXB0ID0gYCR7c2x1Z30tJHtzaG9ydH0tJHtpfS5tZGA7XG4gICAgICB9XG4gICAgICBjYW5kaWRhdGUgPSBhdHRlbXB0O1xuICAgIH1cbiAgICB1c2VkLmFkZChjYW5kaWRhdGUpO1xuXG4gICAgY29uc3QgZnVsbFBhdGggPSBwYXRoLmpvaW4oZGVzdERpciwgY2FuZGlkYXRlKTtcbiAgICBpZFRvRmlsZW5hbWUuc2V0KGQuaWQsIGZ1bGxQYXRoKTtcblxuICAgIGNvbnN0IGNvbnRlbnQgPSBkLnRleHQgPz8gYCMgJHtkLnRpdGxlfVxcblxcbmA7XG4gICAgaWYgKCFEUllfUlVOKSB7XG4gICAgICBhd2FpdCBmcy5ta2RpcihkZXN0RGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgICAgIGF3YWl0IGZzLndyaXRlRmlsZShmdWxsUGF0aCwgY29udGVudCwgXCJ1dGY4XCIpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgYFtkcnktcnVuXSB3b3VsZCB3cml0ZSAke2Z1bGxQYXRofSAoJHtjb250ZW50Lmxlbmd0aH0gYnl0ZXMpYCxcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgLy8gMikgYnVpbGQgbm9kZXMgbWFwIChhbGwgbm9kZXMgcHJlc2VudCBiZWZvcmUgYXR0YWNoaW5nIGNoaWxkcmVuKVxuICBjb25zdCBtYXAgPSBuZXcgTWFwPHN0cmluZywgUGFnZUVudHJ5ICYgeyByYXc/OiBhbnkgfT4oKTtcbiAgZm9yIChjb25zdCBkIG9mIGRvY3MpIHtcbiAgICBtYXAuc2V0KGQuaWQsIHtcbiAgICAgIHRpdGxlOiBkLnRpdGxlLFxuICAgICAgZmlsZTpcbiAgICAgICAgaWRUb0ZpbGVuYW1lLmdldChkLmlkKSB8fFxuICAgICAgICBwYXRoLmpvaW4oZGVzdERpciwgYCR7c2x1Z2lmeVRpdGxlKGQudGl0bGUpfS5tZGApLFxuICAgICAgaWQ6IGQuaWQsXG4gICAgICBjaGlsZHJlbjogW10sXG4gICAgICByYXc6IGQsXG4gICAgfSBhcyBhbnkpO1xuICB9XG5cbiAgLy8gMykgYXR0YWNoIGNoaWxkcmVuIOKAlCByb2J1c3QgdG8gYm90aCBwYXJlbnREb2N1bWVudElkIGFuZCBwYXJlbnRJZFxuICBjb25zdCByb290czogKFBhZ2VFbnRyeSAmIHsgcmF3PzogYW55IH0pW10gPSBbXTtcbiAgZm9yIChjb25zdCBub2RlIG9mIG1hcC52YWx1ZXMoKSkge1xuICAgIGNvbnN0IHJhdyA9IG5vZGUucmF3IHx8IHt9O1xuICAgIGNvbnN0IHBhcmVudElkID0gcmF3LnBhcmVudERvY3VtZW50SWQgPz8gcmF3LnBhcmVudElkID8/IG51bGw7XG4gICAgaWYgKHBhcmVudElkICYmIG1hcC5oYXMocGFyZW50SWQpKSB7XG4gICAgICBtYXAuZ2V0KHBhcmVudElkKSEuY2hpbGRyZW4hLnB1c2gobm9kZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJvb3RzLnB1c2gobm9kZSk7XG4gICAgfVxuICB9XG5cbiAgLy8gNCkgc3RyaXAgaW50ZXJuYWwgYHJhd2AgYW5kIHJldHVybiB0cmVlIHJlY3Vyc2l2ZWx5XG4gIGZ1bmN0aW9uIHN0cmlwKG46IGFueSk6IFBhZ2VFbnRyeSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHRpdGxlOiBuLnRpdGxlLFxuICAgICAgZmlsZTogbi5maWxlLFxuICAgICAgaWQ6IG4uaWQsXG4gICAgICBjaGlsZHJlbjogKG4uY2hpbGRyZW4gfHwgW10pLm1hcChzdHJpcCksXG4gICAgfTtcbiAgfVxuICByZXR1cm4gcm9vdHMubWFwKHN0cmlwKTtcbn1cblxuLyogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgRXhpc3Rpbmcgc3luYyBsb2dpYyAodW5jaGFuZ2VkKVxuICAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqL1xuXG5hc3luYyBmdW5jdGlvbiBwZXJzaXN0TWFuaWZlc3QobWFuaWZlc3Q6IE1hbmlmZXN0LCBmaWxlUGF0aDogc3RyaW5nKSB7XG4gIGlmIChEUllfUlVOKSB7XG4gICAgY29uc29sZS5sb2coYFtkcnktcnVuXSB3b3VsZCBwZXJzaXN0IG1hbmlmZXN0IHRvICR7ZmlsZVBhdGh9YCk7XG4gICAgcmV0dXJuO1xuICB9XG4gIGF3YWl0IGZzLndyaXRlRmlsZShcbiAgICBmaWxlUGF0aCxcbiAgICBgJHtKU09OLnN0cmluZ2lmeShtYW5pZmVzdCwgbnVsbCwgMil9XFxuYCxcbiAgICBcInV0ZjhcIixcbiAgKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gbG9hZE1hbmlmZXN0KGZpbGVQYXRoOiBzdHJpbmcpOiBQcm9taXNlPE1hbmlmZXN0PiB7XG4gIGlmICghZXhpc3RzU3luYyhmaWxlUGF0aCkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgTWFuaWZlc3QgJHtmaWxlUGF0aH0gbm90IGZvdW5kLiBDcmVhdGUgJHtmaWxlUGF0aH0gd2l0aCBzdHJ1Y3R1cmUgZGVzY3JpYmVkIGluIFJFQURNRS5gLFxuICAgICk7XG4gIH1cbiAgY29uc3QgcmF3ID0gYXdhaXQgZnMucmVhZEZpbGUoZmlsZVBhdGgsIFwidXRmOFwiKTtcbiAgcmV0dXJuIEpTT04ucGFyc2UocmF3KSBhcyBNYW5pZmVzdDtcbn1cblxuYXN5bmMgZnVuY3Rpb24gc3luY1BhZ2UoXG4gIG1hbmlmZXN0OiBNYW5pZmVzdCxcbiAgcGFnZTogUGFnZUVudHJ5LFxuICBwYXJlbnRJZDogc3RyaW5nIHwgbnVsbCxcbiAgbWFuaWZlc3RQYXRoOiBzdHJpbmcsXG4gIHJlc29sdmVkQ29sbGVjdGlvbklkOiBzdHJpbmcsXG4pIHtcbiAgY29uc3QgZmlsZVBhdGggPSBwYWdlLmZpbGU7XG4gIGNvbnN0IGFic1BhdGggPSBwYXRoLnJlc29sdmUoZmlsZVBhdGgpO1xuICBjb25zdCBmaWxlRXhpc3RzID0gZXhpc3RzU3luYyhhYnNQYXRoKTtcblxuICBsZXQgbG9jYWxUcyA9IDA7XG4gIGlmIChmaWxlRXhpc3RzKSB7XG4gICAgdHJ5IHtcbiAgICAgIGxvY2FsVHMgPSBhd2FpdCBnZXRMb2NhbFRpbWVzdGFtcE1zKGFic1BhdGgpO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgY29uc29sZS53YXJuKGBDb3VsZG4ndCBzdGF0IGZpbGUgJHthYnNQYXRofTogJHtlcnJ9YCk7XG4gICAgICBsb2NhbFRzID0gMDtcbiAgICB9XG4gIH1cblxuICBpZiAocGFnZS5pZCkge1xuICAgIGxldCBkb2M6IGFueSA9IG51bGw7XG4gICAgdHJ5IHtcbiAgICAgIGRvYyA9IGF3YWl0IGZldGNoT3V0bGluZUluZm8ocGFnZS5pZCk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBjb25zb2xlLmVycm9yKFxuICAgICAgICBgRmFpbGVkIHRvIGZldGNoIE91dGxpbmUgaW5mbyBmb3IgJHtwYWdlLnRpdGxlfSAoJHtwYWdlLmlkfSk6ICR7ZXJyfWAsXG4gICAgICApO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICghZG9jKSB7XG4gICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgYE91dGxpbmUgZG9jICR7cGFnZS5pZH0gbm90IGZvdW5kIC0gd2lsbCBjcmVhdGUgYXMgbmV3IHVuZGVyIGNvbGxlY3Rpb24gJHtyZXNvbHZlZENvbGxlY3Rpb25JZH0uYCxcbiAgICAgICk7XG4gICAgICBwYWdlLmlkID0gbnVsbDtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgcmVtb3RlVXBkYXRlZEF0ID0gZG9jLnVwZGF0ZWRBdFxuICAgICAgICA/IG5ldyBEYXRlKGRvYy51cGRhdGVkQXQpLmdldFRpbWUoKVxuICAgICAgICA6IDA7XG5cbiAgICAgIGlmICghZmlsZUV4aXN0cykge1xuICAgICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgICBgW1BVTExdIExvY2FsIGZpbGUgbWlzc2luZyBmb3IgXCIke3BhZ2UudGl0bGV9XCIgLT4gZmV0Y2hpbmcgcmVtb3RlYCxcbiAgICAgICAgKTtcbiAgICAgICAgYXdhaXQgc2FmZVdyaXRlRmlsZShhYnNQYXRoLCBkb2MudGV4dCB8fCBcIlwiKTtcbiAgICAgIH0gZWxzZSBpZiAobG9jYWxUcyA+IHJlbW90ZVVwZGF0ZWRBdCArIDUwMCkge1xuICAgICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgICBgW1BVU0hdIExvY2FsIG5ld2VyIGZvciBcIiR7cGFnZS50aXRsZX1cIiAtPiB1cGRhdGluZyBPdXRsaW5lYCxcbiAgICAgICAgKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCBjb250ZW50ID0gYXdhaXQgZnMucmVhZEZpbGUoYWJzUGF0aCwgXCJ1dGY4XCIpO1xuICAgICAgICAgIGF3YWl0IHVwZGF0ZU91dGxpbmVEb2N1bWVudChwYWdlLmlkLCBwYWdlLnRpdGxlLCBjb250ZW50KTtcbiAgICAgICAgICBjb25zb2xlLmxvZyhgICBVcGRhdGVkIE91dGxpbmUgZG9jICR7cGFnZS5pZH1gKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgY29uc29sZS5lcnJvcihgICBGYWlsZWQgdG8gcHVzaCAke3BhZ2UudGl0bGV9OiAke2Vycn1gKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChyZW1vdGVVcGRhdGVkQXQgPiBsb2NhbFRzICsgNTAwKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICAgIGBbUFVMTF0gT3V0bGluZSBuZXdlciBmb3IgXCIke3BhZ2UudGl0bGV9XCIgLT4gb3ZlcndyaXRpbmcgbG9jYWwgZmlsZWAsXG4gICAgICAgICk7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgYXdhaXQgc2FmZVdyaXRlRmlsZShhYnNQYXRoLCBkb2MudGV4dCB8fCBcIlwiKTtcbiAgICAgICAgICBjb25zb2xlLmxvZyhgICBXcm90ZSBsb2NhbCBmaWxlICR7YWJzUGF0aH1gKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgY29uc29sZS5lcnJvcihgICBGYWlsZWQgdG8gd3JpdGUgZmlsZSAke2Fic1BhdGh9OiAke2Vycn1gKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc29sZS5sb2coYFtTS0lQXSBObyBjaGFuZ2VzIGZvciBcIiR7cGFnZS50aXRsZX1cImApO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGlmICghcGFnZS5pZCkge1xuICAgIGlmICghZXhpc3RzU3luYyhhYnNQYXRoKSkge1xuICAgICAgYXdhaXQgZnMubWtkaXIocGF0aC5kaXJuYW1lKGFic1BhdGgpLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgICAgIGF3YWl0IGZzLndyaXRlRmlsZShhYnNQYXRoLCBgIyAke3BhZ2UudGl0bGV9XFxuXFxuYCwgXCJ1dGY4XCIpO1xuICAgICAgY29uc29sZS5sb2coYENyZWF0ZWQgbG9jYWwgcGxhY2Vob2xkZXIgZmlsZSAke2Fic1BhdGh9YCk7XG4gICAgfVxuICAgIGNvbnN0IGNvbnRlbnQgPSBhd2FpdCBmcy5yZWFkRmlsZShhYnNQYXRoLCBcInV0ZjhcIik7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGNyZWF0ZWQgPSBhd2FpdCBjcmVhdGVPdXRsaW5lRG9jdW1lbnQoXG4gICAgICAgIHBhZ2UudGl0bGUsXG4gICAgICAgIGNvbnRlbnQsXG4gICAgICAgIHJlc29sdmVkQ29sbGVjdGlvbklkLFxuICAgICAgICBwYXJlbnRJZCxcbiAgICAgICk7XG4gICAgICBpZiAoY3JlYXRlZD8uaWQpIHtcbiAgICAgICAgcGFnZS5pZCA9IGNyZWF0ZWQuaWQ7XG4gICAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICAgIGBDcmVhdGVkIE91dGxpbmUgZG9jIFwiJHtwYWdlLnRpdGxlfVwiIGlkPSR7cGFnZS5pZH0gaW4gY29sbGVjdGlvbiAke3Jlc29sdmVkQ29sbGVjdGlvbklkfWAsXG4gICAgICAgICk7XG4gICAgICAgIGF3YWl0IHBlcnNpc3RNYW5pZmVzdChtYW5pZmVzdCwgbWFuaWZlc3RQYXRoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUud2FybihgQ3JlYXRlIHJldHVybmVkIG5vIGlkIGZvciBcIiR7cGFnZS50aXRsZX1cImApO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgY29uc29sZS5lcnJvcihgRmFpbGVkIHRvIGNyZWF0ZSBPdXRsaW5lIGRvYyBmb3IgXCIke3BhZ2UudGl0bGV9XCI6ICR7ZXJyfWApO1xuICAgIH1cbiAgfVxuXG4gIGNvbnN0IG5leHRQYXJlbnRJZCA9IHBhZ2UuaWQgfHwgcGFyZW50SWQ7XG4gIGlmIChwYWdlLmNoaWxkcmVuPy5sZW5ndGgpIHtcbiAgICBmb3IgKGNvbnN0IGNoaWxkIG9mIHBhZ2UuY2hpbGRyZW4pIHtcbiAgICAgIGF3YWl0IHN5bmNQYWdlKFxuICAgICAgICBtYW5pZmVzdCxcbiAgICAgICAgY2hpbGQsXG4gICAgICAgIG5leHRQYXJlbnRJZCxcbiAgICAgICAgbWFuaWZlc3RQYXRoLFxuICAgICAgICByZXNvbHZlZENvbGxlY3Rpb25JZCxcbiAgICAgICk7XG4gICAgfVxuICB9XG59XG5cbi8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgIE1haW5cbiAgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi9cblxuYXN5bmMgZnVuY3Rpb24gbWFpbigpIHtcbiAgaWYgKExJU1RfQ09MTEVDVElPTlMpIHtcbiAgICBjb25zb2xlLmxvZyhcIkZldGNoaW5nIGNvbGxlY3Rpb25zLi4uXCIpO1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBjb2xzID0gYXdhaXQgbGlzdENvbGxlY3Rpb25zKCk7XG4gICAgICBmb3IgKGNvbnN0IGMgb2YgY29scykge1xuICAgICAgICBjb25zb2xlLmxvZyhgJHtjLmlkfVxcdCR7Yy5uYW1lfWApO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgY29uc29sZS5lcnJvcihgRmFpbGVkIHRvIGxpc3QgY29sbGVjdGlvbnM6ICR7ZXJyfWApO1xuICAgIH1cbiAgICByZXR1cm47XG4gIH1cblxuICBpZiAoRE9fSU5JVCkge1xuICAgIGNvbnN0IGNvbGxlY3Rpb25JZCA9IENMSV9DT0xMRUNUSU9OX09WRVJSSURFIHx8IEVOVl9DT0xMRUNUSU9OO1xuICAgIGlmICghY29sbGVjdGlvbklkKSB7XG4gICAgICBjb25zb2xlLmVycm9yKFxuICAgICAgICBcIkluaXQgcmVxdWlyZXMgYSBjb2xsZWN0aW9uIGlkLiBQcm92aWRlIHdpdGggLS1jb2xsZWN0aW9uLWlkPUlEIG9yIHNldCBPVVRMSU5FX0NPTExFQ1RJT05fSUQgZW52IHZhci5cIixcbiAgICAgICk7XG4gICAgICBwcm9jZXNzLmV4aXQoMSk7XG4gICAgfVxuICAgIGNvbnNvbGUubG9nKFxuICAgICAgYEJvb3RzdHJhcHBpbmcgbWFuaWZlc3QgZnJvbSBjb2xsZWN0aW9uICR7Y29sbGVjdGlvbklkfSAoZHJ5LXJ1bj0ke0RSWV9SVU59KS4uLmAsXG4gICAgKTtcbiAgICB0cnkge1xuICAgICAgY29uc3QgZG9jcyA9IGF3YWl0IGxpc3REb2N1bWVudHNJbkNvbGxlY3Rpb24oY29sbGVjdGlvbklkKTtcbiAgICAgIGNvbnNvbGUubG9nKGBGZXRjaGVkICR7ZG9jcy5sZW5ndGh9IGRvY3VtZW50cyBmcm9tIE91dGxpbmUuYCk7XG4gICAgICBjb25zdCByb290cyA9IGF3YWl0IG1hdGVyaWFsaXplRG9jc1RvRmlsZXMoZG9jcywgXCJkb2NzXCIpO1xuICAgICAgY29uc3QgbWFuaWZlc3Q6IE1hbmlmZXN0ID0ge1xuICAgICAgICBjb2xsZWN0aW9uSWQsXG4gICAgICAgIHBhZ2VzOiByb290cyxcbiAgICAgIH07XG4gICAgICBhd2FpdCBwZXJzaXN0TWFuaWZlc3QobWFuaWZlc3QsIE1BTklGRVNUKTtcbiAgICAgIGNvbnNvbGUubG9nKGBXcm90ZSBtYW5pZmVzdCB0byAke01BTklGRVNUfSAocGFnZXMgc2F2ZWQgaW50byBkb2NzLykuYCk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBjb25zb2xlLmVycm9yKGBJbml0IGZhaWxlZDogJHtlcnJ9YCk7XG4gICAgfVxuICAgIHJldHVybjtcbiAgfVxuXG4gIC8vIG5vcm1hbCBzeW5jIGZsb3dcbiAgLy8gaWYgbWFuaWZlc3QgbWlzc2luZywgZXJyb3IgYW5kIGhpbnQgdG8gdXNlIC0taW5pdFxuICBpZiAoIWV4aXN0c1N5bmMoTUFOSUZFU1QpKSB7XG4gICAgY29uc29sZS5lcnJvcihcbiAgICAgIGBNYW5pZmVzdCAke01BTklGRVNUfSBub3QgZm91bmQuIFJ1biB3aXRoIC0taW5pdCAtLWNvbGxlY3Rpb24taWQ9Q09MTEVDVElPTl9JRCB0byBib290c3RyYXAuYCxcbiAgICApO1xuICAgIHByb2Nlc3MuZXhpdCgxKTtcbiAgfVxuICBjb25zdCBtYW5pZmVzdCA9IGF3YWl0IGxvYWRNYW5pZmVzdChNQU5JRkVTVCk7XG4gIGNvbnN0IGVmZmVjdGl2ZUNvbGxlY3Rpb25JZCA9IHJlc29sdmVDb2xsZWN0aW9uSWQoXG4gICAgbWFuaWZlc3QuY29sbGVjdGlvbklkID8/IG51bGwsXG4gICk7XG4gIGNvbnNvbGUubG9nKGBTeW5jaW5nIGludG8gc2luZ2xlIGNvbGxlY3Rpb246ICR7ZWZmZWN0aXZlQ29sbGVjdGlvbklkfWApO1xuICBpZiAoRFJZX1JVTilcbiAgICBjb25zb2xlLmxvZyhcbiAgICAgIFwiUnVubmluZyBpbiBkcnktcnVuIG1vZGU7IG5vIGRlc3RydWN0aXZlIGFjdGlvbnMgd2lsbCBiZSBwZXJmb3JtZWQuXCIsXG4gICAgKTtcblxuICBmb3IgKGNvbnN0IHAgb2YgbWFuaWZlc3QucGFnZXMpIHtcbiAgICBhd2FpdCBzeW5jUGFnZShcbiAgICAgIG1hbmlmZXN0LFxuICAgICAgcCxcbiAgICAgIG51bGwsXG4gICAgICBwYXRoLnJlc29sdmUoTUFOSUZFU1QpLFxuICAgICAgZWZmZWN0aXZlQ29sbGVjdGlvbklkLFxuICAgICk7XG4gIH1cbiAgYXdhaXQgcGVyc2lzdE1hbmlmZXN0KG1hbmlmZXN0LCBwYXRoLnJlc29sdmUoTUFOSUZFU1QpKTtcbiAgY29uc29sZS5sb2coXCJTeW5jIGNvbXBsZXRlLlwiKTtcbn1cblxubWFpbigpO1xuIgogIF0sCiAgIm1hcHBpbmdzIjogIjtBQWdCQSwyQkFDQSxxQkFBUyxXQUNULG9CQWNBLElBQU0sRUFBVyxhQUVYLEVBQU8sUUFBUSxLQUFLLE1BQU0sQ0FBQyxFQUM3QixFQUFXLFFBQVEsSUFBSSxrQkFBb0IsS0FDM0MsRUFBVSxRQUFRLElBQUksaUJBQW1CLEtBQ3pDLEVBQXlDLEtBQ3pDLEVBQVUsR0FDVixFQUFVLEdBQ1YsRUFBbUIsR0FFdkIsUUFBVyxLQUFLLEVBQ2QsR0FBSSxFQUFFLFdBQVcsa0JBQWtCLEVBQ2pDLEVBQTBCLEVBQUUsTUFBTSxHQUFHLEVBQUUsSUFBTSxLQUN4QyxRQUFJLElBQU0sWUFD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QUFRLEVBQ3hDLFFBQVEsSUFBSSxxQkFBcUIsNkJBQW9DLEVBQ3JFLE1BQU8sRUFBSyxDQUNaLFFBQVEsTUFBTSxnQkFBZ0IsR0FBSyxFQUVyQyxPQUtGLElBQUssRUFBVyxDQUFRLEVBQ3RCLFFBQVEsTUFDTixZQUFZLDBFQUNkLEVBQ0EsUUFBUSxLQUFLLENBQUMsRUFFaEIsSUFBTSxFQUFXLE1BQU0sRUFBYSxDQUFRLEVBQ3RDLEVBQXdCLEVBQzVCLEVBQVMsY0FBZ0IsSUFDM0IsRUFFQSxHQURBLFFBQVEsSUFBSSxtQ0FBbUMsR0FBdUIsRUFDbEUsRUFDRixRQUFRLElBQ04sb0VBQ0YsRUFFRixRQUFXLEtBQUssRUFBUyxNQUN2QixNQUFNLEVBQ0osRUFDQSxFQUNBLEtBQ0EsRUFBSyxRQUFRLENBQVEsRUFDckIsQ0FDRixFQUVGLE1BQU0sRUFBZ0IsRUFBVSxFQUFLLFFBQVEsQ0FBUSxDQUFDLEVBQ3RELFFBQVEsSUFBSSxnQkFBZ0IsRUFHOUIsRUFBSyIsCiAgImRlYnVnSWQiOiAiNTA3OTJCNDBFRkY1MkMxQzY0NzU2RTIxNjQ3NTZFMjEiLAogICJuYW1lcyI6IFtdCn0=
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dockstat/outline-sync",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A simple outline git-sync library",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/sync.js",
|
|
7
|
+
"types": "./dist/sync.d.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"outline-sync": "./dist/sync.js"
|
|
10
|
+
},
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/sync.d.ts",
|
|
14
|
+
"import": "./dist/sync.js",
|
|
15
|
+
"default": "./dist/sync.js"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist/**/*",
|
|
20
|
+
"README.md"
|
|
21
|
+
],
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "bun run ./build.ts",
|
|
24
|
+
"dev": "bun build sync.ts",
|
|
25
|
+
"lint": "biome lint .",
|
|
26
|
+
"lint:fix": "biome lint --write .",
|
|
27
|
+
"check-types": "bunx tsc --noEmit",
|
|
28
|
+
"test": "bun run test.ts",
|
|
29
|
+
"clean": "rm -rf dist",
|
|
30
|
+
"prepublishOnly": "npm run clean && npm run build"
|
|
31
|
+
},
|
|
32
|
+
"keywords": [
|
|
33
|
+
"outline",
|
|
34
|
+
"sync",
|
|
35
|
+
"documentation",
|
|
36
|
+
"typescript",
|
|
37
|
+
"bun",
|
|
38
|
+
"git-sync",
|
|
39
|
+
"cli"
|
|
40
|
+
],
|
|
41
|
+
"author": "Its4Nik",
|
|
42
|
+
"license": "MIT",
|
|
43
|
+
"repository": {
|
|
44
|
+
"type": "git",
|
|
45
|
+
"url": "https://github.com/Its4Nik/DockStat",
|
|
46
|
+
"directory": "packages/outline-sync"
|
|
47
|
+
},
|
|
48
|
+
"bugs": {
|
|
49
|
+
"url": "https://github.com/Its4Nik/DockStat/issues"
|
|
50
|
+
},
|
|
51
|
+
"homepage": "https://github.com/Its4Nik/DockStat/tree/main/packages/outline-sync",
|
|
52
|
+
"engines": {
|
|
53
|
+
"bun": ">=1.0.0"
|
|
54
|
+
},
|
|
55
|
+
"peerDependencies": {
|
|
56
|
+
"typescript": "^5"
|
|
57
|
+
},
|
|
58
|
+
"devDependencies": {
|
|
59
|
+
"@types/bun": "latest"
|
|
60
|
+
}
|
|
61
|
+
}
|