From a34b9e8df29840417084a9314a10b8c9fbeff241 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 16 Aug 2026 02:21:33 +0000 Subject: [PATCH] docs(deployment): retire the Vercel and ObjectQL-migration pages (#8904) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Maintainer rulings 2026-08-15: the Vercel guide is no longer needed (Docker is the shipping path) and the `@objectql/core` port guide is 作废. Both pages are deleted, dropped from the section meta.json, and their inbound URLs re-pointed. `apps/docs/redirects.mjs` had both deleted pages as redirect DESTINATIONS. Next matches the table once per request, so those two entries are re-pointed at the final destination rather than supplemented — a chained entry would cost the old URL a second round trip. Two new exact entries cover the retired URLs themselves, placed before the wildcard catch-alls per the file's ordering rule. Mechanically required by the deletion, each printed by its own gate: - `.claude/workflows/docs-accuracy-audit.js` regenerated (check:docs-audit-scope) - `scripts/role-word-baseline.json` ratcheted down (check:role-word) `packages/objectql/README.md` linked into the deleted migration guide by relative path. It sits outside lychee's scan surface, so nothing would have caught it. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_013gLCsJ1sDoJZZruDKMsHH3 --- .claude/workflows/docs-accuracy-audit.js | 2 - apps/docs/redirects.mjs | 13 +- content/docs/deployment/meta.json | 2 - .../deployment/migration-from-objectql.mdx | 179 ---------------- content/docs/deployment/self-hosting.mdx | 4 +- content/docs/deployment/vercel.mdx | 195 ------------------ packages/objectql/README.md | 5 +- scripts/role-word-baseline.json | 1 - 8 files changed, 14 insertions(+), 387 deletions(-) delete mode 100644 content/docs/deployment/migration-from-objectql.mdx delete mode 100644 content/docs/deployment/vercel.mdx diff --git a/.claude/workflows/docs-accuracy-audit.js b/.claude/workflows/docs-accuracy-audit.js index d8b47af209..6a85f6c3f0 100644 --- a/.claude/workflows/docs-accuracy-audit.js +++ b/.claude/workflows/docs-accuracy-audit.js @@ -98,7 +98,6 @@ const ALL_HANDWRITTEN = [ "content/docs/deployment/cli.mdx", "content/docs/deployment/environment-variables.mdx", "content/docs/deployment/index.mdx", - "content/docs/deployment/migration-from-objectql.mdx", "content/docs/deployment/production-readiness.mdx", "content/docs/deployment/publish-and-preview.mdx", "content/docs/deployment/self-hosting.mdx", @@ -106,7 +105,6 @@ const ALL_HANDWRITTEN = [ "content/docs/deployment/tenancy-modes.mdx", "content/docs/deployment/troubleshooting.mdx", "content/docs/deployment/validating-metadata.mdx", - "content/docs/deployment/vercel.mdx", "content/docs/getting-started/build-with-claude-code.mdx", "content/docs/getting-started/common-patterns.mdx", "content/docs/getting-started/examples.mdx", diff --git a/apps/docs/redirects.mjs b/apps/docs/redirects.mjs index 2f5ccb8e40..f853bb6d5d 100644 --- a/apps/docs/redirects.mjs +++ b/apps/docs/redirects.mjs @@ -92,14 +92,23 @@ export const docsRedirects = [ ['/docs/concepts/cluster-semantics', '/docs/kernel/cluster'], // deployment ['/docs/guides/cloud-deployment', '/docs/deployment'], - ['/docs/guides/deployment-vercel', '/docs/deployment/vercel'], + ['/docs/guides/deployment-vercel', '/docs/deployment/self-hosting'], ['/docs/guides/production-readiness', '/docs/deployment/production-readiness'], ['/docs/guides/publish-and-preview', '/docs/deployment/publish-and-preview'], ['/docs/guides/environment-variables', '/docs/deployment/environment-variables'], ['/docs/guides/single-project-mode', '/docs/deployment/single-project-mode'], ['/docs/concepts/cloud-artifact-api', '/docs/deployment/cloud-artifact-api'], - ['/docs/guides/objectql-migration', '/docs/deployment/migration-from-objectql'], + ['/docs/guides/objectql-migration', '/docs/deployment'], ['/docs/guides/troubleshooting', '/docs/deployment/troubleshooting'], + // Retired deployment pages (maintainer ruling 2026-08-15). Docker / + // self-hosting is the shipping path, so the Vercel guide lands on + // self-hosting; the `@objectql/core` port guide has no successor page, so it + // lands on the section index. The two `/docs/guides/*` entries ABOVE are + // re-pointed at these same destinations rather than left aimed here: Next + // matches this table once per request, so a chained entry would cost the old + // URLs a second round trip (and every redirect hop is SEO signal lost). + ['/docs/deployment/vercel', '/docs/deployment/self-hosting'], + ['/docs/deployment/migration-from-objectql', '/docs/deployment'], // protocol / releases ['/docs/guides/cheatsheets/protocol-diagram', '/docs/protocol/diagram'], ['/docs/guides/cheatsheets/backward-compatibility', '/docs/protocol/backward-compatibility'], diff --git a/content/docs/deployment/meta.json b/content/docs/deployment/meta.json index 84498c36e3..aef1433b2e 100644 --- a/content/docs/deployment/meta.json +++ b/content/docs/deployment/meta.json @@ -6,13 +6,11 @@ "validating-metadata", "self-hosting", "backup-restore", - "vercel", "production-readiness", "publish-and-preview", "environment-variables", "single-project-mode", "tenancy-modes", - "migration-from-objectql", "troubleshooting" ] } diff --git a/content/docs/deployment/migration-from-objectql.mdx b/content/docs/deployment/migration-from-objectql.mdx deleted file mode 100644 index 980708f473..0000000000 --- a/content/docs/deployment/migration-from-objectql.mdx +++ /dev/null @@ -1,179 +0,0 @@ ---- -title: Migrating from @objectql/core -description: Step-by-step guide for migrating from @objectql/core to @objectstack/objectql ---- - -# Migrating from `@objectql/core` to `@objectstack/objectql` - -The core functionality previously provided by `@objectql/core` — the introspection types, the utility functions, and the kernel factory — was upstreamed into `@objectstack/objectql` in **v3.0.4** and has shipped in every release since (the current release line is **v16.x**). This guide walks you through migrating your project so that `@objectql/core` can be removed. - -## Why Migrate? - -| | `@objectql/core` (deprecated) | `@objectstack/objectql` (recommended) | -| :--- | :--- | :--- | -| **Engine** | Bridge class extending upstream `ObjectQL` | Canonical `ObjectQL` engine | -| **Kernel Factory** | `createObjectQLKernel()` | `createObjectQLKernel()` (identical API) | -| **Introspection** | `toTitleCase`, `convertIntrospectedSchemaToObjects` | Same functions, same signatures | -| **Registry** | Re-exports from upstream | Direct exports | -| **MetadataRegistry** | `@objectql/types` `MetadataRegistry` class | `MetadataFacade` (async `IMetadataService`) | -| **Maintenance** | Planned deprecation | Actively maintained | - -## Step 1 — Update Dependencies - -```diff - // package.json - { - "dependencies": { -- "@objectql/core": "^4.x", -- "@objectql/types": "^4.x", -+ "@objectstack/objectql": "^16.1.0" - } - } -``` - -Then re-install: - -```bash -pnpm install -``` - -## Step 2 — Update Imports - -### Engine, Repository & Context - -```diff -- import { ObjectQL, ObjectRepository, ScopedContext } from '@objectql/core'; -+ import { ObjectQL, ObjectRepository, ScopedContext } from '@objectstack/objectql'; -``` - -```diff -- import type { HookHandler, HookEntry, OperationContext, EngineMiddleware } from '@objectql/core'; -+ import type { HookHandler, HookEntry, OperationContext, EngineMiddleware } from '@objectstack/objectql'; -``` - -### Schema Registry - -```diff -- import { SchemaRegistry } from '@objectql/core'; -+ import { SchemaRegistry } from '@objectstack/objectql'; -``` - -### Kernel Factory - -```diff -- import { createObjectQLKernel } from '@objectql/core'; -- import type { ObjectQLKernelOptions } from '@objectql/core'; -+ import { createObjectQLKernel } from '@objectstack/objectql'; -+ import type { ObjectQLKernelOptions } from '@objectstack/objectql'; -``` - -### Utility Functions - -```diff -- import { toTitleCase, convertIntrospectedSchemaToObjects } from '@objectql/core'; -+ import { toTitleCase, convertIntrospectedSchemaToObjects } from '@objectstack/objectql'; -``` - -### Introspection Types - -```diff -- import type { IntrospectedSchema, IntrospectedTable } from '@objectql/types'; -+ import type { IntrospectedSchema, IntrospectedTable } from '@objectstack/objectql'; -``` - -```diff -- import type { IntrospectedColumn, IntrospectedForeignKey } from '@objectql/types'; -+ import type { IntrospectedColumn, IntrospectedForeignKey } from '@objectstack/objectql'; -``` - -## Step 3 — API Differences - -### `createObjectQLKernel()` - -The function signature is identical. The only change is the return type uses the upstream `ObjectKernel`: - -```typescript -import { createObjectQLKernel } from '@objectstack/objectql'; - -const kernel = await createObjectQLKernel({ - plugins: [myDriverPlugin], -}); -await kernel.bootstrap(); -``` - -### `convertIntrospectedSchemaToObjects()` - -Same signature and behavior: - -```typescript -import { convertIntrospectedSchemaToObjects } from '@objectstack/objectql'; - -const objects = convertIntrospectedSchemaToObjects(schema, { - excludeTables: ['migrations'], - includeTables: undefined, // optional: whitelist - skipSystemColumns: true, // default: skips id, created_at, updated_at -}); -``` - -### MetadataRegistry → MetadataFacade - -If you were using `MetadataRegistry` from `@objectql/types`, the upstream equivalent is `MetadataFacade`. There are two differences: `MetadataFacade` is constructed over a `SchemaRegistry` instance, and its methods are **async** (returns `Promise`): - -```diff -- import { MetadataRegistry } from '@objectql/types'; -- const registry = new MetadataRegistry(); -- registry.register('object', myObject); -- const obj = registry.get('object', 'account'); -+ import { MetadataFacade, SchemaRegistry } from '@objectstack/objectql'; -+ const facade = new MetadataFacade(new SchemaRegistry()); -+ await facade.register('object', 'account', myObject); -+ const obj = await facade.get('object', 'account'); -``` - -### ObjectQLPlugin - -Both packages export an `ObjectQLPlugin`, but they serve different roles: - -| | `@objectql/core` `ObjectQLPlugin` | `@objectstack/objectql` `ObjectQLPlugin` | -| :--- | :--- | :--- | -| Interface | `RuntimePlugin` (from `@objectql/types`) | `Plugin` (from `@objectstack/core`) | -| Role | Orchestrator composing sub-plugins (validator, formula, query) | Kernel plugin registering ObjectQL as core services | -| Methods | `install()`, `onStart()`, `init()`, `start()` | `init()`, `start()` | - -If you were using the `@objectql/core` `ObjectQLPlugin` to compose sub-plugins (`ValidatorPlugin`, `FormulaPlugin`, `QueryPlugin`), those downstream plugins are **not** part of this migration — they remain in the `@objectql` ecosystem. - -## Step 4 — Type Mapping Reference - -The `convertIntrospectedSchemaToObjects()` utility maps database column types as follows: - -| Database Type | ObjectStack FieldType | -| :--- | :--- | -| `varchar`, `char` | `text` | -| `text` | `textarea` | -| `integer`, `int`, `bigint`, `smallint` | `number` | -| `float`, `double`, `decimal`, `numeric`, `real` | `number` | -| `boolean`, `bool` | `boolean` | -| `timestamp`, `datetime` | `datetime` | -| `date` | `date` | -| `time` | `time` | -| `json`, `jsonb` | `json` | -| Foreign key column | `lookup` (with `reference` set to target table) | -| _anything else_ | `text` (fallback) | - -## Step 5 — Remove `@objectql/core` - -Once all imports are updated and tests pass: - -```bash -pnpm remove @objectql/core @objectql/types -``` - -## Checklist - -- [ ] Replace `@objectql/core` dependency with `@objectstack/objectql` in `package.json` -- [ ] Update all `import` statements (engine, registry, kernel factory, utilities, types) -- [ ] Replace `MetadataRegistry` usage with `MetadataFacade` (add `await`) -- [ ] Verify `ObjectQLPlugin` usage matches the upstream interface -- [ ] Run `pnpm build` and fix any remaining type errors -- [ ] Run `pnpm test` to verify behavior -- [ ] Remove `@objectql/core` and `@objectql/types` from dependencies diff --git a/content/docs/deployment/self-hosting.mdx b/content/docs/deployment/self-hosting.mdx index 0a9898d88c..39a2684da7 100644 --- a/content/docs/deployment/self-hosting.mdx +++ b/content/docs/deployment/self-hosting.mdx @@ -7,8 +7,7 @@ description: Run a compiled ObjectStack app on your own infrastructure — bare This guide takes the artifact produced by `os build` / `os compile` and runs it on infrastructure **you** operate: a Linux host, a Docker container, or a -compose stack with Postgres. It complements the platform-specific -[Vercel guide](/docs/deployment/vercel) and assumes you have read +compose stack with Postgres. It assumes you have read [Deployment Modes](/docs/deployment). The deployment model is deliberately simple: @@ -421,5 +420,4 @@ Disable with `OS_MCP_SERVER_ENABLED=false`. See - [Deployment Modes](/docs/deployment) — the map of local / standalone / Cloud - [`os start` reference](/docs/deployment/cli#os-start) — every flag and env var - [Environment Variables](/docs/deployment/environment-variables) — the full catalog -- [Deploy to Vercel](/docs/deployment/vercel) — the serverless alternative - [Troubleshooting & FAQ](/docs/deployment/troubleshooting) diff --git a/content/docs/deployment/vercel.mdx b/content/docs/deployment/vercel.mdx deleted file mode 100644 index ed2e051ed7..0000000000 --- a/content/docs/deployment/vercel.mdx +++ /dev/null @@ -1,195 +0,0 @@ ---- -title: Deploy to Vercel -description: Deploy ObjectStack applications to Vercel with the Hono server adapter. ---- - -# Deploy to Vercel - -ObjectStack deploys to Vercel in **server mode** — serverless functions running the **Hono** adapter (`@objectstack/hono`). The Console SPA can also be deployed on its own as a static Vite build that points at a separate ObjectStack server (via `VITE_SERVER_URL`) — but that build comes from the Console source repo ([objectui](https://github.com/objectstack-ai/objectui)), not from the prebuilt `@objectstack/console` package. - - -**Removed in 11.** The in-browser MSW mode (`@objectstack/plugin-msw`) and the Next.js adapter (`@objectstack/nextjs`) are no longer published — use the Hono server path below. - - ---- - -## Server Mode (Serverless Functions) - -In Server mode, ObjectStack runs inside Vercel Serverless Functions. API requests are handled by real backend logic with a real database. - -### Architecture - -``` -┌─── Vercel ────────────────────────────────────────────────────┐ -│ │ -│ Static Assets (React SPA) │ -│ ┌───────────────────────────────────┐ │ -│ │ /index.html, /assets/* │ │ -│ └───────────────────────────────────┘ │ -│ │ -│ Serverless Functions │ -│ ┌───────────────────────────────────┐ │ -│ │ /api/index.ts │ │ -│ │ → ObjectKernel │ │ -│ │ → ObjectQL │ │ -│ │ → PostgreSQL / MongoDB / ... │──── External DB │ -│ └───────────────────────────────────┘ │ -│ │ -└───────────────────────────────────────────────────────────────┘ -``` - -### Hono serverless function (`@objectstack/hono`) - -This is a valid self-contained pattern when you want to ship a Vite SPA *and* its API from a single Vercel project: the SPA is served as static assets, and a Hono-based serverless function handles `/api/*` requests. - - -The framework-vendored Console (`@objectstack/console`) does **not** use this topology. It is a **prebuilt, dist-only** package — no source and no build step, just static assets — that an ObjectStack server mounts at `/_console` (`os serve --ui`, on by default). Its bundle is baked same-origin, and `VITE_SERVER_URL` is a build-time Vite flag, so aiming a Console at a *different* origin means building it yourself from the Console source repo ([objectui](https://github.com/objectstack-ai/objectui)). For the server itself, prefer the CLI (`os serve`) over a hand-rolled Hono function. - - -**1. Create the kernel singleton** (`api/_kernel.ts` — prefixed with `_` to prevent Vercel from creating a route): - -```typescript -// api/_kernel.ts -import { ObjectKernel, DriverPlugin, AppPlugin } from '@objectstack/runtime'; -import { ObjectQLPlugin } from '@objectstack/objectql'; -import { InMemoryDriver } from '@objectstack/driver-memory'; -import { createHonoApp } from '@objectstack/hono'; -import { Hono } from 'hono'; -import appConfig from '../objectstack.config'; - -let _kernel: ObjectKernel | null = null; -let _app: Hono | null = null; - -async function ensureKernel(): Promise { - if (_kernel) return _kernel; - _kernel = new ObjectKernel(); - await _kernel.use(new ObjectQLPlugin()); - await _kernel.use(new DriverPlugin(new InMemoryDriver(), 'memory')); - await _kernel.use(new AppPlugin(appConfig)); - await _kernel.bootstrap(); - return _kernel; -} - -export async function ensureApp(): Promise { - if (_app) return _app; - const kernel = await ensureKernel(); - _app = createHonoApp({ kernel, prefix: '/api/v1' }); - return _app; -} -``` - - -`InMemoryDriver` keeps this snippet self-contained, but on serverless **all data -is lost on every cold start** — fine for a demo, wrong for anything real. Before -going past a proof of concept, swap the driver for a real database (see -[Database Drivers](/docs/data-modeling/drivers)). A hand-built kernel does **not** -resolve `OS_DATABASE_URL` on its own — that precedence lives in the CLI and in -`createStandaloneStack()` — so read the connection string yourself, e.g. -`new SqlDriver({ client: 'pg', connection: process.env.OS_DATABASE_URL })`. - - -**2. Create the API entrypoint** (`api/index.ts`): - -```typescript -// api/index.ts -import { Hono } from 'hono'; -import { handle } from 'hono/vercel'; -import { ensureApp } from './_kernel'; - -const app = new Hono(); - -app.all('*', async (c) => { - const inner = await ensureApp(); - return inner.fetch(c.req.raw); -}); - -export default handle(app); -``` - -**3. `vercel.json`:** - -```json -{ - "$schema": "https://openapi.vercel.sh/vercel.json", - "framework": "vite", - "buildCommand": "vite build", - "outputDirectory": "dist", - "build": { - "env": { - "VITE_USE_MOCK_SERVER": "false", - "VITE_SERVER_URL": "" - } - }, - "rewrites": [ - { "source": "/api/(.*)", "destination": "/api" }, - { "source": "/((?!api/).*)", "destination": "/index.html" } - ] -} -``` - - -Setting `VITE_SERVER_URL` to empty string tells the client SDK to use same-origin API calls. The first rewrite routes all `/api/*` sub-paths to the `api/index.ts` serverless function. The second rewrite excludes `/api/` paths so all other paths serve the SPA. - - ---- - -## Environment Variables - -Configure these in Vercel Project Settings → Environment Variables: - -### Console / SPA build - -| Variable | Description | -| :--- | :--- | -| `VITE_USE_MOCK_SERVER` | Leave `false` — the SPA talks to a real backend at `VITE_SERVER_URL`. (The `true` in-browser mock mode was removed in 11.) A **build-time** flag baked into the SPA bundle. | -| `VITE_SERVER_URL` | Backend API URL (empty for same-origin) | - -### Cloud control plane - -The Cloud control-plane distribution lives outside this framework repo. If you -deploy a Cloud host on Vercel, remember that Vercel functions have an -**ephemeral, read-only filesystem** — local SQLite and local-FS storage will not -persist between invocations. Use a durable database and S3-compatible object -storage for artifacts. - -| Variable | Required | Description | -| :--- | :--- | :--- | -| `OS_AUTH_SECRET` | yes | ≥ 32 chars (`AUTH_SECRET` is accepted as a deprecated alias) | -| `OS_CONTROL_DATABASE_URL` | yes | `libsql://…` (Turso) — control plane DB | -| `OS_CONTROL_DATABASE_AUTH_TOKEN` | yes | Turso token (or `TURSO_AUTH_TOKEN`) | -| `OS_STORAGE_ADAPTER` | yes | `s3` (must, on Vercel) | -| `OS_S3_BUCKET` | yes (s3) | Bucket name | -| `OS_S3_REGION` | yes (s3) | `us-east-1`, or `auto` for Cloudflare R2 | -| `OS_S3_ENDPOINT` | optional | For R2 / MinIO / B2 / non-AWS | -| `OS_S3_ACCESS_KEY_ID` | optional | Falls back to AWS SDK credential chain | -| `OS_S3_SECRET_ACCESS_KEY` | optional | Falls back to AWS SDK credential chain | -| `OS_S3_FORCE_PATH_STYLE` | optional | `1` for MinIO / self-hosted | - -> The Cloud control plane's storage backend (S3, Cloudflare R2, MinIO, etc.) is -> configured and documented in that separate distribution, not in this framework -> repo. See [Publish, Versioning & Preview](/docs/deployment/publish-and-preview) -> for the package publish/install workflow the control plane exposes to the CLI. - - -**Never commit secrets.** Use Vercel's environment variable UI or the Vercel CLI (`vercel env add`) to configure tokens and S3 credentials. - - ---- - -## Deployment Checklist - -- [ ] `api/index.ts` Hono entrypoint exists with `handle(app)` export -- [ ] `api/_kernel.ts` boots the kernel with the correct driver -- [ ] `vercel.json` sets `VITE_USE_MOCK_SERVER=false` and `VITE_SERVER_URL=` (empty) -- [ ] Rewrite rule routes `/api/*` to `/api` and excludes `/api/` from SPA rewrite -- [ ] The production connection string is set in Vercel environment variables **and** read explicitly by the driver you construct in `api/_kernel.ts` (`OS_DATABASE_URL` is resolved by the CLI / `createStandaloneStack()`, not by a hand-built kernel) -- [ ] CORS is configured if frontend and API are on different origins - ---- - -## Related - -- [Plugin System](/docs/plugins) — the Hono server adapter -- [Client SDK](/docs/api/client-sdk) — Frontend data fetching -- [Driver Configuration](/docs/data-modeling/drivers) — Database setup -- [Architecture](/docs/concepts/architecture) — Kernel and runtime overview diff --git a/packages/objectql/README.md b/packages/objectql/README.md index b177ea2334..5b5ebb3b3b 100644 --- a/packages/objectql/README.md +++ b/packages/objectql/README.md @@ -96,9 +96,8 @@ computeFQN('base', 'user'); // => 'user' (reserved namespace) ## Migrating from `@objectql/core` -If you are migrating from the downstream `@objectql/core` package, see the -[Migration Guide](../../content/docs/deployment/migration-from-objectql.mdx) for -step-by-step instructions. +If you are migrating from the downstream `@objectql/core` package, the change is +an import rewrite — the exports below keep the same names and signatures. **Quick summary:** diff --git a/scripts/role-word-baseline.json b/scripts/role-word-baseline.json index b61b7f14d6..119885f46c 100644 --- a/scripts/role-word-baseline.json +++ b/scripts/role-word-baseline.json @@ -7,7 +7,6 @@ "content/docs/concepts/architecture.mdx": 4, "content/docs/data-modeling/seed-data.mdx": 2, "content/docs/deployment/cli.mdx": 1, - "content/docs/deployment/migration-from-objectql.mdx": 2, "content/docs/getting-started/common-patterns.mdx": 1, "content/docs/getting-started/index.mdx": 1, "content/docs/getting-started/quick-start.mdx": 1,