Skip to content

Commit 2e32fd1

Browse files
authored
Expand @proofkit/new init parity (#163)
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Unified, searchable CLI prompts with keyword search, clearer "no matches" messages, and improved cancellation handling for smoother interactive flows * New "new" project scaffolder (proofkit-new): guided init from templates, package-manager-aware steps, automated post-create next-steps and optional install/codegen/git * FileMaker integration in init: hosted or local setup, API key and layout/schema selection, and optional automated bootstrap into the new project <!-- end of auto-generated comment: release notes by coderabbit.ai -->
1 parent 9b30aac commit 2e32fd1

64 files changed

Lines changed: 5064 additions & 95 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

packages/cli/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
"@better-fetch/fetch": "1.1.17",
5858
"@clack/core": "^0.3.5",
5959
"@clack/prompts": "^0.11.0",
60+
"@inquirer/prompts": "^8.3.2",
6061
"@proofkit/fmdapi": "workspace:*",
6162
"@proofkit/typegen": "workspace:*",
6263
"@types/glob": "^8.1.0",

packages/cli/src/cli/add/auth.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { cancel, select } from "@clack/prompts";
21
import chalk from "chalk";
32
import { Command } from "commander";
43
import { z } from "zod/v4";
4+
import { cancel, select } from "~/cli/prompts.js";
55

66
import { addAuth } from "~/generators/auth.js";
77
import { ciOption, debugOption, nonInteractiveOption } from "~/globalOptions.js";

packages/cli/src/cli/add/data-source/deploy-demo-file.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
import * as p from "@clack/prompts";
2-
31
import { createDataAPIKeyWithCredentials, getDeploymentStatus, startDeployment } from "~/cli/ottofms.js";
2+
import * as p from "~/cli/prompts.js";
43

54
export const filename = "ProofKitDemo.fmp12";
65

packages/cli/src/cli/add/data-source/filemaker.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
import * as p from "@clack/prompts";
21
import chalk from "chalk";
32
import { SemVer } from "semver";
43
import type { z } from "zod/v4";
5-
64
import { createDataAPIKey, getOttoFMSToken, listAPIKeys, listFiles } from "~/cli/ottofms.js";
5+
import * as p from "~/cli/prompts.js";
76
import { abortIfCancel } from "~/cli/utils.js";
87
import { addLayout, addToFmschemaConfig, ensureWebviewerFmHttpConfig } from "~/generators/fmdapi.js";
98
import { getFmHttpStatus } from "~/helpers/fmHttp.js";
@@ -151,20 +150,23 @@ export async function promptForFileMakerDataSource({
151150
fmFile =
152151
opts.fileName ||
153152
abortIfCancel(
154-
await p.select({
153+
await p.searchSelect({
155154
message: `Which file would you like to connect to? ${chalk.dim("(TIP: Select the file where your data is stored)")}`,
156-
maxItems: 10,
155+
emptyMessage: "No matching files found.",
157156
options: [
158157
{
159158
value: "$deployDemoFile",
160159
label: "Deploy NEW ProofKit Demo File",
161160
hint: "Use OttoFMS to deploy a new file for testing",
161+
keywords: ["demo", "proofkit"],
162162
},
163163
...fileList
164164
.sort((a, b) => a.filename.localeCompare(b.filename))
165165
.map((file) => ({
166166
value: file.filename,
167167
label: file.filename,
168+
hint: file.status,
169+
keywords: [file.filename],
168170
})),
169171
],
170172
}),
@@ -178,8 +180,6 @@ export async function promptForFileMakerDataSource({
178180
const replace = abortIfCancel(
179181
await p.confirm({
180182
message: "The demo file already exists, do you want to replace it with a fresh copy?",
181-
active: "Yes, replace",
182-
inactive: "No, select another file",
183183
initialValue: false,
184184
}),
185185
);
@@ -212,18 +212,21 @@ export async function promptForFileMakerDataSource({
212212

213213
if (!dataApiKey && thisFileApiKeys.length > 0) {
214214
const selectedKey = abortIfCancel(
215-
await p.select({
215+
await p.searchSelect({
216216
message: `Which OttoFMS Data API key would you like to use? ${chalk.dim(`(This determines the access that you'll have to the data in this file)`)}`,
217+
emptyMessage: "No matching API keys found.",
217218
options: [
218219
...thisFileApiKeys.map((key) => ({
219220
value: key.key,
220221
label: `${chalk.bold(key.label)} - ${key.user}`,
221222
hint: `${key.key.slice(0, 5)}...${key.key.slice(-4)}`,
223+
keywords: [key.label, key.user, key.database],
222224
})),
223225
{
224226
value: "create",
225227
label: "Create a new API key",
226228
hint: "Requires FileMaker credentials for this file",
229+
keywords: ["create", "new"],
227230
},
228231
],
229232
}),

packages/cli/src/cli/add/data-source/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import * as p from "@clack/prompts";
21
import { Command } from "commander";
32
import { z } from "zod/v4";
3+
import * as p from "~/cli/prompts.js";
44

55
import { ensureProofKitProject } from "~/cli/utils.js";
66
import { ciOption, nonInteractiveOption } from "~/globalOptions.js";

packages/cli/src/cli/add/fmschema.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import path from "node:path";
2-
import * as p from "@clack/prompts";
32
import type { OttoAPIKey } from "@proofkit/fmdapi";
43
import type { ValueListsOptions } from "@proofkit/typegen/config";
54
import chalk from "chalk";
65
import { Command } from "commander";
76
import dotenv from "dotenv";
87
import { z } from "zod/v4";
8+
import * as p from "~/cli/prompts.js";
99
import { addLayout, getExistingSchemas } from "~/generators/fmdapi.js";
1010
import { state } from "~/state.js";
1111
import { getSettings, type Settings } from "~/utils/parseSettings.js";
@@ -110,14 +110,15 @@ export const runAddSchemaAction = async (opts?: {
110110
const selectedLayout =
111111
passedInLayoutName ??
112112
abortIfCancel(
113-
await p.select({
113+
await p.searchSelect({
114114
message: "Select a new layout to read data from",
115-
maxItems: 10,
115+
emptyMessage: "No matching layouts found.",
116116
options: layouts
117117
.filter((layout) => !existingLayouts.includes(layout))
118118
.map((layout) => ({
119119
label: layout,
120120
value: layout,
121+
keywords: [layout],
121122
})),
122123
}),
123124
);
@@ -130,7 +131,6 @@ export const runAddSchemaAction = async (opts?: {
130131
message: `Enter a friendly name for the new schema.\n${chalk.dim("This will the name by which you refer to this layout in your codebase")}`,
131132
// initialValue: selectedLayout,
132133
defaultValue: defaultSchemaName,
133-
placeholder: defaultSchemaName,
134134
validate: (input) => {
135135
if (input === "") {
136136
return; // allow empty input for the default value

packages/cli/src/cli/add/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { select } from "@clack/prompts";
21
import type { RegistryIndex } from "@proofkit/registry";
32
import { Command } from "commander";
43
import { capitalize, groupBy, uniq } from "es-toolkit";
54
import ora from "ora";
5+
import { select } from "~/cli/prompts.js";
66
import { ciOption, debugOption, nonInteractiveOption } from "~/globalOptions.js";
77
import { initProgramState, state } from "~/state.js";
88
import { logger } from "~/utils/logger.js";

packages/cli/src/cli/add/page/index.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
import path from "node:path";
2-
import * as p from "@clack/prompts";
32
import chalk from "chalk";
43
import { Command } from "commander";
54
import { capitalize } from "es-toolkit";
65
import fs from "fs-extra";
7-
86
import { nextjsTemplates, wvTemplates } from "~/cli/add/page/templates.js";
7+
import * as p from "~/cli/prompts.js";
98
import { PKG_ROOT } from "~/consts.js";
109
import { getExistingSchemas } from "~/generators/fmdapi.js";
1110
import { addRouteToNav } from "~/generators/route.js";
@@ -62,7 +61,6 @@ export const runAddPageAction = async (opts?: {
6261
routeName = abortIfCancel(
6362
await p.text({
6463
message: "Enter the URL PATH for your new page",
65-
placeholder: "/my-page",
6664
validate: (value) => {
6765
if (value.length === 0) {
6866
return "URL path is required";
@@ -224,7 +222,7 @@ async function promptForSchemaFromDataSource({
224222
const schemaName = abortIfCancel(
225223
await p.select({
226224
message: "Which schema should this page load data from?",
227-
options: schemas.map((o) => ({ label: o, value: o ?? "" })),
225+
options: schemas.map((schema) => ({ label: schema ?? "", value: schema ?? "" })),
228226
}),
229227
);
230228
return schemaName;

packages/cli/src/cli/add/registry/install.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import * as p from "@clack/prompts";
21
import { getOtherProofKitDependencies } from "@proofkit/registry";
32
import { capitalize, uniq } from "es-toolkit";
43
import ora from "ora";
54
import semver from "semver";
5+
import * as p from "~/cli/prompts.js";
66

77
import { abortIfCancel } from "~/cli/utils.js";
88
import { getExistingSchemas } from "~/generators/fmdapi.js";
@@ -32,7 +32,7 @@ async function promptForSchemaFromDataSource({
3232
dataSourceName: dataSource.name,
3333
})
3434
.map((s) => s.schemaName)
35-
.filter(Boolean);
35+
.filter((schemaName): schemaName is string => Boolean(schemaName));
3636

3737
if (schemas.length === 0) {
3838
p.cancel("This data source doesn't have any schemas to load data from");
@@ -46,7 +46,7 @@ async function promptForSchemaFromDataSource({
4646
const schemaName = abortIfCancel(
4747
await p.select({
4848
message: "Which schema should this template use?",
49-
options: schemas.map((o) => ({ label: o, value: o ?? "" })),
49+
options: schemas.map((schema) => ({ label: schema, value: schema })),
5050
}),
5151
);
5252
return schemaName;
@@ -125,7 +125,6 @@ export async function installFromRegistry(name: string) {
125125
routeName = abortIfCancel(
126126
await p.text({
127127
message: "Enter the URL PATH for your new page",
128-
placeholder: "/my-page",
129128
validate: (value) => {
130129
if (value.length === 0) {
131130
return "URL path is required";

packages/cli/src/cli/deploy/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import path from "node:path";
2-
import * as p from "@clack/prompts";
32
import chalk from "chalk";
43
import { Command, Option } from "commander";
54
import { execa } from "execa";
65
import fs from "fs-extra";
76
import type { PackageJson } from "type-fest";
7+
import * as p from "~/cli/prompts.js";
88

99
import { ciOption, debugOption } from "~/globalOptions.js";
1010

0 commit comments

Comments
 (0)