From 8f0a32c35bc8c1db32e55f519b7595618c0a9684 Mon Sep 17 00:00:00 2001 From: dolanske Date: Sun, 14 Jun 2026 13:28:49 +0300 Subject: [PATCH 01/10] chore: move files around, add `createOrbitApp` --- apps/web/src/main.ts | 7 ++-- packages/core/package.json | 1 + packages/core/src/components/OrbitApp.vue | 8 +---- packages/core/src/index.ts | 5 ++- packages/core/src/lib/setup.ts | 17 ++++++++++ packages/platform/src/composables.ts | 14 ++++++++ packages/platform/src/constants.ts | 4 +++ packages/platform/src/index.ts | 7 +++- .../index.ts => platform/src/types.ts} | 32 ------------------- packages/platform/src/web.ts | 2 +- pnpm-lock.yaml | 3 ++ 11 files changed, 51 insertions(+), 49 deletions(-) create mode 100644 packages/core/src/lib/setup.ts create mode 100644 packages/platform/src/composables.ts create mode 100644 packages/platform/src/constants.ts rename packages/{core/src/platform/index.ts => platform/src/types.ts} (54%) diff --git a/apps/web/src/main.ts b/apps/web/src/main.ts index 3271afb..cbf6a5f 100644 --- a/apps/web/src/main.ts +++ b/apps/web/src/main.ts @@ -1,9 +1,6 @@ -import { createApp } from "vue" -import { providePlatform, router } from "core" +import { createOrbitApp } from "core" import { createWebPlatform } from "platform" import App from "./App.vue" -const app = createApp(App) -app.use(router) -providePlatform(app, createWebPlatform()) +const app = createOrbitApp(App, createWebPlatform()) app.mount("#app") diff --git a/packages/core/package.json b/packages/core/package.json index f48a5ef..420bf6d 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -12,6 +12,7 @@ "dependencies": { "@dolanske/vui": "catalog:", "pinia": "catalog:", + "platform": "workspace:*", "vue": "^3.5.34", "vue-router": "catalog:" }, diff --git a/packages/core/src/components/OrbitApp.vue b/packages/core/src/components/OrbitApp.vue index f76bf82..ec37c11 100644 --- a/packages/core/src/components/OrbitApp.vue +++ b/packages/core/src/components/OrbitApp.vue @@ -1,15 +1,9 @@ diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 314ef29..c7e0299 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -1,5 +1,4 @@ import OrbitApp from "./components/OrbitApp.vue" -import { router } from "./router/index.ts" +import { createOrbitApp } from "./lib/setup.ts" -export { OrbitApp, router } -export * from "./platform/index.ts" +export { OrbitApp, createOrbitApp } diff --git a/packages/core/src/lib/setup.ts b/packages/core/src/lib/setup.ts new file mode 100644 index 0000000..c21ebf2 --- /dev/null +++ b/packages/core/src/lib/setup.ts @@ -0,0 +1,17 @@ +import { createApp, type Component } from "vue" +import { router } from "../router" +import { type Platform, PLATFORM_KEY } from "platform" + +/** + * Creates an Orbit app. + * + * @param root Root component + * @param platform Platform adapter + * @returns Vue application instance + */ +export function createOrbitApp(root: Component, platform: Platform) { + const app = createApp(root) + app.use(router) + app.provide(PLATFORM_KEY, platform) + return app +} diff --git a/packages/platform/src/composables.ts b/packages/platform/src/composables.ts new file mode 100644 index 0000000..bf7d751 --- /dev/null +++ b/packages/platform/src/composables.ts @@ -0,0 +1,14 @@ +import { inject } from "vue" +import type { Platform } from "./types" +import { PLATFORM_KEY } from "./constants" + +/** + * Access the injected platform adapter from a component or composable. + * */ +export function usePlatform(): Platform { + const platform = inject(PLATFORM_KEY) + if (!platform) { + throw new Error("No platform adapter provided. Call providePlatform(app, ...) at app boot.") + } + return platform +} diff --git a/packages/platform/src/constants.ts b/packages/platform/src/constants.ts new file mode 100644 index 0000000..482f4eb --- /dev/null +++ b/packages/platform/src/constants.ts @@ -0,0 +1,4 @@ +import type { InjectionKey } from "vue" +import type { Platform } from "./types" + +export const PLATFORM_KEY: InjectionKey = Symbol("orbit-platform") diff --git a/packages/platform/src/index.ts b/packages/platform/src/index.ts index e73af34..d7d33e4 100644 --- a/packages/platform/src/index.ts +++ b/packages/platform/src/index.ts @@ -1 +1,6 @@ -export { createWebPlatform } from "./web.ts" +import { createWebPlatform } from "./web" +import type { Platform } from "./types" +import { PLATFORM_KEY } from "./constants" +import { usePlatform } from "./composables" + +export { createWebPlatform, type Platform, PLATFORM_KEY, usePlatform } diff --git a/packages/core/src/platform/index.ts b/packages/platform/src/types.ts similarity index 54% rename from packages/core/src/platform/index.ts rename to packages/platform/src/types.ts index a2269b2..4a25988 100644 --- a/packages/core/src/platform/index.ts +++ b/packages/platform/src/types.ts @@ -1,16 +1,3 @@ -import type { App, InjectionKey } from "vue" -import { inject } from "vue" - -// The platform contract. `packages/core` owns this and consumes it through -// the injected `Platform`; it never imports `@tauri-apps/api` or touches raw -// `navigator.*` directly. Each app entrypoint (web, desktop, mobile) supplies -// a concrete adapter from `packages/platform` and injects it once at boot. -// -// The seam is shaped by capability, not by platform: core asks a port to do a -// thing, it never asks "am I running in Tauri". A port an environment cannot -// provide is `null`, and core degrades explicitly rather than scattering -// platform checks. - export interface NotificationOptions { title: string body?: string @@ -18,9 +5,7 @@ export interface NotificationOptions { } export interface NotificationPort { - /** Request permission to display notifications. Resolves to whether granted. */ requestPermission: () => Promise - /** Display a notification. No-op if permission has not been granted. */ notify: (options: NotificationOptions) => Promise } @@ -69,7 +54,6 @@ export interface DnsPort { } export interface Platform { - /** Identifies which adapter is active. */ readonly target: "web" | "desktop" | "mobile" readonly notifications: NotificationPort readonly tray: TrayPort | null @@ -78,19 +62,3 @@ export interface Platform { readonly fileTransfer: FileTransferPort readonly dns: DnsPort | null } - -export const PLATFORM_KEY: InjectionKey = Symbol("orbit-platform") - -/** Wire a concrete platform adapter into the app at boot. */ -export function providePlatform(app: App, platform: Platform): void { - app.provide(PLATFORM_KEY, platform) -} - -/** Access the injected platform adapter from a component or composable. */ -export function usePlatform(): Platform { - const platform = inject(PLATFORM_KEY) - if (!platform) { - throw new Error("No platform adapter provided. Call providePlatform(app, ...) at app boot.") - } - return platform -} diff --git a/packages/platform/src/web.ts b/packages/platform/src/web.ts index e653ce7..0e5fe53 100644 --- a/packages/platform/src/web.ts +++ b/packages/platform/src/web.ts @@ -1,4 +1,4 @@ -import type { AudioDevice, AudioDevicePort, FileTransferPort, NotificationPort, Platform } from "core" +import type { AudioDevice, AudioDevicePort, FileTransferPort, NotificationPort, Platform } from "./types" function createNotificationPort(): NotificationPort { return { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 54d6b83..5e674f7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -79,6 +79,9 @@ importers: pinia: specifier: 'catalog:' version: 3.0.4(typescript@6.0.3)(vue@3.5.35(typescript@6.0.3)) + platform: + specifier: workspace:* + version: link:../platform vue: specifier: ^3.5.34 version: 3.5.35(typescript@6.0.3) From 11cb8a28cce7d71ec86d5ae6992f47b7b3c2c311 Mon Sep 17 00:00:00 2001 From: dolanske Date: Sun, 14 Jun 2026 14:31:04 +0300 Subject: [PATCH 02/10] chore: add & fix tests --- apps/web/src/main.ts | 4 +++- packages/core/test/fixtures/TestApp.vue | 10 ++++++++++ packages/core/test/setup.test.ts | 25 +++++++++++++++++++++++++ packages/platform/src/composables.ts | 2 +- packages/platform/test/web.test.ts | 2 +- 5 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 packages/core/test/fixtures/TestApp.vue create mode 100644 packages/core/test/setup.test.ts diff --git a/apps/web/src/main.ts b/apps/web/src/main.ts index cbf6a5f..11d6c12 100644 --- a/apps/web/src/main.ts +++ b/apps/web/src/main.ts @@ -2,5 +2,7 @@ import { createOrbitApp } from "core" import { createWebPlatform } from "platform" import App from "./App.vue" -const app = createOrbitApp(App, createWebPlatform()) +const platform = createWebPlatform() +const app = createOrbitApp(App, platform) + app.mount("#app") diff --git a/packages/core/test/fixtures/TestApp.vue b/packages/core/test/fixtures/TestApp.vue new file mode 100644 index 0000000..f2ed10e --- /dev/null +++ b/packages/core/test/fixtures/TestApp.vue @@ -0,0 +1,10 @@ + + + diff --git a/packages/core/test/setup.test.ts b/packages/core/test/setup.test.ts new file mode 100644 index 0000000..b5dd52e --- /dev/null +++ b/packages/core/test/setup.test.ts @@ -0,0 +1,25 @@ +import { describe, expect, it } from "vite-plus/test" +import { createOrbitApp } from "../src/index.ts" +import { createWebPlatform } from "platform/src/web.ts" +import { PLATFORM_KEY } from "platform" +import { mount } from "@vue/test-utils" +import TestApp from "./fixtures/TestApp.vue" + +describe("Setup Orbit application", () => { + it("should create an app instance with a web platform adapter", () => { + const platform = createWebPlatform() + const app = createOrbitApp(TestApp, platform) + expect(app._context.provides[PLATFORM_KEY]).toBe(platform) + }) + + it("should should be available within vue components when using usePlatform", () => { + const selector = mount(TestApp, { + global: { + provide: { + [PLATFORM_KEY]: createWebPlatform(), + }, + }, + }) + expect(selector.get("[data-test-target]")).not.toBeNull() + }) +}) diff --git a/packages/platform/src/composables.ts b/packages/platform/src/composables.ts index bf7d751..b6ae6e2 100644 --- a/packages/platform/src/composables.ts +++ b/packages/platform/src/composables.ts @@ -8,7 +8,7 @@ import { PLATFORM_KEY } from "./constants" export function usePlatform(): Platform { const platform = inject(PLATFORM_KEY) if (!platform) { - throw new Error("No platform adapter provided. Call providePlatform(app, ...) at app boot.") + throw new Error("No platform adapter provided. Make sure to provide a platform adapter during Orbit app initialization.") } return platform } diff --git a/packages/platform/test/web.test.ts b/packages/platform/test/web.test.ts index e77d0ea..3582bf7 100644 --- a/packages/platform/test/web.test.ts +++ b/packages/platform/test/web.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it, vi } from "vite-plus/test" -import { createWebPlatform } from "../src/index.ts" +import { createWebPlatform } from "../src/web.ts" describe("web platform adapter", () => { it("reports the web target", () => { From fccf4ca985c2ea46638254a7e9c1dfd7c30634f8 Mon Sep 17 00:00:00 2001 From: dolanske Date: Sun, 14 Jun 2026 14:34:51 +0300 Subject: [PATCH 03/10] Remove unused workspace dep --- packages/core/test/fixtures/TestApp.vue | 1 - packages/platform/package.json | 1 - 2 files changed, 2 deletions(-) diff --git a/packages/core/test/fixtures/TestApp.vue b/packages/core/test/fixtures/TestApp.vue index f2ed10e..230da68 100644 --- a/packages/core/test/fixtures/TestApp.vue +++ b/packages/core/test/fixtures/TestApp.vue @@ -1,6 +1,5 @@ diff --git a/packages/platform/package.json b/packages/platform/package.json index e9f26dc..0ec967a 100644 --- a/packages/platform/package.json +++ b/packages/platform/package.json @@ -10,7 +10,6 @@ "test": "vp test" }, "dependencies": { - "core": "workspace:*", "vue": "^3.5.34" }, "devDependencies": { From 6dfeaa234e6869c2ebcd9a214040d225c238735d Mon Sep 17 00:00:00 2001 From: dolanske Date: Sun, 14 Jun 2026 17:01:19 +0300 Subject: [PATCH 04/10] Remove core as a dep of platform --- pnpm-lock.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5e674f7..62f9bf9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -119,9 +119,6 @@ importers: packages/platform: dependencies: - core: - specifier: workspace:* - version: link:../core vue: specifier: ^3.5.34 version: 3.5.35(typescript@6.0.3) From 4eac173de3473c1e4fb9f29ed521561a1b336541 Mon Sep 17 00:00:00 2001 From: dolanske Date: Sun, 14 Jun 2026 21:49:11 +0300 Subject: [PATCH 05/10] chore: make setup test more rigid --- packages/core/test/setup.test.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/core/test/setup.test.ts b/packages/core/test/setup.test.ts index b5dd52e..a329613 100644 --- a/packages/core/test/setup.test.ts +++ b/packages/core/test/setup.test.ts @@ -20,6 +20,8 @@ describe("Setup Orbit application", () => { }, }, }) - expect(selector.get("[data-test-target]")).not.toBeNull() + + const target = selector.get("[data-test-target]") + expect(target.attributes("data-test-target")).toBe("web") }) }) From f9ee157b877ec7586575b35de6f00b209efed87a Mon Sep 17 00:00:00 2001 From: dolanske Date: Fri, 19 Jun 2026 10:42:18 +0300 Subject: [PATCH 06/10] Rename `core` to `app`, add placeholder `depot` package --- apps/web/package.json | 2 +- apps/web/src/App.vue | 2 +- apps/web/src/main.ts | 2 +- packages/{core => app}/.gitignore | 0 .../{core => app}/.vscode/extensions.json | 0 packages/{core => app}/README.md | 8 +- packages/{core => app}/package.json | 2 +- .../{core => app}/src/components/OrbitApp.vue | 0 packages/{core => app}/src/env.d.ts | 0 packages/{core => app}/src/index.ts | 0 packages/{core => app}/src/lib/setup.ts | 0 packages/{core => app}/src/router/index.ts | 0 .../src/router/views/RouteMain.vue | 0 packages/{core => app}/src/style/index.css | 0 packages/{core => app}/test/example.test.ts | 0 .../{core => app}/test/fixtures/TestApp.vue | 0 packages/{core => app}/test/setup.test.ts | 0 packages/{core => app}/tsconfig.app.json | 0 packages/{core => app}/tsconfig.json | 0 packages/{core => app}/tsconfig.node.json | 0 packages/{core => app}/vite.config.ts | 0 packages/depot/.gitignore | 4 + packages/depot/README.md | 3 + packages/depot/package.json | 40 + packages/depot/src/api.ts | 19 + packages/depot/src/index.ts | 3 + packages/depot/tsconfig.json | 20 + packages/depot/vite.config.ts | 17 + pnpm-lock.yaml | 1165 ++++++++++++----- 29 files changed, 978 insertions(+), 309 deletions(-) rename packages/{core => app}/.gitignore (100%) rename packages/{core => app}/.vscode/extensions.json (100%) rename packages/{core => app}/README.md (69%) rename packages/{core => app}/package.json (97%) rename packages/{core => app}/src/components/OrbitApp.vue (100%) rename packages/{core => app}/src/env.d.ts (100%) rename packages/{core => app}/src/index.ts (100%) rename packages/{core => app}/src/lib/setup.ts (100%) rename packages/{core => app}/src/router/index.ts (100%) rename packages/{core => app}/src/router/views/RouteMain.vue (100%) rename packages/{core => app}/src/style/index.css (100%) rename packages/{core => app}/test/example.test.ts (100%) rename packages/{core => app}/test/fixtures/TestApp.vue (100%) rename packages/{core => app}/test/setup.test.ts (100%) rename packages/{core => app}/tsconfig.app.json (100%) rename packages/{core => app}/tsconfig.json (100%) rename packages/{core => app}/tsconfig.node.json (100%) rename packages/{core => app}/vite.config.ts (100%) create mode 100644 packages/depot/.gitignore create mode 100644 packages/depot/README.md create mode 100644 packages/depot/package.json create mode 100644 packages/depot/src/api.ts create mode 100644 packages/depot/src/index.ts create mode 100644 packages/depot/tsconfig.json create mode 100644 packages/depot/vite.config.ts diff --git a/apps/web/package.json b/apps/web/package.json index 6521a73..8ead0f1 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -9,7 +9,7 @@ "preview": "vp preview" }, "dependencies": { - "core": "workspace:*", + "app": "workspace:*", "platform": "workspace:*", "vue": "^3.5.34" }, diff --git a/apps/web/src/App.vue b/apps/web/src/App.vue index 9de6887..c3a8911 100644 --- a/apps/web/src/App.vue +++ b/apps/web/src/App.vue @@ -1,5 +1,5 @@