diff --git a/.github/workflows/onPushToMain.yml b/.github/workflows/onPushToMain.yml index eedc76f..427bb83 100644 --- a/.github/workflows/onPushToMain.yml +++ b/.github/workflows/onPushToMain.yml @@ -1,5 +1,9 @@ name: release on push to main +env: + # Increase heap to keep Nitro/Vite SSR builds (editor) from OOMing while treeshaking. + NODE_OPTIONS: --max-old-space-size=4096 + on: push: branches: [main] diff --git a/.github/workflows/onRelease.yml b/.github/workflows/onRelease.yml index 67374f5..6c3cb35 100644 --- a/.github/workflows/onRelease.yml +++ b/.github/workflows/onRelease.yml @@ -1,5 +1,9 @@ name: publish on release +env: + # Increase heap to keep Nitro/Vite SSR builds (editor) from OOMing while treeshaking. + NODE_OPTIONS: --max-old-space-size=4096 + on: release: types: [released] diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 84705ca..3860028 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,5 +1,9 @@ name: tests +env: + # Increase heap to keep Nitro/Vite SSR builds (editor) from OOMing while treeshaking. + NODE_OPTIONS: --max-old-space-size=4096 + on: push: branches-ignore: [main] @@ -23,4 +27,5 @@ jobs: - name: Check formatting run: pnpm exec prettier --check . - run: pnpm run build - - run: pnpm run test + - name: Run tests + run: pnpm run test diff --git a/.husky/pre-commit b/.husky/pre-commit index 0c1f9be..6a457f2 100644 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -8,10 +8,7 @@ fi git diff --cached --name-only -z --diff-filter=ACMR \ | xargs -0 pnpm prettier --write --ignore-unknown -if git diff --cached --name-only --diff-filter=ACMR -- '*.js' '*.cjs' '*.mjs' '*.ts' '*.tsx' | grep -q .; then - git diff --cached --name-only -z --diff-filter=ACMR -- '*.js' '*.cjs' '*.mjs' '*.ts' '*.tsx' \ - | xargs -0 pnpm eslint --fix -fi +pnpm lint:fix git diff --cached --name-only -z --diff-filter=ACMR \ | xargs -0 git add -- diff --git a/.prettierignore b/.prettierignore index a4965ac..863be0d 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,3 +1,6 @@ pnpm-lock.yaml **/pnpm-lock.yaml **/*.json +.output +editor-dist +routeTree.gen.ts diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..00b5278 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,11 @@ +{ + "files.watcherExclude": { + "**/routeTree.gen.ts": true + }, + "search.exclude": { + "**/routeTree.gen.ts": true + }, + "files.readonlyInclude": { + "**/routeTree.gen.ts": true + } +} diff --git a/README.md b/README.md index 93dbe8b..316aaa4 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ Monorepo for the PowerSync CLI and related tooling. Built with [pnpm](https://pnpm.io) workspaces and [OCLIF](https://oclif.io). +- Architecture, scripts, and troubleshooting tips live in [packages/editor/README.md](./packages/editor/README.md). + ## Requirements - **Node**: LTS v24+ (see [.nvmrc](./.nvmrc); use `nvm use` to switch) @@ -11,19 +13,23 @@ Monorepo for the PowerSync CLI and related tooling. Built with [pnpm](https://pn The workspace is split into the main CLI, shared **packages**, and optional **plugins**: -| Package | Path | Description | -| ---------------------------------------------------- | -------------------- | ---------------------------------------------------------------------------------- | -| [**@powersync/cli**](./cli) | `cli/` | Main CLI — manage instances, config, sync config, cloud and self-hosted | -| [**@powersync/cli-core**](./packages/cli-core) | `packages/cli-core/` | Core types and base commands shared by the CLI and plugins | -| [**@powersync/cli-schemas**](./packages/schemas) | `packages/schemas/` | Shared config schemas (cli.yaml, service.yaml, etc.) | -| [**@powersync/cli-plugin-docker**](./plugins/docker) | `plugins/docker/` | Docker plugin — self-hosted PowerSync with Compose (configure, reset, start, stop) | +| Package | Path | Description | +| -------------------------------------------------------------- | ---------------------- | --------------------------------------------------------------------------------------------------- | +| [**@powersync/cli**](./cli) | `cli/` | Main CLI — manage instances, config, sync config, cloud and self-hosted | +| [**PowerSync CLI Config Studio**](./packages/editor) | `packages/editor/` | Monaco-based UI that edits `service.yaml`/`sync-config.yaml` and ships with the config-edit plugin | +| [**@powersync/cli-core**](./packages/cli-core) | `packages/cli-core/` | Core types and base commands shared by the CLI and plugins | +| [**@powersync/cli-schemas**](./packages/schemas) | `packages/schemas/` | Shared config schemas (cli.yaml, service.yaml, etc.) | +| [**@powersync/cli-plugin-config-edit**](./plugins/config-edit) | `plugins/config-edit/` | CLI plugin that sets `POWERSYNC_PROJECT_CONTEXT` and serves the Config Studio with the Nitro server | +| [**@powersync/cli-plugin-docker**](./plugins/docker) | `plugins/docker/` | Docker plugin — self-hosted PowerSync with Compose (configure, reset, start, stop) | ``` ├── cli/ # @powersync/cli — main CLI (commands, cloud/self-hosted, templates) ├── packages/ │ ├── cli-core/ # @powersync/cli-core — base commands & YAML utils (used by CLI + plugins) +│ ├── editor/ # CLI Config Studio — Monaco web app that edits service.yaml/sync-config.yaml │ └── schemas/ # @powersync/cli-schemas — config validation (LinkConfig, CLIConfig) ├── plugins/ +│ ├── config-edit/ # @powersync/cli-plugin-config-edit — serves the Config Studio preview │ └── docker/ # @powersync/cli-plugin-docker — docker configure, reset, start, stop ├── examples/ # Sample projects initialized with the CLI (see examples/README.md) │ ├── cloud/ @@ -33,17 +39,19 @@ The workspace is split into the main CLI, shared **packages**, and optional **pl └── usage-docker.md # Docker plugin (configure, reset, start, stop, templates) ``` -- **cli** depends on **cli-core**, **cli-schemas**, and **@powersync/cli-plugin-docker**. It loads the docker plugin and re-exports base command types from cli-core. -- **plugin-docker** (in **plugins/docker**) depends on **cli-core** and **cli-schemas**. No dependency on the CLI package. +- **cli** depends on **cli-core**, **cli-schemas**, **@powersync/cli-plugin-config-edit**, and **@powersync/cli-plugin-docker**. It loads the bundled plugins and re-exports base command types from cli-core. - **cli-core** depends on **schemas**. It provides `SelfHostedInstanceCommand`, YAML helpers (`!env`), and shared types for plugins. +- **packages/editor** builds the Config Studio assets consumed by the config-edit plugin and embeds schemas from `@powersync/cli-schemas`. +- **@powersync/cli-plugin-config-edit** depends on **cli-core** and serves the built editor from `plugins/config-edit/editor-dist` using the Nitro server. +- **@powersync/cli-plugin-docker** depends on **cli-core** and **cli-schemas**. No dependency on the CLI package. Workspace roots are listed in [pnpm-workspace.yaml](./pnpm-workspace.yaml): `cli`, `packages/*`, `plugins/*`. ## OCLIF plugins -We rely on standard [OCLIF plugin loading](https://oclif.io/docs/plugins/) so plugins can register new commands or hook into command execution. The main CLI ships with a Docker plugin under [plugins/docker](./plugins/docker), and any other OCLIF-compatible plugin can be installed the same way. +We rely on standard [OCLIF plugin loading](https://oclif.io/docs/plugins/) so plugins can register new commands or hook into command execution. The main CLI ships with Docker and Config Studio plugins under [plugins/docker](./plugins/docker) and [plugins/config-edit](./plugins/config-edit), and any other OCLIF-compatible plugin can be installed the same way. -For PowerSync-specific plugins, the optional [@powersync/cli-core](./packages/cli-core) package exposes base command helpers and shared types. The Docker plugin consumes these helpers and adds Docker-focused commands as a reference implementation. +For PowerSync-specific plugins, the optional [@powersync/cli-core](./packages/cli-core) package exposes base command helpers and shared types. The bundled plugins consume these helpers and serve as reference implementations. Users can manage their own installed plugins dynamically at runtime. Run `powersync plugins --help` for install, uninstall, and inspection options. @@ -72,6 +80,21 @@ powersync docker start See [plugins/docker](./plugins/docker/README.md) and [docs/usage-docker.md](./docs/usage-docker.md) for details. +### Configuration editor + +Open the Monaco-based Config Studio that edits `service.yaml`/`sync-config.yaml` directly inside your project: + +```bash +pnpm build # ensures packages/editor copies its dist to plugins/config-edit/editor-dist +powersync edit config --directory ./powersync --port 3000 +``` + +- The command above is provided by **@powersync/cli-plugin-config-edit** and automatically sets `POWERSYNC_PROJECT_CONTEXT` (based on the linked project) before serving the built editor through the Nitro server. +- Features include YAML schema validation, Monaco-powered completions, unsaved-change tracking, reset/save controls, and an error panel for schema violations. +- For local UI work (without running the CLI command) export `POWERSYNC_PROJECT_CONTEXT` JSON that points at your project (the CLI sets this for you) and start the dev server: `POWERSYNC_PROJECT_CONTEXT='{"linkedProject":{"projectDirectory":"/path/to/project","linked":{"type":"self-hosted"}}}' pnpm --filter editor dev`. +- Prefer the default host (127.0.0.1); only pass `--host 0.0.0.0` when you explicitly intend to expose the editor on your network. +- Architecture, scripts, and troubleshooting tips live in [packages/editor/README.md](./packages/editor/README.md). + ## Examples The [**examples/**](./examples) folder contains basic projects initialized with the CLI. See [examples/README.md](./examples/README.md) for the full list and links to each example's README. diff --git a/cli/README.md b/cli/README.md index 9d39253..46cf4cd 100644 --- a/cli/README.md +++ b/cli/README.md @@ -264,6 +264,7 @@ See [docs/usage.md](../docs/usage.md) for full usage and resolution order (flags - [`powersync docker reset`](#powersync-docker-reset) - [`powersync docker start`](#powersync-docker-start) - [`powersync docker stop`](#powersync-docker-stop) +- [`powersync edit config`](#powersync-edit-config) - [`powersync fetch config`](#powersync-fetch-config) - [`powersync fetch instances`](#powersync-fetch-instances) - [`powersync fetch status`](#powersync-fetch-status) @@ -632,6 +633,46 @@ EXAMPLES $ powersync docker stop --project-name=powersync_myapp --remove ``` +## `powersync edit config` + +Open the PowerSync configuration editor (Nitro server). + +``` +USAGE + $ powersync edit config [--api-url | --instance-id | --org-id | --project-id ] + [--directory ] [--host ] [--port ] + +FLAGS + --host= [default: 127.0.0.1] Host to bind the editor preview server. Pass 0.0.0.0 to expose on all interfaces. + --port= [default: 3000] Port for the editor preview server. + +SELF_HOSTED_PROJECT FLAGS + --api-url= [Self-hosted] PowerSync API URL. When set, context is treated as self-hosted (exclusive with + --instance-id). Resolved: flag → cli.yaml → API_URL. + +PROJECT FLAGS + --directory= [default: powersync] Directory containing PowerSync config. Defaults to "powersync". This is + required if multiple powersync config files are present in subdirectories of the current working + directory. + +CLOUD_PROJECT FLAGS + --instance-id= [Cloud] PowerSync Cloud instance ID (BSON ObjectID). When set, context is treated as cloud + (exclusive with --api-url). Resolved: flag → cli.yaml → INSTANCE_ID. + --org-id= [Cloud] Organization ID (optional). Defaults to the token’s single org when only one is + available; pass explicitly if the token has multiple orgs. Resolved: flag → cli.yaml → ORG_ID. + --project-id= [Cloud] Project ID. Resolved: flag → cli.yaml → PROJECT_ID. + +DESCRIPTION + Open the PowerSync configuration editor (Nitro server). + + Loads the linked project context and runs the editor Nitro server to edit config files. + +EXAMPLES + $ powersync edit config + + $ powersync edit config --directory ./powersync +``` + ## `powersync fetch config` [Cloud only] Print linked Cloud instance config (YAML or JSON). @@ -748,13 +789,12 @@ Generate client schema file from instance schema and sync config. ``` USAGE - $ powersync generate schema --output dart|dotNet|flutterFlow|js|jsLegacy|kotlin|swift|ts --output-path - [--api-url | --instance-id | --org-id | --project-id ] [--directory ] + $ powersync generate schema --output dart|dotNet|js|jsLegacy|kotlin|swift|ts --output-path [--api-url + | --instance-id | --org-id | --project-id ] [--directory ] FLAGS - --output=