From 9d679e8222f6937ee408df432dc8ba13567dfd75 Mon Sep 17 00:00:00 2001 From: stopachka Date: Fri, 19 Dec 2025 14:53:08 -0800 Subject: [PATCH 01/11] Experiment: what if we made surgical updates --- .../cli/__tests__/mergeSchema.test.ts | 197 ----- .../cli/__tests__/updateSchemaFile.test.ts | 159 ++++ client/packages/cli/src/index.js | 38 +- client/packages/cli/src/util/mergeSchema.js | 364 --------- .../packages/cli/src/util/updateSchemaFile.ts | 773 ++++++++++++++++++ 5 files changed, 961 insertions(+), 570 deletions(-) delete mode 100644 client/packages/cli/__tests__/mergeSchema.test.ts create mode 100644 client/packages/cli/__tests__/updateSchemaFile.test.ts delete mode 100644 client/packages/cli/src/util/mergeSchema.js create mode 100644 client/packages/cli/src/util/updateSchemaFile.ts diff --git a/client/packages/cli/__tests__/mergeSchema.test.ts b/client/packages/cli/__tests__/mergeSchema.test.ts deleted file mode 100644 index 1f4ed8989c..0000000000 --- a/client/packages/cli/__tests__/mergeSchema.test.ts +++ /dev/null @@ -1,197 +0,0 @@ -import { describe, test, expect } from 'vitest'; -import { mergeSchema } from '../src/util/mergeSchema'; - -test('preserves type annotations', () => { - const oldFile = ` -import { i } from '@instantdb/core'; -import { Label } from './types'; - -const _schema = i.schema({ - entities: { - $users: i.entity({ - email: i.string().unique().indexed(), - }), - todos: i.entity({ - title: i.string(), - status: i.string<'todo' | 'in_progress' | 'done'>(), - priority: i.number<1 | 2 | 3>(), - labels: i.json().optional(), - }), - projects: i.entity({ - name: i.string(), - }), - }, - links: { - todoProject: { - forward: { on: 'todos', has: 'one', label: 'project' }, - reverse: { on: 'projects', has: 'many', label: 'todos' }, - }, - projectOwner: { - forward: { on: 'projects', has: 'one', label: 'owner' }, - reverse: { on: '$users', has: 'many', label: 'projects' }, - }, - }, - rooms: { - projectRoom: { - presence: i.entity({ - cursor: i.json<{ x: number; y: number }>(), - }), - }, - }, -}); - -export default _schema; -`; - - const newFile = ` -import { i } from '@instantdb/core'; - -const _schema = i.schema({ - entities: { - $users: i.entity({ - email: i.string().unique().indexed(), - }), - todos: i.entity({ - title: i.string(), - status: i.string(), - priority: i.number(), - labels: i.json().optional(), - }), - projects: i.entity({ - name: i.string(), - }), - }, - links: { - todoProject: { - forward: { on: 'todos', has: 'one', label: 'project' }, - reverse: { on: 'projects', has: 'many', label: 'todos' }, - }, - projectOwner: { - forward: { on: 'projects', has: 'one', label: 'owner' }, - reverse: { on: '$users', has: 'many', label: 'projects' }, - }, - }, - rooms: { - projectRoom: { - presence: i.entity({ - cursor: i.json(), - }), - }, - }, -}); - -export default _schema; -`; - - const result = mergeSchema(oldFile, newFile); - - // Type annotations preserved - expect(result).toContain("i.string<'todo' | 'in_progress' | 'done'>()"); - expect(result).toContain('i.number<1 | 2 | 3>()'); - expect(result).toContain('i.json()'); - expect(result).toContain('i.json<{ x: number; y: number }>()'); - - // Import preserved - expect(result).toContain("import { Label } from './types';"); -}); - -test('preserves different import styles', () => { - const oldFile = ` -import { i } from '@instantdb/core'; -import { Label } from './types'; -import { Tag as MyTag } from './types'; -import Priority from './Priority'; -import * as Models from './models'; -import type { Meta } from './meta'; - -const _schema = i.schema({ - entities: { - a: i.entity({ f: i.json