@proofkit/cli 1.2.0-beta.1 → 2.0.0-beta.1

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 (130) hide show
  1. package/CHANGELOG.md +133 -0
  2. package/dist/add-CfoeMDFa.js +57 -0
  3. package/dist/add-CfoeMDFa.js.map +1 -0
  4. package/dist/addPackageDependency-BE76r_Gs.js +4 -0
  5. package/dist/addPackageDependency-BE76r_Gs.js.map +1 -0
  6. package/dist/consts-BZnOMxpW.js +10 -0
  7. package/dist/consts-BZnOMxpW.js.map +1 -0
  8. package/dist/deploy-ib8_w4Q8.js +34 -0
  9. package/dist/deploy-ib8_w4Q8.js.map +1 -0
  10. package/dist/fmdapi-LpkpfSZp.js +3 -0
  11. package/dist/fmdapi-LpkpfSZp.js.map +1 -0
  12. package/dist/getUserPkgManager-Cph_6l1P.js +2 -0
  13. package/dist/getUserPkgManager-Cph_6l1P.js.map +1 -0
  14. package/dist/globalOptions-DmUayYY3.js +2 -0
  15. package/dist/globalOptions-DmUayYY3.js.map +1 -0
  16. package/dist/index-dr0nV3hP.d.ts +365 -0
  17. package/dist/index-dr0nV3hP.d.ts.map +1 -0
  18. package/dist/index.js +11 -147
  19. package/dist/index.js.map +1 -0
  20. package/dist/logger-DCEXcH26.js +2 -0
  21. package/dist/logger-DCEXcH26.js.map +1 -0
  22. package/dist/parseSettings-DYvHU8yJ.js +2 -0
  23. package/dist/parseSettings-DYvHU8yJ.js.map +1 -0
  24. package/dist/remove-D-aGocFU.js +2 -0
  25. package/dist/remove-D-aGocFU.js.map +1 -0
  26. package/dist/state-CiURqLoM.js +41 -0
  27. package/dist/state-CiURqLoM.js.map +1 -0
  28. package/dist/typegen-CNWUG1wR.js +2 -0
  29. package/dist/typegen-CNWUG1wR.js.map +1 -0
  30. package/dist/update-CDaX7MZ5.js +7 -0
  31. package/dist/update-CDaX7MZ5.js.map +1 -0
  32. package/dist/utils-CQMjIwwz.js +3 -0
  33. package/dist/utils-CQMjIwwz.js.map +1 -0
  34. package/package.json +61 -53
  35. package/template/extras/emailTemplates/auth-code.tsx +7 -26
  36. package/template/extras/emailTemplates/generic.tsx +8 -31
  37. package/template/extras/fmaddon-auth/emails/auth-code.tsx +7 -26
  38. package/template/extras/src/app/api/auth/[...nextauth]/route.ts +1 -1
  39. package/template/extras/src/server/next-auth/base.ts +3 -3
  40. package/template/fm-addon/ProofKitWV/de.xml +517 -20
  41. package/template/fm-addon/ProofKitWV/en.xml +517 -20
  42. package/template/fm-addon/ProofKitWV/es.xml +517 -20
  43. package/template/fm-addon/ProofKitWV/fr.xml +517 -20
  44. package/template/fm-addon/ProofKitWV/icon.png +0 -0
  45. package/template/fm-addon/ProofKitWV/icon@2x.png +0 -0
  46. package/template/fm-addon/ProofKitWV/info.json +9 -6
  47. package/template/fm-addon/ProofKitWV/info_de.json +12 -5
  48. package/template/fm-addon/ProofKitWV/info_en.json +16 -5
  49. package/template/fm-addon/ProofKitWV/info_es.json +12 -5
  50. package/template/fm-addon/ProofKitWV/info_fr.json +12 -5
  51. package/template/fm-addon/ProofKitWV/info_it.json +12 -5
  52. package/template/fm-addon/ProofKitWV/info_ja.json +12 -5
  53. package/template/fm-addon/ProofKitWV/info_ko.json +12 -5
  54. package/template/fm-addon/ProofKitWV/info_nl.json +12 -5
  55. package/template/fm-addon/ProofKitWV/info_pt.json +12 -5
  56. package/template/fm-addon/ProofKitWV/info_sv.json +12 -5
  57. package/template/fm-addon/ProofKitWV/info_zh.json +12 -5
  58. package/template/fm-addon/ProofKitWV/it.xml +517 -20
  59. package/template/fm-addon/ProofKitWV/ja.xml +517 -20
  60. package/template/fm-addon/ProofKitWV/ko.xml +517 -20
  61. package/template/fm-addon/ProofKitWV/nl.xml +517 -20
  62. package/template/fm-addon/ProofKitWV/preview.png +0 -0
  63. package/template/fm-addon/ProofKitWV/pt.xml +517 -20
  64. package/template/fm-addon/ProofKitWV/records_de.xml +0 -0
  65. package/template/fm-addon/ProofKitWV/records_en.xml +0 -0
  66. package/template/fm-addon/ProofKitWV/records_es.xml +0 -0
  67. package/template/fm-addon/ProofKitWV/records_fr.xml +0 -0
  68. package/template/fm-addon/ProofKitWV/records_it.xml +0 -0
  69. package/template/fm-addon/ProofKitWV/records_ja.xml +0 -0
  70. package/template/fm-addon/ProofKitWV/records_ko.xml +0 -0
  71. package/template/fm-addon/ProofKitWV/records_nl.xml +0 -0
  72. package/template/fm-addon/ProofKitWV/records_pt.xml +0 -0
  73. package/template/fm-addon/ProofKitWV/records_sv.xml +0 -0
  74. package/template/fm-addon/ProofKitWV/records_zh.xml +0 -0
  75. package/template/fm-addon/ProofKitWV/sv.xml +517 -20
  76. package/template/fm-addon/ProofKitWV/template.xml +0 -0
  77. package/template/fm-addon/ProofKitWV/zh.xml +517 -20
  78. package/template/nextjs-mantine/AGENTS.md +1 -0
  79. package/template/nextjs-mantine/package.json +4 -4
  80. package/template/nextjs-shadcn/AGENTS.md +1 -0
  81. package/template/nextjs-shadcn/biome.json +18 -13
  82. package/template/nextjs-shadcn/package.json +11 -9
  83. package/template/nextjs-shadcn/src/app/layout.tsx +11 -11
  84. package/template/nextjs-shadcn/src/components/mode-toggle.tsx +39 -0
  85. package/template/nextjs-shadcn/src/components/ui/button.tsx +61 -0
  86. package/template/nextjs-shadcn/src/components/ui/dropdown-menu.tsx +267 -0
  87. package/template/nextjs-shadcn/src/components/ui/sonner.tsx +31 -0
  88. package/template/nextjs-shadcn/src/lib/env.ts +1 -1
  89. package/template/pages/nextjs/table-infinite/actions.ts +1 -1
  90. package/template/pages/nextjs/table-infinite-edit/actions.ts +1 -1
  91. package/template/vite-wv/.claude/launch.json +18 -0
  92. package/template/vite-wv/AGENTS.md +1 -0
  93. package/template/vite-wv/_gitignore +1 -0
  94. package/template/vite-wv/components.json +6 -6
  95. package/template/vite-wv/index.html +2 -2
  96. package/template/vite-wv/package.json +21 -35
  97. package/template/vite-wv/proofkit-typegen.config.jsonc +18 -0
  98. package/template/vite-wv/proofkit.json +4 -1
  99. package/template/vite-wv/scripts/filemaker.js +96 -0
  100. package/template/vite-wv/scripts/launch-fm.js +19 -0
  101. package/template/vite-wv/scripts/upload.js +17 -14
  102. package/template/vite-wv/src/App.tsx +84 -0
  103. package/template/vite-wv/src/index.css +96 -0
  104. package/template/vite-wv/src/lib/utils.ts +6 -0
  105. package/template/vite-wv/src/main.tsx +14 -35
  106. package/template/vite-wv/src/router.tsx +57 -0
  107. package/template/vite-wv/src/routes/query-demo.tsx +37 -0
  108. package/template/vite-wv/tsconfig.json +3 -1
  109. package/template/vite-wv/vite.config.ts +5 -5
  110. package/dist/external-DCpQkgKf.js +0 -1
  111. package/template/extras/config/_eslint.js +0 -27
  112. package/template/extras/config/_prettier.config.js +0 -6
  113. package/template/nextjs-mantine/.prettierrc +0 -3
  114. package/template/nextjs-shadcn/.prettierrc +0 -3
  115. package/template/nextjs-shadcn/next-env.d.ts +0 -6
  116. package/template/vite-wv/.prettierrc +0 -3
  117. package/template/vite-wv/pnpm-lock.yaml +0 -2294
  118. package/template/vite-wv/postcss.config.cjs +0 -15
  119. package/template/vite-wv/scripts/launch-fm.sh +0 -3
  120. package/template/vite-wv/src/components/AppLogo.tsx +0 -5
  121. package/template/vite-wv/src/components/full-screen-loader.tsx +0 -9
  122. package/template/vite-wv/src/config/env.ts +0 -16
  123. package/template/vite-wv/src/config/theme/globals.css +0 -125
  124. package/template/vite-wv/src/config/theme/mantine-theme.ts +0 -22
  125. package/template/vite-wv/src/routeTree.gen.ts +0 -111
  126. package/template/vite-wv/src/routes/__root.tsx +0 -21
  127. package/template/vite-wv/src/routes/index.tsx +0 -63
  128. package/template/vite-wv/src/routes/secondary.tsx +0 -28
  129. package/template/vite-wv/src/utils/notification-helpers.ts +0 -32
  130. package/template/vite-wv/src/utils/styles.ts +0 -6
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["parseJsonc","chalk","intro","clackIntro","log","clackLog","note","clackNote","spinner","clackSpinner","isCancel","clackIsCancel","inquirerInput","inquirerPassword","inquirerConfirm","inquirerSelect","inquirerSearch","inquirerCheckbox","isCancel","log","note","fs","createSpinner","optionalArg","textArg","withArgDescription","optionalOption","textOption","withOptionDescription","choiceOption","makeCommand","booleanOption","withCommandDescription","nodeContextLayer"],"sources":["../src/core/context.ts","../src/core/errors.ts","../src/utils/projectFiles.ts","../src/utils/versioning.ts","../src/core/planInit.ts","../src/core/executeInitPlan.ts","../src/utils/projectName.ts","../src/core/resolveInitRequest.ts","../src/utils/browserOpen.ts","../src/utils/http.ts","../src/utils/packageManager.ts","../src/utils/prompts.ts","../src/services/live.ts","../src/utils/renderTitle.ts","../src/index.ts"],"sourcesContent":["import { Context } from \"effect\";\nimport type { AppType, FileMakerEnvNames, FileMakerInputs, ProofKitSettings, UIType } from \"~/core/types.js\";\nimport type { PackageManager } from \"~/utils/packageManager.js\";\n\nexport interface CliContextValue {\n cwd: string;\n debug: boolean;\n nonInteractive: boolean;\n packageManager: PackageManager;\n resolvedProjectConfig?: {\n appType?: AppType;\n ui?: UIType;\n projectDir?: string;\n };\n}\n\nexport const CliContext = Context.GenericTag<CliContextValue>(\"@proofkit/cli/CliContext\");\n\nexport interface PromptService {\n readonly text: (options: {\n message: string;\n defaultValue?: string;\n validate?: (value: string) => string | undefined;\n }) => Promise<string>;\n readonly password: (options: {\n message: string;\n validate?: (value: string) => string | undefined;\n }) => Promise<string>;\n readonly select: <T extends string>(options: {\n message: string;\n options: Array<{ value: T; label: string; hint?: string; disabled?: boolean | string }>;\n }) => Promise<T>;\n readonly searchSelect: <T extends string>(options: {\n message: string;\n emptyMessage?: string;\n options: Array<{ value: T; label: string; hint?: string; keywords?: string[]; disabled?: boolean | string }>;\n }) => Promise<T>;\n readonly multiSearchSelect: <T extends string>(options: {\n message: string;\n options: Array<{ value: T; label: string; hint?: string; keywords?: string[]; disabled?: boolean | string }>;\n required?: boolean;\n }) => Promise<T[]>;\n readonly confirm: (options: { message: string; initialValue?: boolean }) => Promise<boolean>;\n}\n\nexport const PromptService = Context.GenericTag<PromptService>(\"@proofkit/cli/PromptService\");\n\nexport interface ConsoleService {\n readonly info: (message: string) => void;\n readonly warn: (message: string) => void;\n readonly error: (message: string) => void;\n readonly success: (message: string) => void;\n readonly note: (message: string, title?: string) => void;\n}\n\nexport const ConsoleService = Context.GenericTag<ConsoleService>(\"@proofkit/cli/ConsoleService\");\n\nexport interface FileSystemService {\n readonly exists: (path: string) => Promise<boolean>;\n readonly readdir: (path: string) => Promise<string[]>;\n readonly emptyDir: (path: string) => Promise<void>;\n readonly copyDir: (from: string, to: string, options?: { overwrite?: boolean }) => Promise<void>;\n readonly rename: (from: string, to: string) => Promise<void>;\n readonly remove: (path: string) => Promise<void>;\n readonly readJson: <T>(path: string) => Promise<T>;\n readonly writeJson: (path: string, value: unknown) => Promise<void>;\n readonly writeFile: (path: string, content: string) => Promise<void>;\n readonly readFile: (path: string) => Promise<string>;\n}\n\nexport const FileSystemService = Context.GenericTag<FileSystemService>(\"@proofkit/cli/FileSystemService\");\n\nexport interface TemplateService {\n readonly getTemplateDir: (appType: AppType, ui: UIType) => string;\n}\n\nexport const TemplateService = Context.GenericTag<TemplateService>(\"@proofkit/cli/TemplateService\");\n\nexport interface PackageManagerService {\n readonly getVersion: (packageManager: PackageManager, cwd: string) => Promise<string | undefined>;\n}\n\nexport const PackageManagerService = Context.GenericTag<PackageManagerService>(\"@proofkit/cli/PackageManagerService\");\n\nexport interface ProcessService {\n readonly run: (\n command: string,\n args: string[],\n options: {\n cwd: string;\n stdout?: \"pipe\" | \"inherit\" | \"ignore\";\n stderr?: \"pipe\" | \"inherit\" | \"ignore\";\n },\n ) => Promise<{ stdout: string; stderr: string }>;\n}\n\nexport const ProcessService = Context.GenericTag<ProcessService>(\"@proofkit/cli/ProcessService\");\n\nexport interface GitService {\n readonly initialize: (projectDir: string) => Promise<void>;\n}\n\nexport const GitService = Context.GenericTag<GitService>(\"@proofkit/cli/GitService\");\n\nexport interface SettingsService {\n readonly writeSettings: (projectDir: string, settings: ProofKitSettings) => Promise<void>;\n readonly appendEnvVars: (projectDir: string, vars: Record<string, string>) => Promise<void>;\n readonly ensureTypegenConfig: (\n projectDir: string,\n options: { appType: AppType; fileMaker?: FileMakerInputs },\n ) => Promise<void>;\n}\n\nexport const SettingsService = Context.GenericTag<SettingsService>(\"@proofkit/cli/SettingsService\");\n\nexport interface FmHttpStatus {\n baseUrl: string;\n healthy: boolean;\n connectedFiles: string[];\n}\n\nexport interface FileMakerServerVersions {\n fmsVersion: string;\n ottoVersion: string | null;\n}\n\nexport interface OttoFileInfo {\n filename: string;\n status: string;\n}\n\nexport interface OttoApiKeyInfo {\n key: string;\n user: string;\n database: string;\n label: string;\n}\n\nexport interface FileMakerDataSourceEntry {\n type: \"fm\";\n name: string;\n envNames: FileMakerEnvNames;\n}\n\nexport interface FileMakerBootstrapArtifacts {\n settings: ProofKitSettings;\n envVars: Record<string, string>;\n envSchemaEntries: Array<{\n name: string;\n zodSchema: string;\n defaultValue: string;\n }>;\n typegenConfig: {\n mode: FileMakerInputs[\"mode\"];\n dataSourceName: string;\n envNames?: FileMakerEnvNames;\n fmHttpBaseUrl?: string;\n connectedFileName?: string;\n layoutName?: string;\n schemaName?: string;\n appType: AppType;\n };\n}\n\nexport interface FileMakerService {\n readonly detectLocalFmHttp: (baseUrl?: string) => Promise<FmHttpStatus>;\n readonly validateHostedServerUrl: (\n serverUrl: string,\n ottoPort?: number | null,\n ) => Promise<{\n normalizedUrl: string;\n versions: FileMakerServerVersions;\n }>;\n readonly getOttoFMSToken: (options: { url: URL }) => Promise<{ token: string }>;\n readonly listFiles: (options: { url: URL; token: string }) => Promise<OttoFileInfo[]>;\n readonly listAPIKeys: (options: { url: URL; token: string }) => Promise<OttoApiKeyInfo[]>;\n readonly createDataAPIKeyWithCredentials: (options: {\n url: URL;\n filename: string;\n username: string;\n password: string;\n }) => Promise<{ apiKey: string }>;\n readonly deployDemoFile: (options: {\n url: URL;\n token: string;\n operation: \"install\" | \"replace\";\n }) => Promise<{ apiKey: string; filename: string }>;\n readonly listLayouts: (options: { dataApiKey: string; fmFile: string; server: string }) => Promise<string[]>;\n readonly createFileMakerBootstrapArtifacts: (\n settings: ProofKitSettings,\n inputs: FileMakerInputs,\n appType: AppType,\n ) => Promise<FileMakerBootstrapArtifacts>;\n readonly bootstrap: (\n projectDir: string,\n settings: ProofKitSettings,\n inputs: FileMakerInputs,\n appType: AppType,\n ) => Promise<ProofKitSettings>;\n}\n\nexport const FileMakerService = Context.GenericTag<FileMakerService>(\"@proofkit/cli/FileMakerService\");\n\nexport interface CodegenService {\n readonly runInitial: (projectDir: string, packageManager: PackageManager) => Promise<void>;\n}\n\nexport const CodegenService = Context.GenericTag<CodegenService>(\"@proofkit/cli/CodegenService\");\n","export class UserAbortedError extends Error {\n constructor(message = \"User aborted the operation\") {\n super(message);\n this.name = \"UserAbortedError\";\n }\n}\n","import { readFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { applyEdits, modify, parse as parseJsonc } from \"jsonc-parser\";\nimport { PKG_ROOT } from \"~/consts.js\";\nimport type { FileMakerEnvNames } from \"~/core/types.js\";\nimport type { PackageManager } from \"~/utils/packageManager.js\";\n\nconst commonFileMakerLayoutPrefixes = [\"API_\", \"API \", \"dapi_\", \"dapi\"];\nconst TRAILING_SLASH_REGEX = /[^/]$/;\nconst textFileExtensions = new Set([\n \".ts\",\n \".tsx\",\n \".js\",\n \".jsx\",\n \".json\",\n \".jsonc\",\n \".md\",\n \".css\",\n \".scss\",\n \".html\",\n \".mjs\",\n \".cjs\",\n]);\n\nexport function getDefaultSchemaName(layoutName: string) {\n let schemaName = layoutName.replace(/[-\\s]/g, \"_\");\n for (const prefix of commonFileMakerLayoutPrefixes) {\n if (schemaName.startsWith(prefix)) {\n schemaName = schemaName.replace(prefix, \"\");\n }\n }\n return schemaName;\n}\n\nexport function createDataSourceEnvNames(dataSourceName: string): FileMakerEnvNames {\n if (dataSourceName === \"filemaker\") {\n return {\n database: \"FM_DATABASE\",\n server: \"FM_SERVER\",\n apiKey: \"OTTO_API_KEY\",\n };\n }\n\n const upperName = dataSourceName.toUpperCase();\n return {\n database: `${upperName}_FM_DATABASE`,\n server: `${upperName}_FM_SERVER`,\n apiKey: `${upperName}_OTTO_API_KEY`,\n };\n}\n\nexport function formatPackageManagerCommand(packageManager: PackageManager, command: string) {\n return [\"npm\", \"bun\"].includes(packageManager) ? `${packageManager} run ${command}` : `${packageManager} ${command}`;\n}\n\nexport function getTemplatePackageCommand(packageManager: PackageManager) {\n if (packageManager === \"npm\") {\n return \"npm run\";\n }\n return packageManager;\n}\n\nexport function normalizeImportAlias(importAlias: string) {\n return importAlias.replace(/\\*/g, \"\").replace(TRAILING_SLASH_REGEX, \"$&/\");\n}\n\nexport async function replaceTextInFiles(\n fs: {\n readdir: (path: string) => Promise<string[]>;\n readFile: (path: string) => Promise<string>;\n writeFile: (path: string, content: string) => Promise<void>;\n },\n rootDir: string,\n searchValue: string,\n replaceValue: string,\n) {\n const entries = await fs.readdir(rootDir);\n for (const entry of entries) {\n const fullPath = path.join(rootDir, entry);\n const childEntries = await fs.readdir(fullPath).catch((error: unknown) => {\n const code =\n typeof error === \"object\" && error !== null && \"code\" in error && typeof error.code === \"string\"\n ? error.code\n : undefined;\n\n if (code === \"ENOTDIR\") {\n return undefined;\n }\n\n throw error;\n });\n if (childEntries) {\n await replaceTextInFiles(fs, fullPath, searchValue, replaceValue);\n continue;\n }\n\n const extension = path.extname(entry);\n if (!textFileExtensions.has(extension)) {\n continue;\n }\n\n const content = await fs.readFile(fullPath).catch(() => undefined);\n if (!content?.includes(searchValue)) {\n continue;\n }\n\n await fs.writeFile(fullPath, content.replaceAll(searchValue, replaceValue));\n }\n}\n\nexport async function updateEnvSchemaFile(\n fs: {\n exists: (path: string) => Promise<boolean>;\n readFile: (path: string) => Promise<string>;\n writeFile: (path: string, content: string) => Promise<void>;\n },\n projectDir: string,\n envEntries: Array<{ name: string; zodSchema: string }>,\n) {\n const envFilePath = path.join(projectDir, \"src/lib/env.ts\");\n if (!(await fs.exists(envFilePath))) {\n return;\n }\n\n let content = await fs.readFile(envFilePath);\n const marker = \" server: {\";\n const markerIndex = content.indexOf(marker);\n if (markerIndex === -1) {\n return;\n }\n\n const insertIndex = content.indexOf(\" },\", markerIndex);\n if (insertIndex === -1) {\n return;\n }\n\n const additions = envEntries\n .filter((entry) => !content.includes(`${entry.name}:`))\n .map((entry) => ` ${entry.name}: ${entry.zodSchema},`)\n .join(\"\\n\");\n\n if (!additions) {\n return;\n }\n\n content = `${content.slice(0, insertIndex)}${additions}\\n${content.slice(insertIndex)}`;\n await fs.writeFile(envFilePath, content);\n}\n\ninterface TypegenFileContent {\n $schema?: string;\n config: Record<string, unknown>[] | Record<string, unknown>;\n}\n\nexport async function updateTypegenConfig(\n fs: {\n exists: (path: string) => Promise<boolean>;\n readFile: (path: string) => Promise<string>;\n writeFile: (path: string, content: string) => Promise<void>;\n },\n projectDir: string,\n options: {\n appType: \"browser\" | \"webviewer\";\n dataSourceName: string;\n envNames?: FileMakerEnvNames;\n fmHttpBaseUrl?: string;\n connectedFileName?: string;\n layoutName?: string;\n schemaName?: string;\n },\n) {\n const configPath = path.join(projectDir, \"proofkit-typegen.config.jsonc\");\n const dsPath = `./src/config/schemas/${options.dataSourceName}`;\n const nextDataSource: Record<string, unknown> = {\n type: \"fmdapi\",\n layouts: [],\n path: dsPath,\n clearOldFiles: true,\n clientSuffix: \"Layout\",\n };\n\n if (options.envNames) {\n nextDataSource.envNames = {\n server: options.envNames.server,\n db: options.envNames.database,\n auth: { apiKey: options.envNames.apiKey },\n };\n }\n\n if (options.appType === \"webviewer\") {\n nextDataSource.webviewerScriptName = \"ExecuteDataApi\";\n }\n\n if (options.fmHttpBaseUrl) {\n nextDataSource.fmHttp = {\n enabled: true,\n baseUrl: options.fmHttpBaseUrl,\n ...(options.connectedFileName ? { connectedFileName: options.connectedFileName } : {}),\n };\n }\n\n const layout =\n options.layoutName && options.schemaName\n ? {\n layoutName: options.layoutName,\n schemaName: options.schemaName,\n valueLists: \"allowEmpty\",\n }\n : undefined;\n\n if (layout) {\n nextDataSource.layouts = [layout];\n }\n\n if (!(await fs.exists(configPath))) {\n const nextContent: TypegenFileContent = {\n $schema: \"https://proofkit.dev/typegen-config-schema.json\",\n config: [nextDataSource],\n };\n await fs.writeFile(configPath, `${JSON.stringify(nextContent, null, 2)}\\n`);\n return;\n }\n\n const original = await fs.readFile(configPath);\n const parsed = parseJsonc(original) as TypegenFileContent;\n const configArray = Array.isArray(parsed.config) ? parsed.config : [parsed.config];\n const existingIndex = configArray.findIndex((entry) => entry.path === dsPath);\n\n if (existingIndex === -1) {\n configArray.push(nextDataSource);\n } else {\n const existing = (configArray[existingIndex] ?? {}) as Record<string, unknown>;\n const existingLayouts = Array.isArray(existing.layouts) ? existing.layouts : [];\n let nextLayouts = existingLayouts;\n if (layout && !existingLayouts.some((item) => item?.layoutName === layout.layoutName)) {\n nextLayouts = [...existingLayouts, layout];\n }\n configArray[existingIndex] = {\n ...existing,\n ...nextDataSource,\n layouts: nextLayouts,\n };\n }\n\n const nextConfig = Array.isArray(parsed.config) ? configArray : (configArray[0] ?? nextDataSource);\n const edits = modify(original, [\"config\"], nextConfig, {\n formattingOptions: {\n insertSpaces: true,\n tabSize: 2,\n eol: \"\\n\",\n },\n });\n await fs.writeFile(configPath, applyEdits(original, edits));\n}\n\nexport function getScaffoldVersion() {\n const candidates = [path.resolve(PKG_ROOT, \"package.json\"), path.resolve(PKG_ROOT, \"../cli/package.json\")];\n\n for (const candidate of candidates) {\n try {\n const packageJson = JSON.parse(readFileSync(candidate, \"utf8\")) as { version?: string };\n if (packageJson.version && packageJson.version !== \"0.0.0-private\") {\n return packageJson.version;\n }\n } catch {\n // ignore and continue searching\n }\n }\n\n return \"0.0.0-private\";\n}\n","export function getProofkitReleaseTag() {\n return \"beta\";\n}\n\nexport function getNodeMajorVersion() {\n return process.versions.node.split(\".\")[0] ?? \"22\";\n}\n","import path from \"node:path\";\nimport type { PackageJson } from \"type-fest\";\n\nimport type { InitPlan, InitRequest, ProofKitSettings } from \"~/core/types.js\";\nimport { formatPackageManagerCommand, getScaffoldVersion, getTemplatePackageCommand } from \"~/utils/projectFiles.js\";\nimport { getNodeMajorVersion, getProofkitReleaseTag } from \"~/utils/versioning.js\";\n\nfunction createDefaultSettings(request: InitRequest): ProofKitSettings {\n return {\n ui: request.ui,\n appType: request.appType,\n envFile: \".env\",\n dataSources: [],\n replacedMainPage: false,\n registryTemplates: [],\n };\n}\n\nfunction createEnvFileContent() {\n return [\"# When adding additional environment variables, update the schema alongside this file.\", \"\"].join(\"\\n\");\n}\n\nconst sharedUiDependencies = {\n \"@radix-ui/react-slot\": \"^1.2.3\",\n \"class-variance-authority\": \"^0.7.1\",\n clsx: \"^2.1.1\",\n \"lucide-react\": \"^0.577.0\",\n \"tailwind-merge\": \"^3.5.0\",\n tailwindcss: \"^4.1.10\",\n \"tw-animate-css\": \"^1.4.0\",\n} satisfies Record<string, string>;\n\nexport function planInit(\n request: InitRequest,\n options: { templateDir: string; packageManagerVersion?: string },\n): InitPlan {\n const targetDir = path.resolve(request.cwd, request.appDir);\n const releaseTag = getProofkitReleaseTag();\n const settings = createDefaultSettings(request);\n const packageManagerCommand = getTemplatePackageCommand(request.packageManager);\n\n const packageJson: InitPlan[\"packageJson\"] = {\n name: request.scopedAppName,\n packageManager: options.packageManagerVersion\n ? `${request.packageManager}@${options.packageManagerVersion}`\n : undefined,\n proofkitMetadata: {\n initVersion: getScaffoldVersion(),\n scaffoldPackage: \"@proofkit/cli\",\n },\n dependencies: {},\n devDependencies: {\n \"@proofkit/cli\": releaseTag,\n \"@types/node\": `^${getNodeMajorVersion()}`,\n },\n };\n\n if (request.appType === \"browser\") {\n Object.assign(packageJson.dependencies, sharedUiDependencies);\n packageJson.dependencies[\"@tailwindcss/postcss\"] = \"^4.1.10\";\n packageJson.dependencies[\"next-themes\"] = \"^0.4.6\";\n }\n\n if (request.appType === \"webviewer\") {\n Object.assign(packageJson.dependencies, sharedUiDependencies);\n packageJson.dependencies[\"@proofkit/fmdapi\"] = releaseTag;\n packageJson.dependencies[\"@proofkit/webviewer\"] = releaseTag;\n packageJson.dependencies[\"@tanstack/react-query\"] = \"^5.90.21\";\n packageJson.dependencies[\"@tanstack/react-router\"] = \"^1.167.4\";\n packageJson.dependencies.zod = \"^4\";\n packageJson.devDependencies[\"@proofkit/typegen\"] = releaseTag;\n packageJson.devDependencies[\"@tailwindcss/vite\"] = \"^4.2.1\";\n packageJson.devDependencies.ultracite = \"7.0.8\";\n }\n\n return {\n request,\n targetDir,\n templateDir: options.templateDir,\n packageManagerCommand,\n packageJson,\n settings,\n envFile: {\n path: path.join(targetDir, \".env\"),\n content: createEnvFileContent(),\n },\n writes: [],\n commands: [\n ...(request.noInstall ? [] : [{ type: \"install\" as const }]),\n ...(request.dataSource === \"filemaker\" &&\n !request.skipFileMakerSetup &&\n !(request.appType === \"webviewer\" && request.nonInteractive && !request.hasExplicitFileMakerInputs)\n ? [{ type: \"codegen\" as const }]\n : []),\n ...(request.noGit ? [] : [{ type: \"git-init\" as const }]),\n ],\n tasks: {\n bootstrapFileMaker: request.dataSource === \"filemaker\" && !request.skipFileMakerSetup,\n runInstall: !request.noInstall,\n runInitialCodegen:\n request.dataSource === \"filemaker\" &&\n !request.skipFileMakerSetup &&\n !(request.appType === \"webviewer\" && request.nonInteractive && !request.hasExplicitFileMakerInputs),\n initializeGit: !request.noGit,\n },\n nextSteps: [\n `cd ${request.appDir}`,\n ...(request.noInstall ? [request.packageManager === \"yarn\" ? \"yarn\" : `${request.packageManager} install`] : []),\n \"npx @tanstack/intent@latest install\",\n formatPackageManagerCommand(request.packageManager, \"dev\"),\n ...(request.appType === \"webviewer\"\n ? [\n formatPackageManagerCommand(request.packageManager, \"typegen\"),\n formatPackageManagerCommand(request.packageManager, \"launch-fm\"),\n ]\n : []),\n formatPackageManagerCommand(request.packageManager, \"proofkit\"),\n ],\n };\n}\n\nexport function applyPackageJsonMutations(\n packageJson: PackageJson,\n mutations: InitPlan[\"packageJson\"],\n overwriteDependencies = true,\n) {\n packageJson.name = mutations.name;\n packageJson.proofkitMetadata = mutations.proofkitMetadata as PackageJson[\"proofkitMetadata\"];\n if (mutations.packageManager) {\n packageJson.packageManager = mutations.packageManager;\n }\n\n if (!packageJson.dependencies) {\n packageJson.dependencies = {};\n }\n if (!packageJson.devDependencies) {\n packageJson.devDependencies = {};\n }\n\n const merge = (target: Record<string, string>, source: Record<string, string>) => {\n for (const [name, version] of Object.entries(source)) {\n if (overwriteDependencies || !(name in target)) {\n target[name] = version;\n }\n }\n };\n\n merge(packageJson.dependencies as Record<string, string>, mutations.dependencies);\n merge(packageJson.devDependencies as Record<string, string>, mutations.devDependencies);\n\n return packageJson;\n}\n","import path from \"node:path\";\nimport { Chalk } from \"chalk\";\nimport { Effect } from \"effect\";\nimport sortPackageJson from \"sort-package-json\";\n\nimport { AGENT_INSTRUCTIONS } from \"~/consts.js\";\nimport {\n CliContext,\n CodegenService,\n ConsoleService,\n FileMakerService,\n FileSystemService,\n GitService,\n PackageManagerService,\n ProcessService,\n PromptService,\n SettingsService,\n} from \"~/core/context.js\";\nimport { UserAbortedError } from \"~/core/errors.js\";\nimport { applyPackageJsonMutations } from \"~/core/planInit.js\";\nimport type { InitPlan } from \"~/core/types.js\";\nimport { normalizeImportAlias, replaceTextInFiles } from \"~/utils/projectFiles.js\";\n\nconst AGENT_METADATA_DIRS = new Set([\".agents\", \".claude\", \".clawed\", \".clinerules\", \".cursor\", \".windsurf\"]);\nconst IMPORT_ALIAS_WILDCARD_REGEX = /\\*/g;\nconst IMPORT_ALIAS_TRAILING_SLASH_REGEX = /\\/?$/;\nconst chalk = new Chalk({ level: 1 });\n\nconst formatCommand = (command: string) => chalk.cyan(command);\nconst formatHeading = (heading: string) => chalk.bold(heading);\nconst formatPath = (value: string) => chalk.yellow(value);\n\nfunction renderNextSteps(plan: InitPlan) {\n const lines = [\n `${formatHeading(\"Project root:\")} ${formatCommand(`cd ${formatPath(plan.request.appDir)}`)}`,\n \"\",\n formatHeading(\"Agent setup:\"),\n \"Have your agent run this in the new project and complete the interactive prompt so it can load the right skills:\",\n ` ${formatCommand(\"npx @tanstack/intent@latest install\")}`,\n ];\n\n if (plan.request.noInstall) {\n lines.push(\n \"\",\n formatHeading(\"Install dependencies:\"),\n ` ${formatCommand(plan.request.packageManager === \"yarn\" ? \"yarn\" : `${plan.request.packageManager} install`)}`,\n );\n }\n\n lines.push(\"\", formatHeading(\"Start the app:\"), ` ${formatCommand(`${plan.packageManagerCommand} dev`)}`);\n\n if (plan.request.appType === \"webviewer\") {\n lines.push(\n \"\",\n formatHeading(\"When your FileMaker file is ready:\"),\n ` ${formatCommand(`${plan.packageManagerCommand} typegen`)}`,\n ` ${formatCommand(`${plan.packageManagerCommand} launch-fm`)}`,\n );\n }\n\n lines.push(\n \"\",\n formatHeading(\"More ProofKit commands:\"),\n ` ${formatCommand(`${plan.packageManagerCommand} proofkit`)}`,\n );\n\n return lines.join(\"\\n\");\n}\n\nfunction getMeaningfulDirectoryEntries(entries: string[]) {\n return entries.filter((entry) => {\n if (AGENT_METADATA_DIRS.has(entry)) {\n return false;\n }\n if (entry === \".gitignore\") {\n return true;\n }\n if (entry.startsWith(\".\")) {\n return false;\n }\n return true;\n });\n}\n\nexport const prepareDirectory = (plan: InitPlan) =>\n Effect.gen(function* () {\n const fs = yield* FileSystemService;\n const consoleService = yield* ConsoleService;\n const cliContext = yield* CliContext;\n const prompts = yield* PromptService;\n\n const exists = yield* Effect.promise(() => fs.exists(plan.targetDir));\n if (!exists) {\n return;\n }\n\n const entries = yield* Effect.promise(() => fs.readdir(plan.targetDir));\n const meaningfulEntries = getMeaningfulDirectoryEntries(entries);\n if (meaningfulEntries.length === 0) {\n return;\n }\n\n if (plan.request.force) {\n yield* Effect.promise(() => fs.emptyDir(plan.targetDir));\n return;\n }\n\n if (cliContext.nonInteractive) {\n throw new Error(\n `${plan.request.appDir} already exists and isn't empty. Remove the existing files or choose a different directory.`,\n );\n }\n\n const overwriteMode = yield* Effect.promise(() =>\n prompts.select({\n message: `${plan.request.appDir} already exists and isn't empty. How would you like to proceed?`,\n options: [\n { value: \"abort\", label: \"Abort installation\" },\n { value: \"clear\", label: \"Clear the directory and continue\" },\n { value: \"overwrite\", label: \"Continue and overwrite conflicting files\" },\n ],\n }),\n );\n\n if (overwriteMode === \"abort\") {\n throw new UserAbortedError();\n }\n\n if (overwriteMode === \"clear\") {\n const confirmed = yield* Effect.promise(() =>\n prompts.confirm({\n message: \"Are you sure you want to clear the directory?\",\n initialValue: false,\n }),\n );\n if (!confirmed) {\n throw new UserAbortedError();\n }\n yield* Effect.promise(() => fs.emptyDir(plan.targetDir));\n return;\n }\n\n consoleService.warn(`Continuing in ${plan.request.appDir} and overwriting conflicting files when needed.`);\n });\n\nexport const executeInitPlan = (plan: InitPlan) =>\n Effect.gen(function* () {\n const fs = yield* FileSystemService;\n const consoleService = yield* ConsoleService;\n const settingsService = yield* SettingsService;\n const fileMakerService = yield* FileMakerService;\n const processService = yield* ProcessService;\n const gitService = yield* GitService;\n const codegenService = yield* CodegenService;\n const packageManagerService = yield* PackageManagerService;\n\n yield* prepareDirectory(plan);\n\n consoleService.info(`Scaffolding in ${plan.targetDir}`);\n yield* Effect.promise(() => fs.copyDir(plan.templateDir, plan.targetDir, { overwrite: true }));\n\n const stagedGitignore = path.join(plan.targetDir, \"_gitignore\");\n const finalGitignore = path.join(plan.targetDir, \".gitignore\");\n if (yield* Effect.promise(() => fs.exists(stagedGitignore))) {\n if (yield* Effect.promise(() => fs.exists(finalGitignore))) {\n yield* Effect.promise(() => fs.remove(stagedGitignore));\n } else {\n yield* Effect.promise(() => fs.rename(stagedGitignore, finalGitignore));\n }\n }\n\n const packageJsonPath = path.join(plan.targetDir, \"package.json\");\n const packageJson = yield* Effect.promise(() => fs.readJson<Record<string, unknown>>(packageJsonPath));\n const updatedPackageJson = sortPackageJson(\n applyPackageJsonMutations(packageJson as never, plan.packageJson) as never,\n );\n yield* Effect.promise(() => fs.writeJson(packageJsonPath, updatedPackageJson));\n\n yield* Effect.promise(() => settingsService.writeSettings(plan.targetDir, plan.settings));\n yield* Effect.promise(() => fs.writeFile(plan.envFile.path, plan.envFile.content));\n for (const write of plan.writes) {\n yield* Effect.promise(() => fs.writeFile(write.path, write.content));\n }\n\n yield* Effect.promise(() => replaceTextInFiles(fs, plan.targetDir, \"__PNPM_COMMAND__\", plan.packageManagerCommand));\n yield* Effect.promise(() =>\n replaceTextInFiles(fs, plan.targetDir, \"__PACKAGE_MANAGER__\", plan.request.packageManager),\n );\n yield* Effect.promise(() => replaceTextInFiles(fs, plan.targetDir, \"__AGENT_INSTRUCTIONS__\", AGENT_INSTRUCTIONS));\n if (plan.request.importAlias !== \"~/\") {\n yield* Effect.promise(() =>\n replaceTextInFiles(fs, plan.targetDir, \"~/\", normalizeImportAlias(plan.request.importAlias)),\n );\n yield* Effect.promise(() =>\n replaceTextInFiles(\n fs,\n plan.targetDir,\n \"@/\",\n plan.request.importAlias\n .replace(IMPORT_ALIAS_WILDCARD_REGEX, \"\")\n .replace(IMPORT_ALIAS_TRAILING_SLASH_REGEX, \"/\"),\n ),\n );\n }\n\n let nextSettings = plan.settings;\n if (plan.tasks.bootstrapFileMaker && plan.request.fileMaker) {\n const fileMakerInputs = plan.request.fileMaker;\n nextSettings = yield* Effect.promise(() =>\n fileMakerService.bootstrap(plan.targetDir, nextSettings, fileMakerInputs, plan.request.appType),\n );\n yield* Effect.promise(() => settingsService.writeSettings(plan.targetDir, nextSettings));\n }\n\n if (plan.tasks.runInstall) {\n let installArgs: string[] = [\"install\"];\n if (plan.request.packageManager === \"yarn\") {\n installArgs = [];\n }\n yield* Effect.promise(() =>\n processService.run(plan.request.packageManager, installArgs, {\n cwd: plan.targetDir,\n stdout: \"pipe\",\n stderr: \"pipe\",\n }),\n );\n }\n\n if (plan.tasks.runInitialCodegen) {\n yield* Effect.promise(() => codegenService.runInitial(plan.targetDir, plan.request.packageManager));\n }\n\n if (plan.tasks.initializeGit) {\n yield* Effect.promise(() => gitService.initialize(plan.targetDir));\n }\n\n const packageManagerVersion = yield* Effect.promise(() =>\n packageManagerService.getVersion(plan.request.packageManager, plan.targetDir),\n );\n\n consoleService.success(\n `Created ${plan.request.scopedAppName} in ${plan.targetDir}${\n packageManagerVersion ? ` using ${plan.request.packageManager}@${packageManagerVersion}` : \"\"\n }`,\n );\n consoleService.info(chalk.bold(\"Next steps:\"));\n consoleService.info(renderNextSteps(plan));\n return plan;\n });\n","import path from \"node:path\";\n\nconst TRAILING_SLASHES_REGEX = /\\/+$/;\nconst PATH_SEPARATOR_REGEX = /\\\\/g;\nconst VALID_APP_NAME_REGEX = /^(?:@[a-z0-9-*~][a-z0-9-*._~]*\\/)?[a-z0-9-~][a-z0-9-._~]*$/;\n\nfunction normalizeProjectName(value: string) {\n return value.replace(PATH_SEPARATOR_REGEX, \"/\");\n}\n\nfunction trimTrailingSlashes(value: string) {\n return normalizeProjectName(value).replace(TRAILING_SLASHES_REGEX, \"\");\n}\n\nexport function parseNameAndPath(projectName: string): [scopedAppName: string, appDir: string] {\n const normalized = trimTrailingSlashes(projectName);\n const segments = normalized.split(\"/\");\n let scopedAppName = segments.at(-1) ?? \"\";\n\n if (scopedAppName === \".\") {\n scopedAppName = path.basename(path.resolve(process.cwd()));\n }\n\n const scopeIndex = segments.findIndex((segment) => segment.startsWith(\"@\"));\n if (scopeIndex !== -1) {\n scopedAppName = segments.slice(scopeIndex).join(\"/\");\n }\n\n const appDir = segments.filter((segment) => !segment.startsWith(\"@\")).join(\"/\");\n\n return [scopedAppName, appDir];\n}\n\nexport function validateAppName(projectName: string) {\n const normalized = trimTrailingSlashes(projectName);\n if (normalized === \".\") {\n const currentDirName = path.basename(path.resolve(process.cwd()));\n return VALID_APP_NAME_REGEX.test(currentDirName)\n ? undefined\n : \"Name must consist of only lowercase alphanumeric characters, '-', and '_'\";\n }\n\n const segments = normalized.split(\"/\");\n const scopeIndex = segments.findIndex((segment) => segment.startsWith(\"@\"));\n let scopedAppName = segments.at(-1);\n\n if (scopeIndex !== -1) {\n scopedAppName = segments.slice(scopeIndex).join(\"/\");\n }\n\n if (VALID_APP_NAME_REGEX.test(scopedAppName ?? \"\")) {\n return;\n }\n\n return \"Name must consist of only lowercase alphanumeric characters, '-', and '_'\";\n}\n","import { Effect } from \"effect\";\n\nimport { DEFAULT_APP_NAME } from \"~/consts.js\";\nimport { CliContext, FileMakerService, PromptService } from \"~/core/context.js\";\nimport type { AppType, CliFlags, DataSourceType, FileMakerInputs, InitRequest } from \"~/core/types.js\";\nimport { createDataSourceEnvNames, getDefaultSchemaName } from \"~/utils/projectFiles.js\";\nimport { parseNameAndPath, validateAppName } from \"~/utils/projectName.js\";\n\nconst defaultFlags: CliFlags = {\n noGit: false,\n noInstall: false,\n force: false,\n default: false,\n CI: false,\n importAlias: \"~/\",\n};\n\nfunction compareSemver(left: string, right: string) {\n const leftParts = left.split(\".\").map((part) => Number.parseInt(part, 10) || 0);\n const rightParts = right.split(\".\").map((part) => Number.parseInt(part, 10) || 0);\n\n for (let index = 0; index < Math.max(leftParts.length, rightParts.length); index += 1) {\n const leftValue = leftParts[index] ?? 0;\n const rightValue = rightParts[index] ?? 0;\n if (leftValue > rightValue) {\n return 1;\n }\n if (leftValue < rightValue) {\n return -1;\n }\n }\n\n return 0;\n}\n\nfunction validateLayoutInputs(flags: CliFlags) {\n const hasLayoutName = Boolean(flags.layoutName);\n const hasSchemaName = Boolean(flags.schemaName);\n\n if (hasLayoutName !== hasSchemaName) {\n throw new Error(\"Both --layout-name and --schema-name must be provided together.\");\n }\n}\n\nasync function resolveHostedFileMakerInputs({\n prompt,\n fileMakerService,\n flags,\n nonInteractive,\n}: {\n prompt: PromptService;\n fileMakerService: FileMakerService;\n flags: CliFlags;\n nonInteractive: boolean;\n}): Promise<FileMakerInputs> {\n validateLayoutInputs(flags);\n\n if (!flags.server && nonInteractive) {\n throw new Error(\n \"Missing required hosted FileMaker inputs in non-interactive mode: --server, --file-name, and --data-api-key.\",\n );\n }\n\n const rawServer =\n flags.server ??\n (await prompt.text({\n message: \"What is the URL of your FileMaker Server?\",\n validate: (value) => {\n try {\n const normalized = value.startsWith(\"http\") ? value : `https://${value}`;\n new URL(normalized);\n return;\n } catch {\n return \"Please enter a valid URL\";\n }\n },\n }));\n\n const { normalizedUrl, versions } = await fileMakerService.validateHostedServerUrl(rawServer);\n const hostedUrl = new URL(normalizedUrl);\n const demoFileName = \"ProofKitDemo.fmp12\";\n\n let selectedFile = flags.fileName;\n let dataApiKey = flags.dataApiKey;\n let layoutName = flags.layoutName;\n let schemaName = flags.schemaName;\n let token: string | undefined;\n let files: Awaited<ReturnType<FileMakerService[\"listFiles\"]>> = [];\n const requireHostedToken = () => {\n if (!token) {\n throw new Error(\"OttoFMS authentication is required for hosted setup.\");\n }\n return token;\n };\n\n if (!(selectedFile && dataApiKey)) {\n if (!(flags.adminApiKey || (versions.ottoVersion && compareSemver(versions.ottoVersion, \"4.7.0\") >= 0))) {\n throw new Error(\n \"OttoFMS 4.7.0 or later is required to auto-login. Upgrade OttoFMS or pass --admin-api-key for hosted setup.\",\n );\n }\n token = flags.adminApiKey ?? (await fileMakerService.getOttoFMSToken({ url: hostedUrl })).token;\n }\n\n if (!selectedFile) {\n if (nonInteractive) {\n throw new Error(\"Missing required FileMaker inputs in non-interactive mode: --file-name, --data-api-key.\");\n }\n\n files = await fileMakerService.listFiles({ url: hostedUrl, token: requireHostedToken() });\n selectedFile = await prompt.searchSelect({\n message: \"Which file would you like to connect to?\",\n options: [\n {\n value: \"$deploy-demo\",\n label: \"Deploy NEW ProofKit Demo File\",\n hint: \"Use OttoFMS to deploy a new file for testing\",\n keywords: [\"demo\", \"proofkit\"],\n },\n ...files\n .slice()\n .sort((left, right) => left.filename.localeCompare(right.filename))\n .map((file) => ({\n value: file.filename,\n label: file.filename,\n hint: file.status,\n keywords: [file.filename],\n })),\n ],\n });\n }\n\n if (!selectedFile) {\n throw new Error(\"No FileMaker file was selected.\");\n }\n\n if (selectedFile === \"$deploy-demo\") {\n if (files.length === 0) {\n files = await fileMakerService.listFiles({ url: hostedUrl, token: requireHostedToken() });\n }\n const demoExists = files.some((file) => file.filename === demoFileName);\n const replaceDemo =\n demoExists && !nonInteractive\n ? await prompt.confirm({\n message: \"The demo file already exists. Do you want to replace it with a fresh copy?\",\n initialValue: false,\n })\n : demoExists;\n const deployed = await fileMakerService.deployDemoFile({\n url: hostedUrl,\n token: requireHostedToken(),\n operation: replaceDemo ? \"replace\" : \"install\",\n });\n selectedFile = deployed.filename;\n dataApiKey = deployed.apiKey;\n layoutName ??= \"API_Contacts\";\n schemaName ??= \"Contacts\";\n }\n\n if (!dataApiKey && nonInteractive) {\n throw new Error(\"Missing required FileMaker inputs in non-interactive mode: --data-api-key.\");\n }\n\n if (!dataApiKey) {\n const apiKeys = (await fileMakerService.listAPIKeys({ url: hostedUrl, token: requireHostedToken() })).filter(\n (apiKey) => apiKey.database === selectedFile,\n );\n\n const selection =\n apiKeys.length === 0\n ? \"create\"\n : await prompt.searchSelect({\n message: \"Which OttoFMS Data API key would you like to use?\",\n options: [\n ...apiKeys.map((apiKey) => ({\n value: apiKey.key,\n label: `${apiKey.label} - ${apiKey.user}`,\n hint: `${apiKey.key.slice(0, 5)}...${apiKey.key.slice(-4)}`,\n keywords: [apiKey.label, apiKey.user, apiKey.database],\n })),\n {\n value: \"create\",\n label: \"Create a new API key\",\n hint: \"Requires FileMaker credentials for this file\",\n keywords: [\"create\", \"new\"],\n },\n ],\n });\n\n if (selection === \"create\") {\n const username = await prompt.text({\n message: `Enter the account name for ${selectedFile}`,\n validate: (value) => (value ? undefined : \"An account name is required\"),\n });\n const password = await prompt.password({\n message: `Enter the password for ${username}`,\n validate: (value) => (value ? undefined : \"A password is required\"),\n });\n dataApiKey = (\n await fileMakerService.createDataAPIKeyWithCredentials({\n url: hostedUrl,\n filename: selectedFile,\n username,\n password,\n })\n ).apiKey;\n } else {\n dataApiKey = selection;\n }\n }\n\n if (!dataApiKey) {\n throw new Error(\"No FileMaker Data API key was selected.\");\n }\n\n const layouts = await fileMakerService.listLayouts({\n dataApiKey,\n fmFile: selectedFile,\n server: hostedUrl.origin,\n });\n\n if (layoutName && !layouts.includes(layoutName)) {\n throw new Error(`Layout \"${layoutName}\" was not found in ${selectedFile}.`);\n }\n\n if (!(nonInteractive || layoutName || schemaName)) {\n const shouldConfigureLayout = await prompt.confirm({\n message: \"Do you want to configure an initial layout for type generation now?\",\n initialValue: false,\n });\n\n if (shouldConfigureLayout) {\n layoutName = await prompt.searchSelect({\n message: \"Select a layout to read data from\",\n options: layouts.map((layout) => ({\n value: layout,\n label: layout,\n keywords: [layout],\n })),\n });\n\n schemaName = await prompt.text({\n message: \"What should the generated schema be called?\",\n defaultValue: getDefaultSchemaName(layoutName),\n validate: (value) => (value ? undefined : \"A schema name is required\"),\n });\n }\n }\n\n return {\n mode: \"hosted-otto\",\n dataSourceName: \"filemaker\",\n envNames: createDataSourceEnvNames(\"filemaker\"),\n server: hostedUrl.origin,\n fileName: selectedFile,\n dataApiKey,\n layoutName,\n schemaName,\n adminApiKey: flags.adminApiKey,\n fmsVersion: versions.fmsVersion,\n ottoVersion: versions.ottoVersion,\n };\n}\n\nasync function resolveFileMakerInputs({\n prompt,\n fileMakerService,\n flags,\n appType,\n nonInteractive,\n}: {\n prompt: PromptService;\n fileMakerService: FileMakerService;\n flags: CliFlags;\n appType: AppType;\n nonInteractive: boolean;\n}) {\n if (flags.dataSource !== \"filemaker\") {\n return { fileMaker: undefined, skipFileMakerSetup: false };\n }\n\n validateLayoutInputs(flags);\n\n if (appType === \"webviewer\" && !flags.server) {\n while (true) {\n const localFmHttp = await fileMakerService.detectLocalFmHttp();\n if (localFmHttp.healthy && localFmHttp.connectedFiles[0]) {\n return {\n fileMaker: {\n mode: \"local-fm-http\",\n dataSourceName: \"filemaker\",\n envNames: createDataSourceEnvNames(\"filemaker\"),\n fmHttpBaseUrl: localFmHttp.baseUrl,\n fileName: localFmHttp.connectedFiles[0],\n layoutName: flags.layoutName,\n schemaName: flags.schemaName,\n } satisfies FileMakerInputs,\n skipFileMakerSetup: false,\n };\n }\n\n if (nonInteractive) {\n if (localFmHttp.healthy) {\n throw new Error(\n \"ProofKit MCP Server was detected, but no FileMaker files are open. Open a file in FileMaker and rerun, or pass --server.\",\n );\n }\n\n throw new Error(\n \"ProofKit MCP Server was not detected and no FileMaker server was provided. Start the ProofKit MCP Server locally or rerun with --server.\",\n );\n }\n\n const fallbackAction = await prompt.select({\n message: localFmHttp.healthy\n ? \"I noticed you have the ProofKit MCP Server installed, but no files are open. How would you like to continue?\"\n : \"ProofKit MCP Server was not detected. How would you like to continue?\",\n options: [\n {\n value: \"retry\",\n label: \"Try again\",\n hint: localFmHttp.healthy\n ? \"Open a FileMaker file, then retry detection\"\n : \"Retry ProofKit MCP Server detection\",\n },\n {\n value: \"hosted\",\n label: \"Continue with hosted setup\",\n hint: \"Use OttoFMS and a hosted FileMaker server\",\n },\n {\n value: \"skip\",\n label: \"Skip for now\",\n hint: \"Create the project and configure FileMaker later\",\n },\n ],\n });\n\n if (fallbackAction === \"retry\") {\n continue;\n }\n\n if (fallbackAction === \"skip\") {\n return {\n fileMaker: undefined,\n skipFileMakerSetup: true,\n };\n }\n\n break;\n }\n }\n\n return {\n fileMaker: await resolveHostedFileMakerInputs({\n prompt,\n fileMakerService,\n flags,\n nonInteractive,\n }),\n skipFileMakerSetup: false,\n };\n}\n\nexport const resolveInitRequest = (name?: string, rawFlags?: CliFlags) =>\n Effect.gen(function* () {\n const flags = { ...defaultFlags, ...rawFlags };\n const prompt = yield* PromptService;\n const fileMakerService = yield* FileMakerService;\n const cliContext = yield* CliContext;\n const nonInteractive = cliContext.nonInteractive || flags.CI || flags.nonInteractive === true;\n\n let projectName = name;\n if (!projectName) {\n if (nonInteractive) {\n return yield* Effect.fail(new Error(\"Project name is required in non-interactive mode.\"));\n }\n\n projectName = yield* Effect.promise(() =>\n prompt.text({\n message: \"What will your project be called?\",\n defaultValue: DEFAULT_APP_NAME,\n validate: validateAppName,\n }),\n );\n }\n\n if (!projectName) {\n return yield* Effect.fail(new Error(\"Project name is required.\"));\n }\n\n const validationError = validateAppName(projectName);\n if (validationError) {\n return yield* Effect.fail(new Error(validationError));\n }\n\n let appType: AppType = flags.appType ?? \"browser\";\n if (!(flags.appType || nonInteractive)) {\n appType = yield* Effect.promise(() =>\n prompt.select({\n message: \"What kind of app do you want to build?\",\n options: [\n {\n value: \"browser\",\n label: \"Web App for Browsers\",\n hint: \"Uses Next.js and hosted deployment\",\n },\n {\n value: \"webviewer\",\n label: \"FileMaker Web Viewer\",\n hint: \"Uses Vite for FileMaker web viewers\",\n },\n ],\n }),\n ).pipe(Effect.map((value) => value as AppType));\n }\n\n const hasExplicitFileMakerInputs = Boolean(\n flags.server || flags.adminApiKey || flags.dataApiKey || flags.fileName || flags.layoutName || flags.schemaName,\n );\n\n let dataSource: DataSourceType = \"none\";\n if (flags.dataSource) {\n dataSource = flags.dataSource;\n } else if (appType === \"webviewer\") {\n dataSource = hasExplicitFileMakerInputs || !(nonInteractive && !flags.server) ? \"filemaker\" : \"none\";\n }\n\n if (!(nonInteractive || flags.dataSource) && appType !== \"webviewer\") {\n dataSource = yield* Effect.promise(() =>\n prompt.select({\n message: \"Do you want to connect to a FileMaker Database now?\",\n options: [\n {\n value: \"filemaker\",\n label: \"Yes\",\n hint: \"Set up env, datasource config, and typegen now\",\n },\n {\n value: \"none\",\n label: \"No\",\n hint: \"You can add a data source later\",\n },\n ],\n }),\n ).pipe(Effect.map((value) => value as DataSourceType));\n }\n\n if (nonInteractive && !flags.dataSource && hasExplicitFileMakerInputs) {\n return yield* Effect.fail(new Error(\"FileMaker flags require --data-source filemaker in non-interactive mode.\"));\n }\n\n if (nonInteractive && dataSource !== \"filemaker\" && hasExplicitFileMakerInputs) {\n return yield* Effect.fail(new Error(\"FileMaker flags require --data-source filemaker in non-interactive mode.\"));\n }\n\n const { fileMaker, skipFileMakerSetup } = yield* Effect.promise(() =>\n resolveFileMakerInputs({\n prompt,\n fileMakerService,\n flags: { ...flags, dataSource },\n appType,\n nonInteractive,\n }),\n );\n\n const [scopedAppName, appDir] = parseNameAndPath(projectName);\n\n return {\n projectName,\n scopedAppName,\n appDir,\n appType,\n ui: flags.ui ?? \"shadcn\",\n dataSource,\n packageManager: cliContext.packageManager,\n noInstall: flags.noInstall,\n noGit: flags.noGit,\n force: flags.force,\n cwd: cliContext.cwd,\n importAlias: flags.importAlias,\n nonInteractive,\n debug: cliContext.debug,\n fileMaker,\n skipFileMakerSetup,\n hasExplicitFileMakerInputs,\n } satisfies InitRequest;\n });\n","import open from \"open\";\n\nexport async function openBrowser(url: string): Promise<void> {\n try {\n await open(url);\n } catch {\n // Ignore open failures and let the user copy the URL manually.\n }\n}\n\nexport const openExternal: (url: string) => Promise<void> = openBrowser;\n","import https from \"node:https\";\nimport axios from \"axios\";\n\nfunction createHttpsAgent() {\n return new https.Agent({\n rejectUnauthorized: process.env.PROOFKIT_ALLOW_INSECURE_TLS !== \"1\",\n });\n}\n\nexport async function getJson<T>(url: string, options?: { headers?: Record<string, string>; timeout?: number }) {\n const response = await axios.get<T>(url, {\n headers: options?.headers,\n httpsAgent: createHttpsAgent(),\n timeout: options?.timeout ?? 10_000,\n validateStatus: null,\n });\n return response;\n}\n\nexport async function postJson<T>(\n url: string,\n data: unknown,\n options?: { headers?: Record<string, string>; timeout?: number },\n) {\n const response = await axios.post<T>(url, data, {\n headers: options?.headers,\n httpsAgent: createHttpsAgent(),\n timeout: options?.timeout ?? 10_000,\n validateStatus: null,\n });\n return response;\n}\n\nexport async function deleteJson(url: string, options?: { headers?: Record<string, string>; timeout?: number }) {\n const response = await axios.delete(url, {\n headers: options?.headers,\n httpsAgent: createHttpsAgent(),\n timeout: options?.timeout ?? 10_000,\n validateStatus: null,\n });\n return response;\n}\n\nexport async function requestJson<T>(\n url: string | URL,\n options?: {\n method?: \"GET\" | \"POST\" | \"DELETE\";\n headers?: Record<string, string>;\n body?: Record<string, unknown>;\n timeoutMs?: number;\n },\n) {\n const response = await axios.request<T>({\n url: url.toString(),\n method: options?.method ?? \"GET\",\n data: options?.body,\n headers: options?.headers,\n httpsAgent: createHttpsAgent(),\n timeout: options?.timeoutMs ?? 10_000,\n });\n return response;\n}\n\nexport async function requestText(\n url: string | URL,\n options?: {\n method?: \"GET\" | \"POST\" | \"DELETE\";\n headers?: Record<string, string>;\n timeoutMs?: number;\n },\n) {\n const response = await axios.request<string>({\n url: url.toString(),\n method: options?.method ?? \"GET\",\n headers: options?.headers,\n httpsAgent: createHttpsAgent(),\n timeout: options?.timeoutMs ?? 10_000,\n responseType: \"text\",\n validateStatus: null,\n });\n return {\n status: response.status,\n data: response.data,\n };\n}\n","export type PackageManager = \"npm\" | \"pnpm\" | \"yarn\" | \"bun\";\n\nexport function detectUserPackageManager(): PackageManager {\n const userAgent = process.env.npm_config_user_agent;\n\n if (userAgent) {\n if (userAgent.startsWith(\"yarn\")) {\n return \"yarn\";\n }\n if (userAgent.startsWith(\"pnpm\")) {\n return \"pnpm\";\n }\n if (userAgent.startsWith(\"bun\")) {\n return \"bun\";\n }\n return \"npm\";\n }\n\n return \"npm\";\n}\n","import {\n intro as clackIntro,\n isCancel as clackIsCancel,\n log as clackLog,\n note as clackNote,\n outro as clackOutro,\n spinner as clackSpinner,\n} from \"@clack/prompts\";\nimport {\n checkbox as inquirerCheckbox,\n confirm as inquirerConfirm,\n input as inquirerInput,\n password as inquirerPassword,\n search as inquirerSearch,\n select as inquirerSelect,\n} from \"@inquirer/prompts\";\n\nconst CANCEL_SYMBOL = Symbol.for(\"@proofkit/new/prompt-cancelled\");\n\nexport const intro = clackIntro;\nexport const log = clackLog;\nexport const note = clackNote;\nexport const outro = clackOutro;\nexport const spinner = clackSpinner;\n\nfunction isPromptCancel(error: unknown) {\n return error instanceof Error && error.name === \"ExitPromptError\";\n}\n\nfunction withCancelSentinel<T>(fn: () => Promise<T>): Promise<T | symbol> {\n return fn().catch((error: unknown) => {\n if (isPromptCancel(error)) {\n return CANCEL_SYMBOL;\n }\n throw error;\n });\n}\n\nexport function isCancel(value: unknown): value is symbol {\n return value === CANCEL_SYMBOL || clackIsCancel(value);\n}\n\nexport interface PromptOption<T extends string> {\n value: T;\n label: string;\n hint?: string;\n disabled?: boolean | string;\n}\n\nexport interface SearchPromptOption<T extends string> extends PromptOption<T> {\n keywords?: readonly string[];\n}\n\nfunction normalizeValidate(\n validate: ((value: string) => string | undefined) | undefined,\n): ((value: string) => string | boolean) | undefined {\n if (!validate) {\n return undefined;\n }\n\n return (value: string) => validate(value) ?? true;\n}\n\nfunction matchesSearch(option: SearchPromptOption<string>, query: string) {\n const haystack = [option.label, option.hint ?? \"\", ...(option.keywords ?? [])].join(\" \").toLowerCase();\n return haystack.includes(query.trim().toLowerCase());\n}\n\nfunction normalizeDisabledMessage(value: boolean | string | undefined) {\n if (typeof value === \"string\") {\n return value;\n }\n return value ? true : undefined;\n}\n\nexport function filterSearchOptions<T extends string>(\n options: readonly SearchPromptOption<T>[],\n query: string | undefined,\n) {\n const term = query?.trim();\n if (!term) {\n return options;\n }\n\n return options.filter((option) => matchesSearch(option, term));\n}\n\nexport function textPrompt(options: {\n message: string;\n defaultValue?: string;\n validate?: (value: string) => string | undefined;\n}) {\n return withCancelSentinel(() =>\n inquirerInput({\n message: options.message,\n default: options.defaultValue,\n validate: normalizeValidate(options.validate),\n }),\n );\n}\n\nexport function passwordPrompt(options: { message: string; validate?: (value: string) => string | undefined }) {\n return withCancelSentinel(() =>\n inquirerPassword({\n message: options.message,\n validate: normalizeValidate(options.validate),\n }),\n );\n}\n\nexport function confirmPrompt(options: { message: string; initialValue?: boolean }) {\n return withCancelSentinel(() =>\n inquirerConfirm({\n message: options.message,\n default: options.initialValue,\n }),\n );\n}\n\nexport function selectPrompt<T extends string>(options: { message: string; options: PromptOption<T>[] }) {\n return withCancelSentinel(() =>\n inquirerSelect<T>({\n message: options.message,\n pageSize: 10,\n choices: options.options.map((option) => ({\n value: option.value,\n name: option.label,\n description: option.hint,\n disabled: normalizeDisabledMessage(option.disabled),\n })),\n }),\n );\n}\n\nexport function searchSelectPrompt<T extends string>(options: {\n message: string;\n emptyMessage?: string;\n options: SearchPromptOption<T>[];\n}) {\n return withCancelSentinel(() =>\n inquirerSearch<T>({\n message: options.message,\n pageSize: 10,\n source: (input) => {\n const filtered = filterSearchOptions(options.options, input);\n if (filtered.length === 0) {\n return [\n {\n value: \"__no_matches__\" as T,\n name: options.emptyMessage ?? \"No matches found. Keep typing to refine your search.\",\n disabled: options.emptyMessage ?? \"No matches found\",\n },\n ];\n }\n\n return filtered.map((option) => ({\n value: option.value,\n name: option.label,\n description: option.hint,\n disabled: normalizeDisabledMessage(option.disabled),\n }));\n },\n }),\n );\n}\n\nexport function multiSearchSelectPrompt<T extends string>(options: {\n message: string;\n options: SearchPromptOption<T>[];\n required?: boolean;\n}) {\n return withCancelSentinel(() =>\n inquirerCheckbox<T>({\n message: options.message,\n pageSize: 10,\n required: options.required,\n choices: options.options.map((option) => ({\n value: option.value,\n name: option.label,\n description: option.hint,\n disabled: normalizeDisabledMessage(option.disabled),\n })),\n }),\n );\n}\n","import { randomUUID } from \"node:crypto\";\nimport path from \"node:path\";\nimport { Effect, Layer } from \"effect\";\nimport { execa } from \"execa\";\nimport fs from \"fs-extra\";\nimport { TEMPLATE_ROOT } from \"~/consts.js\";\nimport {\n CliContext,\n type CliContextValue,\n CodegenService,\n ConsoleService,\n type FileMakerBootstrapArtifacts,\n FileMakerService,\n FileSystemService,\n GitService,\n type OttoApiKeyInfo,\n type OttoFileInfo,\n PackageManagerService,\n ProcessService,\n PromptService,\n SettingsService,\n TemplateService,\n} from \"~/core/context.js\";\nimport { UserAbortedError } from \"~/core/errors.js\";\nimport type { AppType, FileMakerInputs, ProofKitSettings, UIType } from \"~/core/types.js\";\nimport { openBrowser } from \"~/utils/browserOpen.js\";\nimport { deleteJson, getJson, postJson } from \"~/utils/http.js\";\nimport { detectUserPackageManager } from \"~/utils/packageManager.js\";\nimport { createDataSourceEnvNames, updateEnvSchemaFile, updateTypegenConfig } from \"~/utils/projectFiles.js\";\nimport {\n confirmPrompt,\n spinner as createSpinner,\n isCancel,\n log,\n multiSearchSelectPrompt,\n note,\n passwordPrompt,\n searchSelectPrompt,\n selectPrompt,\n textPrompt,\n} from \"~/utils/prompts.js\";\n\nfunction unwrap<T>(value: T | symbol): T {\n if (isCancel(value)) {\n throw new UserAbortedError();\n }\n return value as T;\n}\n\nfunction normalizeUrl(serverUrl: string) {\n if (serverUrl.startsWith(\"https://\")) {\n return serverUrl;\n }\n if (serverUrl.startsWith(\"http://\")) {\n return serverUrl.replace(\"http://\", \"https://\");\n }\n return `https://${serverUrl}`;\n}\n\ninterface LayoutFolder {\n isFolder?: boolean;\n name?: string;\n folderLayoutNames?: LayoutFolder[];\n}\n\nfunction transformLayoutList(layouts: LayoutFolder[]): string[] {\n const flatten = (layout: LayoutFolder): string[] => {\n if (layout.isFolder === true) {\n const folderLayouts = Array.isArray(layout.folderLayoutNames) ? layout.folderLayoutNames : [];\n return folderLayouts.flatMap((item) => flatten(item));\n }\n return typeof layout.name === \"string\" ? [layout.name] : [];\n };\n\n return layouts.flatMap(flatten).sort((left, right) => left.localeCompare(right));\n}\n\nconst promptService = {\n text: async (options: { message: string; defaultValue?: string; validate?: (value: string) => string | undefined }) =>\n unwrap(\n await textPrompt({\n message: options.message,\n defaultValue: options.defaultValue,\n validate: options.validate,\n }),\n ).toString(),\n password: async (options: { message: string; validate?: (value: string) => string | undefined }) =>\n unwrap(\n await passwordPrompt({\n message: options.message,\n validate: options.validate,\n }),\n ).toString(),\n select: async <T extends string>(options: {\n message: string;\n options: Array<{ value: T; label: string; hint?: string }>;\n }) =>\n unwrap(\n await selectPrompt({\n message: options.message,\n options: options.options,\n }),\n ) as T,\n searchSelect: async <T extends string>(options: {\n message: string;\n emptyMessage?: string;\n options: Array<{ value: T; label: string; hint?: string; keywords?: string[]; disabled?: boolean | string }>;\n }) => unwrap(await searchSelectPrompt(options)) as T,\n multiSearchSelect: async <T extends string>(options: {\n message: string;\n options: Array<{ value: T; label: string; hint?: string; keywords?: string[]; disabled?: boolean | string }>;\n required?: boolean;\n }) => unwrap(await multiSearchSelectPrompt(options)),\n confirm: async (options: { message: string; initialValue?: boolean }) =>\n unwrap(\n await confirmPrompt({\n message: options.message,\n initialValue: options.initialValue,\n }),\n ) as boolean,\n};\n\nconst consoleService = {\n info: (message: string) => log.info(message),\n warn: (message: string) => log.warn(message),\n error: (message: string) => log.error(message),\n success: (message: string) => log.success(message),\n note: (message: string, title?: string) => note(message, title),\n};\n\nconst fileSystemService = {\n exists: async (targetPath: string) => fs.pathExists(targetPath),\n readdir: async (targetPath: string) => fs.readdir(targetPath),\n emptyDir: async (targetPath: string) => fs.emptyDir(targetPath),\n copyDir: async (from: string, to: string, options?: { overwrite?: boolean }) =>\n fs.copy(from, to, { overwrite: options?.overwrite ?? true }),\n rename: async (from: string, to: string) => fs.rename(from, to),\n remove: async (targetPath: string) => fs.remove(targetPath),\n readJson: async <T>(targetPath: string) => fs.readJson(targetPath) as Promise<T>,\n writeJson: async (targetPath: string, value: unknown) => fs.writeJson(targetPath, value, { spaces: 2 }),\n writeFile: async (targetPath: string, content: string) => fs.writeFile(targetPath, content, \"utf8\"),\n readFile: async (targetPath: string) => fs.readFile(targetPath, \"utf8\"),\n};\n\nconst templateService = {\n getTemplateDir: (appType: AppType, ui: UIType) => {\n if (appType === \"webviewer\") {\n return path.join(TEMPLATE_ROOT, \"vite-wv\");\n }\n if (ui === \"mantine\") {\n return path.join(TEMPLATE_ROOT, \"nextjs-mantine\");\n }\n return path.join(TEMPLATE_ROOT, \"nextjs-shadcn\");\n },\n};\n\nconst packageManagerService = {\n getVersion: async (packageManager: string, cwd: string) => {\n if (packageManager === \"bun\") {\n return undefined;\n }\n const { stdout } = await execa(packageManager, [\"-v\"], { cwd });\n return stdout.trim();\n },\n};\n\nconst processService = {\n run: async (\n command: string,\n args: string[],\n options: {\n cwd: string;\n stdout?: \"pipe\" | \"inherit\" | \"ignore\";\n stderr?: \"pipe\" | \"inherit\" | \"ignore\";\n },\n ) => {\n const result = await execa(command, args, {\n cwd: options.cwd,\n stdout: options.stdout ?? \"pipe\",\n stderr: options.stderr ?? \"pipe\",\n });\n return {\n stdout: result.stdout ?? \"\",\n stderr: result.stderr ?? \"\",\n };\n },\n};\n\nconst gitService = {\n initialize: async (projectDir: string) => {\n await execa(\"git\", [\"init\"], { cwd: projectDir });\n await execa(\"git\", [\"add\", \".\"], { cwd: projectDir });\n await execa(\"git\", [\"commit\", \"-m\", \"Initial commit\"], { cwd: projectDir });\n },\n};\n\nconst settingsService = {\n writeSettings: async (projectDir: string, settings: ProofKitSettings) =>\n fs.writeJson(path.join(projectDir, \"proofkit.json\"), settings, { spaces: 2 }),\n appendEnvVars: async (projectDir: string, vars: Record<string, string>) => {\n const envPath = path.join(projectDir, \".env\");\n const existing = (await fs.pathExists(envPath)) ? await fs.readFile(envPath, \"utf8\") : \"\";\n const additions = Object.entries(vars)\n .map(([name, value]) => `${name}=${value}`)\n .join(\"\\n\");\n const nextContent = [existing.trimEnd(), additions].filter(Boolean).join(\"\\n\").concat(\"\\n\");\n await fs.writeFile(envPath, nextContent, \"utf8\");\n },\n ensureTypegenConfig: async (_projectDir: string, _options: { appType: AppType; fileMaker?: FileMakerInputs }) =>\n undefined,\n};\n\nfunction createDataSourceEntry(dataSourceName: string) {\n return {\n type: \"fm\" as const,\n name: dataSourceName,\n envNames: createDataSourceEnvNames(dataSourceName),\n };\n}\n\nfunction createFileMakerBootstrapArtifacts(\n settings: ProofKitSettings,\n inputs: FileMakerInputs,\n appType: AppType,\n): Promise<FileMakerBootstrapArtifacts> {\n const dataSourceEntry = createDataSourceEntry(inputs.dataSourceName);\n const nextSettings: ProofKitSettings = {\n ...settings,\n dataSources: settings.dataSources.some((entry) => entry.name === dataSourceEntry.name)\n ? settings.dataSources\n : [...settings.dataSources, dataSourceEntry],\n };\n\n if (inputs.mode === \"local-fm-http\") {\n return Promise.resolve({\n settings: nextSettings,\n envVars: {},\n envSchemaEntries: [],\n typegenConfig: {\n mode: inputs.mode,\n dataSourceName: inputs.dataSourceName,\n fmHttpBaseUrl: inputs.fmHttpBaseUrl,\n connectedFileName: inputs.fileName,\n layoutName: inputs.layoutName,\n schemaName: inputs.schemaName,\n appType,\n },\n });\n }\n\n return Promise.resolve({\n settings: nextSettings,\n envVars: {\n [inputs.envNames.database]: inputs.fileName,\n [inputs.envNames.server]: inputs.server,\n [inputs.envNames.apiKey]: inputs.dataApiKey,\n },\n envSchemaEntries: [\n {\n name: inputs.envNames.database,\n zodSchema: 'z.string().endsWith(\".fmp12\")',\n defaultValue: inputs.fileName,\n },\n {\n name: inputs.envNames.server,\n zodSchema: \"z.string().url()\",\n defaultValue: inputs.server,\n },\n {\n name: inputs.envNames.apiKey,\n zodSchema: 'z.string().startsWith(\"dk_\")',\n defaultValue: inputs.dataApiKey,\n },\n ],\n typegenConfig: {\n mode: inputs.mode,\n dataSourceName: inputs.dataSourceName,\n envNames: inputs.envNames,\n layoutName: inputs.layoutName,\n schemaName: inputs.schemaName,\n appType,\n },\n });\n}\n\nconst fileMakerService = {\n detectLocalFmHttp: async (baseUrl = process.env.FM_HTTP_BASE_URL ?? \"http://127.0.0.1:1365\") => {\n try {\n const health = await fetch(`${baseUrl}/health`, { signal: AbortSignal.timeout(3000) });\n if (!health.ok) {\n return { baseUrl, healthy: false, connectedFiles: [] };\n }\n const connectedFiles = await fetch(`${baseUrl}/connectedFiles`, { signal: AbortSignal.timeout(3000) })\n .then(async (response) => (response.ok ? ((await response.json()) as unknown) : []))\n .catch(() => []);\n return {\n baseUrl,\n healthy: true,\n connectedFiles: Array.isArray(connectedFiles)\n ? connectedFiles.filter((item): item is string => typeof item === \"string\")\n : [],\n };\n } catch {\n return { baseUrl, healthy: false, connectedFiles: [] };\n }\n },\n validateHostedServerUrl: async (serverUrl: string, ottoPort?: number | null) => {\n const normalizedUrl = normalizeUrl(serverUrl);\n const fmsUrl = new URL(\"/fmws/serverinfo\", normalizedUrl).toString();\n const fmsResponse = await getJson<{ data?: { ServerVersion?: string } }>(fmsUrl);\n const serverVersion = fmsResponse.data?.data?.ServerVersion?.split(\" \")[0];\n if (!serverVersion) {\n throw new Error(`Invalid FileMaker Server URL: ${normalizedUrl}`);\n }\n\n let ottoVersion: string | null = null;\n const otto4Response = await getJson<{ response?: { Otto?: { version?: string } } }>(\n new URL(\"/otto/api/info\", normalizedUrl).toString(),\n ).catch(() => undefined);\n ottoVersion = otto4Response?.data?.response?.Otto?.version ?? null;\n\n if (!ottoVersion) {\n const otto3Url = new URL(normalizedUrl);\n otto3Url.port = ottoPort ? String(ottoPort) : \"3030\";\n otto3Url.pathname = \"/api/otto/info\";\n const otto3Response = await getJson<{ Otto?: { version?: string } }>(otto3Url.toString()).catch(() => undefined);\n ottoVersion = otto3Response?.data?.Otto?.version ?? null;\n }\n\n return {\n normalizedUrl: new URL(normalizedUrl).origin,\n versions: {\n fmsVersion: serverVersion,\n ottoVersion,\n },\n };\n },\n getOttoFMSToken: async ({ url }: { url: URL }) => {\n const hash = randomUUID().replaceAll(\"-\", \"\").slice(0, 18);\n const loginUrl = new URL(`/otto/wizard/${hash}`, url.origin);\n log.info(`If the browser window didn't open automatically, use this Otto login URL:\\n${loginUrl.toString()}`);\n await openBrowser(loginUrl.toString());\n\n const spin = createSpinner();\n spin.start(\"Waiting for OttoFMS login\");\n\n const deadline = Date.now() + 180_000;\n while (Date.now() < deadline) {\n const response = await getJson<{ response?: { token?: string } }>(\n `${url.origin}/otto/api/cli/checkHash/${hash}`,\n { headers: { \"Accept-Encoding\": \"deflate\" }, timeout: 5000 },\n ).catch(() => undefined);\n const token = response?.data?.response?.token;\n if (token) {\n spin.stop(\"Login complete\");\n await deleteJson(`${url.origin}/otto/api/cli/checkHash/${hash}`, {\n headers: { \"Accept-Encoding\": \"deflate\" },\n }).catch(() => undefined);\n return { token };\n }\n await new Promise((resolve) => setTimeout(resolve, 500));\n }\n\n spin.stop(\"Login timed out\");\n throw new Error(\"OttoFMS login timed out after 3 minutes.\");\n },\n listFiles: async ({ url, token }: { url: URL; token: string }) => {\n const response = await getJson<{ response?: { databases?: Array<{ filename?: string; status?: string }> } }>(\n `${url.origin}/otto/fmi/admin/api/v2/databases`,\n {\n headers: {\n Authorization: `Bearer ${token}`,\n },\n },\n );\n const databases = (response.data?.response?.databases ?? []) as Record<string, unknown>[];\n return databases\n .filter((database): database is { filename: string; status?: string } => typeof database.filename === \"string\")\n .map(\n (database) =>\n ({\n filename: database.filename,\n status: database.status ?? \"unknown\",\n }) satisfies OttoFileInfo,\n );\n },\n listAPIKeys: async ({ url, token }: { url: URL; token: string }) => {\n const response = await getJson<{ response?: { \"api-keys\"?: Record<string, unknown>[] } }>(\n `${url.origin}/otto/api/api-key`,\n {\n headers: {\n Authorization: `Bearer ${token}`,\n },\n },\n );\n const apiKeys = (response.data?.response?.[\"api-keys\"] ?? []) as Record<string, unknown>[];\n return apiKeys\n .filter(\n (apiKey): apiKey is { key: string; user: string; database: string; label: string } =>\n typeof apiKey.key === \"string\" &&\n typeof apiKey.user === \"string\" &&\n typeof apiKey.database === \"string\" &&\n typeof apiKey.label === \"string\",\n )\n .map(\n (apiKey) =>\n ({\n key: apiKey.key,\n user: apiKey.user,\n database: apiKey.database,\n label: apiKey.label,\n }) satisfies OttoApiKeyInfo,\n );\n },\n createDataAPIKeyWithCredentials: async ({\n url,\n filename,\n username,\n password: userPassword,\n }: {\n url: URL;\n filename: string;\n username: string;\n password: string;\n }) => {\n const response = await postJson<{ response?: { key?: string } }>(`${url.origin}/otto/api/api-key/create-only`, {\n database: filename,\n label: \"For FM Web App\",\n user: username,\n pass: userPassword,\n });\n const apiKey = response.data?.response?.key;\n if (!apiKey) {\n throw new Error(`Failed to create a Data API key for ${filename}.`);\n }\n return { apiKey };\n },\n startDeployment: async ({ payload, url, token }: { payload: unknown; url: URL; token: string }) =>\n postJson<{ response?: { subDeploymentIds?: number[] } }>(`${url.origin}/otto/api/deployment`, payload, {\n headers: {\n Authorization: `Bearer ${token}`,\n },\n }),\n getDeploymentStatus: async ({ url, token, deploymentId }: { url: URL; token: string; deploymentId: number }) =>\n getJson<{ response?: { status?: string; running?: boolean } }>(\n `${url.origin}/otto/api/deployment/${deploymentId}`,\n {\n headers: {\n Authorization: `Bearer ${token}`,\n },\n },\n ),\n deployDemoFile: async ({ url, token, operation }: { url: URL; token: string; operation: \"install\" | \"replace\" }) => {\n const demoFileName = \"ProofKitDemo.fmp12\";\n const spin = createSpinner();\n spin.start(\"Deploying ProofKit Demo file\");\n\n const deploymentPayload = {\n scheduled: false,\n label: \"Install ProofKit Demo\",\n deployments: [\n {\n name: \"Install ProofKit Demo\",\n source: {\n type: \"url\",\n url: \"https://proofkit.dev/proofkit-demo/manifest.json\",\n },\n fileOperations: [\n {\n target: {\n fileName: demoFileName,\n },\n operation,\n source: {\n fileName: demoFileName,\n },\n location: {\n folder: \"default\",\n subFolder: \"\",\n },\n },\n ],\n concurrency: 1,\n options: {\n closeFilesAfterBuild: false,\n keepFilesClosedAfterComplete: false,\n transferContainerData: false,\n },\n },\n ],\n abortRemaining: false,\n };\n\n const deployment = await fileMakerService.startDeployment({\n payload: deploymentPayload,\n url,\n token,\n });\n\n const deploymentId = deployment.data?.response?.subDeploymentIds?.[0];\n if (!deploymentId) {\n spin.stop(\"Demo deployment failed\");\n throw new Error(\"No deployment ID was returned when deploying the demo file.\");\n }\n\n const deploymentDeadline = Date.now() + 300_000;\n let deploymentCompleted = false;\n while (Date.now() < deploymentDeadline) {\n await new Promise((resolve) => setTimeout(resolve, 2500));\n const status = await fileMakerService.getDeploymentStatus({\n url,\n token,\n deploymentId,\n });\n\n if (!status.data?.response?.running) {\n if (status.data?.response?.status !== \"complete\") {\n spin.stop(\"Demo deployment failed\");\n throw new Error(\"ProofKit Demo deployment did not complete successfully.\");\n }\n deploymentCompleted = true;\n break;\n }\n }\n\n if (!deploymentCompleted) {\n spin.stop(\"Demo deployment timed out\");\n throw new Error(\"ProofKit Demo deployment timed out after 5 minutes.\");\n }\n\n const apiKey = await fileMakerService.createDataAPIKeyWithCredentials({\n url,\n filename: demoFileName,\n username: \"admin\",\n password: \"admin\",\n });\n spin.stop(\"Demo file deployed\");\n return { apiKey: apiKey.apiKey, filename: demoFileName };\n },\n listLayouts: async ({ dataApiKey, fmFile, server }: { dataApiKey: string; fmFile: string; server: string }) => {\n const response = await getJson<{ response?: { layouts?: LayoutFolder[] } }>(\n `${server}/otto/fmi/data/vLatest/databases/${encodeURIComponent(fmFile)}/layouts`,\n {\n headers: {\n Authorization: `Bearer ${dataApiKey}`,\n },\n },\n );\n return transformLayoutList(response.data?.response?.layouts ?? []);\n },\n createFileMakerBootstrapArtifacts,\n bootstrap: async (projectDir: string, settings: ProofKitSettings, inputs: FileMakerInputs, appType: AppType) => {\n const artifacts = await createFileMakerBootstrapArtifacts(settings, inputs, appType);\n if (Object.keys(artifacts.envVars).length > 0) {\n await settingsService.appendEnvVars(projectDir, artifacts.envVars);\n await updateEnvSchemaFile(fileSystemService, projectDir, artifacts.envSchemaEntries);\n }\n\n await updateTypegenConfig(fileSystemService, projectDir, {\n appType: artifacts.typegenConfig.appType,\n dataSourceName: artifacts.typegenConfig.dataSourceName,\n envNames: artifacts.typegenConfig.envNames,\n fmHttpBaseUrl: artifacts.typegenConfig.fmHttpBaseUrl,\n connectedFileName: artifacts.typegenConfig.connectedFileName,\n layoutName: artifacts.typegenConfig.layoutName,\n schemaName: artifacts.typegenConfig.schemaName,\n });\n\n return artifacts.settings;\n },\n};\n\nconst codegenService = {\n runInitial: async (projectDir: string, packageManager: CliContextValue[\"packageManager\"]) => {\n let commandParts: string[];\n if (packageManager === \"npm\") {\n commandParts = [\"npm\", \"run\", \"typegen\"];\n } else if (packageManager === \"bun\") {\n commandParts = [\"bun\", \"run\", \"typegen\"];\n } else {\n commandParts = [packageManager, \"typegen\"];\n }\n const command = commandParts[0];\n if (!command) {\n throw new Error(\"Unable to resolve the codegen command\");\n }\n const args = commandParts.slice(1);\n await execa(command, args, { cwd: projectDir });\n },\n};\n\nexport function makeLiveLayer(options: { cwd: string; debug: boolean; nonInteractive: boolean }) {\n const cliContext: CliContextValue = {\n cwd: options.cwd,\n debug: options.debug,\n nonInteractive: options.nonInteractive,\n packageManager: detectUserPackageManager(),\n };\n\n const layer = Layer.mergeAll(\n Layer.succeed(CliContext, cliContext),\n Layer.succeed(PromptService, promptService),\n Layer.succeed(ConsoleService, consoleService),\n Layer.succeed(FileSystemService, fileSystemService),\n Layer.succeed(TemplateService, templateService),\n Layer.succeed(PackageManagerService, packageManagerService),\n Layer.succeed(ProcessService, processService),\n Layer.succeed(GitService, gitService),\n Layer.succeed(SettingsService, settingsService),\n Layer.succeed(FileMakerService, fileMakerService),\n Layer.succeed(CodegenService, codegenService),\n );\n\n return <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.provide(effect, layer);\n}\n","import gradient from \"gradient-string\";\nimport { getTitleText } from \"~/consts.js\";\nimport { detectUserPackageManager } from \"~/utils/packageManager.js\";\n\nconst proofTheme = {\n purple: \"#89216B\",\n lightPurple: \"#D15ABB\",\n orange: \"#FF595E\",\n};\n\nexport const proofGradient = gradient(Object.values(proofTheme));\nexport function renderTitle(version = \"0.0.0-private\") {\n const pkgManager = detectUserPackageManager();\n if (pkgManager === \"yarn\" || pkgManager === \"pnpm\") {\n console.log(\"\");\n }\n console.log(proofGradient.multiline(getTitleText(version)));\n}\n","#!/usr/bin/env node\nimport { readFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { optional as optionalArg, text as textArg, withDescription as withArgDescription } from \"@effect/cli/Args\";\nimport {\n make as makeCommand,\n run,\n withDescription as withCommandDescription,\n withSubcommands,\n} from \"@effect/cli/Command\";\nimport {\n boolean as booleanOption,\n choice as choiceOption,\n optional as optionalOption,\n text as textOption,\n withAlias,\n withDescription as withOptionDescription,\n} from \"@effect/cli/Options\";\nimport { isValidationError } from \"@effect/cli/ValidationError\";\nimport { layer as nodeContextLayer } from \"@effect/platform-node/NodeContext\";\nimport { Cause, Effect, Exit } from \"effect\";\nimport { getOrUndefined } from \"effect/Option\";\nimport { cliName } from \"~/consts.js\";\nimport {\n CliContext,\n ConsoleService,\n FileSystemService,\n PackageManagerService,\n TemplateService,\n} from \"~/core/context.js\";\nimport { executeInitPlan } from \"~/core/executeInitPlan.js\";\nimport { planInit } from \"~/core/planInit.js\";\nimport { resolveInitRequest } from \"~/core/resolveInitRequest.js\";\nimport type { CliFlags } from \"~/core/types.js\";\nimport { makeLiveLayer } from \"~/services/live.js\";\nimport { intro } from \"~/utils/prompts.js\";\nimport { proofGradient, renderTitle } from \"~/utils/renderTitle.js\";\n\nconst defaultCliFlags: CliFlags = {\n noGit: false,\n noInstall: false,\n force: false,\n default: false,\n CI: false,\n importAlias: \"~/\",\n};\n\nfunction getCliVersion() {\n try {\n const packageJsonUrl = new URL(\"../package.json\", import.meta.url);\n const packageJson = JSON.parse(readFileSync(fileURLToPath(packageJsonUrl), \"utf8\")) as { version?: string };\n return packageJson.version ?? \"0.0.0-private\";\n } catch {\n return \"0.0.0-private\";\n }\n}\n\nexport const runInit = (name?: string, rawFlags?: Partial<CliFlags>) =>\n Effect.gen(function* () {\n const templateService = yield* TemplateService;\n const packageManagerService = yield* PackageManagerService;\n const request = yield* resolveInitRequest(name, { ...defaultCliFlags, ...rawFlags });\n const templateDir = templateService.getTemplateDir(request.appType, request.ui);\n const packageManagerVersion = yield* Effect.promise(() =>\n packageManagerService.getVersion(request.packageManager, request.cwd),\n );\n const plan = planInit(request, { templateDir, packageManagerVersion });\n yield* executeInitPlan(plan);\n return { request, plan };\n });\n\nexport const runDefaultCommand = (rawFlags?: Partial<CliFlags>) =>\n Effect.gen(function* () {\n const cliContext = yield* CliContext;\n const fsService = yield* FileSystemService;\n const consoleService = yield* ConsoleService;\n const flags = { ...defaultCliFlags, ...rawFlags };\n\n if (cliContext.nonInteractive || flags.CI || flags.nonInteractive) {\n throw new Error(\n \"The default command is interactive-only in non-interactive mode. Run an explicit command such as `proofkit init <name> --non-interactive`.\",\n );\n }\n\n const settingsPath = path.join(cliContext.cwd, \"proofkit.json\");\n const hasProofKitProject = yield* Effect.promise(() => fsService.exists(settingsPath));\n\n if (hasProofKitProject) {\n intro(`Found ${proofGradient(\"ProofKit\")} project`);\n consoleService.note(\n [\n \"Project command routing is being migrated into the Effect CLI surface.\",\n \"Use an explicit command such as `proofkit add`, `proofkit remove`, `proofkit typegen`, `proofkit deploy`, or `proofkit upgrade`.\",\n ].join(\"\\n\"),\n \"Project commands\",\n );\n return;\n }\n\n intro(`No ${proofGradient(\"ProofKit\")} project found, running \\`init\\``);\n yield* runInit(undefined, {\n ...flags,\n default: true,\n });\n });\n\nconst initDirectoryArg = optionalArg(textArg({ name: \"dir\" })).pipe(\n withArgDescription(\"The project name or target directory\"),\n);\n\nfunction optionalTextOption(name: string, description: string) {\n return optionalOption(textOption(name).pipe(withOptionDescription(description)));\n}\n\nfunction optionalChoiceOption<Choices extends readonly string[]>(name: string, choices: Choices, description: string) {\n return optionalOption(choiceOption(name, choices).pipe(withOptionDescription(description)));\n}\n\nfunction legacyEffect<T>(runLegacy: () => Promise<T>, options?: { nonInteractive?: boolean; debug?: boolean }) {\n return makeLiveLayer({\n cwd: process.cwd(),\n debug: options?.debug === true,\n nonInteractive: options?.nonInteractive === true,\n })(Effect.promise(runLegacy));\n}\n\nfunction makeInitCommand() {\n return makeCommand(\n \"init\",\n {\n dir: initDirectoryArg,\n appType: optionalChoiceOption(\"app-type\", [\"browser\", \"webviewer\"] as const, \"The type of app to create\"),\n ui: optionalChoiceOption(\"ui\", [\"shadcn\", \"mantine\"] as const, \"The UI scaffold to create\"),\n server: optionalTextOption(\"server\", \"The URL of your FileMaker Server\"),\n adminApiKey: optionalTextOption(\"admin-api-key\", \"Admin API key for OttoFMS\"),\n fileName: optionalTextOption(\"file-name\", \"The name of the FileMaker file\"),\n layoutName: optionalTextOption(\"layout-name\", \"The FileMaker layout name to scaffold\"),\n schemaName: optionalTextOption(\"schema-name\", \"The generated schema name\"),\n dataApiKey: optionalTextOption(\"data-api-key\", \"The Otto Data API key to use\"),\n dataSource: optionalChoiceOption(\"data-source\", [\"filemaker\", \"none\"] as const, \"The data source to use\"),\n noGit: booleanOption(\"no-git\").pipe(withOptionDescription(\"Skip git initialization\")),\n noInstall: booleanOption(\"no-install\").pipe(withOptionDescription(\"Skip package installation\")),\n force: booleanOption(\"force\").pipe(\n withAlias(\"f\"),\n withOptionDescription(\"Force overwrite target directory when it already contains files\"),\n ),\n CI: booleanOption(\"ci\").pipe(withOptionDescription(\"Deprecated alias for --non-interactive\")),\n nonInteractive: booleanOption(\"non-interactive\").pipe(\n withOptionDescription(\"Never prompt for input; fail when required values are missing\"),\n ),\n debug: booleanOption(\"debug\").pipe(withOptionDescription(\"Run in debug mode\")),\n },\n ({ dir, ...options }) => {\n const flags: CliFlags = {\n ...defaultCliFlags,\n appType: getOrUndefined(options.appType),\n ui: getOrUndefined(options.ui),\n server: getOrUndefined(options.server),\n adminApiKey: getOrUndefined(options.adminApiKey),\n fileName: getOrUndefined(options.fileName),\n layoutName: getOrUndefined(options.layoutName),\n schemaName: getOrUndefined(options.schemaName),\n dataApiKey: getOrUndefined(options.dataApiKey),\n dataSource: getOrUndefined(options.dataSource),\n noGit: options.noGit,\n noInstall: options.noInstall,\n force: options.force,\n CI: options.CI,\n nonInteractive: options.nonInteractive,\n debug: options.debug,\n };\n\n return makeLiveLayer({\n cwd: process.cwd(),\n debug: flags.debug === true,\n nonInteractive: Boolean(flags.CI || flags.nonInteractive),\n })(runInit(getOrUndefined(dir), flags));\n },\n ).pipe(withCommandDescription(\"Create a new project with ProofKit\"));\n}\n\nfunction makeAddCommand() {\n return makeCommand(\n \"add\",\n {\n name: optionalArg(textArg({ name: \"name\" })).pipe(withArgDescription(\"Component or registry item to add\")),\n noInstall: booleanOption(\"no-install\").pipe(withOptionDescription(\"Skip package installation\")),\n CI: booleanOption(\"ci\").pipe(withOptionDescription(\"Deprecated alias for --non-interactive\")),\n nonInteractive: booleanOption(\"non-interactive\").pipe(\n withOptionDescription(\"Never prompt for input; fail when required values are missing\"),\n ),\n debug: booleanOption(\"debug\").pipe(withOptionDescription(\"Run in debug mode\")),\n },\n ({ name, noInstall, CI, nonInteractive, debug }) =>\n legacyEffect(\n async () => {\n const [{ runAdd }, { initProgramState, state }] = await Promise.all([\n import(\"~/cli/add/index.js\"),\n import(\"~/state.js\"),\n ]);\n initProgramState({\n noInstall,\n ci: CI,\n nonInteractive,\n debug,\n });\n state.baseCommand = \"add\";\n state.projectDir = process.cwd();\n await runAdd(getOrUndefined(name), { noInstall });\n },\n { nonInteractive: CI || nonInteractive, debug },\n ),\n ).pipe(withCommandDescription(\"Add a new component to your project\"));\n}\n\nfunction makeRemoveCommand() {\n return makeCommand(\n \"remove\",\n {\n name: optionalArg(textArg({ name: \"name\" })).pipe(withArgDescription(\"Component type to remove\")),\n CI: booleanOption(\"ci\").pipe(withOptionDescription(\"Deprecated alias for --non-interactive\")),\n nonInteractive: booleanOption(\"non-interactive\").pipe(\n withOptionDescription(\"Never prompt for input; fail when required values are missing\"),\n ),\n debug: booleanOption(\"debug\").pipe(withOptionDescription(\"Run in debug mode\")),\n },\n ({ name, CI, nonInteractive, debug }) =>\n legacyEffect(\n async () => {\n const [{ runRemove }, { initProgramState, state }] = await Promise.all([\n import(\"~/cli/remove/index.js\"),\n import(\"~/state.js\"),\n ]);\n initProgramState({\n ci: CI,\n nonInteractive,\n debug,\n });\n state.baseCommand = \"remove\";\n state.projectDir = process.cwd();\n await runRemove(getOrUndefined(name));\n },\n { nonInteractive: CI || nonInteractive, debug },\n ),\n ).pipe(withCommandDescription(\"Remove a component from your project\"));\n}\n\nfunction makeTypegenCommand() {\n return makeCommand(\n \"typegen\",\n {\n debug: booleanOption(\"debug\").pipe(withOptionDescription(\"Run in debug mode\")),\n },\n ({ debug }) =>\n legacyEffect(\n async () => {\n const [{ runTypegen }, { state }] = await Promise.all([\n import(\"~/cli/typegen/index.js\"),\n import(\"~/state.js\"),\n ]);\n state.projectDir = process.cwd();\n await runTypegen({\n settings: (await import(\"~/utils/parseSettings.js\")).getSettings(),\n });\n },\n { debug },\n ),\n ).pipe(withCommandDescription(\"Generate types for your project\"));\n}\n\nfunction makeDeployCommand() {\n return makeCommand(\n \"deploy\",\n {\n debug: booleanOption(\"debug\").pipe(withOptionDescription(\"Run in debug mode\")),\n },\n ({ debug }) =>\n legacyEffect(\n async () => {\n const [{ runDeploy }, { initProgramState, state }] = await Promise.all([\n import(\"~/cli/deploy/index.js\"),\n import(\"~/state.js\"),\n ]);\n initProgramState({ debug });\n state.baseCommand = \"deploy\";\n state.projectDir = process.cwd();\n await runDeploy();\n },\n { debug },\n ),\n ).pipe(withCommandDescription(\"Deploy your app\"));\n}\n\nfunction makeUpgradeCommand() {\n return makeCommand(\n \"upgrade\",\n {\n CI: booleanOption(\"ci\").pipe(withOptionDescription(\"Deprecated alias for --non-interactive\")),\n nonInteractive: booleanOption(\"non-interactive\").pipe(\n withOptionDescription(\"Never prompt for input; fail when required values are missing\"),\n ),\n debug: booleanOption(\"debug\").pipe(withOptionDescription(\"Run in debug mode\")),\n },\n ({ CI, nonInteractive, debug }) =>\n legacyEffect(\n async () => {\n const [{ runUpgrade }, { initProgramState, state }] = await Promise.all([\n import(\"~/cli/update/index.js\"),\n import(\"~/state.js\"),\n ]);\n initProgramState({ ci: CI, nonInteractive, debug });\n state.baseCommand = \"upgrade\";\n state.projectDir = process.cwd();\n await runUpgrade();\n },\n { nonInteractive: CI || nonInteractive, debug },\n ),\n ).pipe(withCommandDescription(\"Upgrade ProofKit components in your project\"));\n}\n\nconst rootCommand = makeCommand(\n cliName,\n {\n CI: booleanOption(\"ci\").pipe(withOptionDescription(\"Deprecated alias for --non-interactive\")),\n nonInteractive: booleanOption(\"non-interactive\").pipe(\n withOptionDescription(\"Never prompt for input; fail when required values are missing\"),\n ),\n debug: booleanOption(\"debug\").pipe(withOptionDescription(\"Run in debug mode\")),\n },\n (options) =>\n makeLiveLayer({\n cwd: process.cwd(),\n debug: options.debug === true,\n nonInteractive: Boolean(options.CI || options.nonInteractive),\n })(\n runDefaultCommand({\n ...defaultCliFlags,\n CI: options.CI,\n nonInteractive: options.nonInteractive,\n debug: options.debug,\n }),\n ),\n).pipe(\n withCommandDescription(\"Interactive CLI to scaffold and manage ProofKit projects\"),\n withSubcommands([\n makeInitCommand(),\n makeAddCommand(),\n makeRemoveCommand(),\n makeTypegenCommand(),\n makeDeployCommand(),\n makeUpgradeCommand(),\n ]),\n);\n\nexport const cli = run(rootCommand, {\n name: \"ProofKit\",\n version: getCliVersion(),\n});\n\nconst isMainModule = process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url);\n\nconst debugFlagNames = new Set([\"--debug\"]);\n\nfunction shouldShowDebugDetails(argv: readonly string[]) {\n return argv.some((arg) => debugFlagNames.has(arg));\n}\n\nfunction renderFailure(cause: Cause.Cause<unknown>, showDebugDetails: boolean) {\n const failure = getOrUndefined(Cause.failureOption(cause));\n\n if (!(failure && isValidationError(failure))) {\n const error = Cause.squash(cause);\n console.error(error instanceof Error ? error.message : String(error));\n }\n\n if (showDebugDetails) {\n console.error(`\\n[debug] ${Cause.pretty(cause)}`);\n }\n}\n\nasync function main(argv: readonly string[]) {\n const showDebugDetails = shouldShowDebugDetails(argv);\n const exit = await Effect.runPromiseExit(cli(argv).pipe(Effect.provide(nodeContextLayer)));\n\n if (Exit.isFailure(exit)) {\n renderFailure(exit.cause, showDebugDetails);\n process.exitCode = 1;\n }\n}\n\nif (isMainModule) {\n renderTitle(getCliVersion());\n main(process.argv).catch((error) => {\n console.error(error instanceof Error ? error.message : String(error));\n process.exitCode = 1;\n });\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import e from"chalk";const t={error(...t){console.log(e.red(...t))},warn(...t){console.log(e.yellow(...t))},info(...t){console.log(e.cyan(...t))},success(...t){console.log(e.green(...t))},dim(...t){console.log(e.dim(...t))}};export{t};
2
+ //# sourceMappingURL=logger-DCEXcH26.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger-DCEXcH26.js","names":[],"sources":["../src/utils/logger.ts"],"sourcesContent":["import chalk from \"chalk\";\n\nexport const logger = {\n error(...args: unknown[]) {\n console.log(chalk.red(...args));\n },\n warn(...args: unknown[]) {\n console.log(chalk.yellow(...args));\n },\n info(...args: unknown[]) {\n console.log(chalk.cyan(...args));\n },\n success(...args: unknown[]) {\n console.log(chalk.green(...args));\n },\n dim(...args: unknown[]) {\n console.log(chalk.dim(...args));\n },\n};\n"],"mappings":"qBAEA,MAAa,EAAS,CACpB,MAAM,GAAG,EAAiB,CACxB,QAAQ,IAAI,EAAM,IAAI,GAAG,EAAK,CAAC,EAEjC,KAAK,GAAG,EAAiB,CACvB,QAAQ,IAAI,EAAM,OAAO,GAAG,EAAK,CAAC,EAEpC,KAAK,GAAG,EAAiB,CACvB,QAAQ,IAAI,EAAM,KAAK,GAAG,EAAK,CAAC,EAElC,QAAQ,GAAG,EAAiB,CAC1B,QAAQ,IAAI,EAAM,MAAM,GAAG,EAAK,CAAC,EAEnC,IAAI,GAAG,EAAiB,CACtB,QAAQ,IAAI,EAAM,IAAI,GAAG,EAAK,CAAC,EAElC"}
@@ -0,0 +1,2 @@
1
+ import{_ as e,c as t,d as n,h as r,l as i,m as a,p as o,r as s,s as c,u as l}from"./state-CiURqLoM.js";import u from"node:path";import d from"fs-extra";var f=e({appTypes:()=>g,dataSourceSchema:()=>h,defaultSettings:()=>v,envNamesSchema:()=>m,getSettings:()=>b,mergeSettings:()=>x,setSettings:()=>S,validateAndSetEnvFile:()=>C});const p=l(`type`,[o({type:n(`clerk`)}),o({type:n(`next-auth`)}),o({type:n(`proofkit`).transform(()=>`fmaddon`)}),o({type:n(`fmaddon`)}),o({type:n(`better-auth`)}),o({type:n(`none`)})]).default({type:`none`}),m=o({database:a().default(`FM_DATABASE`),server:a().default(`FM_SERVER`),apiKey:a().default(`OTTO_API_KEY`)}),h=l(`type`,[o({type:n(`fm`),name:a(),envNames:m}),o({type:n(`supabase`),name:a()})]),g=[`browser`,`webviewer`],_=l(`ui`,[o({ui:n(`mantine`),appType:c(g).default(`browser`),auth:p,envFile:a().optional(),dataSources:t(h).default([]),tanstackQuery:i().catch(!1),replacedMainPage:i().catch(!1),reactEmail:i().catch(!1),reactEmailServer:i().catch(!1),appliedUpgrades:t(a()).default([]),registryUrl:r().optional(),registryTemplates:t(a()).default([])}),o({ui:n(`shadcn`),appType:c(g).default(`browser`),envFile:a().optional(),dataSources:t(h).default([]),replacedMainPage:i().catch(!1),registryUrl:r().optional(),registryTemplates:t(a()).default([])})]),v=_.parse({auth:{type:`none`},ui:`shadcn`,appType:`browser`,dataSources:[],replacedMainPage:!1,registryTemplates:[]});let y;const b=()=>{if(y)return y;let e=u.join(s.projectDir,`proofkit.json`);if(!d.existsSync(e))throw Error(`ProofKit settings file not found at: ${e}`);let t=d.readJSONSync(e);typeof t==`object`&&t&&!(`ui`in t)&&(t={...t,ui:`mantine`});let n=_.parse(t);return s.appType=n.appType,n};function x(e){let t={...b(),...e};S(_.parse(t))}function S(e){return d.writeJSONSync(u.join(s.projectDir,`proofkit.json`),e,{spaces:2}),y=e,y}function C(e=`.env`){let t=b(),n=u.join(s.projectDir,e);if(d.existsSync(n))return S({...t,envFile:e}),e;if(t.envFile){let{envFile:e,...n}=t;S(n)}}export{S as a,f as i,b as n,C as o,x as r,v as t};
2
+ //# sourceMappingURL=parseSettings-DYvHU8yJ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseSettings-DYvHU8yJ.js","names":["z\n .discriminatedUnion","z.object","z.literal","z.string","z.discriminatedUnion","z.enum","z.array","z.boolean","z.url"],"sources":["../src/utils/parseSettings.ts"],"sourcesContent":["import path from \"node:path\";\nimport fs from \"fs-extra\";\nimport { z } from \"zod/v4\";\n\nimport { state } from \"~/state.js\";\n\nconst authSchema = z\n .discriminatedUnion(\"type\", [\n z.object({\n type: z.literal(\"clerk\"),\n }),\n z.object({\n type: z.literal(\"next-auth\"),\n }),\n z.object({\n type: z.literal(\"proofkit\").transform(() => \"fmaddon\"),\n }),\n z.object({\n type: z.literal(\"fmaddon\"),\n }),\n z.object({\n type: z.literal(\"better-auth\"),\n }),\n z.object({\n type: z.literal(\"none\"),\n }),\n ])\n .default({ type: \"none\" });\n\nexport const envNamesSchema = z.object({\n database: z.string().default(\"FM_DATABASE\"),\n server: z.string().default(\"FM_SERVER\"),\n apiKey: z.string().default(\"OTTO_API_KEY\"),\n});\nexport const dataSourceSchema = z.discriminatedUnion(\"type\", [\n z.object({\n type: z.literal(\"fm\"),\n name: z.string(),\n envNames: envNamesSchema,\n }),\n z.object({\n type: z.literal(\"supabase\"),\n name: z.string(),\n }),\n]);\nexport type DataSource = z.infer<typeof dataSourceSchema>;\n\nexport const appTypes = [\"browser\", \"webviewer\"] as const;\n\nexport const uiTypes = [\"shadcn\", \"mantine\"] as const;\nexport type Ui = (typeof uiTypes)[number];\n\nconst settingsSchema = z.discriminatedUnion(\"ui\", [\n z.object({\n ui: z.literal(\"mantine\"),\n appType: z.enum(appTypes).default(\"browser\"),\n auth: authSchema,\n envFile: z.string().optional(),\n dataSources: z.array(dataSourceSchema).default([]),\n tanstackQuery: z.boolean().catch(false),\n replacedMainPage: z.boolean().catch(false),\n // Whether React Email scaffolding has been installed\n reactEmail: z.boolean().catch(false),\n // Whether provider-specific server email sender files have been installed\n reactEmailServer: z.boolean().catch(false),\n appliedUpgrades: z.array(z.string()).default([]),\n registryUrl: z.url().optional(),\n registryTemplates: z.array(z.string()).default([]),\n }),\n z.object({\n ui: z.literal(\"shadcn\"),\n appType: z.enum(appTypes).default(\"browser\"),\n envFile: z.string().optional(),\n dataSources: z.array(dataSourceSchema).default([]),\n replacedMainPage: z.boolean().catch(false),\n registryUrl: z.url().optional(),\n registryTemplates: z.array(z.string()).default([]),\n }),\n]);\n\nexport const defaultSettings = settingsSchema.parse({\n auth: { type: \"none\" },\n ui: \"shadcn\",\n appType: \"browser\",\n dataSources: [],\n replacedMainPage: false,\n registryTemplates: [],\n});\n\nlet settings: Settings | undefined;\nexport const getSettings = () => {\n if (settings) {\n return settings;\n }\n\n const settingsPath = path.join(state.projectDir, \"proofkit.json\");\n\n // Check if the settings file exists before trying to read it\n if (!fs.existsSync(settingsPath)) {\n throw new Error(`ProofKit settings file not found at: ${settingsPath}`);\n }\n\n let settingsFile: unknown = fs.readJSONSync(settingsPath);\n\n if (typeof settingsFile === \"object\" && settingsFile !== null && !(\"ui\" in settingsFile)) {\n settingsFile = { ...settingsFile, ui: \"mantine\" };\n }\n\n const parsed = settingsSchema.parse(settingsFile);\n\n state.appType = parsed.appType;\n return parsed;\n};\n\nexport type Settings = z.infer<typeof settingsSchema>;\n\nexport function mergeSettings(_settings: Partial<Settings>) {\n const settings = getSettings();\n const merged = { ...settings, ..._settings };\n const validated = settingsSchema.parse(merged);\n setSettings(validated);\n}\n\nexport function setSettings(_settings: Settings) {\n fs.writeJSONSync(path.join(state.projectDir, \"proofkit.json\"), _settings, {\n spaces: 2,\n });\n settings = _settings;\n return settings;\n}\n\n/**\n * Validates and sets the envFile in settings only if the file exists.\n * Used during stealth initialization to avoid setting non-existent env files.\n */\nexport function validateAndSetEnvFile(envFileName = \".env\") {\n const settings = getSettings();\n const envFilePath = path.join(state.projectDir, envFileName);\n\n if (fs.existsSync(envFilePath)) {\n const updatedSettings = { ...settings, envFile: envFileName };\n setSettings(updatedSettings);\n return envFileName;\n }\n\n // If no env file exists, ensure envFile is undefined in settings\n if (settings.envFile) {\n const { envFile, ...settingsWithoutEnvFile } = settings;\n setSettings(settingsWithoutEnvFile as Settings);\n }\n\n return undefined;\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{m as e,n as t,p as n,r,t as i}from"./state-CiURqLoM.js";import"./consts-BZnOMxpW.js";import{a,c as o,f as s,i as c,l,n as u,o as d,p as f,r as p,t as m}from"./utils-CQMjIwwz.js";import{n as h,r as g,t as _}from"./globalOptions-DmUayYY3.js";import"./logger-DCEXcH26.js";import{a as v,n as y}from"./parseSettings-DYvHU8yJ.js";import{c as b,f as x,l as S,o as C,p as w,u as T}from"./fmdapi-LpkpfSZp.js";import E from"node:path";import D from"fs-extra";import{Command as O}from"commander";import{Node as k,SyntaxKind as A}from"ts-morph";import j from"dotenv";function M(e){if(e.type!==`fm`)return e.type;let t=E.join(r.projectDir,`.env`);D.existsSync(t)&&j.config({path:t});let n=process.env[e.envNames.server]||`unknown server`,i=process.env[e.envNames.database]||`unknown database`;try{return`${new URL(n).hostname}/${i}`}catch(e){return r.debug&&console.error(`Error parsing server URL:`,e),`${n}/${i}`}}const N=async e=>{let n=y();if(n.dataSources.length===0){o(`No data sources found in your project.`);return}let i=e;if(i){if(!n.dataSources.some(e=>e.name===i))throw Error(`Data source "${i}" not found in your project.`)}else i=u(await s({message:`Which data source do you want to remove?`,options:n.dataSources.map(e=>{let t=``;try{t=M(e)}catch(e){r.debug&&console.error(`Error getting data source info:`,e),t=`unknown connection`}return{label:`${e.name} (${t})`,value:e.name}})}));let c=!0;if(!t()&&(c=u(await a({message:`Are you sure you want to remove the data source "${i}"? This will only remove it from your configuration, not replace any possible usage, which may cause TypeScript errors.`})),!c))throw new m;let l=n.dataSources.find(e=>e.name===i);if(n.dataSources=n.dataSources.filter(e=>e.name!==i),v(n),l?.type===`fm`){b({dataSourceName:i}),r.debug&&o(`Removed schemas from fmschema.config.mjs`);let e=E.join(r.projectDir,`src`,`config`,`schemas`,i);D.existsSync(e)&&(D.removeSync(e),r.debug&&o(`Removed schema folder at ${e}`)),await T(),r.debug&&o(`Successfully regenerated types`)}o(`Successfully removed data source "${i}"`)},P=()=>{let t=new O(`data`).description(`Remove a data source from your project`).option(`--name <name>`,`Name of the data source to remove`).addOption(_).addOption(g).addOption(h).action(async t=>{await N(n({name:e().optional()}).parse(t).name)});return t.hook(`preAction`,(e,t)=>{i(t.opts()),r.baseCommand=`remove`,p({commandName:`remove`})}),t},F=e=>{let t=E.join(r.projectDir,`src/app/navigation.tsx`);if(!D.existsSync(t))return[];let n=e.addSourceFileAtPath(t),i=[],a=n.getVariableDeclaration(`primaryRoutes`)?.getInitializerIfKind(A.ArrayLiteralExpression)?.getElements();if(a){for(let e of a)if(k.isObjectLiteralExpression(e)){let t=e.getProperties().find(e=>k.isPropertyAssignment(e)&&e.getName()===`label`),n=e.getProperties().find(e=>k.isPropertyAssignment(e)&&e.getName()===`href`),r=t?.getInitializer()?.getText().replace(/['"]/g,``),a=n?.getInitializer()?.getText().replace(/['"]/g,``);r&&a&&i.push({label:r,href:a})}}let o=n.getVariableDeclaration(`secondaryRoutes`)?.getInitializerIfKind(A.ArrayLiteralExpression)?.getElements();if(o){for(let e of o)if(k.isObjectLiteralExpression(e)){let t=e.getProperties().find(e=>k.isPropertyAssignment(e)&&e.getName()===`label`),n=e.getProperties().find(e=>k.isPropertyAssignment(e)&&e.getName()===`href`),r=t?.getInitializer()?.getText().replace(/['"]/g,``),a=n?.getInitializer()?.getText().replace(/['"]/g,``);r&&a&&i.push({label:r,href:a})}}return i},I=async(e,t)=>{let n=E.join(r.projectDir,`src/app/navigation.tsx`);if(!D.existsSync(n))return;let i=e.addSourceFileAtPath(n),a=i.getVariableDeclaration(`primaryRoutes`)?.getInitializerIfKind(A.ArrayLiteralExpression);if(a){let e=a.getElements();for(let n=e.length-1;n>=0;n--){let r=e[n];k.isObjectLiteralExpression(r)&&r.getProperties().find(e=>k.isPropertyAssignment(e)&&e.getName()===`href`)?.getInitializer()?.getText().replace(/['"]/g,``)===t&&a.removeElement(n)}}let o=i.getVariableDeclaration(`secondaryRoutes`)?.getInitializerIfKind(A.ArrayLiteralExpression);if(o){let e=o.getElements();for(let n=e.length-1;n>=0;n--){let r=e[n];k.isObjectLiteralExpression(r)&&r.getProperties().find(e=>k.isPropertyAssignment(e)&&e.getName()===`href`)?.getInitializer()?.getText().replace(/['"]/g,``)===t&&o.removeElement(n)}}await w(e)},L=async e=>{y();let t=r.projectDir,n=x(t),i=F(n);if(i.length===0)return c(`No pages found in the navigation.`);let a=e;a||=u(await s({message:`Select the page to remove`,options:i.map(e=>({label:`${e.label} (${e.href})`,value:e.href}))})),a.startsWith(`/`)||(a=`/${a}`);let o=r.appType===`browser`?E.join(t,`src/app/(main)`,a):E.join(t,`src/routes`,a),l=f();l.start(`Removing page`);try{if(!D.existsSync(o))return l.stop(`Page not found!`),c(`Page at ${a} does not exist`);await I(n,a),await D.remove(o),l.stop(`Page removed successfully!`)}catch(e){l.stop(`Failed to remove page!`),console.error(`Error removing page:`,e),process.exit(1)}},R=()=>{let e=new O(`page`).description(`Remove a page from your project`).argument(`[route]`,`The route of the page to remove`).addOption(_).addOption(h).action(async e=>{await L(e)});return e.hook(`preAction`,(e,t)=>{i(t.opts()),r.baseCommand=`remove`,p({commandName:`remove`})}),e},z=async t=>{let n=t?.settings??y(),i=t?.projectDir??r.projectDir,f=t?.sourceName;if(!f&&n.dataSources.filter(e=>e.type===`fm`).length>1){let t=await s({message:`Which FileMaker data source do you want to remove a layout from?`,options:n.dataSources.filter(e=>e.type===`fm`).map(e=>({label:e.name,value:e.name}))});d(t)&&(c(),process.exit(0)),f=e().parse(t)}if(f||=`filemaker`,!n.dataSources.filter(e=>e.type===`fm`).find(e=>e.name===f))throw Error(`FileMaker data source ${f} not found in your ProofKit config`);let p=C({projectDir:i,dataSourceName:f});if(p.length===0){o(`No layouts found in data source "${f}"`,`Nothing to remove`);return}let m=t?.schemaName??u(await s({message:`Select a layout to remove`,options:p.map(e=>({label:`${e.layout} (${e.schemaName})`,value:e.schemaName??``})).filter(e=>e.value!==``)})),h=await a({message:`Are you sure you want to remove the layout "${m}"?`,initialValue:!1});(d(h)||!h)&&(c(`Operation cancelled`),process.exit(0)),await S({projectDir:i,dataSourceName:f,schemaName:m,runCodegen:!0}),l(`Layout "${m}" has been removed from your project`)},B=()=>new O(`layout`).alias(`schema`).description(`Remove a layout from your fmschema file`).action(async e=>{let t=e.settings;await z({settings:t})}),V=async e=>{let t=u(await s({message:`What do you want to remove from your project?`,options:[{label:`Page`,value:`page`},{label:`Schema`,value:`schema`,hint:`remove a table or layout schema`},...y().appType===`browser`?[{label:`Data Source`,value:`data`,hint:`remove a database or FileMaker connection`}]:[]]}));t===`data`?await N():t===`page`?await L():t===`schema`&&await z()};function H(){let e=new O(`remove`).description(`Remove a component from your project`).argument(`[name]`,`Type of component to remove`).addOption(_).addOption(h).action(V);return e.hook(`preAction`,(e,t)=>{i(t.opts()),r.baseCommand=`remove`,p({commandName:`remove`})}),e.hook(`preSubcommand`,(e,t)=>{i(t.opts()),r.baseCommand=`remove`,p({commandName:`remove`})}),e.addCommand(P()),e.addCommand(R()),e.addCommand(B()),e}export{H as makeRemoveCommand,V as runRemove};
2
+ //# sourceMappingURL=remove-D-aGocFU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remove-D-aGocFU.js","names":["p.select","p.confirm","z.object","z.string","p.cancel","p.select","spinner","p.spinner","p.select","p.isCancel","z.string","p.confirm","p.select"],"sources":["../src/cli/remove/data-source.ts","../src/cli/remove/page.ts","../src/cli/remove/schema.ts","../src/cli/remove/index.ts"],"sourcesContent":["import path from \"node:path\";\nimport { Command } from \"commander\";\nimport dotenv from \"dotenv\";\nimport fs from \"fs-extra\";\nimport { z } from \"zod/v4\";\nimport * as p from \"~/cli/prompts.js\";\n\nimport { removeFromFmschemaConfig, runCodegenCommand } from \"~/generators/fmdapi.js\";\nimport { ciOption, debugOption, nonInteractiveOption } from \"~/globalOptions.js\";\nimport { initProgramState, isNonInteractiveMode, state } from \"~/state.js\";\nimport { type DataSource, getSettings, setSettings } from \"~/utils/parseSettings.js\";\nimport { abortIfCancel, ensureProofKitProject, UserAbortedError } from \"../utils.js\";\n\nfunction getDataSourceInfo(source: DataSource) {\n if (source.type !== \"fm\") {\n return source.type;\n }\n\n const envFile = path.join(state.projectDir, \".env\");\n if (fs.existsSync(envFile)) {\n dotenv.config({ path: envFile });\n }\n\n const server = process.env[source.envNames.server] || \"unknown server\";\n const database = process.env[source.envNames.database] || \"unknown database\";\n\n try {\n // Format the server URL to be more readable\n const serverUrl = new URL(server);\n const formattedServer = serverUrl.hostname;\n return `${formattedServer}/${database}`;\n } catch (error) {\n if (state.debug) {\n console.error(\"Error parsing server URL:\", error);\n }\n return `${server}/${database}`;\n }\n}\n\nexport const runRemoveDataSourceCommand = async (name?: string) => {\n const settings = getSettings();\n\n if (settings.dataSources.length === 0) {\n p.note(\"No data sources found in your project.\");\n return;\n }\n\n let dataSourceName = name;\n\n // If no name provided, prompt for selection\n if (dataSourceName) {\n // Validate that the provided name exists\n const dataSourceExists = settings.dataSources.some((source) => source.name === dataSourceName);\n if (!dataSourceExists) {\n throw new Error(`Data source \"${dataSourceName}\" not found in your project.`);\n }\n } else {\n dataSourceName = abortIfCancel(\n await p.select({\n message: \"Which data source do you want to remove?\",\n options: settings.dataSources.map((source) => {\n let info = \"\";\n try {\n info = getDataSourceInfo(source);\n } catch (error) {\n if (state.debug) {\n console.error(\"Error getting data source info:\", error);\n }\n info = \"unknown connection\";\n }\n return {\n label: `${source.name} (${info})`,\n value: source.name,\n };\n }),\n }),\n );\n }\n\n let confirmed = true;\n if (!isNonInteractiveMode()) {\n confirmed = abortIfCancel(\n await p.confirm({\n message: `Are you sure you want to remove the data source \"${dataSourceName}\"? This will only remove it from your configuration, not replace any possible usage, which may cause TypeScript errors.`,\n }),\n );\n\n if (!confirmed) {\n throw new UserAbortedError();\n }\n }\n\n // Get the data source before removing it\n const dataSource = settings.dataSources.find((source) => source.name === dataSourceName);\n\n // Remove the data source from settings\n settings.dataSources = settings.dataSources.filter((source) => source.name !== dataSourceName);\n\n // Save the updated settings\n setSettings(settings);\n\n if (dataSource?.type === \"fm\") {\n // For FileMaker data sources, remove from fmschema.config.mjs\n removeFromFmschemaConfig({\n dataSourceName,\n });\n\n if (state.debug) {\n p.note(\"Removed schemas from fmschema.config.mjs\");\n }\n\n // Remove the schema folder for this data source\n const schemaFolderPath = path.join(state.projectDir, \"src\", \"config\", \"schemas\", dataSourceName);\n if (fs.existsSync(schemaFolderPath)) {\n fs.removeSync(schemaFolderPath);\n if (state.debug) {\n p.note(`Removed schema folder at ${schemaFolderPath}`);\n }\n }\n\n // Run typegen to regenerate types\n await runCodegenCommand();\n if (state.debug) {\n p.note(\"Successfully regenerated types\");\n }\n }\n\n p.note(`Successfully removed data source \"${dataSourceName}\"`);\n};\n\nexport const makeRemoveDataSourceCommand = () => {\n const removeDataSourceCommand = new Command(\"data\")\n .description(\"Remove a data source from your project\")\n .option(\"--name <name>\", \"Name of the data source to remove\")\n .addOption(ciOption)\n .addOption(nonInteractiveOption)\n .addOption(debugOption)\n .action(async (options) => {\n const schema = z.object({\n name: z.string().optional(),\n });\n const validated = schema.parse(options);\n await runRemoveDataSourceCommand(validated.name);\n });\n\n removeDataSourceCommand.hook(\"preAction\", (_thisCommand, actionCommand) => {\n initProgramState(actionCommand.opts());\n state.baseCommand = \"remove\";\n ensureProofKitProject({ commandName: \"remove\" });\n });\n\n return removeDataSourceCommand;\n};\n","import path from \"node:path\";\nimport { Command } from \"commander\";\nimport fs from \"fs-extra\";\nimport { Node, type Project, type PropertyAssignment, SyntaxKind } from \"ts-morph\";\nimport * as p from \"~/cli/prompts.js\";\n\nimport { ciOption, debugOption } from \"~/globalOptions.js\";\nimport { initProgramState, state } from \"~/state.js\";\nimport { getSettings } from \"~/utils/parseSettings.js\";\nimport { formatAndSaveSourceFiles, getNewProject } from \"~/utils/ts-morph.js\";\nimport { abortIfCancel, ensureProofKitProject } from \"../utils.js\";\n\nconst getExistingRoutes = (project: Project): { label: string; href: string }[] => {\n const navFilePath = path.join(state.projectDir, \"src/app/navigation.tsx\");\n\n // If navigation file doesn't exist (e.g., webviewer apps), there are no nav routes to remove\n if (!fs.existsSync(navFilePath)) {\n return [];\n }\n\n const sourceFile = project.addSourceFileAtPath(navFilePath);\n\n const routes: { label: string; href: string }[] = [];\n\n // Get primary routes\n const primaryRoutes = sourceFile\n .getVariableDeclaration(\"primaryRoutes\")\n ?.getInitializerIfKind(SyntaxKind.ArrayLiteralExpression)\n ?.getElements();\n\n if (primaryRoutes) {\n for (const element of primaryRoutes) {\n if (Node.isObjectLiteralExpression(element)) {\n const labelProp = element\n .getProperties()\n .find((prop): prop is PropertyAssignment => Node.isPropertyAssignment(prop) && prop.getName() === \"label\");\n const hrefProp = element\n .getProperties()\n .find((prop): prop is PropertyAssignment => Node.isPropertyAssignment(prop) && prop.getName() === \"href\");\n\n const label = labelProp?.getInitializer()?.getText().replace(/['\"]/g, \"\");\n const href = hrefProp?.getInitializer()?.getText().replace(/['\"]/g, \"\");\n\n if (label && href) {\n routes.push({ label, href });\n }\n }\n }\n }\n\n // Get secondary routes\n const secondaryRoutes = sourceFile\n .getVariableDeclaration(\"secondaryRoutes\")\n ?.getInitializerIfKind(SyntaxKind.ArrayLiteralExpression)\n ?.getElements();\n\n if (secondaryRoutes) {\n for (const element of secondaryRoutes) {\n if (Node.isObjectLiteralExpression(element)) {\n const labelProp = element\n .getProperties()\n .find((prop): prop is PropertyAssignment => Node.isPropertyAssignment(prop) && prop.getName() === \"label\");\n const hrefProp = element\n .getProperties()\n .find((prop): prop is PropertyAssignment => Node.isPropertyAssignment(prop) && prop.getName() === \"href\");\n\n const label = labelProp?.getInitializer()?.getText().replace(/['\"]/g, \"\");\n const href = hrefProp?.getInitializer()?.getText().replace(/['\"]/g, \"\");\n\n if (label && href) {\n routes.push({ label, href });\n }\n }\n }\n }\n\n return routes;\n};\n\nconst removeRouteFromNav = async (project: Project, routeToRemove: string) => {\n const navFilePath = path.join(state.projectDir, \"src/app/navigation.tsx\");\n\n // Skip if there is no navigation file\n if (!fs.existsSync(navFilePath)) {\n return;\n }\n\n const sourceFile = project.addSourceFileAtPath(navFilePath);\n\n // Remove from primary routes\n const primaryRoutes = sourceFile\n .getVariableDeclaration(\"primaryRoutes\")\n ?.getInitializerIfKind(SyntaxKind.ArrayLiteralExpression);\n\n if (primaryRoutes) {\n const elements = primaryRoutes.getElements();\n for (let i = elements.length - 1; i >= 0; i--) {\n const element = elements[i];\n if (Node.isObjectLiteralExpression(element)) {\n const hrefProp = element\n .getProperties()\n .find((prop): prop is PropertyAssignment => Node.isPropertyAssignment(prop) && prop.getName() === \"href\");\n\n const href = hrefProp?.getInitializer()?.getText().replace(/['\"]/g, \"\");\n\n if (href === routeToRemove) {\n primaryRoutes.removeElement(i);\n }\n }\n }\n }\n\n // Remove from secondary routes\n const secondaryRoutes = sourceFile\n .getVariableDeclaration(\"secondaryRoutes\")\n ?.getInitializerIfKind(SyntaxKind.ArrayLiteralExpression);\n\n if (secondaryRoutes) {\n const elements = secondaryRoutes.getElements();\n for (let i = elements.length - 1; i >= 0; i--) {\n const element = elements[i];\n if (Node.isObjectLiteralExpression(element)) {\n const hrefProp = element\n .getProperties()\n .find((prop): prop is PropertyAssignment => Node.isPropertyAssignment(prop) && prop.getName() === \"href\");\n\n const href = hrefProp?.getInitializer()?.getText().replace(/['\"]/g, \"\");\n\n if (href === routeToRemove) {\n secondaryRoutes.removeElement(i);\n }\n }\n }\n }\n\n await formatAndSaveSourceFiles(project);\n};\n\nexport const runRemovePageAction = async (routeName?: string) => {\n const _settings = getSettings();\n const projectDir = state.projectDir;\n const project = getNewProject(projectDir);\n\n // Get existing routes\n const routes = getExistingRoutes(project);\n\n if (routes.length === 0) {\n return p.cancel(\"No pages found in the navigation.\");\n }\n\n let selectedRouteName = routeName;\n if (!selectedRouteName) {\n selectedRouteName = abortIfCancel(\n await p.select({\n message: \"Select the page to remove\",\n options: routes.map((route) => ({\n label: `${route.label} (${route.href})`,\n value: route.href,\n })),\n }),\n );\n }\n\n if (!selectedRouteName.startsWith(\"/\")) {\n selectedRouteName = `/${selectedRouteName}`;\n }\n\n const pagePath =\n state.appType === \"browser\"\n ? path.join(projectDir, \"src/app/(main)\", selectedRouteName)\n : path.join(projectDir, \"src/routes\", selectedRouteName);\n\n const spinner = p.spinner();\n spinner.start(\"Removing page\");\n\n try {\n // Check if directory exists\n if (!fs.existsSync(pagePath)) {\n spinner.stop(\"Page not found!\");\n return p.cancel(`Page at ${selectedRouteName} does not exist`);\n }\n\n // Remove from navigation first (if present)\n await removeRouteFromNav(project, selectedRouteName);\n\n // Remove the page directory\n await fs.remove(pagePath);\n\n spinner.stop(\"Page removed successfully!\");\n } catch (error) {\n spinner.stop(\"Failed to remove page!\");\n console.error(\"Error removing page:\", error);\n process.exit(1);\n }\n};\n\nexport const makeRemovePageCommand = () => {\n const removePageCommand = new Command(\"page\")\n .description(\"Remove a page from your project\")\n .argument(\"[route]\", \"The route of the page to remove\")\n .addOption(ciOption)\n .addOption(debugOption)\n .action(async (route: string) => {\n await runRemovePageAction(route);\n });\n\n removePageCommand.hook(\"preAction\", (_thisCommand, actionCommand) => {\n initProgramState(actionCommand.opts());\n state.baseCommand = \"remove\";\n ensureProofKitProject({ commandName: \"remove\" });\n });\n\n return removePageCommand;\n};\n","import { Command } from \"commander\";\nimport { z } from \"zod/v4\";\nimport * as p from \"~/cli/prompts.js\";\n\nimport { getExistingSchemas, removeLayout } from \"~/generators/fmdapi.js\";\nimport { state } from \"~/state.js\";\nimport { getSettings, type Settings } from \"~/utils/parseSettings.js\";\nimport { abortIfCancel } from \"../utils.js\";\n\nexport const runRemoveSchemaAction = async (opts?: {\n projectDir?: string;\n settings?: Settings;\n sourceName?: string;\n schemaName?: string;\n}) => {\n const settings = opts?.settings ?? getSettings();\n const projectDir = opts?.projectDir ?? state.projectDir;\n let sourceName = opts?.sourceName;\n\n // If there is more than one fm data source, prompt for which one to remove from\n if (!sourceName && settings.dataSources.filter((s) => s.type === \"fm\").length > 1) {\n const dataSourceName = await p.select({\n message: \"Which FileMaker data source do you want to remove a layout from?\",\n options: settings.dataSources.filter((s) => s.type === \"fm\").map((s) => ({ label: s.name, value: s.name })),\n });\n if (p.isCancel(dataSourceName)) {\n p.cancel();\n process.exit(0);\n }\n sourceName = z.string().parse(dataSourceName);\n }\n\n if (!sourceName) {\n sourceName = \"filemaker\";\n }\n\n const dataSource = settings.dataSources.filter((s) => s.type === \"fm\").find((s) => s.name === sourceName);\n if (!dataSource) {\n throw new Error(`FileMaker data source ${sourceName} not found in your ProofKit config`);\n }\n\n // Get existing schemas for this data source\n const existingSchemas = getExistingSchemas({\n projectDir,\n dataSourceName: sourceName,\n });\n\n if (existingSchemas.length === 0) {\n p.note(`No layouts found in data source \"${sourceName}\"`, \"Nothing to remove\");\n return;\n }\n\n // Show existing schemas and let user pick one to remove\n const schemaToRemove =\n opts?.schemaName ??\n abortIfCancel(\n await p.select({\n message: \"Select a layout to remove\",\n options: existingSchemas\n .map((schema) => ({\n label: `${schema.layout} (${schema.schemaName})`,\n value: schema.schemaName ?? \"\",\n }))\n .filter((opt) => opt.value !== \"\"),\n }),\n );\n\n // Confirm removal\n const confirmRemoval = await p.confirm({\n message: `Are you sure you want to remove the layout \"${schemaToRemove}\"?`,\n initialValue: false,\n });\n\n if (p.isCancel(confirmRemoval) || !confirmRemoval) {\n p.cancel(\"Operation cancelled\");\n process.exit(0);\n }\n\n // Remove the schema\n await removeLayout({\n projectDir,\n dataSourceName: sourceName,\n schemaName: schemaToRemove,\n runCodegen: true,\n });\n\n p.outro(`Layout \"${schemaToRemove}\" has been removed from your project`);\n};\n\nexport const makeRemoveSchemaCommand = () => {\n const removeSchemaCommand = new Command(\"layout\")\n .alias(\"schema\")\n .description(\"Remove a layout from your fmschema file\")\n .action(async (opts: { settings: Settings }) => {\n const settings = opts.settings;\n await runRemoveSchemaAction({ settings });\n });\n\n return removeSchemaCommand;\n};\n","import { Command } from \"commander\";\nimport * as p from \"~/cli/prompts.js\";\n\nimport { ciOption, debugOption } from \"~/globalOptions.js\";\nimport { initProgramState, state } from \"~/state.js\";\nimport { getSettings } from \"~/utils/parseSettings.js\";\nimport { abortIfCancel, ensureProofKitProject } from \"../utils.js\";\nimport { makeRemoveDataSourceCommand, runRemoveDataSourceCommand } from \"./data-source.js\";\nimport { makeRemovePageCommand, runRemovePageAction } from \"./page.js\";\nimport { makeRemoveSchemaCommand, runRemoveSchemaAction } from \"./schema.js\";\n\nexport const runRemove = async (_name: string | undefined) => {\n const settings = getSettings();\n\n const removeType = abortIfCancel(\n await p.select({\n message: \"What do you want to remove from your project?\",\n options: [\n { label: \"Page\", value: \"page\" },\n {\n label: \"Schema\",\n value: \"schema\",\n hint: \"remove a table or layout schema\",\n },\n ...(settings.appType === \"browser\"\n ? [\n {\n label: \"Data Source\",\n value: \"data\",\n hint: \"remove a database or FileMaker connection\",\n },\n ]\n : []),\n ],\n }),\n );\n\n if (removeType === \"data\") {\n await runRemoveDataSourceCommand();\n } else if (removeType === \"page\") {\n await runRemovePageAction();\n } else if (removeType === \"schema\") {\n await runRemoveSchemaAction();\n }\n};\n\nexport function makeRemoveCommand() {\n const removeCommand = new Command(\"remove\")\n .description(\"Remove a component from your project\")\n .argument(\"[name]\", \"Type of component to remove\")\n .addOption(ciOption)\n .addOption(debugOption)\n .action(runRemove);\n\n removeCommand.hook(\"preAction\", (_thisCommand, _actionCommand) => {\n initProgramState(_actionCommand.opts());\n state.baseCommand = \"remove\";\n ensureProofKitProject({ commandName: \"remove\" });\n });\n removeCommand.hook(\"preSubcommand\", (_thisCommand, _subCommand) => {\n initProgramState(_subCommand.opts());\n state.baseCommand = \"remove\";\n ensureProofKitProject({ commandName: \"remove\" });\n });\n\n // Add subcommands\n removeCommand.addCommand(makeRemoveDataSourceCommand());\n removeCommand.addCommand(makeRemovePageCommand());\n removeCommand.addCommand(makeRemoveSchemaCommand());\n\n return removeCommand;\n}\n"],"mappings":"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"}