create-convex-monorepo 0.2.0 → 0.3.0

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.
@@ -0,0 +1,326 @@
1
+ import { mkdtemp, readdir, readFile, rm, lstat } from 'node:fs/promises';
2
+ import { tmpdir } from 'node:os';
3
+ import { join } from 'node:path';
4
+ import { generateProject, normalizeOptions } from '../generator/index.js';
5
+ import { readText } from './project.js';
6
+ import { readBackendEnvironment } from './env.js';
7
+ import { deploymentUrl, linkEnvironment, publicVariable, } from '../../assets/setup/convex-setup.mjs';
8
+ const json = (value) => `${JSON.stringify(value, null, 2)}\n`;
9
+ const normalizeNewlines = (text) => text?.replace(/\r\n/g, '\n');
10
+ const equivalent = (left, right) => normalizeNewlines(left) === normalizeNewlines(right);
11
+ const retainNewlines = (text, original) => original?.includes('\r\n') ? text.replace(/\r?\n/g, '\r\n') : text;
12
+ async function render(workspace, apps, example, auth) {
13
+ const temporary = await mkdtemp(join(tmpdir(), 'ccm-add-'));
14
+ try {
15
+ const root = await generateProject({
16
+ name: workspace.config.name,
17
+ apps,
18
+ example,
19
+ auth,
20
+ install: false,
21
+ git: false,
22
+ initConvex: false,
23
+ }, { cwd: temporary });
24
+ const files = new Map();
25
+ async function visit(dir) {
26
+ for (const entry of await readdir(join(root, dir), {
27
+ withFileTypes: true,
28
+ })) {
29
+ const path = dir ? `${dir}/${entry.name}` : entry.name;
30
+ if (entry.isDirectory())
31
+ await visit(path);
32
+ else
33
+ files.set(path, await readFile(join(root, path), 'utf8'));
34
+ }
35
+ }
36
+ await visit('');
37
+ return files;
38
+ }
39
+ finally {
40
+ await rm(temporary, { recursive: true, force: true });
41
+ }
42
+ }
43
+ function initialPlan(workspace) {
44
+ return {
45
+ root: workspace.root,
46
+ changes: [],
47
+ notes: [],
48
+ guards: [{ path: 'convex-monorepo.json', contents: workspace.configText }],
49
+ };
50
+ }
51
+ async function guardedRead(workspace, plan, path) {
52
+ const contents = await readText(workspace.root, path);
53
+ plan.guards.push({ path, contents });
54
+ return contents;
55
+ }
56
+ async function verifyWorkspace(workspace, plan) {
57
+ const yaml = await guardedRead(workspace, plan, 'pnpm-workspace.yaml');
58
+ // Support the generated workspace layout, including comments and unrelated
59
+ // pnpm settings. Refuse aliases, inline lists, exclusions and custom globs.
60
+ const section = yaml?.match(/^packages:\s*(?:#.*)?\n((?:[ \t]+[^\n]*\n|\s*\n)*)/m)?.[1];
61
+ const patterns = section
62
+ ?.split('\n')
63
+ .map((line) => line.replace(/\s+#.*$/, '').trim())
64
+ .filter((line) => line && !line.startsWith('#'))
65
+ .map((line) => /^-\s+['"]?(apps\/\*|packages\/\*)['"]?$/.exec(line)?.[1]);
66
+ if ((yaml?.match(/^packages:/gm)?.length ?? 0) !== 1 ||
67
+ !patterns ||
68
+ patterns.length !== 2 ||
69
+ !patterns.includes('apps/*') ||
70
+ !patterns.includes('packages/*'))
71
+ throw new Error('Unsupported pnpm-workspace.yaml packages configuration. Expected apps/* and packages/* without exclusions or other globs.');
72
+ for (const name of ['backend', 'typescript-config', 'eslint-config']) {
73
+ const path = `packages/${name}/package.json`;
74
+ const contents = await guardedRead(workspace, plan, path);
75
+ const manifest = contents === null
76
+ ? null
77
+ : JSON.parse(contents);
78
+ if (manifest?.name !== `@${workspace.config.name}/${name}`)
79
+ throw new Error(`Incompatible shared package ${path}. Expected @${workspace.config.name}/${name}.`);
80
+ if (name === 'backend') {
81
+ const expected = {
82
+ './api': {
83
+ types: './convex/_generated/api.d.ts',
84
+ default: './convex/_generated/api.js',
85
+ },
86
+ './dataModel': { types: './convex/_generated/dataModel.d.ts' },
87
+ };
88
+ const actual = manifest.exports;
89
+ for (const [key, value] of Object.entries(expected)) {
90
+ if (Object.entries(value).some(([condition, target]) => object(actual?.[key], path)[condition] !== target))
91
+ throw new Error(`Incompatible backend export ${key} in ${path}. Restore the generated backend export before adding an app.`);
92
+ }
93
+ }
94
+ }
95
+ }
96
+ async function verifyMessages(workspace, plan, baseline) {
97
+ for (const name of ['schema.ts', 'messages.ts', 'access.ts']) {
98
+ const path = `packages/backend/convex/${name}`;
99
+ const contents = await guardedRead(workspace, plan, path);
100
+ if (contents === null || !equivalent(contents, baseline.get(path)))
101
+ throw new Error(`Incompatible messages backend: ${path} is missing or customized. Restore the generated messages contract, or add an app with --example none.`);
102
+ }
103
+ }
104
+ function object(value, path) {
105
+ if (value === undefined)
106
+ return {};
107
+ if (value === null || typeof value !== 'object' || Array.isArray(value))
108
+ throw new Error(`Expected an object in ${path}.`);
109
+ return value;
110
+ }
111
+ function mergePackage(currentText, beforeText, afterText, path) {
112
+ const current = object(JSON.parse(currentText), path);
113
+ const before = object(JSON.parse(beforeText), path);
114
+ const after = object(JSON.parse(afterText), path);
115
+ const result = { ...current };
116
+ const groups = [
117
+ 'dependencies',
118
+ 'devDependencies',
119
+ 'peerDependencies',
120
+ 'optionalDependencies',
121
+ 'scripts',
122
+ ];
123
+ for (const key of new Set([...Object.keys(before), ...Object.keys(after)])) {
124
+ if (JSON.stringify(before[key]) === JSON.stringify(after[key]))
125
+ continue;
126
+ if (!groups.includes(key))
127
+ throw new Error(`Unsupported package change ${path}: ${key}.`);
128
+ const prev = object(before[key], path);
129
+ const next = object(after[key], path);
130
+ const existing = object(current[key], path);
131
+ const merged = { ...existing };
132
+ for (const entry of new Set([...Object.keys(prev), ...Object.keys(next)])) {
133
+ if (prev[entry] === next[entry])
134
+ continue;
135
+ if (next[entry] === undefined)
136
+ throw new Error(`Unsupported package removal ${path}: ${entry}.`);
137
+ if (existing[entry] !== prev[entry] && existing[entry] !== next[entry])
138
+ throw new Error(`Conflict in ${path}: ${key}.${entry} is customized.`);
139
+ if (key !== 'scripts') {
140
+ for (const other of groups.filter((group) => group !== 'scripts' && group !== key)) {
141
+ const value = object(current[other], path)[entry];
142
+ if (value !== undefined && value !== next[entry])
143
+ throw new Error(`Conflicting dependency ${entry} in ${path}.`);
144
+ }
145
+ }
146
+ Object.defineProperty(merged, entry, {
147
+ value: next[entry],
148
+ writable: true,
149
+ enumerable: true,
150
+ configurable: true,
151
+ });
152
+ }
153
+ result[key] = merged;
154
+ }
155
+ return json(result);
156
+ }
157
+ async function metadata(workspace, plan, patch) {
158
+ plan.changes.push({
159
+ path: 'convex-monorepo.json',
160
+ before: workspace.configText,
161
+ after: json({ ...workspace.rawConfig, ...patch }),
162
+ });
163
+ }
164
+ export async function planAddApp(workspace, options) {
165
+ const example = options.example ?? workspace.config.example;
166
+ const normalized = normalizeOptions({
167
+ name: workspace.config.name,
168
+ apps: [{ name: options.name, framework: options.framework }],
169
+ example,
170
+ auth: workspace.config.auth,
171
+ });
172
+ const app = normalized.apps[0];
173
+ if (workspace.config.apps.some((existing) => existing.name === app.name))
174
+ throw new Error(`Application ${app.name} already exists.`);
175
+ const plan = initialPlan(workspace);
176
+ await verifyWorkspace(workspace, plan);
177
+ const dir = `apps/${app.name}`;
178
+ plan.absentPaths = [dir];
179
+ // readText checks every parent for symlinks; lstat additionally detects an
180
+ // existing empty directory, which must never become owned by this command.
181
+ await readText(workspace.root, `${dir}/package.json`);
182
+ try {
183
+ await lstat(join(workspace.root, dir));
184
+ throw new Error(`Application path ${dir} already exists.`);
185
+ }
186
+ catch (error) {
187
+ if (error.code !== 'ENOENT')
188
+ throw error;
189
+ }
190
+ const generated = await render(workspace, [...workspace.config.apps, app], example, workspace.config.auth);
191
+ const newPort = (app.framework === 'expo' ? 8081 : 3000) + workspace.config.apps.length;
192
+ for (const existing of workspace.config.apps) {
193
+ const packagePath = `apps/${existing.name}/package.json`;
194
+ const packageText = await guardedRead(workspace, plan, packagePath);
195
+ if (packageText === null)
196
+ throw new Error(`Missing application manifest: ${packagePath}.`);
197
+ const scripts = object(object(JSON.parse(packageText), packagePath).scripts, packagePath);
198
+ const dev = typeof scripts.dev === 'string' ? scripts.dev : '';
199
+ const ports = [...dev.matchAll(/--port(?:=|\s+)(\d+)\b/g)].map((match) => Number(match[1]));
200
+ if (existing.framework === 'vite' ||
201
+ existing.framework === 'tanstack-start') {
202
+ const configPath = `apps/${existing.name}/vite.config.ts`;
203
+ const config = await guardedRead(workspace, plan, configPath);
204
+ ports.push(...[...(config ?? '').matchAll(/\bport\s*:\s*(\d+)\b/g)].map((match) => Number(match[1])));
205
+ }
206
+ if (ports.includes(newPort))
207
+ throw new Error(`Development port ${newPort} is already configured in apps/${existing.name}. Choose a different port there before adding this app.`);
208
+ }
209
+ if (example === 'messages')
210
+ await verifyMessages(workspace, plan, generated);
211
+ if (workspace.config.auth === 'clerk') {
212
+ const path = 'packages/backend/convex/auth.config.ts';
213
+ if (!equivalent(await guardedRead(workspace, plan, path), generated.get(path)))
214
+ throw new Error(`Incompatible Clerk configuration in ${path}.`);
215
+ }
216
+ for (const [path, after] of generated) {
217
+ if (path.startsWith(`${dir}/`))
218
+ plan.changes.push({ path, before: null, after });
219
+ }
220
+ const path = 'package.json';
221
+ const before = await guardedRead(workspace, plan, path);
222
+ if (before === null)
223
+ throw new Error('Missing root package.json.');
224
+ const manifest = object(JSON.parse(before), path);
225
+ const scripts = { ...object(manifest.scripts, path) };
226
+ const script = `dev:${app.name}`;
227
+ if (Object.hasOwn(scripts, script))
228
+ throw new Error(`Root script ${script} already exists.`);
229
+ scripts[script] = `pnpm --filter @${workspace.config.name}/${app.name} dev`;
230
+ const previousDev = `turbo run dev --ui=stream --concurrency=${workspace.config.apps.length + 2}`;
231
+ if (scripts.dev !== previousDev)
232
+ throw new Error('Root dev script is customized. Restore the generated Turbo dev script before adding an app.');
233
+ scripts.dev = `turbo run dev --ui=stream --concurrency=${workspace.config.apps.length + 3}`;
234
+ plan.changes.push({ path, before, after: json({ ...manifest, scripts }) });
235
+ const rawApps = workspace.rawConfig.apps;
236
+ await metadata(workspace, plan, {
237
+ apps: [
238
+ ...rawApps,
239
+ { ...app, ...(options.example === undefined ? {} : { example }) },
240
+ ],
241
+ });
242
+ const backend = await readBackendEnvironment(workspace);
243
+ plan.guards.push(...backend.guards);
244
+ if (backend.values.CONVEX_URL) {
245
+ const url = deploymentUrl(backend.values.CONVEX_URL);
246
+ plan.changes.push({
247
+ path: `${dir}/.env.local`,
248
+ before: null,
249
+ after: linkEnvironment('', publicVariable(app.framework), url),
250
+ mode: 0o600,
251
+ });
252
+ plan.notes.push(`Will link the public Convex URL into ${dir}/.env.local. Run pnpm install before starting the app.`);
253
+ if (app.framework === 'expo' &&
254
+ ['localhost', '127.0.0.1', '[::1]'].includes(new URL(url).hostname))
255
+ plan.notes.push('Physical phones need a reachable Convex URL. localhost points to the phone itself.');
256
+ }
257
+ else {
258
+ plan.notes.push(`Run pnpm install, then pnpm convex:setup or pnpm convex:link to configure ${dir}/.env.local.`);
259
+ }
260
+ if (workspace.config.auth === 'clerk')
261
+ plan.notes.push(`Add the Clerk keys listed in apps/${app.name}/.env.clerk.example.`);
262
+ return plan;
263
+ }
264
+ export async function planAddAuth(workspace, provider) {
265
+ if (provider !== 'clerk')
266
+ throw new Error(`Unsupported authentication provider: ${provider}.`);
267
+ const plan = initialPlan(workspace);
268
+ if (workspace.config.auth === 'clerk') {
269
+ plan.notes.push('Clerk is already configured.');
270
+ return plan;
271
+ }
272
+ await verifyWorkspace(workspace, plan);
273
+ const first = workspace.config.apps[0];
274
+ const backendBefore = await render(workspace, [first], workspace.config.example, 'none');
275
+ const backendAfter = await render(workspace, [first], workspace.config.example, 'clerk');
276
+ if (workspace.config.example === 'messages')
277
+ await verifyMessages(workspace, plan, backendBefore);
278
+ async function patchFiles(before, after, select) {
279
+ for (const [path, target] of after) {
280
+ if (!select(path) || before.get(path) === target)
281
+ continue;
282
+ const baseline = before.get(path) ?? null;
283
+ const current = await readText(workspace.root, path);
284
+ if (equivalent(current, target)) {
285
+ plan.guards.push({ path, contents: current });
286
+ continue;
287
+ }
288
+ let next = target;
289
+ if (path.endsWith('/package.json') &&
290
+ current !== null &&
291
+ baseline !== null)
292
+ next = mergePackage(current, baseline, target, path);
293
+ else if (!equivalent(current, baseline))
294
+ throw new Error(`Conflict in ${path}: file is customized or already exists. No files were changed.`);
295
+ plan.changes.push({
296
+ path,
297
+ before: current,
298
+ after: retainNewlines(next, current),
299
+ });
300
+ }
301
+ }
302
+ await patchFiles(backendBefore, backendAfter, (path) => [
303
+ 'packages/backend/convex/access.ts',
304
+ 'packages/backend/convex/auth.config.ts',
305
+ 'packages/backend/.env.clerk.example',
306
+ ].includes(path));
307
+ for (const app of workspace.config.apps) {
308
+ const example = app.example ?? workspace.config.example;
309
+ const baseline = await render(workspace, [app], example, 'none');
310
+ const target = await render(workspace, [app], example, 'clerk');
311
+ await patchFiles(baseline, target, (path) => path.startsWith(`apps/${app.name}/`));
312
+ }
313
+ const readme = backendAfter.get('README.md');
314
+ const start = readme.indexOf('## Clerk setup');
315
+ const end = readme.indexOf('\n## Development', start);
316
+ const setup = `${readme.slice(start, end).trim()}\n\nRun pnpm install after applying this change. Existing public messages have no owner and will not appear in authenticated accounts. This command does not migrate stored data.\n`;
317
+ const existing = await readText(workspace.root, 'CLERK_SETUP.md');
318
+ if (existing !== null && existing !== setup)
319
+ throw new Error('CLERK_SETUP.md already exists with different content. No files were changed.');
320
+ if (existing === null)
321
+ plan.changes.push({ path: 'CLERK_SETUP.md', before: null, after: setup });
322
+ await metadata(workspace, plan, { auth: 'clerk' });
323
+ plan.notes.push('Run pnpm install and follow CLERK_SETUP.md to configure Clerk keys and the Convex issuer.');
324
+ return plan;
325
+ }
326
+ //# sourceMappingURL=add.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add.js","sourceRoot":"","sources":["../../src/workspace/add.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ export interface FileChange {
2
+ path: string;
3
+ before: string | null;
4
+ after: string;
5
+ mode?: number;
6
+ }
7
+ export interface ChangePlan {
8
+ root: string;
9
+ changes: FileChange[];
10
+ notes: string[];
11
+ guards?: Array<{
12
+ path: string;
13
+ contents: string | null;
14
+ }>;
15
+ absentPaths?: string[];
16
+ }
17
+ export interface ApplySettings {
18
+ dryRun?: boolean;
19
+ signal?: AbortSignal;
20
+ onProgress?: (path: string) => void | Promise<void>;
21
+ }
22
+ /** A failed edit restores only files which still contain this operation's output. */
23
+ export declare function applyPlan(plan: ChangePlan, settings?: ApplySettings): Promise<void>;
@@ -0,0 +1,157 @@
1
+ import { lstat, mkdir, open, rename, rmdir, unlink } from 'node:fs/promises';
2
+ import { dirname, relative, resolve } from 'node:path';
3
+ import { randomUUID } from 'node:crypto';
4
+ import { isMissing, readText, safePath } from './project.js';
5
+ /** A failed edit restores only files which still contain this operation's output. */
6
+ export async function applyPlan(plan, settings = {}) {
7
+ const root = resolve(plan.root);
8
+ const unique = new Set();
9
+ for (const change of plan.changes) {
10
+ const target = await safePath(root, change.path);
11
+ if (unique.has(target))
12
+ throw new Error(`Duplicate planned file: ${change.path}`);
13
+ if (change.path === '.convex-monorepo.lock')
14
+ throw new Error('The workspace lock cannot be edited.');
15
+ unique.add(target);
16
+ }
17
+ async function preflight() {
18
+ settings.signal?.throwIfAborted();
19
+ for (const path of plan.absentPaths ?? []) {
20
+ const target = await safePath(root, path);
21
+ try {
22
+ await lstat(target);
23
+ throw new Error(`Path appeared while planning: ${path}. No changes were applied.`);
24
+ }
25
+ catch (error) {
26
+ if (!isMissing(error))
27
+ throw error;
28
+ }
29
+ }
30
+ for (const guard of plan.guards ?? []) {
31
+ if ((await readText(root, guard.path)) !== guard.contents)
32
+ throw new Error(`Workspace changed while planning: ${guard.path}. Run the command again.`);
33
+ }
34
+ for (const change of plan.changes) {
35
+ if ((await readText(root, change.path)) !== change.before)
36
+ throw new Error(`File conflict: ${change.path}. No changes were applied.`);
37
+ }
38
+ }
39
+ if (settings.dryRun || !plan.changes.length) {
40
+ await preflight();
41
+ return;
42
+ }
43
+ const lockPath = await safePath(root, '.convex-monorepo.lock');
44
+ let lock;
45
+ try {
46
+ lock = await open(lockPath, 'wx', 0o600);
47
+ }
48
+ catch (error) {
49
+ if (error instanceof Error && 'code' in error && error.code === 'EEXIST')
50
+ throw new Error('Another workspace operation is running. If it crashed, remove .convex-monorepo.lock only after confirming no command is active.');
51
+ throw error;
52
+ }
53
+ const createdDirectories = [];
54
+ const committed = [];
55
+ async function parents(path) {
56
+ const parent = dirname(path);
57
+ if (parent === root)
58
+ return;
59
+ await safePath(root, relative(root, parent).split('\\').join('/'));
60
+ try {
61
+ const stat = await lstat(parent);
62
+ if (!stat.isDirectory())
63
+ throw new Error(`Expected directory: ${parent}`);
64
+ }
65
+ catch (error) {
66
+ if (!isMissing(error))
67
+ throw error;
68
+ await parents(parent);
69
+ await mkdir(parent);
70
+ createdDirectories.push(parent);
71
+ }
72
+ }
73
+ async function write(path, contents, mode, before) {
74
+ const target = await safePath(root, path);
75
+ await parents(target);
76
+ if ((await readText(root, path)) !== before)
77
+ throw new Error(`File changed during operation: ${path}.`);
78
+ if (before === null) {
79
+ const handle = await open(target, 'wx', mode);
80
+ try {
81
+ await handle.writeFile(contents, 'utf8');
82
+ }
83
+ catch (error) {
84
+ await handle.close();
85
+ await unlink(target);
86
+ throw error;
87
+ }
88
+ finally {
89
+ await handle.close();
90
+ }
91
+ }
92
+ else {
93
+ const temporary = `${target}.ccm-${randomUUID()}`;
94
+ const handle = await open(temporary, 'wx', mode);
95
+ try {
96
+ await handle.writeFile(contents, 'utf8');
97
+ await handle.close();
98
+ await safePath(root, path);
99
+ if ((await readText(root, path)) !== before)
100
+ throw new Error(`File changed during operation: ${path}.`);
101
+ await rename(temporary, target);
102
+ }
103
+ finally {
104
+ await handle.close();
105
+ await unlink(temporary).catch((error) => {
106
+ if (!isMissing(error))
107
+ throw error;
108
+ });
109
+ }
110
+ }
111
+ }
112
+ try {
113
+ await lock.writeFile(`${JSON.stringify({ pid: process.pid, startedAt: new Date().toISOString() })}\n`);
114
+ await preflight();
115
+ for (const change of plan.changes) {
116
+ settings.signal?.throwIfAborted();
117
+ if (change.before === change.after)
118
+ continue;
119
+ const target = await safePath(root, change.path);
120
+ const mode = change.before === null
121
+ ? (change.mode ?? 0o644)
122
+ : (await lstat(target)).mode & 0o777;
123
+ await write(change.path, change.after, mode, change.before);
124
+ committed.push({ change, mode });
125
+ await settings.onProgress?.(change.path);
126
+ }
127
+ settings.signal?.throwIfAborted();
128
+ }
129
+ catch (error) {
130
+ const preserved = [];
131
+ for (const { change, mode } of committed.reverse()) {
132
+ try {
133
+ if ((await readText(root, change.path)) !== change.after) {
134
+ preserved.push(change.path);
135
+ continue;
136
+ }
137
+ if (change.before === null)
138
+ await unlink(await safePath(root, change.path));
139
+ else
140
+ await write(change.path, change.before, mode, change.after);
141
+ }
142
+ catch {
143
+ preserved.push(change.path);
144
+ }
145
+ }
146
+ for (const dir of createdDirectories.reverse())
147
+ await rmdir(dir).catch(() => undefined);
148
+ if (preserved.length)
149
+ throw new Error(`Operation failed. Concurrently changed files were preserved: ${preserved.join(', ')}. Inspect them before retrying.`, { cause: error });
150
+ throw error;
151
+ }
152
+ finally {
153
+ await lock.close();
154
+ await unlink(lockPath);
155
+ }
156
+ }
157
+ //# sourceMappingURL=changes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"changes.js","sourceRoot":"","sources":["../../src/workspace/changes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { type Workspace } from './project.js';
2
+ export interface DoctorIssue {
3
+ code: string;
4
+ severity: 'error' | 'warning';
5
+ message: string;
6
+ fix: string;
7
+ }
8
+ export interface DoctorResult {
9
+ issues: DoctorIssue[];
10
+ /** Successfully completed checks, including explicit limits of static checks. */
11
+ checks: string[];
12
+ }
13
+ /** Inspect files and installed types without running project scripts or writing probes. */
14
+ export declare function doctor(workspace: Workspace, options?: {
15
+ signal?: AbortSignal;
16
+ }): Promise<DoctorResult>;