signalk-backup 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.
Files changed (43) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +71 -0
  3. package/assets/icon.png +0 -0
  4. package/assets/icon.svg +46 -0
  5. package/package.json +91 -0
  6. package/plugin/backup-client.d.ts +60 -0
  7. package/plugin/backup-client.d.ts.map +1 -0
  8. package/plugin/backup-client.js +87 -0
  9. package/plugin/backup-client.js.map +1 -0
  10. package/plugin/config/schema.d.ts +32 -0
  11. package/plugin/config/schema.d.ts.map +1 -0
  12. package/plugin/config/schema.js +83 -0
  13. package/plugin/config/schema.js.map +1 -0
  14. package/plugin/database-export/index.d.ts +33 -0
  15. package/plugin/database-export/index.d.ts.map +1 -0
  16. package/plugin/database-export/index.js +55 -0
  17. package/plugin/database-export/index.js.map +1 -0
  18. package/plugin/database-export/questdb.d.ts +41 -0
  19. package/plugin/database-export/questdb.d.ts.map +1 -0
  20. package/plugin/database-export/questdb.js +143 -0
  21. package/plugin/database-export/questdb.js.map +1 -0
  22. package/plugin/database-export/types.d.ts +30 -0
  23. package/plugin/database-export/types.d.ts.map +1 -0
  24. package/plugin/database-export/types.js +10 -0
  25. package/plugin/database-export/types.js.map +1 -0
  26. package/plugin/index.d.ts +4 -0
  27. package/plugin/index.d.ts.map +1 -0
  28. package/plugin/index.js +477 -0
  29. package/plugin/index.js.map +1 -0
  30. package/plugin/proxy.d.ts +13 -0
  31. package/plugin/proxy.d.ts.map +1 -0
  32. package/plugin/proxy.js +100 -0
  33. package/plugin/proxy.js.map +1 -0
  34. package/plugin/types.d.ts +121 -0
  35. package/plugin/types.d.ts.map +1 -0
  36. package/plugin/types.js +2 -0
  37. package/plugin/types.js.map +1 -0
  38. package/public/assets/index-B7P78qlq.js +2 -0
  39. package/public/assets/index-B7P78qlq.js.map +1 -0
  40. package/public/assets/main-DQRPJ7oa.js +11 -0
  41. package/public/assets/main-DQRPJ7oa.js.map +1 -0
  42. package/public/icon.svg +46 -0
  43. package/public/index.html +27 -0
@@ -0,0 +1,121 @@
1
+ import { ServerAPI } from '@signalk/server-api';
2
+ export type BackupServerAPI = ServerAPI;
3
+ export type ContainerState = 'running' | 'stopped' | 'missing' | 'no-runtime';
4
+ export interface ContainerRuntimeInfo {
5
+ runtime: 'podman' | 'docker';
6
+ version: string;
7
+ isPodmanDockerShim: boolean;
8
+ }
9
+ export interface ContainerResourceLimits {
10
+ cpus?: number | null;
11
+ cpuShares?: number | null;
12
+ cpusetCpus?: string | null;
13
+ memory?: string | null;
14
+ memorySwap?: string | null;
15
+ memoryReservation?: string | null;
16
+ pidsLimit?: number | null;
17
+ oomScoreAdj?: number | null;
18
+ }
19
+ export interface ContainerConfig {
20
+ image: string;
21
+ tag: string;
22
+ ports?: Record<string, string>;
23
+ volumes?: Record<string, string>;
24
+ env?: Record<string, string>;
25
+ restart?: 'no' | 'unless-stopped' | 'always';
26
+ command?: string[];
27
+ networkMode?: string;
28
+ resources?: ContainerResourceLimits;
29
+ /**
30
+ * Mount the SignalK data dir at this path inside the container, regardless
31
+ * of how SignalK is deployed (bare-metal, named volume, bind mount).
32
+ */
33
+ signalkDataMount?: string;
34
+ /**
35
+ * Mount the SignalK *config root* (the entire `~/.signalk/` tree) at this
36
+ * path inside the container. Distinct from `signalkDataMount`, which
37
+ * resolves to the plugin-private subdir. Use this when the container
38
+ * needs settings.json, security.json, or the whole plugin-config-data tree
39
+ * (e.g. backup tools). Requires signalk-container >= 1.5.0.
40
+ */
41
+ signalkConfigRootMount?: string;
42
+ /**
43
+ * Ports inside the container that the SignalK process must be able to
44
+ * reach back to. signalk-container picks the right networking strategy
45
+ * automatically and exposes the chosen address via resolveContainerAddress.
46
+ */
47
+ signalkAccessiblePorts?: number[];
48
+ }
49
+ export interface ContainerInfo {
50
+ name: string;
51
+ image: string;
52
+ state: ContainerState;
53
+ }
54
+ export interface UpdateResourcesResult {
55
+ method: 'live' | 'recreated';
56
+ warnings?: string[];
57
+ }
58
+ export type UpdateReason = 'newer-version' | 'digest-drift' | 'older-than-pinned' | 'up-to-date' | 'offline' | 'unknown' | 'error';
59
+ export type UpdateTagKind = 'semver' | 'floating' | 'unknown';
60
+ export interface UpdateCheckResult {
61
+ pluginId: string;
62
+ containerName: string;
63
+ runningTag: string;
64
+ tagKind: UpdateTagKind;
65
+ currentVersion: string | null;
66
+ latestVersion: string | null;
67
+ updateAvailable: boolean;
68
+ reason: UpdateReason;
69
+ error?: string;
70
+ checkedAt: string;
71
+ lastSuccessfulCheckAt: string | null;
72
+ fromCache: boolean;
73
+ }
74
+ export interface VersionSource {
75
+ fetch: (...args: unknown[]) => Promise<unknown>;
76
+ }
77
+ export interface UpdateRegistration {
78
+ pluginId: string;
79
+ containerName: string;
80
+ image: string;
81
+ currentTag: () => string;
82
+ versionSource: VersionSource;
83
+ currentVersion?: () => Promise<string | null>;
84
+ checkInterval?: string;
85
+ }
86
+ export interface UpdateServiceApi {
87
+ register: (reg: UpdateRegistration) => void;
88
+ unregister: (pluginId: string) => void;
89
+ checkOne: (pluginId: string) => Promise<UpdateCheckResult>;
90
+ checkAll: () => Promise<UpdateCheckResult[]>;
91
+ getLastResult: (pluginId: string) => UpdateCheckResult | null;
92
+ sources: {
93
+ githubReleases: (repo: string, options?: {
94
+ allowPrerelease?: boolean;
95
+ tagPrefix?: string;
96
+ }) => VersionSource;
97
+ dockerHubTags: (image: string, options?: {
98
+ filter?: (tag: string) => boolean;
99
+ }) => VersionSource;
100
+ };
101
+ }
102
+ export interface ContainerManagerApi {
103
+ getRuntime: () => ContainerRuntimeInfo | null;
104
+ pullImage: (image: string, onProgress?: (msg: string) => void) => Promise<void>;
105
+ imageExists: (image: string) => Promise<boolean>;
106
+ getImageDigest: (imageOrContainer: string) => Promise<string | null>;
107
+ ensureRunning: (name: string, config: ContainerConfig) => Promise<void>;
108
+ start: (name: string) => Promise<void>;
109
+ stop: (name: string) => Promise<void>;
110
+ remove: (name: string) => Promise<void>;
111
+ getState: (name: string) => Promise<ContainerState>;
112
+ listContainers: () => Promise<ContainerInfo[]>;
113
+ updateResources: (name: string, limits: ContainerResourceLimits) => Promise<UpdateResourcesResult>;
114
+ getResources: (name: string) => ContainerResourceLimits;
115
+ resolveContainerAddress: (name: string, port: number) => Promise<string | null>;
116
+ updates: UpdateServiceApi;
117
+ }
118
+ declare global {
119
+ var __signalk_containerManager: ContainerManagerApi | undefined;
120
+ }
121
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAE/C,MAAM,MAAM,eAAe,GAAG,SAAS,CAAA;AAevC,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,YAAY,CAAA;AAE7E,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,QAAQ,GAAG,QAAQ,CAAA;IAC5B,OAAO,EAAE,MAAM,CAAA;IACf,kBAAkB,EAAE,OAAO,CAAA;CAC5B;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACjC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC5B;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAChC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC5B,OAAO,CAAC,EAAE,IAAI,GAAG,gBAAgB,GAAG,QAAQ,CAAA;IAC5C,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,uBAAuB,CAAA;IACnC;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB;;;;;;OAMG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAA;IAC/B;;;;OAIG;IACH,sBAAsB,CAAC,EAAE,MAAM,EAAE,CAAA;CAClC;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,cAAc,CAAA;CACtB;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,GAAG,WAAW,CAAA;IAC5B,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;CACpB;AAED,MAAM,MAAM,YAAY,GACpB,eAAe,GACf,cAAc,GACd,mBAAmB,GACnB,YAAY,GACZ,SAAS,GACT,SAAS,GACT,OAAO,CAAA;AAEX,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,UAAU,GAAG,SAAS,CAAA;AAE7D,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAA;IAChB,aAAa,EAAE,MAAM,CAAA;IACrB,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,aAAa,CAAA;IACtB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,eAAe,EAAE,OAAO,CAAA;IACxB,MAAM,EAAE,YAAY,CAAA;IACpB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;IACjB,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAA;IACpC,SAAS,EAAE,OAAO,CAAA;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;CAChD;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAA;IAChB,aAAa,EAAE,MAAM,CAAA;IACrB,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,MAAM,MAAM,CAAA;IACxB,aAAa,EAAE,aAAa,CAAA;IAC5B,cAAc,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IAC7C,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,CAAC,GAAG,EAAE,kBAAkB,KAAK,IAAI,CAAA;IAC3C,UAAU,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAA;IACtC,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,iBAAiB,CAAC,CAAA;IAC1D,QAAQ,EAAE,MAAM,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAA;IAC5C,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,iBAAiB,GAAG,IAAI,CAAA;IAC7D,OAAO,EAAE;QACP,cAAc,EAAE,CACd,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;YAAE,eAAe,CAAC,EAAE,OAAO,CAAC;YAAC,SAAS,CAAC,EAAE,MAAM,CAAA;SAAE,KACxD,aAAa,CAAA;QAClB,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;YAAE,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAA;SAAE,KAAK,aAAa,CAAA;KACjG,CAAA;CACF;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,oBAAoB,GAAG,IAAI,CAAA;IAC7C,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC/E,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IAChD,cAAc,EAAE,CAAC,gBAAgB,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IACpE,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACvE,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACtC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACrC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACvC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,CAAA;IACnD,cAAc,EAAE,MAAM,OAAO,CAAC,aAAa,EAAE,CAAC,CAAA;IAC9C,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,uBAAuB,KAAK,OAAO,CAAC,qBAAqB,CAAC,CAAA;IAClG,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,uBAAuB,CAAA;IACvD,uBAAuB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IAC/E,OAAO,EAAE,gBAAgB,CAAA;CAC1B;AAED,OAAO,CAAC,MAAM,CAAC;IACb,IAAI,0BAA0B,EAAE,mBAAmB,GAAG,SAAS,CAAA;CAChE"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ (function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),e.crossOrigin===`use-credentials`?t.credentials=`include`:e.crossOrigin===`anonymous`?t.credentials=`omit`:t.credentials=`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var e=`modulepreload`,t=function(e){return`/signalk-backup/`+e},n={},r=function(r,i,a){let o=Promise.resolve();if(i&&i.length>0){let r=document.getElementsByTagName(`link`),s=document.querySelector(`meta[property=csp-nonce]`),c=s?.nonce||s?.getAttribute(`nonce`);function l(e){return Promise.all(e.map(e=>Promise.resolve(e).then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}))))}o=l(i.map(i=>{if(i=t(i,a),i in n)return;n[i]=!0;let o=i.endsWith(`.css`),s=o?`[rel="stylesheet"]`:``;if(a)for(let e=r.length-1;e>=0;e--){let t=r[e];if(t.href===i&&(!o||t.rel===`stylesheet`))return}else if(document.querySelector(`link[href="${i}"]${s}`))return;let l=document.createElement(`link`);if(l.rel=o?`stylesheet`:e,o||(l.as=`script`),l.crossOrigin=``,l.href=i,c&&l.setAttribute(`nonce`,c),document.head.appendChild(l),o)return new Promise((e,t)=>{l.addEventListener(`load`,e),l.addEventListener(`error`,()=>t(Error(`Unable to preload CSS for ${i}`)))})}))}function s(e){let t=new Event(`vite:preloadError`,{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return o.then(e=>{for(let t of e||[])t.status===`rejected`&&s(t.reason);return r().catch(s)})};async function i(){let e=await fetch(`/admin/.vite/manifest.json`);if(!e.ok)return;let t=await e.json(),n=new Set;for(let e of Object.values(t))if(e){for(let t of e.css??[])n.add(t);typeof e.file==`string`&&e.file.endsWith(`.css`)&&n.add(e.file)}await Promise.all([...n].map(e=>new Promise(t=>{let n=document.createElement(`link`);n.rel=`stylesheet`,n.href=`/admin/`+e,n.onload=t,n.onerror=t,document.head.appendChild(n)})))}try{await i()}catch(e){console.warn(`signalk-backup: admin CSS not available`,e)}finally{await r(()=>import(`./main-DQRPJ7oa.js`),[])}
2
+ //# sourceMappingURL=index-B7P78qlq.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"mappings":"m2DACM,eAAe,GAAiB,CAC9B,IAAM,EAAM,MAAM,MAAM,6BAA6B,CACrD,GAAI,CAAC,EAAI,GAAI,OACb,IAAM,EAAW,MAAM,EAAI,MAAM,CAC3B,EAAW,IAAI,IAMrB,IAAK,IAAM,KAAS,OAAO,OAAO,EAAS,CACpC,KACL,KAAK,IAAM,KAAO,EAAM,KAAO,EAAE,CAAE,EAAS,IAAI,EAAI,CAChD,OAAO,EAAM,MAAS,UAAY,EAAM,KAAK,SAAS,OAAO,EAC/D,EAAS,IAAI,EAAM,KAAK,CAG5B,MAAM,QAAQ,IACZ,CAAC,GAAG,EAAS,CAAC,IACX,GACC,IAAI,QAAS,GAAY,CACvB,IAAM,EAAO,SAAS,cAAc,OAAO,CAC3C,EAAK,IAAM,aACX,EAAK,KAAO,UAAY,EACxB,EAAK,OAAS,EACd,EAAK,QAAU,EACf,SAAS,KAAK,YAAY,EAAK,EAC/B,CACL,CACF,CAGH,GAAI,CACF,MAAM,GAAgB,OACf,EAAK,CACZ,QAAQ,KAAK,0CAA2C,EAAI,QACpD,CACR,YAAM,OAAO","names":[],"ignoreList":[],"sources":["../../webapp/index.html?html-proxy&index=0.js"],"sourcesContent":["\n async function injectAdminCss() {\n const res = await fetch('/admin/.vite/manifest.json')\n if (!res.ok) return\n const manifest = await res.json()\n const cssFiles = new Set()\n // Two shapes are common: an entry whose `css` array lists its\n // stylesheet imports, OR a top-level entry whose `file` itself\n // ends in `.css` (when Vite extracts a global stylesheet). The\n // current SignalK admin uses the second shape; older builds and\n // the docs example use the first. Cover both.\n for (const entry of Object.values(manifest)) {\n if (!entry) continue\n for (const css of entry.css ?? []) cssFiles.add(css)\n if (typeof entry.file === 'string' && entry.file.endsWith('.css')) {\n cssFiles.add(entry.file)\n }\n }\n await Promise.all(\n [...cssFiles].map(\n (css) =>\n new Promise((resolve) => {\n const link = document.createElement('link')\n link.rel = 'stylesheet'\n link.href = '/admin/' + css\n link.onload = resolve\n link.onerror = resolve\n document.head.appendChild(link)\n })\n )\n )\n }\n\n try {\n await injectAdminCss()\n } catch (err) {\n console.warn('signalk-backup: admin CSS not available', err)\n } finally {\n await import('./src/main.tsx')\n }\n "],"file":"index-B7P78qlq.js"}