@nextclaw/app-runtime 0.10.0 → 0.12.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 (56) hide show
  1. package/README.md +19 -2
  2. package/dist/index.d.ts +7 -2
  3. package/dist/index.js +6 -1
  4. package/dist/package.js +1 -1
  5. package/dist/services/app-home.service.d.ts +4 -0
  6. package/dist/services/app-home.service.d.ts.map +1 -1
  7. package/dist/services/app-home.service.js +15 -1
  8. package/dist/services/app-home.service.js.map +1 -1
  9. package/dist/services/app-install-source.service.js +14 -1
  10. package/dist/services/app-install-source.service.js.map +1 -1
  11. package/dist/services/app-installation-filesystem.service.js +68 -0
  12. package/dist/services/app-installation-filesystem.service.js.map +1 -0
  13. package/dist/services/app-installation-integrity.service.d.ts +20 -0
  14. package/dist/services/app-installation-integrity.service.d.ts.map +1 -0
  15. package/dist/services/app-installation-integrity.service.js +84 -0
  16. package/dist/services/app-installation-integrity.service.js.map +1 -0
  17. package/dist/services/app-installation-lifecycle.service.js +110 -0
  18. package/dist/services/app-installation-lifecycle.service.js.map +1 -0
  19. package/dist/services/app-installation.service.d.ts +21 -11
  20. package/dist/services/app-installation.service.d.ts.map +1 -1
  21. package/dist/services/app-installation.service.js +262 -280
  22. package/dist/services/app-installation.service.js.map +1 -1
  23. package/dist/services/app-instance-inventory.service.d.ts +31 -0
  24. package/dist/services/app-instance-inventory.service.d.ts.map +1 -0
  25. package/dist/services/app-instance-inventory.service.js +136 -0
  26. package/dist/services/app-instance-inventory.service.js.map +1 -0
  27. package/dist/services/app-instance-storage.service.d.ts +55 -0
  28. package/dist/services/app-instance-storage.service.d.ts.map +1 -0
  29. package/dist/services/app-instance-storage.service.js +269 -0
  30. package/dist/services/app-instance-storage.service.js.map +1 -0
  31. package/dist/services/app-manifest.service.d.ts +5 -1
  32. package/dist/services/app-manifest.service.d.ts.map +1 -1
  33. package/dist/services/app-manifest.service.js +59 -3
  34. package/dist/services/app-manifest.service.js.map +1 -1
  35. package/dist/services/app-publish.service.js +1 -1
  36. package/dist/services/app-publish.service.js.map +1 -1
  37. package/dist/services/app-registry.service.d.ts +13 -3
  38. package/dist/services/app-registry.service.d.ts.map +1 -1
  39. package/dist/services/app-registry.service.js +143 -13
  40. package/dist/services/app-registry.service.js.map +1 -1
  41. package/dist/services/file-lock.service.d.ts +20 -0
  42. package/dist/services/file-lock.service.d.ts.map +1 -0
  43. package/dist/services/file-lock.service.js +156 -0
  44. package/dist/services/file-lock.service.js.map +1 -0
  45. package/dist/types/app-installation.types.d.ts +7 -0
  46. package/dist/types/app-installation.types.d.ts.map +1 -1
  47. package/dist/types/app-manifest.types.d.ts +22 -1
  48. package/dist/types/app-manifest.types.d.ts.map +1 -1
  49. package/dist/types/app-manifest.types.js.map +1 -1
  50. package/dist/types/app-registry.types.d.ts +7 -1
  51. package/dist/types/app-registry.types.d.ts.map +1 -1
  52. package/dist/types/app-storage.types.d.ts +64 -0
  53. package/dist/types/app-storage.types.d.ts.map +1 -0
  54. package/dist/types/app-storage.types.js +7 -0
  55. package/dist/types/app-storage.types.js.map +1 -0
  56. package/package.json +1 -1
@@ -0,0 +1,156 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { access, mkdir, open, readFile, rm, stat } from "node:fs/promises";
3
+ import path from "node:path";
4
+ import { setTimeout } from "node:timers/promises";
5
+ //#region src/services/file-lock.service.ts
6
+ const DEFAULT_WAIT_TIMEOUT_MS = 15e3;
7
+ const MALFORMED_LOCK_STALE_AFTER_MS = 3e4;
8
+ const RETRY_DELAY_MS = 25;
9
+ var FileLockService = class FileLockService {
10
+ static localQueues = /* @__PURE__ */ new Map();
11
+ withLock = async (lockPath, operation, options = {}) => {
12
+ const resolvedLockPath = path.resolve(lockPath);
13
+ const current = (FileLockService.localQueues.get(resolvedLockPath) ?? Promise.resolve()).catch(() => void 0).then(async () => {
14
+ const release = await this.acquire(resolvedLockPath, options.waitTimeoutMs);
15
+ try {
16
+ return await operation();
17
+ } finally {
18
+ await release();
19
+ }
20
+ });
21
+ FileLockService.localQueues.set(resolvedLockPath, current);
22
+ try {
23
+ return await current;
24
+ } finally {
25
+ if (FileLockService.localQueues.get(resolvedLockPath) === current) FileLockService.localQueues.delete(resolvedLockPath);
26
+ }
27
+ };
28
+ acquire = async (lockPath, waitTimeoutMs = DEFAULT_WAIT_TIMEOUT_MS) => {
29
+ await mkdir(path.dirname(lockPath), { recursive: true });
30
+ const startedAt = Date.now();
31
+ const recoveryLockPath = `${lockPath}.recovery`;
32
+ while (true) {
33
+ if (await this.pathExists(recoveryLockPath)) {
34
+ await this.waitOrThrow(lockPath, startedAt, waitTimeoutMs);
35
+ continue;
36
+ }
37
+ const metadata = {
38
+ token: randomUUID(),
39
+ pid: process.pid,
40
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
41
+ };
42
+ try {
43
+ const handle = await open(lockPath, "wx", 384);
44
+ try {
45
+ await handle.writeFile(`${JSON.stringify(metadata)}\n`, "utf8");
46
+ await handle.sync();
47
+ } catch (error) {
48
+ await handle.close().catch(() => void 0);
49
+ await rm(lockPath, { force: true }).catch(() => void 0);
50
+ throw error;
51
+ }
52
+ return async () => {
53
+ await handle.close();
54
+ await this.removeOwnedLock(lockPath, metadata.token);
55
+ };
56
+ } catch (error) {
57
+ if (!this.isAlreadyExistsError(error)) throw error;
58
+ if (await this.canRecoverLock(lockPath)) {
59
+ const recovered = await this.recoverAndAcquire(lockPath, recoveryLockPath);
60
+ if (recovered) return recovered;
61
+ }
62
+ await this.waitOrThrow(lockPath, startedAt, waitTimeoutMs);
63
+ }
64
+ }
65
+ };
66
+ recoverAndAcquire = async (lockPath, recoveryLockPath) => {
67
+ let recoveryHandle;
68
+ try {
69
+ recoveryHandle = await open(recoveryLockPath, "wx", 384);
70
+ await recoveryHandle.writeFile(`${process.pid}\n`, "utf8");
71
+ await recoveryHandle.sync();
72
+ } catch (error) {
73
+ await recoveryHandle?.close().catch(() => void 0);
74
+ if (this.isAlreadyExistsError(error)) return;
75
+ throw error;
76
+ }
77
+ try {
78
+ if (!await this.canRecoverLock(lockPath)) return;
79
+ await rm(lockPath, { force: true });
80
+ const metadata = {
81
+ token: randomUUID(),
82
+ pid: process.pid,
83
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
84
+ };
85
+ const handle = await open(lockPath, "wx", 384);
86
+ try {
87
+ await handle.writeFile(`${JSON.stringify(metadata)}\n`, "utf8");
88
+ await handle.sync();
89
+ } catch (error) {
90
+ await handle.close().catch(() => void 0);
91
+ await rm(lockPath, { force: true }).catch(() => void 0);
92
+ throw error;
93
+ }
94
+ return async () => {
95
+ await handle.close();
96
+ await this.removeOwnedLock(lockPath, metadata.token);
97
+ };
98
+ } finally {
99
+ await recoveryHandle.close();
100
+ await rm(recoveryLockPath, { force: true });
101
+ }
102
+ };
103
+ waitOrThrow = async (lockPath, startedAt, waitTimeoutMs) => {
104
+ if (Date.now() - startedAt >= waitTimeoutMs) throw new Error(`等待文件锁超时:${lockPath}`);
105
+ await setTimeout(RETRY_DELAY_MS + Math.floor(Math.random() * RETRY_DELAY_MS));
106
+ };
107
+ removeOwnedLock = async (lockPath, token) => {
108
+ try {
109
+ if (this.parseMetadata(await readFile(lockPath, "utf8"))?.token !== token) throw new Error(`文件锁 owner 已变化,拒绝删除:${lockPath}`);
110
+ await rm(lockPath);
111
+ } catch (error) {
112
+ if (!this.isMissingFileError(error)) throw error;
113
+ }
114
+ };
115
+ canRecoverLock = async (lockPath) => {
116
+ try {
117
+ const [raw, lockStats] = await Promise.all([readFile(lockPath, "utf8"), stat(lockPath)]);
118
+ const metadata = this.parseMetadata(raw);
119
+ if (metadata) return !this.isProcessAlive(metadata.pid);
120
+ return Date.now() - lockStats.mtimeMs >= MALFORMED_LOCK_STALE_AFTER_MS;
121
+ } catch (error) {
122
+ return this.isMissingFileError(error);
123
+ }
124
+ };
125
+ parseMetadata = (raw) => {
126
+ try {
127
+ const candidate = JSON.parse(raw);
128
+ if (typeof candidate.token !== "string" || !candidate.token || typeof candidate.pid !== "number" || !Number.isSafeInteger(candidate.pid) || candidate.pid <= 0 || typeof candidate.createdAt !== "string") return;
129
+ return candidate;
130
+ } catch {
131
+ return;
132
+ }
133
+ };
134
+ isProcessAlive = (pid) => {
135
+ try {
136
+ process.kill(pid, 0);
137
+ return true;
138
+ } catch (error) {
139
+ return typeof error === "object" && error !== null && "code" in error && error.code === "EPERM";
140
+ }
141
+ };
142
+ pathExists = async (targetPath) => {
143
+ try {
144
+ await access(targetPath);
145
+ return true;
146
+ } catch {
147
+ return false;
148
+ }
149
+ };
150
+ isAlreadyExistsError = (error) => typeof error === "object" && error !== null && "code" in error && error.code === "EEXIST";
151
+ isMissingFileError = (error) => typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
152
+ };
153
+ //#endregion
154
+ export { FileLockService };
155
+
156
+ //# sourceMappingURL=file-lock.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-lock.service.js","names":["delay"],"sources":["../../src/services/file-lock.service.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { access, mkdir, open, readFile, rm, stat } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { setTimeout as delay } from \"node:timers/promises\";\n\ntype FileLockMetadata = {\n token: string;\n pid: number;\n createdAt: string;\n};\n\nconst DEFAULT_WAIT_TIMEOUT_MS = 15_000;\nconst MALFORMED_LOCK_STALE_AFTER_MS = 30_000;\nconst RETRY_DELAY_MS = 25;\n\nexport class FileLockService {\n private static readonly localQueues = new Map<string, Promise<unknown>>();\n\n withLock = async <T>(\n lockPath: string,\n operation: () => Promise<T>,\n options: { waitTimeoutMs?: number } = {},\n ): Promise<T> => {\n const resolvedLockPath = path.resolve(lockPath);\n const previous = FileLockService.localQueues.get(resolvedLockPath) ?? Promise.resolve();\n const current = previous.catch(() => undefined).then(async () => {\n const release = await this.acquire(resolvedLockPath, options.waitTimeoutMs);\n try {\n return await operation();\n } finally {\n await release();\n }\n });\n FileLockService.localQueues.set(resolvedLockPath, current);\n try {\n return await current;\n } finally {\n if (FileLockService.localQueues.get(resolvedLockPath) === current) {\n FileLockService.localQueues.delete(resolvedLockPath);\n }\n }\n };\n\n private acquire = async (\n lockPath: string,\n waitTimeoutMs = DEFAULT_WAIT_TIMEOUT_MS,\n ): Promise<() => Promise<void>> => {\n await mkdir(path.dirname(lockPath), { recursive: true });\n const startedAt = Date.now();\n const recoveryLockPath = `${lockPath}.recovery`;\n while (true) {\n if (await this.pathExists(recoveryLockPath)) {\n await this.waitOrThrow(lockPath, startedAt, waitTimeoutMs);\n continue;\n }\n const metadata: FileLockMetadata = {\n token: randomUUID(),\n pid: process.pid,\n createdAt: new Date().toISOString(),\n };\n try {\n const handle = await open(lockPath, \"wx\", 0o600);\n try {\n await handle.writeFile(`${JSON.stringify(metadata)}\\n`, \"utf8\");\n await handle.sync();\n } catch (error) {\n await handle.close().catch(() => undefined);\n await rm(lockPath, { force: true }).catch(() => undefined);\n throw error;\n }\n return async () => {\n await handle.close();\n await this.removeOwnedLock(lockPath, metadata.token);\n };\n } catch (error) {\n if (!this.isAlreadyExistsError(error)) {\n throw error;\n }\n if (await this.canRecoverLock(lockPath)) {\n const recovered = await this.recoverAndAcquire(lockPath, recoveryLockPath);\n if (recovered) {\n return recovered;\n }\n }\n await this.waitOrThrow(lockPath, startedAt, waitTimeoutMs);\n }\n }\n };\n\n private recoverAndAcquire = async (\n lockPath: string,\n recoveryLockPath: string,\n ): Promise<(() => Promise<void>) | undefined> => {\n let recoveryHandle;\n try {\n recoveryHandle = await open(recoveryLockPath, \"wx\", 0o600);\n await recoveryHandle.writeFile(`${process.pid}\\n`, \"utf8\");\n await recoveryHandle.sync();\n } catch (error) {\n await recoveryHandle?.close().catch(() => undefined);\n if (this.isAlreadyExistsError(error)) {\n return undefined;\n }\n throw error;\n }\n try {\n if (!await this.canRecoverLock(lockPath)) {\n return undefined;\n }\n await rm(lockPath, { force: true });\n const metadata: FileLockMetadata = {\n token: randomUUID(),\n pid: process.pid,\n createdAt: new Date().toISOString(),\n };\n const handle = await open(lockPath, \"wx\", 0o600);\n try {\n await handle.writeFile(`${JSON.stringify(metadata)}\\n`, \"utf8\");\n await handle.sync();\n } catch (error) {\n await handle.close().catch(() => undefined);\n await rm(lockPath, { force: true }).catch(() => undefined);\n throw error;\n }\n return async () => {\n await handle.close();\n await this.removeOwnedLock(lockPath, metadata.token);\n };\n } finally {\n await recoveryHandle.close();\n await rm(recoveryLockPath, { force: true });\n }\n };\n\n private waitOrThrow = async (\n lockPath: string,\n startedAt: number,\n waitTimeoutMs: number,\n ): Promise<void> => {\n if (Date.now() - startedAt >= waitTimeoutMs) {\n throw new Error(`等待文件锁超时:${lockPath}`);\n }\n await delay(RETRY_DELAY_MS + Math.floor(Math.random() * RETRY_DELAY_MS));\n };\n\n private removeOwnedLock = async (lockPath: string, token: string): Promise<void> => {\n try {\n const metadata = this.parseMetadata(await readFile(lockPath, \"utf8\"));\n if (metadata?.token !== token) {\n throw new Error(`文件锁 owner 已变化,拒绝删除:${lockPath}`);\n }\n await rm(lockPath);\n } catch (error) {\n if (!this.isMissingFileError(error)) {\n throw error;\n }\n }\n };\n\n private canRecoverLock = async (lockPath: string): Promise<boolean> => {\n try {\n const [raw, lockStats] = await Promise.all([\n readFile(lockPath, \"utf8\"),\n stat(lockPath),\n ]);\n const metadata = this.parseMetadata(raw);\n if (metadata) {\n return !this.isProcessAlive(metadata.pid);\n }\n return Date.now() - lockStats.mtimeMs >= MALFORMED_LOCK_STALE_AFTER_MS;\n } catch (error) {\n return this.isMissingFileError(error);\n }\n };\n\n private parseMetadata = (raw: string): FileLockMetadata | undefined => {\n try {\n const candidate = JSON.parse(raw) as Partial<FileLockMetadata>;\n if (\n typeof candidate.token !== \"string\" ||\n !candidate.token ||\n typeof candidate.pid !== \"number\" ||\n !Number.isSafeInteger(candidate.pid) ||\n candidate.pid <= 0 ||\n typeof candidate.createdAt !== \"string\"\n ) {\n return undefined;\n }\n return candidate as FileLockMetadata;\n } catch {\n return undefined;\n }\n };\n\n private isProcessAlive = (pid: number): boolean => {\n try {\n process.kill(pid, 0);\n return true;\n } catch (error) {\n return typeof error === \"object\" && error !== null &&\n \"code\" in error && (error as { code?: unknown }).code === \"EPERM\";\n }\n };\n\n private pathExists = async (targetPath: string): Promise<boolean> => {\n try {\n await access(targetPath);\n return true;\n } catch {\n return false;\n }\n };\n\n private isAlreadyExistsError = (error: unknown): boolean =>\n typeof error === \"object\" && error !== null &&\n \"code\" in error && (error as { code?: unknown }).code === \"EEXIST\";\n\n private isMissingFileError = (error: unknown): boolean =>\n typeof error === \"object\" && error !== null &&\n \"code\" in error && (error as { code?: unknown }).code === \"ENOENT\";\n}\n"],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  import { AppDistributionMode } from "./app-bundle.types.js";
2
2
  import { AppPermissions, AppResolvedComponent } from "./app-manifest.types.js";
3
3
  import { AppDocumentGrantMap } from "./app-permissions.types.js";
4
+ import { AppInstanceRecord, AppStorageContext, AppStorageUsage } from "./app-storage.types.js";
4
5
  import { AppPublisher } from "./app-remote-registry.types.js";
5
6
  import { AppInstallSourceKind } from "./app-registry.types.js";
6
7
 
@@ -13,6 +14,7 @@ type AppInstallResult = {
13
14
  version: string;
14
15
  installDirectory: string;
15
16
  dataDirectory: string;
17
+ instance: AppInstanceRecord;
16
18
  sourceKind: AppInstallSourceKind;
17
19
  distributionMode?: AppDistributionMode;
18
20
  sourceRef: string;
@@ -33,6 +35,9 @@ type AppInfoResult = {
33
35
  activeVersion: string;
34
36
  enabled: boolean;
35
37
  dataDirectory: string;
38
+ instance: AppInstanceRecord;
39
+ storage: AppStorageContext;
40
+ storageUsage: AppStorageUsage;
36
41
  installedVersions: Array<{
37
42
  version: string;
38
43
  installDirectory: string;
@@ -48,6 +53,7 @@ type AppInfoResult = {
48
53
  manifestSchemaVersion: 1 | 2;
49
54
  components?: AppResolvedComponent[];
50
55
  primaryPanelId?: string;
56
+ contentSha256?: string;
51
57
  }>;
52
58
  grants: AppDocumentGrantMap;
53
59
  };
@@ -70,6 +76,7 @@ type AppLaunchResolution = {
70
76
  appDirectory: string;
71
77
  appId?: string;
72
78
  dataDirectory?: string;
79
+ storage?: AppStorageContext;
73
80
  documentGrantMap: AppDocumentGrantMap;
74
81
  };
75
82
  type AppUpdateResult = AppInstallResult & {
@@ -1 +1 @@
1
- {"version":3,"file":"app-installation.types.d.ts","names":[],"sources":["../../src/types/app-installation.types.ts"],"mappings":";;;;;;;KAMY,uBAAA;AAAA,KAOA,yBAAA,IACV,KAAA,EAAO,uBAAA,YACG,OAAA;AAAA,KAEA,gBAAA;EACV,KAAA;EACA,IAAA;EACA,OAAA;EACA,gBAAA;EACA,aAAA;EACA,UAAA,EAAY,oBAAA;EACZ,gBAAA,GAAmB,mBAAA;EACnB,SAAA;EACA,WAAA,EAAa,cAAA;EACb,WAAA;EACA,SAAA;EACA,MAAA;EACA,SAAA,GAAY,YAAA;EACZ,OAAA;EACA,qBAAA;EACA,UAAA,GAAa,oBAAA;EACb,cAAA;AAAA;AAAA,KAGU,aAAA;EACV,KAAA;EACA,IAAA;EACA,WAAA;EACA,aAAA;EACA,OAAA;EACA,aAAA;EACA,iBAAA,EAAmB,KAAA;IACjB,OAAA;IACA,gBAAA;IACA,UAAA,EAAY,oBAAA;IACZ,gBAAA,GAAmB,mBAAA;IACnB,SAAA;IACA,WAAA;IACA,WAAA,EAAa,cAAA;IACb,WAAA;IACA,SAAA;IACA,MAAA;IACA,SAAA,GAAY,YAAA;IACZ,qBAAA;IACA,UAAA,GAAa,oBAAA;IACb,cAAA;EAAA;EAEF,MAAA,EAAQ,mBAAA;AAAA;AAAA,KAGE,oBAAA;EACV,KAAA;EACA,IAAA;EACA,aAAA;EACA,UAAA,EAAY,oBAAA;EACZ,gBAAA,GAAmB,mBAAA;EACnB,OAAA;EACA,qBAAA;EACA,cAAA;AAAA;AAAA,KAGU,kBAAA;EACV,KAAA;EACA,eAAA;EACA,WAAA;AAAA;AAAA,KAGU,mBAAA;EACV,YAAA;EACA,KAAA;EACA,aAAA;EACA,gBAAA,EAAkB,mBAAA;AAAA;AAAA,KAGR,eAAA,GAAkB,gBAAA;EAC5B,eAAA;EACA,OAAA;AAAA;AAAA,KAGU,mBAAA;EACV,KAAA;EACA,aAAA;EACA,OAAA;AAAA;AAAA,KAGU,iBAAA,GAAoB,mBAAA;EAC9B,eAAA;EACA,UAAA;AAAA"}
1
+ {"version":3,"file":"app-installation.types.d.ts","names":[],"sources":["../../src/types/app-installation.types.ts"],"mappings":";;;;;;;;KAWY,uBAAA;AAAA,KAOA,yBAAA,IACV,KAAA,EAAO,uBAAA,YACG,OAAA;AAAA,KAEA,gBAAA;EACV,KAAA;EACA,IAAA;EACA,OAAA;EACA,gBAAA;EACA,aAAA;EACA,QAAA,EAAU,iBAAA;EACV,UAAA,EAAY,oBAAA;EACZ,gBAAA,GAAmB,mBAAA;EACnB,SAAA;EACA,WAAA,EAAa,cAAA;EACb,WAAA;EACA,SAAA;EACA,MAAA;EACA,SAAA,GAAY,YAAA;EACZ,OAAA;EACA,qBAAA;EACA,UAAA,GAAa,oBAAA;EACb,cAAA;AAAA;AAAA,KAGU,aAAA;EACV,KAAA;EACA,IAAA;EACA,WAAA;EACA,aAAA;EACA,OAAA;EACA,aAAA;EACA,QAAA,EAAU,iBAAA;EACV,OAAA,EAAS,iBAAA;EACT,YAAA,EAAc,eAAA;EACd,iBAAA,EAAmB,KAAA;IACjB,OAAA;IACA,gBAAA;IACA,UAAA,EAAY,oBAAA;IACZ,gBAAA,GAAmB,mBAAA;IACnB,SAAA;IACA,WAAA;IACA,WAAA,EAAa,cAAA;IACb,WAAA;IACA,SAAA;IACA,MAAA;IACA,SAAA,GAAY,YAAA;IACZ,qBAAA;IACA,UAAA,GAAa,oBAAA;IACb,cAAA;IACA,aAAA;EAAA;EAEF,MAAA,EAAQ,mBAAA;AAAA;AAAA,KAGE,oBAAA;EACV,KAAA;EACA,IAAA;EACA,aAAA;EACA,UAAA,EAAY,oBAAA;EACZ,gBAAA,GAAmB,mBAAA;EACnB,OAAA;EACA,qBAAA;EACA,cAAA;AAAA;AAAA,KAGU,kBAAA;EACV,KAAA;EACA,eAAA;EACA,WAAA;AAAA;AAAA,KAGU,mBAAA;EACV,YAAA;EACA,KAAA;EACA,aAAA;EACA,OAAA,GAAU,iBAAA;EACV,gBAAA,EAAkB,mBAAA;AAAA;AAAA,KAGR,eAAA,GAAkB,gBAAA;EAC5B,eAAA;EACA,OAAA;AAAA;AAAA,KAGU,mBAAA;EACV,KAAA;EACA,aAAA;EACA,OAAA;AAAA;AAAA,KAGU,iBAAA,GAAoB,mBAAA;EAC9B,eAAA;EACA,UAAA;AAAA"}
@@ -13,8 +13,25 @@ type AppPermissions = {
13
13
  };
14
14
  capabilities?: {
15
15
  hostBridge?: boolean;
16
+ nativeProcess?: boolean;
16
17
  };
17
18
  };
19
+ type AppRuntimeProfile = "panel-only" | "wasi" | "native-process";
20
+ type AppRuntimeIsolation = "sandboxed" | "host-mediated" | "full-user";
21
+ type AppRuntimeDeclaration = {
22
+ profile: AppRuntimeProfile;
23
+ };
24
+ type AppStorageDeclaration = {
25
+ scope: "global";
26
+ schemaVersion: number;
27
+ };
28
+ type AppPlatformSecuritySummary = {
29
+ runtimeProfile: AppRuntimeProfile;
30
+ isolation: AppRuntimeIsolation;
31
+ hasServiceComponents: boolean;
32
+ inferred: boolean;
33
+ permissions: AppPermissions;
34
+ };
18
35
  type AppCoreWasmMainManifest = {
19
36
  kind: "wasm";
20
37
  entry: string;
@@ -58,6 +75,9 @@ type AppComponentManifest = {
58
75
  presentation?: {
59
76
  primaryPanel?: string;
60
77
  };
78
+ runtime?: AppRuntimeDeclaration;
79
+ storage?: AppStorageDeclaration;
80
+ permissions?: AppPermissions;
61
81
  components: AppComponentReference[];
62
82
  };
63
83
  type AppManifest = AppStandaloneManifest | AppComponentManifest;
@@ -110,10 +130,11 @@ type AppComponentManifestSummary = {
110
130
  iconPath?: string;
111
131
  primaryPanelId?: string;
112
132
  components: AppResolvedComponent[];
133
+ security: AppPlatformSecuritySummary;
113
134
  };
114
135
  type AppManifestSummary = AppStandaloneManifestSummary | AppComponentManifestSummary;
115
136
  declare function isAppStandaloneManifestBundle(bundle: AppManifestBundle): bundle is AppStandaloneManifestBundle;
116
137
  declare function isAppComponentManifestBundle(bundle: AppManifestBundle): bundle is AppComponentManifestBundle;
117
138
  //#endregion
118
- export { AppComponentKind, AppComponentManifest, AppComponentManifestBundle, AppComponentManifestSummary, AppComponentReference, AppCoreWasmMainManifest, AppDocumentAccessMode, AppDocumentAccessScope, AppMainManifest, AppManifest, AppManifestBundle, AppManifestSummary, AppPermissions, AppResolvedComponent, AppStandaloneManifest, AppStandaloneManifestBundle, AppStandaloneManifestSummary, AppUiManifest, AppWasiHttpComponentMainManifest, isAppComponentManifestBundle, isAppStandaloneManifestBundle };
139
+ export { AppComponentKind, AppComponentManifest, AppComponentManifestBundle, AppComponentManifestSummary, AppComponentReference, AppCoreWasmMainManifest, AppDocumentAccessMode, AppDocumentAccessScope, AppMainManifest, AppManifest, AppManifestBundle, AppManifestSummary, AppPermissions, AppPlatformSecuritySummary, AppResolvedComponent, AppRuntimeDeclaration, AppRuntimeIsolation, AppRuntimeProfile, AppStandaloneManifest, AppStandaloneManifestBundle, AppStandaloneManifestSummary, AppStorageDeclaration, AppUiManifest, AppWasiHttpComponentMainManifest, isAppComponentManifestBundle, isAppStandaloneManifestBundle };
119
140
  //# sourceMappingURL=app-manifest.types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"app-manifest.types.d.ts","names":[],"sources":["../../src/types/app-manifest.types.ts"],"mappings":";KAAY,qBAAA;AAAA,KAEA,sBAAA;EACV,EAAA;EACA,IAAA,EAAM,qBAAA;EACN,WAAA;AAAA;AAAA,KAGU,cAAA;EACV,cAAA,GAAiB,sBAAA;EACjB,cAAA;EACA,OAAA;IAAsB,SAAA;EAAA;EACtB,YAAA;IACE,UAAA;EAAA;AAAA;AAAA,KAIQ,uBAAA;EACV,IAAA;EACA,KAAA;EACA,MAAA;EACA,MAAA;AAAA;AAAA,KAGU,gCAAA;EACV,IAAA;EACA,KAAA;AAAA;AAAA,KAGU,eAAA,GAAkB,uBAAA,GAA0B,gCAAA;AAAA,KAE5C,aAAA;EACV,KAAA;AAAA;AAAA,KAGU,qBAAA;EACV,aAAA;EACA,EAAA;EACA,IAAA;EACA,OAAA;EACA,WAAA;EACA,IAAA;EACA,IAAA,EAAM,eAAA;EACN,EAAA,EAAI,aAAA;EACJ,WAAA,GAAc,cAAA;AAAA;AAAA,KAGJ,gBAAA;AAAA,KAEA,qBAAA;EACV,IAAA,EAAM,gBAAA;EACN,IAAA;AAAA;AAAA,KAGU,oBAAA;EACV,aAAA;EACA,EAAA;EACA,IAAA;EACA,OAAA;EACA,WAAA;EACA,IAAA;EACA,OAAA;IACE,QAAA;EAAA;EAEF,YAAA;IACE,YAAA;EAAA;EAEF,UAAA,EAAY,qBAAA;AAAA;AAAA,KAGF,WAAA,GAAc,qBAAA,GAAwB,oBAAA;AAAA,KAEtC,oBAAA,GAAuB,qBAAA;EACjC,EAAA;EACA,kBAAA;EACA,YAAA;AAAA;AAAA,KAGU,2BAAA;EACV,YAAA;EACA,YAAA;EACA,QAAA,EAAU,qBAAA;EACV,aAAA;EACA,WAAA;EACA,eAAA;EACA,mBAAA;EACA,QAAA;AAAA;AAAA,KAGU,0BAAA;EACV,YAAA;EACA,YAAA;EACA,QAAA,EAAU,oBAAA;EACV,UAAA,EAAY,oBAAA;EACZ,mBAAA;EACA,QAAA;EACA,cAAA;AAAA;AAAA,KAGU,iBAAA,GAAoB,2BAAA,GAA8B,0BAAA;AAAA,KAElD,4BAAA;EACV,aAAA;EACA,EAAA;EACA,IAAA;EACA,OAAA;EACA,WAAA;EACA,QAAA,EAAU,eAAA;EACV,MAAA;EACA,YAAA;EACA,aAAA;EACA,WAAA;EACA,QAAA;EACA,WAAA,EAAa,cAAA;AAAA;AAAA,KAGH,2BAAA;EACV,aAAA;EACA,EAAA;EACA,IAAA;EACA,OAAA;EACA,WAAA;EACA,YAAA;EACA,QAAA;EACA,cAAA;EACA,UAAA,EAAY,oBAAA;AAAA;AAAA,KAGF,kBAAA,GAAqB,4BAAA,GAA+B,2BAAA;AAAA,iBAEhD,6BAAA,CACd,MAAA,EAAQ,iBAAA,GACP,MAAA,IAAU,2BAAA;AAAA,iBAIG,4BAAA,CACd,MAAA,EAAQ,iBAAA,GACP,MAAA,IAAU,0BAAA"}
1
+ {"version":3,"file":"app-manifest.types.d.ts","names":[],"sources":["../../src/types/app-manifest.types.ts"],"mappings":";KAAY,qBAAA;AAAA,KAEA,sBAAA;EACV,EAAA;EACA,IAAA,EAAM,qBAAA;EACN,WAAA;AAAA;AAAA,KAGU,cAAA;EACV,cAAA,GAAiB,sBAAA;EACjB,cAAA;EACA,OAAA;IAAsB,SAAA;EAAA;EACtB,YAAA;IACE,UAAA;IACA,aAAA;EAAA;AAAA;AAAA,KAIQ,iBAAA;AAAA,KACA,mBAAA;AAAA,KAEA,qBAAA;EACV,OAAA,EAAS,iBAAA;AAAA;AAAA,KAGC,qBAAA;EACV,KAAA;EACA,aAAA;AAAA;AAAA,KAGU,0BAAA;EACV,cAAA,EAAgB,iBAAA;EAChB,SAAA,EAAW,mBAAA;EACX,oBAAA;EACA,QAAA;EACA,WAAA,EAAa,cAAA;AAAA;AAAA,KAGH,uBAAA;EACV,IAAA;EACA,KAAA;EACA,MAAA;EACA,MAAA;AAAA;AAAA,KAGU,gCAAA;EACV,IAAA;EACA,KAAA;AAAA;AAAA,KAGU,eAAA,GAAkB,uBAAA,GAA0B,gCAAA;AAAA,KAE5C,aAAA;EACV,KAAA;AAAA;AAAA,KAGU,qBAAA;EACV,aAAA;EACA,EAAA;EACA,IAAA;EACA,OAAA;EACA,WAAA;EACA,IAAA;EACA,IAAA,EAAM,eAAA;EACN,EAAA,EAAI,aAAA;EACJ,WAAA,GAAc,cAAA;AAAA;AAAA,KAGJ,gBAAA;AAAA,KAEA,qBAAA;EACV,IAAA,EAAM,gBAAA;EACN,IAAA;AAAA;AAAA,KAGU,oBAAA;EACV,aAAA;EACA,EAAA;EACA,IAAA;EACA,OAAA;EACA,WAAA;EACA,IAAA;EACA,OAAA;IACE,QAAA;EAAA;EAEF,YAAA;IACE,YAAA;EAAA;EAEF,OAAA,GAAU,qBAAA;EACV,OAAA,GAAU,qBAAA;EACV,WAAA,GAAc,cAAA;EACd,UAAA,EAAY,qBAAA;AAAA;AAAA,KAGF,WAAA,GAAc,qBAAA,GAAwB,oBAAA;AAAA,KAEtC,oBAAA,GAAuB,qBAAA;EACjC,EAAA;EACA,kBAAA;EACA,YAAA;AAAA;AAAA,KAGU,2BAAA;EACV,YAAA;EACA,YAAA;EACA,QAAA,EAAU,qBAAA;EACV,aAAA;EACA,WAAA;EACA,eAAA;EACA,mBAAA;EACA,QAAA;AAAA;AAAA,KAGU,0BAAA;EACV,YAAA;EACA,YAAA;EACA,QAAA,EAAU,oBAAA;EACV,UAAA,EAAY,oBAAA;EACZ,mBAAA;EACA,QAAA;EACA,cAAA;AAAA;AAAA,KAGU,iBAAA,GAAoB,2BAAA,GAA8B,0BAAA;AAAA,KAElD,4BAAA;EACV,aAAA;EACA,EAAA;EACA,IAAA;EACA,OAAA;EACA,WAAA;EACA,QAAA,EAAU,eAAA;EACV,MAAA;EACA,YAAA;EACA,aAAA;EACA,WAAA;EACA,QAAA;EACA,WAAA,EAAa,cAAA;AAAA;AAAA,KAGH,2BAAA;EACV,aAAA;EACA,EAAA;EACA,IAAA;EACA,OAAA;EACA,WAAA;EACA,YAAA;EACA,QAAA;EACA,cAAA;EACA,UAAA,EAAY,oBAAA;EACZ,QAAA,EAAU,0BAAA;AAAA;AAAA,KAGA,kBAAA,GAAqB,4BAAA,GAA+B,2BAAA;AAAA,iBAEhD,6BAAA,CACd,MAAA,EAAQ,iBAAA,GACP,MAAA,IAAU,2BAAA;AAAA,iBAIG,4BAAA,CACd,MAAA,EAAQ,iBAAA,GACP,MAAA,IAAU,0BAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"app-manifest.types.js","names":[],"sources":["../../src/types/app-manifest.types.ts"],"sourcesContent":["export type AppDocumentAccessMode = \"read\" | \"read-write\";\n\nexport type AppDocumentAccessScope = {\n id: string;\n mode: AppDocumentAccessMode;\n description?: string;\n};\n\nexport type AppPermissions = {\n documentAccess?: AppDocumentAccessScope[];\n allowedDomains?: string[];\n storage?: boolean | { namespace?: string };\n capabilities?: {\n hostBridge?: boolean;\n };\n};\n\nexport type AppCoreWasmMainManifest = {\n kind: \"wasm\";\n entry: string;\n export: string;\n action: string;\n};\n\nexport type AppWasiHttpComponentMainManifest = {\n kind: \"wasi-http-component\";\n entry: string;\n};\n\nexport type AppMainManifest = AppCoreWasmMainManifest | AppWasiHttpComponentMainManifest;\n\nexport type AppUiManifest = {\n entry: string;\n};\n\nexport type AppStandaloneManifest = {\n schemaVersion: 1;\n id: string;\n name: string;\n version: string;\n description?: string;\n icon?: string;\n main: AppMainManifest;\n ui: AppUiManifest;\n permissions?: AppPermissions;\n};\n\nexport type AppComponentKind = \"panel\" | \"service\";\n\nexport type AppComponentReference = {\n kind: AppComponentKind;\n path: string;\n};\n\nexport type AppComponentManifest = {\n schemaVersion: 2;\n id: string;\n name: string;\n version: string;\n description?: string;\n icon?: string;\n engines?: {\n nextclaw?: string;\n };\n presentation?: {\n primaryPanel?: string;\n };\n components: AppComponentReference[];\n};\n\nexport type AppManifest = AppStandaloneManifest | AppComponentManifest;\n\nexport type AppResolvedComponent = AppComponentReference & {\n id: string;\n componentDirectory: string;\n manifestPath: string;\n};\n\nexport type AppStandaloneManifestBundle = {\n appDirectory: string;\n manifestPath: string;\n manifest: AppStandaloneManifest;\n mainEntryPath: string;\n uiEntryPath: string;\n uiDirectoryPath: string;\n assetsDirectoryPath: string;\n iconPath?: string;\n};\n\nexport type AppComponentManifestBundle = {\n appDirectory: string;\n manifestPath: string;\n manifest: AppComponentManifest;\n components: AppResolvedComponent[];\n assetsDirectoryPath: string;\n iconPath?: string;\n primaryPanelId?: string;\n};\n\nexport type AppManifestBundle = AppStandaloneManifestBundle | AppComponentManifestBundle;\n\nexport type AppStandaloneManifestSummary = {\n schemaVersion: 1;\n id: string;\n name: string;\n version: string;\n description?: string;\n mainKind: AppMainManifest[\"kind\"];\n action?: string;\n manifestPath: string;\n mainEntryPath: string;\n uiEntryPath: string;\n iconPath?: string;\n permissions: AppPermissions;\n};\n\nexport type AppComponentManifestSummary = {\n schemaVersion: 2;\n id: string;\n name: string;\n version: string;\n description?: string;\n manifestPath: string;\n iconPath?: string;\n primaryPanelId?: string;\n components: AppResolvedComponent[];\n};\n\nexport type AppManifestSummary = AppStandaloneManifestSummary | AppComponentManifestSummary;\n\nexport function isAppStandaloneManifestBundle(\n bundle: AppManifestBundle,\n): bundle is AppStandaloneManifestBundle {\n return bundle.manifest.schemaVersion === 1;\n}\n\nexport function isAppComponentManifestBundle(\n bundle: AppManifestBundle,\n): bundle is AppComponentManifestBundle {\n return bundle.manifest.schemaVersion === 2;\n}\n"],"mappings":";AAkIA,SAAgB,8BACd,QACuC;AACvC,QAAO,OAAO,SAAS,kBAAkB;;AAG3C,SAAgB,6BACd,QACsC;AACtC,QAAO,OAAO,SAAS,kBAAkB"}
1
+ {"version":3,"file":"app-manifest.types.js","names":[],"sources":["../../src/types/app-manifest.types.ts"],"sourcesContent":["export type AppDocumentAccessMode = \"read\" | \"read-write\";\n\nexport type AppDocumentAccessScope = {\n id: string;\n mode: AppDocumentAccessMode;\n description?: string;\n};\n\nexport type AppPermissions = {\n documentAccess?: AppDocumentAccessScope[];\n allowedDomains?: string[];\n storage?: boolean | { namespace?: string };\n capabilities?: {\n hostBridge?: boolean;\n nativeProcess?: boolean;\n };\n};\n\nexport type AppRuntimeProfile = \"panel-only\" | \"wasi\" | \"native-process\";\nexport type AppRuntimeIsolation = \"sandboxed\" | \"host-mediated\" | \"full-user\";\n\nexport type AppRuntimeDeclaration = {\n profile: AppRuntimeProfile;\n};\n\nexport type AppStorageDeclaration = {\n scope: \"global\";\n schemaVersion: number;\n};\n\nexport type AppPlatformSecuritySummary = {\n runtimeProfile: AppRuntimeProfile;\n isolation: AppRuntimeIsolation;\n hasServiceComponents: boolean;\n inferred: boolean;\n permissions: AppPermissions;\n};\n\nexport type AppCoreWasmMainManifest = {\n kind: \"wasm\";\n entry: string;\n export: string;\n action: string;\n};\n\nexport type AppWasiHttpComponentMainManifest = {\n kind: \"wasi-http-component\";\n entry: string;\n};\n\nexport type AppMainManifest = AppCoreWasmMainManifest | AppWasiHttpComponentMainManifest;\n\nexport type AppUiManifest = {\n entry: string;\n};\n\nexport type AppStandaloneManifest = {\n schemaVersion: 1;\n id: string;\n name: string;\n version: string;\n description?: string;\n icon?: string;\n main: AppMainManifest;\n ui: AppUiManifest;\n permissions?: AppPermissions;\n};\n\nexport type AppComponentKind = \"panel\" | \"service\";\n\nexport type AppComponentReference = {\n kind: AppComponentKind;\n path: string;\n};\n\nexport type AppComponentManifest = {\n schemaVersion: 2;\n id: string;\n name: string;\n version: string;\n description?: string;\n icon?: string;\n engines?: {\n nextclaw?: string;\n };\n presentation?: {\n primaryPanel?: string;\n };\n runtime?: AppRuntimeDeclaration;\n storage?: AppStorageDeclaration;\n permissions?: AppPermissions;\n components: AppComponentReference[];\n};\n\nexport type AppManifest = AppStandaloneManifest | AppComponentManifest;\n\nexport type AppResolvedComponent = AppComponentReference & {\n id: string;\n componentDirectory: string;\n manifestPath: string;\n};\n\nexport type AppStandaloneManifestBundle = {\n appDirectory: string;\n manifestPath: string;\n manifest: AppStandaloneManifest;\n mainEntryPath: string;\n uiEntryPath: string;\n uiDirectoryPath: string;\n assetsDirectoryPath: string;\n iconPath?: string;\n};\n\nexport type AppComponentManifestBundle = {\n appDirectory: string;\n manifestPath: string;\n manifest: AppComponentManifest;\n components: AppResolvedComponent[];\n assetsDirectoryPath: string;\n iconPath?: string;\n primaryPanelId?: string;\n};\n\nexport type AppManifestBundle = AppStandaloneManifestBundle | AppComponentManifestBundle;\n\nexport type AppStandaloneManifestSummary = {\n schemaVersion: 1;\n id: string;\n name: string;\n version: string;\n description?: string;\n mainKind: AppMainManifest[\"kind\"];\n action?: string;\n manifestPath: string;\n mainEntryPath: string;\n uiEntryPath: string;\n iconPath?: string;\n permissions: AppPermissions;\n};\n\nexport type AppComponentManifestSummary = {\n schemaVersion: 2;\n id: string;\n name: string;\n version: string;\n description?: string;\n manifestPath: string;\n iconPath?: string;\n primaryPanelId?: string;\n components: AppResolvedComponent[];\n security: AppPlatformSecuritySummary;\n};\n\nexport type AppManifestSummary = AppStandaloneManifestSummary | AppComponentManifestSummary;\n\nexport function isAppStandaloneManifestBundle(\n bundle: AppManifestBundle,\n): bundle is AppStandaloneManifestBundle {\n return bundle.manifest.schemaVersion === 1;\n}\n\nexport function isAppComponentManifestBundle(\n bundle: AppManifestBundle,\n): bundle is AppComponentManifestBundle {\n return bundle.manifest.schemaVersion === 2;\n}\n"],"mappings":";AA2JA,SAAgB,8BACd,QACuC;AACvC,QAAO,OAAO,SAAS,kBAAkB;;AAG3C,SAAgB,6BACd,QACsC;AACtC,QAAO,OAAO,SAAS,kBAAkB"}
@@ -1,6 +1,7 @@
1
1
  import { AppDistributionMode } from "./app-bundle.types.js";
2
- import { AppPermissions, AppResolvedComponent } from "./app-manifest.types.js";
2
+ import { AppPermissions, AppPlatformSecuritySummary, AppResolvedComponent } from "./app-manifest.types.js";
3
3
  import { AppDocumentGrantMap } from "./app-permissions.types.js";
4
+ import { AppInstanceRecord } from "./app-storage.types.js";
4
5
  import { AppPublisher } from "./app-remote-registry.types.js";
5
6
 
6
7
  //#region src/types/app-registry.types.d.ts
@@ -20,14 +21,19 @@ type AppRegistryInstalledVersion = {
20
21
  manifestSchemaVersion: 1 | 2;
21
22
  components?: AppResolvedComponent[];
22
23
  primaryPanelId?: string;
24
+ security?: AppPlatformSecuritySummary;
25
+ dataSchemaVersion: number;
26
+ contentSha256?: string;
23
27
  };
24
28
  type AppRegistryAppRecord = {
25
29
  appId: string;
26
30
  name: string;
27
31
  description?: string;
32
+ publisher?: AppPublisher;
28
33
  activeVersion: string;
29
34
  enabled: boolean;
30
35
  dataDirectory: string;
36
+ defaultInstance: AppInstanceRecord;
31
37
  installedVersions: Record<string, AppRegistryInstalledVersion>;
32
38
  grants: AppDocumentGrantMap;
33
39
  };
@@ -1 +1 @@
1
- {"version":3,"file":"app-registry.types.d.ts","names":[],"sources":["../../src/types/app-registry.types.ts"],"mappings":";;;;;;KAKY,oBAAA;AAAA,KAEA,2BAAA;EACV,OAAA;EACA,gBAAA;EACA,UAAA,EAAY,oBAAA;EACZ,SAAA;EACA,WAAA;EACA,gBAAA,GAAmB,mBAAA;EACnB,WAAA,EAAa,cAAA;EACb,WAAA;EACA,SAAA;EACA,MAAA;EACA,SAAA,GAAY,YAAA;EACZ,qBAAA;EACA,UAAA,GAAa,oBAAA;EACb,cAAA;AAAA;AAAA,KAGU,oBAAA;EACV,KAAA;EACA,IAAA;EACA,WAAA;EACA,aAAA;EACA,OAAA;EACA,aAAA;EACA,iBAAA,EAAmB,MAAA,SAAe,2BAAA;EAClC,MAAA,EAAQ,mBAAA;AAAA;AAAA,KAGE,WAAA;EACV,aAAA;EACA,IAAA,EAAM,MAAA,SAAe,oBAAA;EACrB,kBAAA,EAAoB,MAAA;IAClB,YAAA;EAAA;AAAA"}
1
+ {"version":3,"file":"app-registry.types.d.ts","names":[],"sources":["../../src/types/app-registry.types.ts"],"mappings":";;;;;;;KAUY,oBAAA;AAAA,KAEA,2BAAA;EACV,OAAA;EACA,gBAAA;EACA,UAAA,EAAY,oBAAA;EACZ,SAAA;EACA,WAAA;EACA,gBAAA,GAAmB,mBAAA;EACnB,WAAA,EAAa,cAAA;EACb,WAAA;EACA,SAAA;EACA,MAAA;EACA,SAAA,GAAY,YAAA;EACZ,qBAAA;EACA,UAAA,GAAa,oBAAA;EACb,cAAA;EACA,QAAA,GAAW,0BAAA;EACX,iBAAA;EACA,aAAA;AAAA;AAAA,KAGU,oBAAA;EACV,KAAA;EACA,IAAA;EACA,WAAA;EACA,SAAA,GAAY,YAAA;EACZ,aAAA;EACA,OAAA;EACA,aAAA;EACA,eAAA,EAAiB,iBAAA;EACjB,iBAAA,EAAmB,MAAA,SAAe,2BAAA;EAClC,MAAA,EAAQ,mBAAA;AAAA;AAAA,KAGE,WAAA;EACV,aAAA;EACA,IAAA,EAAM,MAAA,SAAe,oBAAA;EACrB,kBAAA,EAAoB,MAAA;IAClB,YAAA;EAAA;AAAA"}
@@ -0,0 +1,64 @@
1
+ //#region src/types/app-storage.types.d.ts
2
+ declare const DEFAULT_APP_INSTANCE_ID = "default";
3
+ declare const APP_STORAGE_LAYOUT_VERSION = 1;
4
+ type AppStorageLayout = "legacy" | "instance-v1";
5
+ type AppStorageContext = {
6
+ layout: AppStorageLayout;
7
+ layoutVersion: typeof APP_STORAGE_LAYOUT_VERSION;
8
+ instanceId: string;
9
+ instanceDirectory: string;
10
+ dataDirectory: string;
11
+ configDirectory: string;
12
+ stateDirectory: string;
13
+ cacheDirectory: string;
14
+ temporaryDirectory: string;
15
+ logsDirectory: string;
16
+ };
17
+ type AppStorageUsage = {
18
+ dataBytes: number;
19
+ configBytes: number;
20
+ stateBytes: number;
21
+ cacheBytes: number;
22
+ temporaryBytes: number;
23
+ logsBytes: number;
24
+ totalBytes: number;
25
+ };
26
+ type AppInstanceRecord = {
27
+ id: string;
28
+ publisherId?: string;
29
+ storage: AppStorageContext;
30
+ dataSchemaVersion: number;
31
+ createdAt: string;
32
+ migratedAt?: string;
33
+ legacyDataDirectory?: string;
34
+ };
35
+ type AppInstanceMetadata = {
36
+ schemaVersion: 1;
37
+ appId: string;
38
+ instanceId: string;
39
+ publisherId?: string;
40
+ layoutVersion: typeof APP_STORAGE_LAYOUT_VERSION;
41
+ createdAt: string;
42
+ migratedAt?: string;
43
+ legacyDataDirectory?: string;
44
+ };
45
+ type AppInstanceInventoryEntry = {
46
+ appId: string;
47
+ instanceId: string;
48
+ publisherId?: string;
49
+ storage: AppStorageContext;
50
+ usage: AppStorageUsage;
51
+ createdAt: string;
52
+ migratedAt?: string;
53
+ };
54
+ type AppInstanceInventoryDiagnostic = {
55
+ instanceDirectory: string;
56
+ message: string;
57
+ };
58
+ type AppInstanceInventory = {
59
+ entries: AppInstanceInventoryEntry[];
60
+ diagnostics: AppInstanceInventoryDiagnostic[];
61
+ };
62
+ //#endregion
63
+ export { APP_STORAGE_LAYOUT_VERSION, AppInstanceInventory, AppInstanceInventoryDiagnostic, AppInstanceInventoryEntry, AppInstanceMetadata, AppInstanceRecord, AppStorageContext, AppStorageLayout, AppStorageUsage, DEFAULT_APP_INSTANCE_ID };
64
+ //# sourceMappingURL=app-storage.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-storage.types.d.ts","names":[],"sources":["../../src/types/app-storage.types.ts"],"mappings":";cAAa,uBAAA;AAAA,cACA,0BAAA;AAAA,KAED,gBAAA;AAAA,KAEA,iBAAA;EACV,MAAA,EAAQ,gBAAA;EACR,aAAA,SAAsB,0BAAA;EACtB,UAAA;EACA,iBAAA;EACA,aAAA;EACA,eAAA;EACA,cAAA;EACA,cAAA;EACA,kBAAA;EACA,aAAA;AAAA;AAAA,KAGU,eAAA;EACV,SAAA;EACA,WAAA;EACA,UAAA;EACA,UAAA;EACA,cAAA;EACA,SAAA;EACA,UAAA;AAAA;AAAA,KAGU,iBAAA;EACV,EAAA;EACA,WAAA;EACA,OAAA,EAAS,iBAAA;EACT,iBAAA;EACA,SAAA;EACA,UAAA;EACA,mBAAA;AAAA;AAAA,KAGU,mBAAA;EACV,aAAA;EACA,KAAA;EACA,UAAA;EACA,WAAA;EACA,aAAA,SAAsB,0BAAA;EACtB,SAAA;EACA,UAAA;EACA,mBAAA;AAAA;AAAA,KAGU,yBAAA;EACV,KAAA;EACA,UAAA;EACA,WAAA;EACA,OAAA,EAAS,iBAAA;EACT,KAAA,EAAO,eAAA;EACP,SAAA;EACA,UAAA;AAAA;AAAA,KAGU,8BAAA;EACV,iBAAA;EACA,OAAA;AAAA;AAAA,KAGU,oBAAA;EACV,OAAA,EAAS,yBAAA;EACT,WAAA,EAAa,8BAAA;AAAA"}
@@ -0,0 +1,7 @@
1
+ //#region src/types/app-storage.types.ts
2
+ const DEFAULT_APP_INSTANCE_ID = "default";
3
+ const APP_STORAGE_LAYOUT_VERSION = 1;
4
+ //#endregion
5
+ export { APP_STORAGE_LAYOUT_VERSION, DEFAULT_APP_INSTANCE_ID };
6
+
7
+ //# sourceMappingURL=app-storage.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-storage.types.js","names":[],"sources":["../../src/types/app-storage.types.ts"],"sourcesContent":["export const DEFAULT_APP_INSTANCE_ID = \"default\";\nexport const APP_STORAGE_LAYOUT_VERSION = 1;\n\nexport type AppStorageLayout = \"legacy\" | \"instance-v1\";\n\nexport type AppStorageContext = {\n layout: AppStorageLayout;\n layoutVersion: typeof APP_STORAGE_LAYOUT_VERSION;\n instanceId: string;\n instanceDirectory: string;\n dataDirectory: string;\n configDirectory: string;\n stateDirectory: string;\n cacheDirectory: string;\n temporaryDirectory: string;\n logsDirectory: string;\n};\n\nexport type AppStorageUsage = {\n dataBytes: number;\n configBytes: number;\n stateBytes: number;\n cacheBytes: number;\n temporaryBytes: number;\n logsBytes: number;\n totalBytes: number;\n};\n\nexport type AppInstanceRecord = {\n id: string;\n publisherId?: string;\n storage: AppStorageContext;\n dataSchemaVersion: number;\n createdAt: string;\n migratedAt?: string;\n legacyDataDirectory?: string;\n};\n\nexport type AppInstanceMetadata = {\n schemaVersion: 1;\n appId: string;\n instanceId: string;\n publisherId?: string;\n layoutVersion: typeof APP_STORAGE_LAYOUT_VERSION;\n createdAt: string;\n migratedAt?: string;\n legacyDataDirectory?: string;\n};\n\nexport type AppInstanceInventoryEntry = {\n appId: string;\n instanceId: string;\n publisherId?: string;\n storage: AppStorageContext;\n usage: AppStorageUsage;\n createdAt: string;\n migratedAt?: string;\n};\n\nexport type AppInstanceInventoryDiagnostic = {\n instanceDirectory: string;\n message: string;\n};\n\nexport type AppInstanceInventory = {\n entries: AppInstanceInventoryEntry[];\n diagnostics: AppInstanceInventoryDiagnostic[];\n};\n"],"mappings":";AAAA,MAAa,0BAA0B;AACvC,MAAa,6BAA6B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextclaw/app-runtime",
3
- "version": "0.10.0",
3
+ "version": "0.12.0",
4
4
  "private": false,
5
5
  "description": "Standalone micro app runtime and CLI for NextClaw apps.",
6
6
  "type": "module",