@offlinejs/devtools-ui 0.1.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/dist/index.d.ts +17 -0
- package/dist/index.js +72 -0
- package/dist/index.js.map +1 -0
- package/package.json +31 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { OfflineEventName, OfflineDB } from '@offlinejs/types';
|
|
2
|
+
|
|
3
|
+
interface DevtoolsEventEntry {
|
|
4
|
+
event: OfflineEventName;
|
|
5
|
+
payload: unknown;
|
|
6
|
+
timestamp: number;
|
|
7
|
+
}
|
|
8
|
+
interface DevtoolsController {
|
|
9
|
+
destroy(): void;
|
|
10
|
+
events(): DevtoolsEventEntry[];
|
|
11
|
+
/** Alias for render — mounts a live-updating timeline into the target. */
|
|
12
|
+
mount(target: HTMLElement): void;
|
|
13
|
+
render(target: HTMLElement): void;
|
|
14
|
+
}
|
|
15
|
+
declare const createDevtoolsController: (db: OfflineDB) => DevtoolsController;
|
|
16
|
+
|
|
17
|
+
export { type DevtoolsController, type DevtoolsEventEntry, createDevtoolsController };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
var events = [
|
|
3
|
+
"sync:start",
|
|
4
|
+
"sync:end",
|
|
5
|
+
"offline",
|
|
6
|
+
"online",
|
|
7
|
+
"queue:add",
|
|
8
|
+
"queue:complete",
|
|
9
|
+
"conflict",
|
|
10
|
+
"error",
|
|
11
|
+
"worker:message",
|
|
12
|
+
"coordination:message"
|
|
13
|
+
];
|
|
14
|
+
var createDevtoolsController = (db) => {
|
|
15
|
+
const entries = [];
|
|
16
|
+
let target = null;
|
|
17
|
+
const refresh = () => {
|
|
18
|
+
if (target) {
|
|
19
|
+
target.innerHTML = createMarkup(entries);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
const disposers = events.map(
|
|
23
|
+
(event) => db.on(event, (payload) => {
|
|
24
|
+
entries.unshift({
|
|
25
|
+
event,
|
|
26
|
+
payload,
|
|
27
|
+
timestamp: Date.now()
|
|
28
|
+
});
|
|
29
|
+
entries.splice(100);
|
|
30
|
+
refresh();
|
|
31
|
+
})
|
|
32
|
+
);
|
|
33
|
+
const render = (nextTarget) => {
|
|
34
|
+
target = nextTarget;
|
|
35
|
+
refresh();
|
|
36
|
+
};
|
|
37
|
+
return {
|
|
38
|
+
destroy() {
|
|
39
|
+
for (const dispose of disposers) {
|
|
40
|
+
dispose();
|
|
41
|
+
}
|
|
42
|
+
target = null;
|
|
43
|
+
},
|
|
44
|
+
events: () => [...entries],
|
|
45
|
+
mount: render,
|
|
46
|
+
render
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
var createMarkup = (entries) => `
|
|
50
|
+
<section class="offlinejs-devtools" style="font-family: ui-sans-serif, system-ui, sans-serif; padding: 12px">
|
|
51
|
+
<div style="display:flex;align-items:baseline;justify-content:space-between;gap:12px;margin-bottom:8px">
|
|
52
|
+
<h2 style="margin:0;font-size:1.05rem">OfflineJS Devtools</h2>
|
|
53
|
+
<span style="opacity:.7;font-size:.85rem">${entries.length} event${entries.length === 1 ? "" : "s"}</span>
|
|
54
|
+
</div>
|
|
55
|
+
${entries.length === 0 ? `<p style="margin:0;opacity:.7">Waiting for sync, queue, network, and conflict events\u2026</p>` : `<ol style="padding-left:20px;margin:0;display:grid;gap:10px">
|
|
56
|
+
${entries.map(
|
|
57
|
+
(entry) => `
|
|
58
|
+
<li>
|
|
59
|
+
<strong>${escapeHtml(entry.event)}</strong>
|
|
60
|
+
<time style="margin-left:8px;opacity:.7;font-size:.85rem">${new Date(entry.timestamp).toLocaleTimeString()}</time>
|
|
61
|
+
<pre style="margin:6px 0 0;padding:8px;overflow:auto;border-radius:8px;background:rgba(0,0,0,.06);font-size:12px">${escapeHtml(JSON.stringify(entry.payload, null, 2))}</pre>
|
|
62
|
+
</li>
|
|
63
|
+
`
|
|
64
|
+
).join("")}
|
|
65
|
+
</ol>`}
|
|
66
|
+
</section>
|
|
67
|
+
`;
|
|
68
|
+
var escapeHtml = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
69
|
+
|
|
70
|
+
export { createDevtoolsController };
|
|
71
|
+
//# sourceMappingURL=index.js.map
|
|
72
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";AAgBA,IAAM,MAAA,GAA6B;AAAA,EACjC,YAAA;AAAA,EACA,UAAA;AAAA,EACA,SAAA;AAAA,EACA,QAAA;AAAA,EACA,WAAA;AAAA,EACA,gBAAA;AAAA,EACA,UAAA;AAAA,EACA,OAAA;AAAA,EACA,gBAAA;AAAA,EACA;AACF,CAAA;AAEO,IAAM,wBAAA,GAA2B,CAAC,EAAA,KAAsC;AAC7E,EAAA,MAAM,UAAgC,EAAC;AACvC,EAAA,IAAI,MAAA,GAA6B,IAAA;AAEjC,EAAA,MAAM,UAAU,MAAY;AAC1B,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,MAAA,CAAO,SAAA,GAAY,aAAa,OAAO,CAAA;AAAA,IACzC;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,YAAY,MAAA,CAAO,GAAA;AAAA,IAAI,CAAC,KAAA,KAC5B,EAAA,CAAG,EAAA,CAAG,KAAA,EAAO,CAAC,OAAA,KAAyC;AACrD,MAAA,OAAA,CAAQ,OAAA,CAAQ;AAAA,QACd,KAAA;AAAA,QACA,OAAA;AAAA,QACA,SAAA,EAAW,KAAK,GAAA;AAAI,OACrB,CAAA;AACD,MAAA,OAAA,CAAQ,OAAO,GAAG,CAAA;AAClB,MAAA,OAAA,EAAQ;AAAA,IACV,CAAC;AAAA,GACH;AAEA,EAAA,MAAM,MAAA,GAAS,CAAC,UAAA,KAAkC;AAChD,IAAA,MAAA,GAAS,UAAA;AACT,IAAA,OAAA,EAAQ;AAAA,EACV,CAAA;AAEA,EAAA,OAAO;AAAA,IACL,OAAA,GAAU;AACR,MAAA,KAAA,MAAW,WAAW,SAAA,EAAW;AAC/B,QAAA,OAAA,EAAQ;AAAA,MACV;AACA,MAAA,MAAA,GAAS,IAAA;AAAA,IACX,CAAA;AAAA,IACA,MAAA,EAAQ,MAAM,CAAC,GAAG,OAAO,CAAA;AAAA,IACzB,KAAA,EAAO,MAAA;AAAA,IACP;AAAA,GACF;AACF;AAEA,IAAM,YAAA,GAAe,CAAC,OAAA,KAA0C;AAAA;AAAA;AAAA;AAAA,gDAAA,EAId,QAAQ,MAAM,CAAA,MAAA,EAAS,QAAQ,MAAA,KAAW,CAAA,GAAI,KAAK,GAAG,CAAA;AAAA;AAAA,IAAA,EAGlG,OAAA,CAAQ,MAAA,KAAW,CAAA,GACf,CAAA,8FAAA,CAAA,GACA,CAAA;AAAA,YAAA,EACI,OAAA,CACC,GAAA;AAAA,EACC,CAAC,KAAA,KAAU;AAAA;AAAA,4BAAA,EAEG,UAAA,CAAW,KAAA,CAAM,KAAK,CAAC,CAAA;AAAA,8EAAA,EAC2B,IAAI,IAAA,CAAK,KAAA,CAAM,SAAS,CAAA,CAAE,oBAAoB,CAAA;AAAA,sIAAA,EACU,UAAA,CAAW,KAAK,SAAA,CAAU,KAAA,CAAM,SAAS,IAAA,EAAM,CAAC,CAAC,CAAC,CAAA;AAAA;AAAA,gBAAA;AAG5K,CAAA,CACC,IAAA,CAAK,EAAE,CAAC;AAAA,eAAA,CAEnB;AAAA;AAAA,CAAA;AAIJ,IAAM,UAAA,GAAa,CAAC,KAAA,KAClB,KAAA,CACG,WAAW,GAAA,EAAK,OAAO,CAAA,CACvB,UAAA,CAAW,GAAA,EAAK,MAAM,EACtB,UAAA,CAAW,GAAA,EAAK,MAAM,CAAA,CACtB,UAAA,CAAW,KAAK,QAAQ,CAAA,CACxB,UAAA,CAAW,GAAA,EAAK,QAAQ,CAAA","file":"index.js","sourcesContent":["import type { OfflineDB, OfflineEventName, OfflineEvents } from \"@offlinejs/types\";\n\nexport interface DevtoolsEventEntry {\n event: OfflineEventName;\n payload: unknown;\n timestamp: number;\n}\n\nexport interface DevtoolsController {\n destroy(): void;\n events(): DevtoolsEventEntry[];\n /** Alias for render — mounts a live-updating timeline into the target. */\n mount(target: HTMLElement): void;\n render(target: HTMLElement): void;\n}\n\nconst events: OfflineEventName[] = [\n \"sync:start\",\n \"sync:end\",\n \"offline\",\n \"online\",\n \"queue:add\",\n \"queue:complete\",\n \"conflict\",\n \"error\",\n \"worker:message\",\n \"coordination:message\"\n];\n\nexport const createDevtoolsController = (db: OfflineDB): DevtoolsController => {\n const entries: DevtoolsEventEntry[] = [];\n let target: HTMLElement | null = null;\n\n const refresh = (): void => {\n if (target) {\n target.innerHTML = createMarkup(entries);\n }\n };\n\n const disposers = events.map((event) =>\n db.on(event, (payload: OfflineEvents[typeof event]) => {\n entries.unshift({\n event,\n payload,\n timestamp: Date.now()\n });\n entries.splice(100);\n refresh();\n })\n );\n\n const render = (nextTarget: HTMLElement): void => {\n target = nextTarget;\n refresh();\n };\n\n return {\n destroy() {\n for (const dispose of disposers) {\n dispose();\n }\n target = null;\n },\n events: () => [...entries],\n mount: render,\n render\n };\n};\n\nconst createMarkup = (entries: DevtoolsEventEntry[]): string => `\n <section class=\"offlinejs-devtools\" style=\"font-family: ui-sans-serif, system-ui, sans-serif; padding: 12px\">\n <div style=\"display:flex;align-items:baseline;justify-content:space-between;gap:12px;margin-bottom:8px\">\n <h2 style=\"margin:0;font-size:1.05rem\">OfflineJS Devtools</h2>\n <span style=\"opacity:.7;font-size:.85rem\">${entries.length} event${entries.length === 1 ? \"\" : \"s\"}</span>\n </div>\n ${\n entries.length === 0\n ? `<p style=\"margin:0;opacity:.7\">Waiting for sync, queue, network, and conflict events…</p>`\n : `<ol style=\"padding-left:20px;margin:0;display:grid;gap:10px\">\n ${entries\n .map(\n (entry) => `\n <li>\n <strong>${escapeHtml(entry.event)}</strong>\n <time style=\"margin-left:8px;opacity:.7;font-size:.85rem\">${new Date(entry.timestamp).toLocaleTimeString()}</time>\n <pre style=\"margin:6px 0 0;padding:8px;overflow:auto;border-radius:8px;background:rgba(0,0,0,.06);font-size:12px\">${escapeHtml(JSON.stringify(entry.payload, null, 2))}</pre>\n </li>\n `\n )\n .join(\"\")}\n </ol>`\n }\n </section>\n`;\n\nconst escapeHtml = (value: string): string =>\n value\n .replaceAll(\"&\", \"&\")\n .replaceAll(\"<\", \"<\")\n .replaceAll(\">\", \">\")\n .replaceAll('\"', \""\")\n .replaceAll(\"'\", \"'\");\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@offlinejs/devtools-ui",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Framework-free Devtools UI for OfflineJS.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"import": "./dist/index.js"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist"
|
|
15
|
+
],
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"@offlinejs/types": "0.1.0"
|
|
18
|
+
},
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"tsup": "latest",
|
|
21
|
+
"typescript": "latest"
|
|
22
|
+
},
|
|
23
|
+
"publishConfig": {
|
|
24
|
+
"access": "public",
|
|
25
|
+
"registry": "https://registry.npmjs.org/"
|
|
26
|
+
},
|
|
27
|
+
"scripts": {
|
|
28
|
+
"build": "tsup",
|
|
29
|
+
"typecheck": "tsc --noEmit"
|
|
30
|
+
}
|
|
31
|
+
}
|