canopycms 0.0.1 → 0.0.3

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.
Files changed (47) hide show
  1. package/dist/auth/plugin.d.ts +8 -0
  2. package/dist/auth/plugin.d.ts.map +1 -1
  3. package/dist/build-mode.d.ts +15 -5
  4. package/dist/build-mode.d.ts.map +1 -1
  5. package/dist/build-mode.js +18 -8
  6. package/dist/build-mode.js.map +1 -1
  7. package/dist/cli/init.d.ts +2 -2
  8. package/dist/cli/init.d.ts.map +1 -1
  9. package/dist/cli/init.js +37 -36
  10. package/dist/cli/init.js.map +1 -1
  11. package/dist/cli/template-files/Dockerfile.cms.template +19 -0
  12. package/dist/cli/template-files/ai-config.ts.template +21 -0
  13. package/dist/cli/template-files/ai-route.ts.template +10 -0
  14. package/dist/cli/template-files/canopy.ts.template +24 -0
  15. package/dist/cli/template-files/canopycms.config.ts.template +11 -0
  16. package/dist/cli/template-files/deploy-cms.yml.template +27 -0
  17. package/dist/cli/template-files/edit-page.tsx.template +32 -0
  18. package/dist/cli/template-files/route.ts.template +12 -0
  19. package/dist/cli/template-files/schemas.ts.template +16 -0
  20. package/dist/cli/templates.d.ts +5 -1
  21. package/dist/cli/templates.d.ts.map +1 -1
  22. package/dist/cli/templates.js +9 -2
  23. package/dist/cli/templates.js.map +1 -1
  24. package/dist/config/schemas/config.d.ts +4 -0
  25. package/dist/config/schemas/config.d.ts.map +1 -1
  26. package/dist/config/schemas/config.js +2 -0
  27. package/dist/config/schemas/config.js.map +1 -1
  28. package/dist/config/types.d.ts +5 -0
  29. package/dist/config/types.d.ts.map +1 -1
  30. package/dist/content-reader.js +2 -2
  31. package/dist/content-reader.js.map +1 -1
  32. package/dist/context.js +5 -5
  33. package/dist/context.js.map +1 -1
  34. package/dist/editor/editor-utils.d.ts.map +1 -1
  35. package/dist/editor/editor-utils.js +3 -1
  36. package/dist/editor/editor-utils.js.map +1 -1
  37. package/dist/operating-mode/client-unsafe-strategy.d.ts.map +1 -1
  38. package/dist/operating-mode/client-unsafe-strategy.js +15 -18
  39. package/dist/operating-mode/client-unsafe-strategy.js.map +1 -1
  40. package/dist/operating-mode/types.d.ts +8 -0
  41. package/dist/operating-mode/types.d.ts.map +1 -1
  42. package/dist/server.d.ts +2 -0
  43. package/dist/server.d.ts.map +1 -1
  44. package/dist/server.js +2 -0
  45. package/dist/server.js.map +1 -1
  46. package/package.json +4 -2
  47. package/src/cli/init.ts +43 -38
package/src/cli/init.ts CHANGED
@@ -1,6 +1,7 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env tsx
2
2
 
3
3
  import fs from 'node:fs/promises'
4
+ import { realpathSync } from 'node:fs'
4
5
  import path from 'node:path'
5
6
  import { fileURLToPath } from 'node:url'
6
7
  import * as p from '@clack/prompts'
@@ -10,17 +11,20 @@ import {
10
11
  schemasTemplate,
11
12
  apiRoute,
12
13
  editPage,
14
+ aiConfig,
15
+ aiRoute,
13
16
  dockerfileCms,
14
17
  githubWorkflowCms,
15
18
  } from './templates'
19
+ import { operatingStrategy } from '../operating-mode'
16
20
 
17
21
  export interface InitOptions {
18
- authProvider: 'clerk' | 'dev'
19
22
  mode: 'prod-sim' | 'dev'
20
23
  appDir: string
21
24
  projectDir: string
22
25
  force: boolean
23
26
  nonInteractive: boolean
27
+ ai: boolean
24
28
  }
25
29
 
26
30
  interface InitDeployOptions {
@@ -89,7 +93,7 @@ function configImportPath(appDir: string, subdirs: number): string {
89
93
  * editing to a Next.js app. Cloud-agnostic.
90
94
  */
91
95
  export async function init(options: InitOptions): Promise<void> {
92
- const { projectDir, mode, appDir, force, nonInteractive } = options
96
+ const { projectDir, mode, appDir, ai, force, nonInteractive } = options
93
97
  const writeOpts = { force, nonInteractive }
94
98
 
95
99
  p.intro('CanopyCMS init')
@@ -109,7 +113,7 @@ export async function init(options: InitOptions): Promise<void> {
109
113
  await writeFile(
110
114
  path.join(projectDir, appDir, 'api/canopycms/[...canopycms]/route.ts'),
111
115
  await apiRoute({
112
- canopyImport: configImportPath(appDir, 4).replace('canopycms.config', 'lib/canopy'),
116
+ canopyImport: '../'.repeat(3) + 'lib/canopy',
113
117
  }),
114
118
  writeOpts,
115
119
  )
@@ -118,6 +122,14 @@ export async function init(options: InitOptions): Promise<void> {
118
122
  await editPage({ configImport: configImportPath(appDir, 1) }),
119
123
  writeOpts,
120
124
  )
125
+ if (ai) {
126
+ await writeFile(path.join(projectDir, appDir, 'ai/config.ts'), await aiConfig(), writeOpts)
127
+ await writeFile(
128
+ path.join(projectDir, appDir, 'ai/[...path]/route.ts'),
129
+ await aiRoute({ configImport: configImportPath(appDir, 2) }),
130
+ writeOpts,
131
+ )
132
+ }
121
133
 
122
134
  // Update .gitignore
123
135
  const gitignorePath = path.join(projectDir, '.gitignore')
@@ -129,13 +141,10 @@ export async function init(options: InitOptions): Promise<void> {
129
141
  }
130
142
  }
131
143
 
132
- const authPackages =
133
- options.authProvider === 'clerk' ? 'canopycms-auth-clerk' : 'canopycms-auth-dev'
134
-
135
144
  p.note(
136
145
  [
137
146
  '1. Install dependencies:',
138
- ` npm install canopycms canopycms-next ${authPackages}`,
147
+ ` npm install canopycms canopycms-next canopycms-auth-clerk canopycms-auth-dev`,
139
148
  '',
140
149
  '2. Add transpilePackages to next.config.ts:',
141
150
  " transpilePackages: ['canopycms']",
@@ -229,9 +238,8 @@ export async function workerRunOnce(options: { projectDir: string }): Promise<vo
229
238
  // For prod-sim without GitHub, just refresh auth cache
230
239
  const authMode = process.env.CANOPY_AUTH_MODE || 'dev'
231
240
  const cachePath =
232
- mode === 'prod-sim'
233
- ? path.join(options.projectDir, '.canopy-prod-sim', '.cache')
234
- : path.join(process.env.CANOPYCMS_WORKSPACE_ROOT ?? '/mnt/efs/workspace', '.cache')
241
+ process.env.CANOPY_AUTH_CACHE_PATH ??
242
+ path.join(operatingStrategy(mode).getWorkspaceRoot(options.projectDir), '.cache')
235
243
 
236
244
  let refreshAuthCache: (() => Promise<void>) | undefined
237
245
 
@@ -299,7 +307,7 @@ function parseFlags(args: string[]): {
299
307
  if (arg.startsWith('--')) {
300
308
  const key = arg.slice(2)
301
309
  // Boolean flags
302
- if (key === 'force' || key === 'non-interactive') {
310
+ if (key === 'force' || key === 'non-interactive' || key === 'no-ai') {
303
311
  flags[key] = true
304
312
  } else if (i + 1 < args.length && !args[i + 1].startsWith('--')) {
305
313
  flags[key] = args[++i]
@@ -322,28 +330,6 @@ async function main() {
322
330
  const nonInteractive = flags['non-interactive'] === true
323
331
  const force = flags['force'] === true
324
332
 
325
- // Resolve options: use flags if provided, otherwise prompt interactively
326
- let authProvider: 'clerk' | 'dev'
327
- if (flags['auth'] === 'clerk' || flags['auth'] === 'dev') {
328
- authProvider = flags['auth']
329
- } else if (nonInteractive) {
330
- authProvider = 'dev'
331
- } else {
332
- const result = await p.select({
333
- message: 'Which auth provider?',
334
- options: [
335
- { value: 'dev' as const, label: 'dev', hint: 'Local development, no real auth' },
336
- { value: 'clerk' as const, label: 'clerk', hint: 'Clerk authentication' },
337
- ],
338
- initialValue: 'dev' as const,
339
- })
340
- if (p.isCancel(result)) {
341
- p.cancel('Init cancelled.')
342
- process.exit(0)
343
- }
344
- authProvider = result
345
- }
346
-
347
333
  let mode: 'dev' | 'prod-sim'
348
334
  if (flags['mode'] === 'dev' || flags['mode'] === 'prod-sim') {
349
335
  mode = flags['mode']
@@ -387,10 +373,27 @@ async function main() {
387
373
  appDir = result
388
374
  }
389
375
 
376
+ let ai: boolean
377
+ if (flags['no-ai'] === true) {
378
+ ai = false
379
+ } else if (nonInteractive) {
380
+ ai = true
381
+ } else {
382
+ const result = await p.confirm({
383
+ message: 'Include AI content endpoint?',
384
+ initialValue: true,
385
+ })
386
+ if (p.isCancel(result)) {
387
+ p.cancel('Init cancelled.')
388
+ process.exit(0)
389
+ }
390
+ ai = result
391
+ }
392
+
390
393
  await init({
391
- authProvider,
392
394
  mode,
393
395
  appDir,
396
+ ai,
394
397
  projectDir: process.cwd(),
395
398
  force,
396
399
  nonInteractive,
@@ -427,9 +430,9 @@ async function main() {
427
430
  console.log('')
428
431
  console.log('Commands:')
429
432
  console.log(' init Add CanopyCMS to a Next.js app')
430
- console.log(' --auth <dev|clerk> Auth provider (default: dev)')
431
433
  console.log(' --mode <dev|prod-sim> Operating mode (default: dev)')
432
434
  console.log(' --app-dir <path> App directory (default: app)')
435
+ console.log(' --no-ai Skip AI content endpoint generation')
433
436
  console.log(' --force Overwrite existing files without asking')
434
437
  console.log(' --non-interactive Use defaults, no prompts')
435
438
  console.log('')
@@ -445,9 +448,11 @@ async function main() {
445
448
  }
446
449
  }
447
450
 
448
- // Only run when executed directly as a CLI, not when imported in tests
451
+ // Only run when executed directly as a CLI, not when imported in tests.
452
+ // Use realpathSync to resolve symlinks — npx creates a symlink in node_modules/.bin/
453
+ // that won't match import.meta.url's resolved real path.
449
454
  const __filename = fileURLToPath(import.meta.url)
450
- const isDirectRun = process.argv[1] === __filename
455
+ const isDirectRun = realpathSync(process.argv[1]) === realpathSync(__filename)
451
456
 
452
457
  if (isDirectRun) {
453
458
  main().catch((err) => {