@khal-os/types 1.0.12 → 1.0.13
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.cjs +2 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -90,6 +90,8 @@ var KhalAppManifestSchema = import_zod.z.object({
|
|
|
90
90
|
env: import_zod.z.record(import_zod.z.string(), import_zod.z.string()),
|
|
91
91
|
ports: import_zod.z.array(import_zod.z.number())
|
|
92
92
|
}).optional(),
|
|
93
|
+
/** Relative path to the pre-built ESM bundle within the package (e.g., "dist/bundle.mjs"). */
|
|
94
|
+
bundlePath: import_zod.z.string().optional(),
|
|
93
95
|
/**
|
|
94
96
|
* When apps is present, the root frontend field is ignored —
|
|
95
97
|
* each entry has its own frontend.
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/manifest.ts","../src/roles.ts"],"sourcesContent":["export type { KhalAuth } from './auth';\nexport type {\n\tAppDeployConfig,\n\tAppDesktopConfig,\n\tAppEnvVar,\n\tAppManifest,\n\tAppManifestView,\n\tAppServiceConfig,\n\tAppTauriConfig,\n\tKhalAppEntry,\n\tKhalAppManifest,\n\tKhalPermission,\n\tKhalServiceSpec,\n\tKhalWindowSpec,\n\tServiceHealthConfig,\n} from './manifest';\nexport {\n\tKhalAppEntrySchema,\n\tKhalAppManifestSchema,\n\tvalidateManifest,\n} from './manifest';\nexport type { ConnectionState } from './nats';\nexport type { Role } from './roles';\nexport { ROLE_HIERARCHY } from './roles';\n","import { z } from 'zod';\nimport type { Role } from './roles';\n\n/** Desktop integration metadata for an app. */\nexport interface AppDesktopConfig {\n\t/** Path to the app icon (relative to the public directory). */\n\ticon: string;\n\t/** Categories for desktop launcher grouping. */\n\tcategories: string[];\n\t/** Short description shown in the desktop launcher. */\n\tcomment: string;\n}\n\n/** A single view within an app manifest. */\nexport interface AppManifestView {\n\t/** Unique view identifier within the app. */\n\tid: string;\n\t/** Human-readable label for the view. */\n\tlabel: string;\n\t/** Permission string required to access this view. */\n\tpermission: string;\n\t/** Minimum role level required. */\n\tminRole: Role;\n\t/** NATS subject segment after `khal.<orgId>.` for this view's services. */\n\tnatsPrefix?: string;\n\t/** Default window dimensions. */\n\tdefaultSize: { width: number; height: number };\n\t/** Relative path to the view's React component. */\n\tcomponent: string;\n}\n\n/** Health check configuration for a service. */\nexport interface ServiceHealthConfig {\n\t/** Check type: tcp (connect to port), http (GET endpoint), command (run shell). */\n\ttype: 'tcp' | 'http' | 'command';\n\t/** Target: port number for tcp, URL for http, shell command for command. */\n\ttarget: string | number;\n\t/** Check interval in milliseconds (default: 30000). */\n\tinterval?: number;\n\t/** Timeout in milliseconds (default: 5000). */\n\ttimeout?: number;\n}\n\n/** Service declaration within an app manifest. */\nexport interface AppServiceConfig {\n\t/** Service name (must be unique across the app). */\n\tname: string;\n\t/** Shell command to start the service (alternative to entry). */\n\tcommand?: string;\n\t/** Entry point file path relative to the package root. */\n\tentry?: string;\n\t/** Runtime environment. */\n\truntime?: 'node' | 'python';\n\t/** Health check configuration. */\n\thealth?: ServiceHealthConfig;\n\t/** Restart policy. */\n\trestart?: 'always' | 'on-failure' | 'never';\n\t/** Ports the service binds to internally. Khal assigns proxy ports. */\n\tports?: number[];\n}\n\n/** Environment variable declaration for app configuration. */\nexport interface AppEnvVar {\n\t/** Variable name (e.g., \"API_KEY\"). */\n\tkey: string;\n\t/** Human-readable description shown in the config UI. */\n\tdescription: string;\n\t/** Whether the variable is required for the app to run. */\n\trequired: boolean;\n\t/** Default value if not configured. */\n\tdefault?: string;\n\t/** Value type — affects config UI rendering and validation. */\n\ttype?: 'string' | 'number' | 'boolean' | 'secret' | 'url';\n\t/** Storage: 'config' for plain ConfigMap, 'vault' for Kubernetes Secret. */\n\tvisibility?: 'config' | 'vault';\n}\n\n/** Kubernetes deployment configuration for apps with backends. */\nexport interface AppDeployConfig {\n\t/** Dockerfile path relative to app root (default: \"Dockerfile\"). */\n\tdockerfile?: string;\n\t/** Build args passed to docker build. */\n\tbuildArgs?: Record<string, string>;\n\t/** Container port the app listens on. */\n\tport?: number;\n\t/** Resource requests and limits for the pod. */\n\tresources?: {\n\t\trequests?: { cpu?: string; memory?: string };\n\t\tlimits?: { cpu?: string; memory?: string };\n\t};\n\t/** Replica count (default: 1). */\n\treplicas?: number;\n\t/** Health check path for k8s readiness/liveness probes. */\n\thealthPath?: string;\n\t/** Ingress configuration for per-app routing. */\n\tingress?: {\n\t\t/** Subdomain prefix: <value>.apps.<domain>. Defaults to app id. */\n\t\tsubdomain?: string;\n\t\t/** Additional path prefixes to route to this app. */\n\t\tpathPrefixes?: string[];\n\t};\n\t/** Horizontal Pod Autoscaler configuration. */\n\tautoscaling?: {\n\t\tenabled: boolean;\n\t\tminReplicas?: number;\n\t\tmaxReplicas?: number;\n\t\ttargetCPU?: number;\n\t};\n\t/** Environment sources injected at runtime from k8s resources. */\n\tenvFrom?: Array<{ secretRef?: string; configMapRef?: string }>;\n}\n\n/** Tauri standalone export configuration. */\nexport interface AppTauriConfig {\n\t/** Whether this app supports standalone Tauri export. */\n\texportable: boolean;\n\t/** Path to src-tauri/ directory (default: \"./src-tauri\"). */\n\ttauriDir?: string;\n\t/** App name for the exported binary. */\n\tappName?: string;\n\t/** App icon path relative to app root. */\n\ticon?: string;\n\t/** Window configuration for standalone mode. */\n\twindow?: { width?: number; height?: number; title?: string };\n}\n\n/**\n * Full app manifest — the type for `manifest.ts` files in KhalOS app packages.\n *\n * Every app package must export a default manifest conforming to this shape.\n * Use `defineManifest()` for compile-time validation and autocomplete.\n *\n * The JSON equivalent (`khal-app.json`) uses the same shape and is the\n * language-agnostic install-time contract that the marketplace reads.\n */\nexport interface AppManifest {\n\t/** Unique app identifier (must match the package directory name). */\n\tid: string;\n\t/** One or more views the app exposes. */\n\tviews: AppManifestView[];\n\t/** Desktop integration configuration. */\n\tdesktop: AppDesktopConfig;\n\t/** Backend services this app runs. Optional — pure UI apps have no services. */\n\tservices?: AppServiceConfig[];\n\n\t// ── v2 fields (all optional for backward compatibility) ──\n\n\t/** Schema version for forward compatibility (default: 1). */\n\tschemaVersion?: number;\n\t/** Human-readable app name. */\n\tname?: string;\n\t/** Semantic version of the app. */\n\tversion?: string;\n\t/** Short description for the marketplace listing. */\n\tdescription?: string;\n\t/** Author name or organization. */\n\tauthor?: string;\n\t/** SPDX license identifier. */\n\tlicense?: string;\n\t/** Source repository URL. */\n\trepository?: string;\n\t/** Minimum KhalOS host version required. */\n\tminHostVersion?: string;\n\t/** Environment variables the app needs — auto-generates config UI. */\n\tenv?: AppEnvVar[];\n\t/** Native Kubernetes deployment configuration. */\n\tdeploy?: AppDeployConfig;\n\t/** Tauri standalone export configuration. */\n\ttauri?: AppTauriConfig;\n}\n\n// ── Pack Contract Types (for standalone pack-* repos) ──\n\nexport const KhalPermission = z.enum([\n\t'nats:publish',\n\t'nats:subscribe',\n\t'files:read',\n\t'files:write',\n\t'pty:spawn',\n\t'http:fetch',\n\t'system:clipboard',\n\t'system:notifications',\n]);\nexport type KhalPermission = z.infer<typeof KhalPermission>;\n\nexport const KhalServiceSpec = z.object({\n\tname: z.string(),\n\tcommand: z.string().optional(),\n\tentry: z.string().optional(),\n\truntime: z.enum(['node', 'bun', 'python']).optional(),\n\tports: z.array(z.number()).optional(),\n\thealth: z\n\t\t.object({\n\t\t\ttype: z.enum(['tcp', 'http', 'command']),\n\t\t\ttarget: z.union([z.string(), z.number()]),\n\t\t\tinterval: z.number().optional(),\n\t\t\ttimeout: z.number().optional(),\n\t\t})\n\t\t.optional(),\n});\nexport type KhalServiceSpec = z.infer<typeof KhalServiceSpec>;\n\nexport const KhalWindowSpec = z.object({\n\tid: z.string(),\n\ttitle: z.string().optional(),\n\twidth: z.number().default(800),\n\theight: z.number().default(600),\n\tresizable: z.boolean().default(true),\n});\nexport type KhalWindowSpec = z.infer<typeof KhalWindowSpec>;\n\n/** A single app entry within a bundle pack manifest. */\nexport const KhalAppEntrySchema = z.object({\n\t/** Unique app identifier within the bundle. */\n\tid: z.string(),\n\t/** Human-readable app name. */\n\tname: z.string(),\n\t/** Frontend package reference for this app. */\n\tfrontend: z\n\t\t.object({\n\t\t\tpackage: z.string(),\n\t\t})\n\t\t.optional(),\n});\nexport type KhalAppEntry = z.infer<typeof KhalAppEntrySchema>;\n\nexport const KhalAppManifestSchema = z\n\t.object({\n\t\t$schema: z.string().optional(),\n\t\tid: z.string(),\n\t\tname: z.string(),\n\t\tversion: z.string(),\n\t\ticon: z.string(),\n\t\tdescription: z.string(),\n\t\tauthor: z.string(),\n\t\tpermissions: z.array(KhalPermission),\n\t\tservices: z.array(KhalServiceSpec).optional(),\n\t\twindows: z.array(KhalWindowSpec).optional(),\n\t\tfrontend: z\n\t\t\t.object({\n\t\t\t\tpackage: z.string(),\n\t\t\t\tentry: z.string().default('default'),\n\t\t\t})\n\t\t\t.optional(),\n\t\tbackend: z\n\t\t\t.object({\n\t\t\t\timage: z.string(),\n\t\t\t\thelmChart: z.string().optional(),\n\t\t\t\tenv: z.record(z.string(), z.string()),\n\t\t\t\tports: z.array(z.number()),\n\t\t\t})\n\t\t\t.optional(),\n\t\t/**\n\t\t * When apps is present, the root frontend field is ignored —\n\t\t * each entry has its own frontend.\n\t\t */\n\t\tapps: z.array(KhalAppEntrySchema).optional(),\n\t})\n\t.strict();\n\nexport type KhalAppManifest = z.infer<typeof KhalAppManifestSchema>;\n\n/** Validate a raw object as KhalAppManifest. Throws ZodError with detailed messages on failure. */\nexport function validateManifest(raw: unknown): KhalAppManifest {\n\treturn KhalAppManifestSchema.parse(raw);\n}\n","/** Canonical role hierarchy from least to most privileged. */\nexport const ROLE_HIERARCHY = ['member', 'platform-dev', 'platform-admin', 'platform-owner'] as const;\nexport type Role = (typeof ROLE_HIERARCHY)[number];\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,iBAAkB;AA6KX,IAAM,iBAAiB,aAAE,KAAK;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,CAAC;AAGM,IAAM,kBAAkB,aAAE,OAAO;AAAA,EACvC,MAAM,aAAE,OAAO;AAAA,EACf,SAAS,aAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,OAAO,aAAE,OAAO,EAAE,SAAS;AAAA,EAC3B,SAAS,aAAE,KAAK,CAAC,QAAQ,OAAO,QAAQ,CAAC,EAAE,SAAS;AAAA,EACpD,OAAO,aAAE,MAAM,aAAE,OAAO,CAAC,EAAE,SAAS;AAAA,EACpC,QAAQ,aACN,OAAO;AAAA,IACP,MAAM,aAAE,KAAK,CAAC,OAAO,QAAQ,SAAS,CAAC;AAAA,IACvC,QAAQ,aAAE,MAAM,CAAC,aAAE,OAAO,GAAG,aAAE,OAAO,CAAC,CAAC;AAAA,IACxC,UAAU,aAAE,OAAO,EAAE,SAAS;AAAA,IAC9B,SAAS,aAAE,OAAO,EAAE,SAAS;AAAA,EAC9B,CAAC,EACA,SAAS;AACZ,CAAC;AAGM,IAAM,iBAAiB,aAAE,OAAO;AAAA,EACtC,IAAI,aAAE,OAAO;AAAA,EACb,OAAO,aAAE,OAAO,EAAE,SAAS;AAAA,EAC3B,OAAO,aAAE,OAAO,EAAE,QAAQ,GAAG;AAAA,EAC7B,QAAQ,aAAE,OAAO,EAAE,QAAQ,GAAG;AAAA,EAC9B,WAAW,aAAE,QAAQ,EAAE,QAAQ,IAAI;AACpC,CAAC;AAIM,IAAM,qBAAqB,aAAE,OAAO;AAAA;AAAA,EAE1C,IAAI,aAAE,OAAO;AAAA;AAAA,EAEb,MAAM,aAAE,OAAO;AAAA;AAAA,EAEf,UAAU,aACR,OAAO;AAAA,IACP,SAAS,aAAE,OAAO;AAAA,EACnB,CAAC,EACA,SAAS;AACZ,CAAC;AAGM,IAAM,wBAAwB,aACnC,OAAO;AAAA,EACP,SAAS,aAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,IAAI,aAAE,OAAO;AAAA,EACb,MAAM,aAAE,OAAO;AAAA,EACf,SAAS,aAAE,OAAO;AAAA,EAClB,MAAM,aAAE,OAAO;AAAA,EACf,aAAa,aAAE,OAAO;AAAA,EACtB,QAAQ,aAAE,OAAO;AAAA,EACjB,aAAa,aAAE,MAAM,cAAc;AAAA,EACnC,UAAU,aAAE,MAAM,eAAe,EAAE,SAAS;AAAA,EAC5C,SAAS,aAAE,MAAM,cAAc,EAAE,SAAS;AAAA,EAC1C,UAAU,aACR,OAAO;AAAA,IACP,SAAS,aAAE,OAAO;AAAA,IAClB,OAAO,aAAE,OAAO,EAAE,QAAQ,SAAS;AAAA,EACpC,CAAC,EACA,SAAS;AAAA,EACX,SAAS,aACP,OAAO;AAAA,IACP,OAAO,aAAE,OAAO;AAAA,IAChB,WAAW,aAAE,OAAO,EAAE,SAAS;AAAA,IAC/B,KAAK,aAAE,OAAO,aAAE,OAAO,GAAG,aAAE,OAAO,CAAC;AAAA,IACpC,OAAO,aAAE,MAAM,aAAE,OAAO,CAAC;AAAA,EAC1B,CAAC,EACA,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,EAKX,MAAM,aAAE,MAAM,kBAAkB,EAAE,SAAS;AAC5C,CAAC,EACA,OAAO;AAKF,SAAS,iBAAiB,KAA+B;AAC/D,SAAO,sBAAsB,MAAM,GAAG;AACvC;;;ACxQO,IAAM,iBAAiB,CAAC,UAAU,gBAAgB,kBAAkB,gBAAgB;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/manifest.ts","../src/roles.ts"],"sourcesContent":["export type { KhalAuth } from './auth';\nexport type {\n\tAppDeployConfig,\n\tAppDesktopConfig,\n\tAppEnvVar,\n\tAppManifest,\n\tAppManifestView,\n\tAppServiceConfig,\n\tAppTauriConfig,\n\tKhalAppEntry,\n\tKhalAppManifest,\n\tKhalPermission,\n\tKhalServiceSpec,\n\tKhalWindowSpec,\n\tServiceHealthConfig,\n} from './manifest';\nexport {\n\tKhalAppEntrySchema,\n\tKhalAppManifestSchema,\n\tvalidateManifest,\n} from './manifest';\nexport type { ConnectionState } from './nats';\nexport type { Role } from './roles';\nexport { ROLE_HIERARCHY } from './roles';\n","import { z } from 'zod';\nimport type { Role } from './roles';\n\n/** Desktop integration metadata for an app. */\nexport interface AppDesktopConfig {\n\t/** Path to the app icon (relative to the public directory). */\n\ticon: string;\n\t/** Categories for desktop launcher grouping. */\n\tcategories: string[];\n\t/** Short description shown in the desktop launcher. */\n\tcomment: string;\n}\n\n/** A single view within an app manifest. */\nexport interface AppManifestView {\n\t/** Unique view identifier within the app. */\n\tid: string;\n\t/** Human-readable label for the view. */\n\tlabel: string;\n\t/** Permission string required to access this view. */\n\tpermission: string;\n\t/** Minimum role level required. */\n\tminRole: Role;\n\t/** NATS subject segment after `khal.<orgId>.` for this view's services. */\n\tnatsPrefix?: string;\n\t/** Default window dimensions. */\n\tdefaultSize: { width: number; height: number };\n\t/** Relative path to the view's React component. */\n\tcomponent: string;\n}\n\n/** Health check configuration for a service. */\nexport interface ServiceHealthConfig {\n\t/** Check type: tcp (connect to port), http (GET endpoint), command (run shell). */\n\ttype: 'tcp' | 'http' | 'command';\n\t/** Target: port number for tcp, URL for http, shell command for command. */\n\ttarget: string | number;\n\t/** Check interval in milliseconds (default: 30000). */\n\tinterval?: number;\n\t/** Timeout in milliseconds (default: 5000). */\n\ttimeout?: number;\n}\n\n/** Service declaration within an app manifest. */\nexport interface AppServiceConfig {\n\t/** Service name (must be unique across the app). */\n\tname: string;\n\t/** Shell command to start the service (alternative to entry). */\n\tcommand?: string;\n\t/** Entry point file path relative to the package root. */\n\tentry?: string;\n\t/** Runtime environment. */\n\truntime?: 'node' | 'python';\n\t/** Health check configuration. */\n\thealth?: ServiceHealthConfig;\n\t/** Restart policy. */\n\trestart?: 'always' | 'on-failure' | 'never';\n\t/** Ports the service binds to internally. Khal assigns proxy ports. */\n\tports?: number[];\n}\n\n/** Environment variable declaration for app configuration. */\nexport interface AppEnvVar {\n\t/** Variable name (e.g., \"API_KEY\"). */\n\tkey: string;\n\t/** Human-readable description shown in the config UI. */\n\tdescription: string;\n\t/** Whether the variable is required for the app to run. */\n\trequired: boolean;\n\t/** Default value if not configured. */\n\tdefault?: string;\n\t/** Value type — affects config UI rendering and validation. */\n\ttype?: 'string' | 'number' | 'boolean' | 'secret' | 'url';\n\t/** Storage: 'config' for plain ConfigMap, 'vault' for Kubernetes Secret. */\n\tvisibility?: 'config' | 'vault';\n}\n\n/** Kubernetes deployment configuration for apps with backends. */\nexport interface AppDeployConfig {\n\t/** Dockerfile path relative to app root (default: \"Dockerfile\"). */\n\tdockerfile?: string;\n\t/** Build args passed to docker build. */\n\tbuildArgs?: Record<string, string>;\n\t/** Container port the app listens on. */\n\tport?: number;\n\t/** Resource requests and limits for the pod. */\n\tresources?: {\n\t\trequests?: { cpu?: string; memory?: string };\n\t\tlimits?: { cpu?: string; memory?: string };\n\t};\n\t/** Replica count (default: 1). */\n\treplicas?: number;\n\t/** Health check path for k8s readiness/liveness probes. */\n\thealthPath?: string;\n\t/** Ingress configuration for per-app routing. */\n\tingress?: {\n\t\t/** Subdomain prefix: <value>.apps.<domain>. Defaults to app id. */\n\t\tsubdomain?: string;\n\t\t/** Additional path prefixes to route to this app. */\n\t\tpathPrefixes?: string[];\n\t};\n\t/** Horizontal Pod Autoscaler configuration. */\n\tautoscaling?: {\n\t\tenabled: boolean;\n\t\tminReplicas?: number;\n\t\tmaxReplicas?: number;\n\t\ttargetCPU?: number;\n\t};\n\t/** Environment sources injected at runtime from k8s resources. */\n\tenvFrom?: Array<{ secretRef?: string; configMapRef?: string }>;\n}\n\n/** Tauri standalone export configuration. */\nexport interface AppTauriConfig {\n\t/** Whether this app supports standalone Tauri export. */\n\texportable: boolean;\n\t/** Path to src-tauri/ directory (default: \"./src-tauri\"). */\n\ttauriDir?: string;\n\t/** App name for the exported binary. */\n\tappName?: string;\n\t/** App icon path relative to app root. */\n\ticon?: string;\n\t/** Window configuration for standalone mode. */\n\twindow?: { width?: number; height?: number; title?: string };\n}\n\n/**\n * Full app manifest — the type for `manifest.ts` files in KhalOS app packages.\n *\n * Every app package must export a default manifest conforming to this shape.\n * Use `defineManifest()` for compile-time validation and autocomplete.\n *\n * The JSON equivalent (`khal-app.json`) uses the same shape and is the\n * language-agnostic install-time contract that the marketplace reads.\n */\nexport interface AppManifest {\n\t/** Unique app identifier (must match the package directory name). */\n\tid: string;\n\t/** One or more views the app exposes. */\n\tviews: AppManifestView[];\n\t/** Desktop integration configuration. */\n\tdesktop: AppDesktopConfig;\n\t/** Backend services this app runs. Optional — pure UI apps have no services. */\n\tservices?: AppServiceConfig[];\n\n\t// ── v2 fields (all optional for backward compatibility) ──\n\n\t/** Schema version for forward compatibility (default: 1). */\n\tschemaVersion?: number;\n\t/** Human-readable app name. */\n\tname?: string;\n\t/** Semantic version of the app. */\n\tversion?: string;\n\t/** Short description for the marketplace listing. */\n\tdescription?: string;\n\t/** Author name or organization. */\n\tauthor?: string;\n\t/** SPDX license identifier. */\n\tlicense?: string;\n\t/** Source repository URL. */\n\trepository?: string;\n\t/** Minimum KhalOS host version required. */\n\tminHostVersion?: string;\n\t/** Environment variables the app needs — auto-generates config UI. */\n\tenv?: AppEnvVar[];\n\t/** Native Kubernetes deployment configuration. */\n\tdeploy?: AppDeployConfig;\n\t/** Tauri standalone export configuration. */\n\ttauri?: AppTauriConfig;\n\t/** URL to the app's pre-built ESM bundle for runtime loading by desktop. */\n\tbundleUrl?: string;\n}\n\n// ── Pack Contract Types (for standalone pack-* repos) ──\n\nexport const KhalPermission = z.enum([\n\t'nats:publish',\n\t'nats:subscribe',\n\t'files:read',\n\t'files:write',\n\t'pty:spawn',\n\t'http:fetch',\n\t'system:clipboard',\n\t'system:notifications',\n]);\nexport type KhalPermission = z.infer<typeof KhalPermission>;\n\nexport const KhalServiceSpec = z.object({\n\tname: z.string(),\n\tcommand: z.string().optional(),\n\tentry: z.string().optional(),\n\truntime: z.enum(['node', 'bun', 'python']).optional(),\n\tports: z.array(z.number()).optional(),\n\thealth: z\n\t\t.object({\n\t\t\ttype: z.enum(['tcp', 'http', 'command']),\n\t\t\ttarget: z.union([z.string(), z.number()]),\n\t\t\tinterval: z.number().optional(),\n\t\t\ttimeout: z.number().optional(),\n\t\t})\n\t\t.optional(),\n});\nexport type KhalServiceSpec = z.infer<typeof KhalServiceSpec>;\n\nexport const KhalWindowSpec = z.object({\n\tid: z.string(),\n\ttitle: z.string().optional(),\n\twidth: z.number().default(800),\n\theight: z.number().default(600),\n\tresizable: z.boolean().default(true),\n});\nexport type KhalWindowSpec = z.infer<typeof KhalWindowSpec>;\n\n/** A single app entry within a bundle pack manifest. */\nexport const KhalAppEntrySchema = z.object({\n\t/** Unique app identifier within the bundle. */\n\tid: z.string(),\n\t/** Human-readable app name. */\n\tname: z.string(),\n\t/** Frontend package reference for this app. */\n\tfrontend: z\n\t\t.object({\n\t\t\tpackage: z.string(),\n\t\t})\n\t\t.optional(),\n});\nexport type KhalAppEntry = z.infer<typeof KhalAppEntrySchema>;\n\nexport const KhalAppManifestSchema = z\n\t.object({\n\t\t$schema: z.string().optional(),\n\t\tid: z.string(),\n\t\tname: z.string(),\n\t\tversion: z.string(),\n\t\ticon: z.string(),\n\t\tdescription: z.string(),\n\t\tauthor: z.string(),\n\t\tpermissions: z.array(KhalPermission),\n\t\tservices: z.array(KhalServiceSpec).optional(),\n\t\twindows: z.array(KhalWindowSpec).optional(),\n\t\tfrontend: z\n\t\t\t.object({\n\t\t\t\tpackage: z.string(),\n\t\t\t\tentry: z.string().default('default'),\n\t\t\t})\n\t\t\t.optional(),\n\t\tbackend: z\n\t\t\t.object({\n\t\t\t\timage: z.string(),\n\t\t\t\thelmChart: z.string().optional(),\n\t\t\t\tenv: z.record(z.string(), z.string()),\n\t\t\t\tports: z.array(z.number()),\n\t\t\t})\n\t\t\t.optional(),\n\t\t/** Relative path to the pre-built ESM bundle within the package (e.g., \"dist/bundle.mjs\"). */\n\t\tbundlePath: z.string().optional(),\n\t\t/**\n\t\t * When apps is present, the root frontend field is ignored —\n\t\t * each entry has its own frontend.\n\t\t */\n\t\tapps: z.array(KhalAppEntrySchema).optional(),\n\t})\n\t.strict();\n\nexport type KhalAppManifest = z.infer<typeof KhalAppManifestSchema>;\n\n/** Validate a raw object as KhalAppManifest. Throws ZodError with detailed messages on failure. */\nexport function validateManifest(raw: unknown): KhalAppManifest {\n\treturn KhalAppManifestSchema.parse(raw);\n}\n","/** Canonical role hierarchy from least to most privileged. */\nexport const ROLE_HIERARCHY = ['member', 'platform-dev', 'platform-admin', 'platform-owner'] as const;\nexport type Role = (typeof ROLE_HIERARCHY)[number];\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,iBAAkB;AA+KX,IAAM,iBAAiB,aAAE,KAAK;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,CAAC;AAGM,IAAM,kBAAkB,aAAE,OAAO;AAAA,EACvC,MAAM,aAAE,OAAO;AAAA,EACf,SAAS,aAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,OAAO,aAAE,OAAO,EAAE,SAAS;AAAA,EAC3B,SAAS,aAAE,KAAK,CAAC,QAAQ,OAAO,QAAQ,CAAC,EAAE,SAAS;AAAA,EACpD,OAAO,aAAE,MAAM,aAAE,OAAO,CAAC,EAAE,SAAS;AAAA,EACpC,QAAQ,aACN,OAAO;AAAA,IACP,MAAM,aAAE,KAAK,CAAC,OAAO,QAAQ,SAAS,CAAC;AAAA,IACvC,QAAQ,aAAE,MAAM,CAAC,aAAE,OAAO,GAAG,aAAE,OAAO,CAAC,CAAC;AAAA,IACxC,UAAU,aAAE,OAAO,EAAE,SAAS;AAAA,IAC9B,SAAS,aAAE,OAAO,EAAE,SAAS;AAAA,EAC9B,CAAC,EACA,SAAS;AACZ,CAAC;AAGM,IAAM,iBAAiB,aAAE,OAAO;AAAA,EACtC,IAAI,aAAE,OAAO;AAAA,EACb,OAAO,aAAE,OAAO,EAAE,SAAS;AAAA,EAC3B,OAAO,aAAE,OAAO,EAAE,QAAQ,GAAG;AAAA,EAC7B,QAAQ,aAAE,OAAO,EAAE,QAAQ,GAAG;AAAA,EAC9B,WAAW,aAAE,QAAQ,EAAE,QAAQ,IAAI;AACpC,CAAC;AAIM,IAAM,qBAAqB,aAAE,OAAO;AAAA;AAAA,EAE1C,IAAI,aAAE,OAAO;AAAA;AAAA,EAEb,MAAM,aAAE,OAAO;AAAA;AAAA,EAEf,UAAU,aACR,OAAO;AAAA,IACP,SAAS,aAAE,OAAO;AAAA,EACnB,CAAC,EACA,SAAS;AACZ,CAAC;AAGM,IAAM,wBAAwB,aACnC,OAAO;AAAA,EACP,SAAS,aAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,IAAI,aAAE,OAAO;AAAA,EACb,MAAM,aAAE,OAAO;AAAA,EACf,SAAS,aAAE,OAAO;AAAA,EAClB,MAAM,aAAE,OAAO;AAAA,EACf,aAAa,aAAE,OAAO;AAAA,EACtB,QAAQ,aAAE,OAAO;AAAA,EACjB,aAAa,aAAE,MAAM,cAAc;AAAA,EACnC,UAAU,aAAE,MAAM,eAAe,EAAE,SAAS;AAAA,EAC5C,SAAS,aAAE,MAAM,cAAc,EAAE,SAAS;AAAA,EAC1C,UAAU,aACR,OAAO;AAAA,IACP,SAAS,aAAE,OAAO;AAAA,IAClB,OAAO,aAAE,OAAO,EAAE,QAAQ,SAAS;AAAA,EACpC,CAAC,EACA,SAAS;AAAA,EACX,SAAS,aACP,OAAO;AAAA,IACP,OAAO,aAAE,OAAO;AAAA,IAChB,WAAW,aAAE,OAAO,EAAE,SAAS;AAAA,IAC/B,KAAK,aAAE,OAAO,aAAE,OAAO,GAAG,aAAE,OAAO,CAAC;AAAA,IACpC,OAAO,aAAE,MAAM,aAAE,OAAO,CAAC;AAAA,EAC1B,CAAC,EACA,SAAS;AAAA;AAAA,EAEX,YAAY,aAAE,OAAO,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,EAKhC,MAAM,aAAE,MAAM,kBAAkB,EAAE,SAAS;AAC5C,CAAC,EACA,OAAO;AAKF,SAAS,iBAAiB,KAA+B;AAC/D,SAAO,sBAAsB,MAAM,GAAG;AACvC;;;AC5QO,IAAM,iBAAiB,CAAC,UAAU,gBAAgB,kBAAkB,gBAAgB;","names":[]}
|
package/dist/index.d.cts
CHANGED
|
@@ -185,6 +185,8 @@ interface AppManifest {
|
|
|
185
185
|
deploy?: AppDeployConfig;
|
|
186
186
|
/** Tauri standalone export configuration. */
|
|
187
187
|
tauri?: AppTauriConfig;
|
|
188
|
+
/** URL to the app's pre-built ESM bundle for runtime loading by desktop. */
|
|
189
|
+
bundleUrl?: string;
|
|
188
190
|
}
|
|
189
191
|
declare const KhalPermission: z.ZodEnum<{
|
|
190
192
|
"nats:publish": "nats:publish";
|
|
@@ -292,6 +294,7 @@ declare const KhalAppManifestSchema: z.ZodObject<{
|
|
|
292
294
|
env: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
293
295
|
ports: z.ZodArray<z.ZodNumber>;
|
|
294
296
|
}, z.core.$strip>>;
|
|
297
|
+
bundlePath: z.ZodOptional<z.ZodString>;
|
|
295
298
|
apps: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
296
299
|
id: z.ZodString;
|
|
297
300
|
name: z.ZodString;
|
package/dist/index.d.ts
CHANGED
|
@@ -185,6 +185,8 @@ interface AppManifest {
|
|
|
185
185
|
deploy?: AppDeployConfig;
|
|
186
186
|
/** Tauri standalone export configuration. */
|
|
187
187
|
tauri?: AppTauriConfig;
|
|
188
|
+
/** URL to the app's pre-built ESM bundle for runtime loading by desktop. */
|
|
189
|
+
bundleUrl?: string;
|
|
188
190
|
}
|
|
189
191
|
declare const KhalPermission: z.ZodEnum<{
|
|
190
192
|
"nats:publish": "nats:publish";
|
|
@@ -292,6 +294,7 @@ declare const KhalAppManifestSchema: z.ZodObject<{
|
|
|
292
294
|
env: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
293
295
|
ports: z.ZodArray<z.ZodNumber>;
|
|
294
296
|
}, z.core.$strip>>;
|
|
297
|
+
bundlePath: z.ZodOptional<z.ZodString>;
|
|
295
298
|
apps: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
296
299
|
id: z.ZodString;
|
|
297
300
|
name: z.ZodString;
|
package/dist/index.js
CHANGED
|
@@ -61,6 +61,8 @@ var KhalAppManifestSchema = z.object({
|
|
|
61
61
|
env: z.record(z.string(), z.string()),
|
|
62
62
|
ports: z.array(z.number())
|
|
63
63
|
}).optional(),
|
|
64
|
+
/** Relative path to the pre-built ESM bundle within the package (e.g., "dist/bundle.mjs"). */
|
|
65
|
+
bundlePath: z.string().optional(),
|
|
64
66
|
/**
|
|
65
67
|
* When apps is present, the root frontend field is ignored —
|
|
66
68
|
* each entry has its own frontend.
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/manifest.ts","../src/roles.ts"],"sourcesContent":["import { z } from 'zod';\nimport type { Role } from './roles';\n\n/** Desktop integration metadata for an app. */\nexport interface AppDesktopConfig {\n\t/** Path to the app icon (relative to the public directory). */\n\ticon: string;\n\t/** Categories for desktop launcher grouping. */\n\tcategories: string[];\n\t/** Short description shown in the desktop launcher. */\n\tcomment: string;\n}\n\n/** A single view within an app manifest. */\nexport interface AppManifestView {\n\t/** Unique view identifier within the app. */\n\tid: string;\n\t/** Human-readable label for the view. */\n\tlabel: string;\n\t/** Permission string required to access this view. */\n\tpermission: string;\n\t/** Minimum role level required. */\n\tminRole: Role;\n\t/** NATS subject segment after `khal.<orgId>.` for this view's services. */\n\tnatsPrefix?: string;\n\t/** Default window dimensions. */\n\tdefaultSize: { width: number; height: number };\n\t/** Relative path to the view's React component. */\n\tcomponent: string;\n}\n\n/** Health check configuration for a service. */\nexport interface ServiceHealthConfig {\n\t/** Check type: tcp (connect to port), http (GET endpoint), command (run shell). */\n\ttype: 'tcp' | 'http' | 'command';\n\t/** Target: port number for tcp, URL for http, shell command for command. */\n\ttarget: string | number;\n\t/** Check interval in milliseconds (default: 30000). */\n\tinterval?: number;\n\t/** Timeout in milliseconds (default: 5000). */\n\ttimeout?: number;\n}\n\n/** Service declaration within an app manifest. */\nexport interface AppServiceConfig {\n\t/** Service name (must be unique across the app). */\n\tname: string;\n\t/** Shell command to start the service (alternative to entry). */\n\tcommand?: string;\n\t/** Entry point file path relative to the package root. */\n\tentry?: string;\n\t/** Runtime environment. */\n\truntime?: 'node' | 'python';\n\t/** Health check configuration. */\n\thealth?: ServiceHealthConfig;\n\t/** Restart policy. */\n\trestart?: 'always' | 'on-failure' | 'never';\n\t/** Ports the service binds to internally. Khal assigns proxy ports. */\n\tports?: number[];\n}\n\n/** Environment variable declaration for app configuration. */\nexport interface AppEnvVar {\n\t/** Variable name (e.g., \"API_KEY\"). */\n\tkey: string;\n\t/** Human-readable description shown in the config UI. */\n\tdescription: string;\n\t/** Whether the variable is required for the app to run. */\n\trequired: boolean;\n\t/** Default value if not configured. */\n\tdefault?: string;\n\t/** Value type — affects config UI rendering and validation. */\n\ttype?: 'string' | 'number' | 'boolean' | 'secret' | 'url';\n\t/** Storage: 'config' for plain ConfigMap, 'vault' for Kubernetes Secret. */\n\tvisibility?: 'config' | 'vault';\n}\n\n/** Kubernetes deployment configuration for apps with backends. */\nexport interface AppDeployConfig {\n\t/** Dockerfile path relative to app root (default: \"Dockerfile\"). */\n\tdockerfile?: string;\n\t/** Build args passed to docker build. */\n\tbuildArgs?: Record<string, string>;\n\t/** Container port the app listens on. */\n\tport?: number;\n\t/** Resource requests and limits for the pod. */\n\tresources?: {\n\t\trequests?: { cpu?: string; memory?: string };\n\t\tlimits?: { cpu?: string; memory?: string };\n\t};\n\t/** Replica count (default: 1). */\n\treplicas?: number;\n\t/** Health check path for k8s readiness/liveness probes. */\n\thealthPath?: string;\n\t/** Ingress configuration for per-app routing. */\n\tingress?: {\n\t\t/** Subdomain prefix: <value>.apps.<domain>. Defaults to app id. */\n\t\tsubdomain?: string;\n\t\t/** Additional path prefixes to route to this app. */\n\t\tpathPrefixes?: string[];\n\t};\n\t/** Horizontal Pod Autoscaler configuration. */\n\tautoscaling?: {\n\t\tenabled: boolean;\n\t\tminReplicas?: number;\n\t\tmaxReplicas?: number;\n\t\ttargetCPU?: number;\n\t};\n\t/** Environment sources injected at runtime from k8s resources. */\n\tenvFrom?: Array<{ secretRef?: string; configMapRef?: string }>;\n}\n\n/** Tauri standalone export configuration. */\nexport interface AppTauriConfig {\n\t/** Whether this app supports standalone Tauri export. */\n\texportable: boolean;\n\t/** Path to src-tauri/ directory (default: \"./src-tauri\"). */\n\ttauriDir?: string;\n\t/** App name for the exported binary. */\n\tappName?: string;\n\t/** App icon path relative to app root. */\n\ticon?: string;\n\t/** Window configuration for standalone mode. */\n\twindow?: { width?: number; height?: number; title?: string };\n}\n\n/**\n * Full app manifest — the type for `manifest.ts` files in KhalOS app packages.\n *\n * Every app package must export a default manifest conforming to this shape.\n * Use `defineManifest()` for compile-time validation and autocomplete.\n *\n * The JSON equivalent (`khal-app.json`) uses the same shape and is the\n * language-agnostic install-time contract that the marketplace reads.\n */\nexport interface AppManifest {\n\t/** Unique app identifier (must match the package directory name). */\n\tid: string;\n\t/** One or more views the app exposes. */\n\tviews: AppManifestView[];\n\t/** Desktop integration configuration. */\n\tdesktop: AppDesktopConfig;\n\t/** Backend services this app runs. Optional — pure UI apps have no services. */\n\tservices?: AppServiceConfig[];\n\n\t// ── v2 fields (all optional for backward compatibility) ──\n\n\t/** Schema version for forward compatibility (default: 1). */\n\tschemaVersion?: number;\n\t/** Human-readable app name. */\n\tname?: string;\n\t/** Semantic version of the app. */\n\tversion?: string;\n\t/** Short description for the marketplace listing. */\n\tdescription?: string;\n\t/** Author name or organization. */\n\tauthor?: string;\n\t/** SPDX license identifier. */\n\tlicense?: string;\n\t/** Source repository URL. */\n\trepository?: string;\n\t/** Minimum KhalOS host version required. */\n\tminHostVersion?: string;\n\t/** Environment variables the app needs — auto-generates config UI. */\n\tenv?: AppEnvVar[];\n\t/** Native Kubernetes deployment configuration. */\n\tdeploy?: AppDeployConfig;\n\t/** Tauri standalone export configuration. */\n\ttauri?: AppTauriConfig;\n}\n\n// ── Pack Contract Types (for standalone pack-* repos) ──\n\nexport const KhalPermission = z.enum([\n\t'nats:publish',\n\t'nats:subscribe',\n\t'files:read',\n\t'files:write',\n\t'pty:spawn',\n\t'http:fetch',\n\t'system:clipboard',\n\t'system:notifications',\n]);\nexport type KhalPermission = z.infer<typeof KhalPermission>;\n\nexport const KhalServiceSpec = z.object({\n\tname: z.string(),\n\tcommand: z.string().optional(),\n\tentry: z.string().optional(),\n\truntime: z.enum(['node', 'bun', 'python']).optional(),\n\tports: z.array(z.number()).optional(),\n\thealth: z\n\t\t.object({\n\t\t\ttype: z.enum(['tcp', 'http', 'command']),\n\t\t\ttarget: z.union([z.string(), z.number()]),\n\t\t\tinterval: z.number().optional(),\n\t\t\ttimeout: z.number().optional(),\n\t\t})\n\t\t.optional(),\n});\nexport type KhalServiceSpec = z.infer<typeof KhalServiceSpec>;\n\nexport const KhalWindowSpec = z.object({\n\tid: z.string(),\n\ttitle: z.string().optional(),\n\twidth: z.number().default(800),\n\theight: z.number().default(600),\n\tresizable: z.boolean().default(true),\n});\nexport type KhalWindowSpec = z.infer<typeof KhalWindowSpec>;\n\n/** A single app entry within a bundle pack manifest. */\nexport const KhalAppEntrySchema = z.object({\n\t/** Unique app identifier within the bundle. */\n\tid: z.string(),\n\t/** Human-readable app name. */\n\tname: z.string(),\n\t/** Frontend package reference for this app. */\n\tfrontend: z\n\t\t.object({\n\t\t\tpackage: z.string(),\n\t\t})\n\t\t.optional(),\n});\nexport type KhalAppEntry = z.infer<typeof KhalAppEntrySchema>;\n\nexport const KhalAppManifestSchema = z\n\t.object({\n\t\t$schema: z.string().optional(),\n\t\tid: z.string(),\n\t\tname: z.string(),\n\t\tversion: z.string(),\n\t\ticon: z.string(),\n\t\tdescription: z.string(),\n\t\tauthor: z.string(),\n\t\tpermissions: z.array(KhalPermission),\n\t\tservices: z.array(KhalServiceSpec).optional(),\n\t\twindows: z.array(KhalWindowSpec).optional(),\n\t\tfrontend: z\n\t\t\t.object({\n\t\t\t\tpackage: z.string(),\n\t\t\t\tentry: z.string().default('default'),\n\t\t\t})\n\t\t\t.optional(),\n\t\tbackend: z\n\t\t\t.object({\n\t\t\t\timage: z.string(),\n\t\t\t\thelmChart: z.string().optional(),\n\t\t\t\tenv: z.record(z.string(), z.string()),\n\t\t\t\tports: z.array(z.number()),\n\t\t\t})\n\t\t\t.optional(),\n\t\t/**\n\t\t * When apps is present, the root frontend field is ignored —\n\t\t * each entry has its own frontend.\n\t\t */\n\t\tapps: z.array(KhalAppEntrySchema).optional(),\n\t})\n\t.strict();\n\nexport type KhalAppManifest = z.infer<typeof KhalAppManifestSchema>;\n\n/** Validate a raw object as KhalAppManifest. Throws ZodError with detailed messages on failure. */\nexport function validateManifest(raw: unknown): KhalAppManifest {\n\treturn KhalAppManifestSchema.parse(raw);\n}\n","/** Canonical role hierarchy from least to most privileged. */\nexport const ROLE_HIERARCHY = ['member', 'platform-dev', 'platform-admin', 'platform-owner'] as const;\nexport type Role = (typeof ROLE_HIERARCHY)[number];\n"],"mappings":";AAAA,SAAS,SAAS;AA6KX,IAAM,iBAAiB,EAAE,KAAK;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,CAAC;AAGM,IAAM,kBAAkB,EAAE,OAAO;AAAA,EACvC,MAAM,EAAE,OAAO;AAAA,EACf,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,OAAO,EAAE,OAAO,EAAE,SAAS;AAAA,EAC3B,SAAS,EAAE,KAAK,CAAC,QAAQ,OAAO,QAAQ,CAAC,EAAE,SAAS;AAAA,EACpD,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS;AAAA,EACpC,QAAQ,EACN,OAAO;AAAA,IACP,MAAM,EAAE,KAAK,CAAC,OAAO,QAAQ,SAAS,CAAC;AAAA,IACvC,QAAQ,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,EAAE,OAAO,CAAC,CAAC;AAAA,IACxC,UAAU,EAAE,OAAO,EAAE,SAAS;AAAA,IAC9B,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,EAC9B,CAAC,EACA,SAAS;AACZ,CAAC;AAGM,IAAM,iBAAiB,EAAE,OAAO;AAAA,EACtC,IAAI,EAAE,OAAO;AAAA,EACb,OAAO,EAAE,OAAO,EAAE,SAAS;AAAA,EAC3B,OAAO,EAAE,OAAO,EAAE,QAAQ,GAAG;AAAA,EAC7B,QAAQ,EAAE,OAAO,EAAE,QAAQ,GAAG;AAAA,EAC9B,WAAW,EAAE,QAAQ,EAAE,QAAQ,IAAI;AACpC,CAAC;AAIM,IAAM,qBAAqB,EAAE,OAAO;AAAA;AAAA,EAE1C,IAAI,EAAE,OAAO;AAAA;AAAA,EAEb,MAAM,EAAE,OAAO;AAAA;AAAA,EAEf,UAAU,EACR,OAAO;AAAA,IACP,SAAS,EAAE,OAAO;AAAA,EACnB,CAAC,EACA,SAAS;AACZ,CAAC;AAGM,IAAM,wBAAwB,EACnC,OAAO;AAAA,EACP,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,IAAI,EAAE,OAAO;AAAA,EACb,MAAM,EAAE,OAAO;AAAA,EACf,SAAS,EAAE,OAAO;AAAA,EAClB,MAAM,EAAE,OAAO;AAAA,EACf,aAAa,EAAE,OAAO;AAAA,EACtB,QAAQ,EAAE,OAAO;AAAA,EACjB,aAAa,EAAE,MAAM,cAAc;AAAA,EACnC,UAAU,EAAE,MAAM,eAAe,EAAE,SAAS;AAAA,EAC5C,SAAS,EAAE,MAAM,cAAc,EAAE,SAAS;AAAA,EAC1C,UAAU,EACR,OAAO;AAAA,IACP,SAAS,EAAE,OAAO;AAAA,IAClB,OAAO,EAAE,OAAO,EAAE,QAAQ,SAAS;AAAA,EACpC,CAAC,EACA,SAAS;AAAA,EACX,SAAS,EACP,OAAO;AAAA,IACP,OAAO,EAAE,OAAO;AAAA,IAChB,WAAW,EAAE,OAAO,EAAE,SAAS;AAAA,IAC/B,KAAK,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,OAAO,CAAC;AAAA,IACpC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC;AAAA,EAC1B,CAAC,EACA,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,EAKX,MAAM,EAAE,MAAM,kBAAkB,EAAE,SAAS;AAC5C,CAAC,EACA,OAAO;AAKF,SAAS,iBAAiB,KAA+B;AAC/D,SAAO,sBAAsB,MAAM,GAAG;AACvC;;;ACxQO,IAAM,iBAAiB,CAAC,UAAU,gBAAgB,kBAAkB,gBAAgB;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/manifest.ts","../src/roles.ts"],"sourcesContent":["import { z } from 'zod';\nimport type { Role } from './roles';\n\n/** Desktop integration metadata for an app. */\nexport interface AppDesktopConfig {\n\t/** Path to the app icon (relative to the public directory). */\n\ticon: string;\n\t/** Categories for desktop launcher grouping. */\n\tcategories: string[];\n\t/** Short description shown in the desktop launcher. */\n\tcomment: string;\n}\n\n/** A single view within an app manifest. */\nexport interface AppManifestView {\n\t/** Unique view identifier within the app. */\n\tid: string;\n\t/** Human-readable label for the view. */\n\tlabel: string;\n\t/** Permission string required to access this view. */\n\tpermission: string;\n\t/** Minimum role level required. */\n\tminRole: Role;\n\t/** NATS subject segment after `khal.<orgId>.` for this view's services. */\n\tnatsPrefix?: string;\n\t/** Default window dimensions. */\n\tdefaultSize: { width: number; height: number };\n\t/** Relative path to the view's React component. */\n\tcomponent: string;\n}\n\n/** Health check configuration for a service. */\nexport interface ServiceHealthConfig {\n\t/** Check type: tcp (connect to port), http (GET endpoint), command (run shell). */\n\ttype: 'tcp' | 'http' | 'command';\n\t/** Target: port number for tcp, URL for http, shell command for command. */\n\ttarget: string | number;\n\t/** Check interval in milliseconds (default: 30000). */\n\tinterval?: number;\n\t/** Timeout in milliseconds (default: 5000). */\n\ttimeout?: number;\n}\n\n/** Service declaration within an app manifest. */\nexport interface AppServiceConfig {\n\t/** Service name (must be unique across the app). */\n\tname: string;\n\t/** Shell command to start the service (alternative to entry). */\n\tcommand?: string;\n\t/** Entry point file path relative to the package root. */\n\tentry?: string;\n\t/** Runtime environment. */\n\truntime?: 'node' | 'python';\n\t/** Health check configuration. */\n\thealth?: ServiceHealthConfig;\n\t/** Restart policy. */\n\trestart?: 'always' | 'on-failure' | 'never';\n\t/** Ports the service binds to internally. Khal assigns proxy ports. */\n\tports?: number[];\n}\n\n/** Environment variable declaration for app configuration. */\nexport interface AppEnvVar {\n\t/** Variable name (e.g., \"API_KEY\"). */\n\tkey: string;\n\t/** Human-readable description shown in the config UI. */\n\tdescription: string;\n\t/** Whether the variable is required for the app to run. */\n\trequired: boolean;\n\t/** Default value if not configured. */\n\tdefault?: string;\n\t/** Value type — affects config UI rendering and validation. */\n\ttype?: 'string' | 'number' | 'boolean' | 'secret' | 'url';\n\t/** Storage: 'config' for plain ConfigMap, 'vault' for Kubernetes Secret. */\n\tvisibility?: 'config' | 'vault';\n}\n\n/** Kubernetes deployment configuration for apps with backends. */\nexport interface AppDeployConfig {\n\t/** Dockerfile path relative to app root (default: \"Dockerfile\"). */\n\tdockerfile?: string;\n\t/** Build args passed to docker build. */\n\tbuildArgs?: Record<string, string>;\n\t/** Container port the app listens on. */\n\tport?: number;\n\t/** Resource requests and limits for the pod. */\n\tresources?: {\n\t\trequests?: { cpu?: string; memory?: string };\n\t\tlimits?: { cpu?: string; memory?: string };\n\t};\n\t/** Replica count (default: 1). */\n\treplicas?: number;\n\t/** Health check path for k8s readiness/liveness probes. */\n\thealthPath?: string;\n\t/** Ingress configuration for per-app routing. */\n\tingress?: {\n\t\t/** Subdomain prefix: <value>.apps.<domain>. Defaults to app id. */\n\t\tsubdomain?: string;\n\t\t/** Additional path prefixes to route to this app. */\n\t\tpathPrefixes?: string[];\n\t};\n\t/** Horizontal Pod Autoscaler configuration. */\n\tautoscaling?: {\n\t\tenabled: boolean;\n\t\tminReplicas?: number;\n\t\tmaxReplicas?: number;\n\t\ttargetCPU?: number;\n\t};\n\t/** Environment sources injected at runtime from k8s resources. */\n\tenvFrom?: Array<{ secretRef?: string; configMapRef?: string }>;\n}\n\n/** Tauri standalone export configuration. */\nexport interface AppTauriConfig {\n\t/** Whether this app supports standalone Tauri export. */\n\texportable: boolean;\n\t/** Path to src-tauri/ directory (default: \"./src-tauri\"). */\n\ttauriDir?: string;\n\t/** App name for the exported binary. */\n\tappName?: string;\n\t/** App icon path relative to app root. */\n\ticon?: string;\n\t/** Window configuration for standalone mode. */\n\twindow?: { width?: number; height?: number; title?: string };\n}\n\n/**\n * Full app manifest — the type for `manifest.ts` files in KhalOS app packages.\n *\n * Every app package must export a default manifest conforming to this shape.\n * Use `defineManifest()` for compile-time validation and autocomplete.\n *\n * The JSON equivalent (`khal-app.json`) uses the same shape and is the\n * language-agnostic install-time contract that the marketplace reads.\n */\nexport interface AppManifest {\n\t/** Unique app identifier (must match the package directory name). */\n\tid: string;\n\t/** One or more views the app exposes. */\n\tviews: AppManifestView[];\n\t/** Desktop integration configuration. */\n\tdesktop: AppDesktopConfig;\n\t/** Backend services this app runs. Optional — pure UI apps have no services. */\n\tservices?: AppServiceConfig[];\n\n\t// ── v2 fields (all optional for backward compatibility) ──\n\n\t/** Schema version for forward compatibility (default: 1). */\n\tschemaVersion?: number;\n\t/** Human-readable app name. */\n\tname?: string;\n\t/** Semantic version of the app. */\n\tversion?: string;\n\t/** Short description for the marketplace listing. */\n\tdescription?: string;\n\t/** Author name or organization. */\n\tauthor?: string;\n\t/** SPDX license identifier. */\n\tlicense?: string;\n\t/** Source repository URL. */\n\trepository?: string;\n\t/** Minimum KhalOS host version required. */\n\tminHostVersion?: string;\n\t/** Environment variables the app needs — auto-generates config UI. */\n\tenv?: AppEnvVar[];\n\t/** Native Kubernetes deployment configuration. */\n\tdeploy?: AppDeployConfig;\n\t/** Tauri standalone export configuration. */\n\ttauri?: AppTauriConfig;\n\t/** URL to the app's pre-built ESM bundle for runtime loading by desktop. */\n\tbundleUrl?: string;\n}\n\n// ── Pack Contract Types (for standalone pack-* repos) ──\n\nexport const KhalPermission = z.enum([\n\t'nats:publish',\n\t'nats:subscribe',\n\t'files:read',\n\t'files:write',\n\t'pty:spawn',\n\t'http:fetch',\n\t'system:clipboard',\n\t'system:notifications',\n]);\nexport type KhalPermission = z.infer<typeof KhalPermission>;\n\nexport const KhalServiceSpec = z.object({\n\tname: z.string(),\n\tcommand: z.string().optional(),\n\tentry: z.string().optional(),\n\truntime: z.enum(['node', 'bun', 'python']).optional(),\n\tports: z.array(z.number()).optional(),\n\thealth: z\n\t\t.object({\n\t\t\ttype: z.enum(['tcp', 'http', 'command']),\n\t\t\ttarget: z.union([z.string(), z.number()]),\n\t\t\tinterval: z.number().optional(),\n\t\t\ttimeout: z.number().optional(),\n\t\t})\n\t\t.optional(),\n});\nexport type KhalServiceSpec = z.infer<typeof KhalServiceSpec>;\n\nexport const KhalWindowSpec = z.object({\n\tid: z.string(),\n\ttitle: z.string().optional(),\n\twidth: z.number().default(800),\n\theight: z.number().default(600),\n\tresizable: z.boolean().default(true),\n});\nexport type KhalWindowSpec = z.infer<typeof KhalWindowSpec>;\n\n/** A single app entry within a bundle pack manifest. */\nexport const KhalAppEntrySchema = z.object({\n\t/** Unique app identifier within the bundle. */\n\tid: z.string(),\n\t/** Human-readable app name. */\n\tname: z.string(),\n\t/** Frontend package reference for this app. */\n\tfrontend: z\n\t\t.object({\n\t\t\tpackage: z.string(),\n\t\t})\n\t\t.optional(),\n});\nexport type KhalAppEntry = z.infer<typeof KhalAppEntrySchema>;\n\nexport const KhalAppManifestSchema = z\n\t.object({\n\t\t$schema: z.string().optional(),\n\t\tid: z.string(),\n\t\tname: z.string(),\n\t\tversion: z.string(),\n\t\ticon: z.string(),\n\t\tdescription: z.string(),\n\t\tauthor: z.string(),\n\t\tpermissions: z.array(KhalPermission),\n\t\tservices: z.array(KhalServiceSpec).optional(),\n\t\twindows: z.array(KhalWindowSpec).optional(),\n\t\tfrontend: z\n\t\t\t.object({\n\t\t\t\tpackage: z.string(),\n\t\t\t\tentry: z.string().default('default'),\n\t\t\t})\n\t\t\t.optional(),\n\t\tbackend: z\n\t\t\t.object({\n\t\t\t\timage: z.string(),\n\t\t\t\thelmChart: z.string().optional(),\n\t\t\t\tenv: z.record(z.string(), z.string()),\n\t\t\t\tports: z.array(z.number()),\n\t\t\t})\n\t\t\t.optional(),\n\t\t/** Relative path to the pre-built ESM bundle within the package (e.g., \"dist/bundle.mjs\"). */\n\t\tbundlePath: z.string().optional(),\n\t\t/**\n\t\t * When apps is present, the root frontend field is ignored —\n\t\t * each entry has its own frontend.\n\t\t */\n\t\tapps: z.array(KhalAppEntrySchema).optional(),\n\t})\n\t.strict();\n\nexport type KhalAppManifest = z.infer<typeof KhalAppManifestSchema>;\n\n/** Validate a raw object as KhalAppManifest. Throws ZodError with detailed messages on failure. */\nexport function validateManifest(raw: unknown): KhalAppManifest {\n\treturn KhalAppManifestSchema.parse(raw);\n}\n","/** Canonical role hierarchy from least to most privileged. */\nexport const ROLE_HIERARCHY = ['member', 'platform-dev', 'platform-admin', 'platform-owner'] as const;\nexport type Role = (typeof ROLE_HIERARCHY)[number];\n"],"mappings":";AAAA,SAAS,SAAS;AA+KX,IAAM,iBAAiB,EAAE,KAAK;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,CAAC;AAGM,IAAM,kBAAkB,EAAE,OAAO;AAAA,EACvC,MAAM,EAAE,OAAO;AAAA,EACf,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,OAAO,EAAE,OAAO,EAAE,SAAS;AAAA,EAC3B,SAAS,EAAE,KAAK,CAAC,QAAQ,OAAO,QAAQ,CAAC,EAAE,SAAS;AAAA,EACpD,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS;AAAA,EACpC,QAAQ,EACN,OAAO;AAAA,IACP,MAAM,EAAE,KAAK,CAAC,OAAO,QAAQ,SAAS,CAAC;AAAA,IACvC,QAAQ,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,EAAE,OAAO,CAAC,CAAC;AAAA,IACxC,UAAU,EAAE,OAAO,EAAE,SAAS;AAAA,IAC9B,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,EAC9B,CAAC,EACA,SAAS;AACZ,CAAC;AAGM,IAAM,iBAAiB,EAAE,OAAO;AAAA,EACtC,IAAI,EAAE,OAAO;AAAA,EACb,OAAO,EAAE,OAAO,EAAE,SAAS;AAAA,EAC3B,OAAO,EAAE,OAAO,EAAE,QAAQ,GAAG;AAAA,EAC7B,QAAQ,EAAE,OAAO,EAAE,QAAQ,GAAG;AAAA,EAC9B,WAAW,EAAE,QAAQ,EAAE,QAAQ,IAAI;AACpC,CAAC;AAIM,IAAM,qBAAqB,EAAE,OAAO;AAAA;AAAA,EAE1C,IAAI,EAAE,OAAO;AAAA;AAAA,EAEb,MAAM,EAAE,OAAO;AAAA;AAAA,EAEf,UAAU,EACR,OAAO;AAAA,IACP,SAAS,EAAE,OAAO;AAAA,EACnB,CAAC,EACA,SAAS;AACZ,CAAC;AAGM,IAAM,wBAAwB,EACnC,OAAO;AAAA,EACP,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,IAAI,EAAE,OAAO;AAAA,EACb,MAAM,EAAE,OAAO;AAAA,EACf,SAAS,EAAE,OAAO;AAAA,EAClB,MAAM,EAAE,OAAO;AAAA,EACf,aAAa,EAAE,OAAO;AAAA,EACtB,QAAQ,EAAE,OAAO;AAAA,EACjB,aAAa,EAAE,MAAM,cAAc;AAAA,EACnC,UAAU,EAAE,MAAM,eAAe,EAAE,SAAS;AAAA,EAC5C,SAAS,EAAE,MAAM,cAAc,EAAE,SAAS;AAAA,EAC1C,UAAU,EACR,OAAO;AAAA,IACP,SAAS,EAAE,OAAO;AAAA,IAClB,OAAO,EAAE,OAAO,EAAE,QAAQ,SAAS;AAAA,EACpC,CAAC,EACA,SAAS;AAAA,EACX,SAAS,EACP,OAAO;AAAA,IACP,OAAO,EAAE,OAAO;AAAA,IAChB,WAAW,EAAE,OAAO,EAAE,SAAS;AAAA,IAC/B,KAAK,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,OAAO,CAAC;AAAA,IACpC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC;AAAA,EAC1B,CAAC,EACA,SAAS;AAAA;AAAA,EAEX,YAAY,EAAE,OAAO,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,EAKhC,MAAM,EAAE,MAAM,kBAAkB,EAAE,SAAS;AAC5C,CAAC,EACA,OAAO;AAKF,SAAS,iBAAiB,KAA+B;AAC/D,SAAO,sBAAsB,MAAM,GAAG;AACvC;;;AC5QO,IAAM,iBAAiB,CAAC,UAAU,gBAAgB,kBAAkB,gBAAgB;","names":[]}
|