create-houdini 2.0.0-next.9 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin.js +119 -27
- package/package.json +9 -7
- package/templates/react/.graphqlrc.yaml +2 -2
- package/templates/react/.meta.gitignore +1 -1
- package/templates/react/package.json +8 -8
- package/templates/react-typescript/.graphqlrc.yaml +2 -2
- package/templates/react-typescript/.meta.gitignore +1 -1
- package/templates/react-typescript/package.json +9 -9
- /package/fragments/localSchema/react/src/{api → server}/+schema.js +0 -0
- /package/fragments/localSchema/react-typescript/src/{api → server}/+schema.ts +0 -0
package/bin.js
CHANGED
|
@@ -16,17 +16,24 @@ let projectName = projectDir
|
|
|
16
16
|
const { version } = JSON.parse(fs.readFileSync(new URL('package.json', import.meta.url), 'utf-8'))
|
|
17
17
|
console.log(`${grey(`create-houdini version ${version}`)}\n`)
|
|
18
18
|
|
|
19
|
-
// derive the dist-tag from our own version, then resolve
|
|
19
|
+
// derive the dist-tag from our own version, then resolve each package to its actual published version
|
|
20
|
+
// independently — packages can be at different versions across a release cycle
|
|
20
21
|
const distTag = version.includes('-') ? version.split('-')[1].split('.')[0] : 'latest'
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
const { execSync } = await import('node:child_process')
|
|
23
|
+
|
|
24
|
+
function resolveVersion(pkg) {
|
|
25
|
+
try {
|
|
26
|
+
const resolved = execSync(`npm view ${pkg}@${distTag} version`, { encoding: 'utf-8' }).trim()
|
|
27
|
+
return resolved || version
|
|
28
|
+
} catch {
|
|
29
|
+
return version
|
|
30
|
+
}
|
|
28
31
|
}
|
|
29
32
|
|
|
33
|
+
const houdiniVersion = resolveVersion('houdini')
|
|
34
|
+
const houdiniReactVersion = resolveVersion('houdini-react')
|
|
35
|
+
const houdiniAdapterVersion = resolveVersion('houdini-adapter-auto')
|
|
36
|
+
|
|
30
37
|
// prepare options
|
|
31
38
|
const templatesDir = sourcePath(`./templates`)
|
|
32
39
|
const options = fs.readdirSync(templatesDir).map((templateDir) => {
|
|
@@ -62,12 +69,11 @@ p.intro('🎩 Welcome to Houdini!')
|
|
|
62
69
|
|
|
63
70
|
// if we weren't given a directory, then we should ask
|
|
64
71
|
if (!projectDir) {
|
|
65
|
-
const dir = await
|
|
72
|
+
const dir = await pathInput({
|
|
66
73
|
message: `Where should we create your project?`,
|
|
67
|
-
placeholder: ' (press Enter to use the current directory)',
|
|
68
74
|
})
|
|
69
75
|
|
|
70
|
-
if (
|
|
76
|
+
if (dir === null) {
|
|
71
77
|
process.exit(1)
|
|
72
78
|
}
|
|
73
79
|
|
|
@@ -141,13 +147,46 @@ let apiUrl = options_cli.schema?.startsWith('http') ? options_cli.schema : templ
|
|
|
141
147
|
if (!localSchema) {
|
|
142
148
|
let pullSchema_content = ''
|
|
143
149
|
if (apiUrl === '') {
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
150
|
+
const apiRunning = await p.confirm({
|
|
151
|
+
message: 'Is your API currently running?',
|
|
152
|
+
initialValue: true,
|
|
153
|
+
})
|
|
154
|
+
if (p.isCancel(apiRunning)) pCancel()
|
|
155
|
+
|
|
156
|
+
if (apiRunning) {
|
|
157
|
+
const { apiUrl: apiUrlCli, pullSchema_content: pullSchema_content_cli } =
|
|
158
|
+
await pullSchemaCli()
|
|
159
|
+
apiUrl = apiUrlCli
|
|
160
|
+
if (pullSchema_content_cli === null) {
|
|
161
|
+
pCancel('There was a problem pulling your shema. Please try again.')
|
|
162
|
+
} else {
|
|
163
|
+
pullSchema_content = pullSchema_content_cli
|
|
164
|
+
}
|
|
149
165
|
} else {
|
|
150
|
-
|
|
166
|
+
const hasSchemaFile = await p.confirm({
|
|
167
|
+
message: 'Do you have a schema file on disk we can use?',
|
|
168
|
+
initialValue: false,
|
|
169
|
+
})
|
|
170
|
+
if (p.isCancel(hasSchemaFile)) pCancel()
|
|
171
|
+
|
|
172
|
+
if (hasSchemaFile) {
|
|
173
|
+
const schemaFilePath = await pathInput({
|
|
174
|
+
message: 'Where is the schema file?',
|
|
175
|
+
initialValue: './schema.graphql',
|
|
176
|
+
validate: (value) => {
|
|
177
|
+
if (!value) return 'Please enter a valid path'
|
|
178
|
+
try {
|
|
179
|
+
fs.statSync(path.resolve(value))
|
|
180
|
+
} catch {
|
|
181
|
+
return 'File not found'
|
|
182
|
+
}
|
|
183
|
+
},
|
|
184
|
+
})
|
|
185
|
+
if (schemaFilePath === null) pCancel()
|
|
186
|
+
pullSchema_content = fs.readFileSync(path.resolve(schemaFilePath), 'utf-8')
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
apiUrl = 'API_URL'
|
|
151
190
|
}
|
|
152
191
|
} else {
|
|
153
192
|
const pullSchema_content_local = await pullSchema(apiUrl, {})
|
|
@@ -158,22 +197,20 @@ if (!localSchema) {
|
|
|
158
197
|
}
|
|
159
198
|
}
|
|
160
199
|
|
|
161
|
-
|
|
200
|
+
if (pullSchema_content) {
|
|
201
|
+
writeFileSync(path.join(projectDir, 'schema.graphql'), pullSchema_content)
|
|
202
|
+
}
|
|
162
203
|
}
|
|
163
204
|
|
|
164
|
-
// the
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
: `{
|
|
168
|
-
url: '${apiUrl}',
|
|
169
|
-
}`
|
|
205
|
+
// the api url lives in houdini.config.js (`url`) now, never the client — passing it to
|
|
206
|
+
// HoudiniClient throws. So the client takes no config here.
|
|
207
|
+
const clientConfig = ``
|
|
170
208
|
|
|
209
|
+
// a remote api sets the top-level `url` (watchSchema defaults to it), env-switched per build.
|
|
171
210
|
const configFile = localSchema
|
|
172
211
|
? ''
|
|
173
212
|
: `
|
|
174
|
-
|
|
175
|
-
url: '${apiUrl}',
|
|
176
|
-
},
|
|
213
|
+
url: import.meta.env.VITE_API_URL ?? '${apiUrl}',
|
|
177
214
|
`
|
|
178
215
|
|
|
179
216
|
copy(
|
|
@@ -183,6 +220,8 @@ copy(
|
|
|
183
220
|
API_URL: apiUrl,
|
|
184
221
|
PROJECT_NAME: projectName,
|
|
185
222
|
HOUDINI_VERSION: houdiniVersion,
|
|
223
|
+
HOUDINI_REACT_VERSION: houdiniReactVersion,
|
|
224
|
+
HOUDINI_ADAPTER_VERSION: houdiniAdapterVersion,
|
|
186
225
|
["'CLIENT_CONFIG'"]: clientConfig,
|
|
187
226
|
["'CONFIG_FILE'"]: configFile,
|
|
188
227
|
},
|
|
@@ -380,6 +419,59 @@ function extractHeadersStr(/** @type {string} */ str) {
|
|
|
380
419
|
return obj
|
|
381
420
|
}
|
|
382
421
|
|
|
422
|
+
async function pathInput({ message, initialValue = '', validate }) {
|
|
423
|
+
const { createInterface } = await import('node:readline')
|
|
424
|
+
|
|
425
|
+
function completer(line) {
|
|
426
|
+
const isTrailingSlash = line.endsWith('/')
|
|
427
|
+
const dir = isTrailingSlash ? line || '.' : path.dirname(line) || '.'
|
|
428
|
+
const base = isTrailingSlash ? '' : path.basename(line)
|
|
429
|
+
let hits = []
|
|
430
|
+
try {
|
|
431
|
+
hits = fs
|
|
432
|
+
.readdirSync(dir)
|
|
433
|
+
.filter((e) => e.startsWith(base))
|
|
434
|
+
.map((e) => {
|
|
435
|
+
const full = path.join(dir, e)
|
|
436
|
+
try {
|
|
437
|
+
return fs.statSync(full).isDirectory() ? full + '/' : full
|
|
438
|
+
} catch {
|
|
439
|
+
return full
|
|
440
|
+
}
|
|
441
|
+
})
|
|
442
|
+
} catch {}
|
|
443
|
+
return [hits, line]
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
process.stdout.write(`\n${gray('◆')} ${message}\n`)
|
|
447
|
+
|
|
448
|
+
for (;;) {
|
|
449
|
+
const answer = await new Promise((resolve) => {
|
|
450
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout, completer })
|
|
451
|
+
rl.setPrompt(`${gray('│')} `)
|
|
452
|
+
rl.prompt()
|
|
453
|
+
rl.once('line', (v) => {
|
|
454
|
+
rl.close()
|
|
455
|
+
resolve(v.trim() || initialValue)
|
|
456
|
+
})
|
|
457
|
+
rl.on('SIGINT', () => {
|
|
458
|
+
rl.close()
|
|
459
|
+
resolve(null)
|
|
460
|
+
})
|
|
461
|
+
})
|
|
462
|
+
|
|
463
|
+
if (answer === null) return null
|
|
464
|
+
if (validate) {
|
|
465
|
+
const err = validate(answer)
|
|
466
|
+
if (err) {
|
|
467
|
+
process.stdout.write(`${gray('▲')} ${err}\n`)
|
|
468
|
+
continue
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
return answer
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
383
475
|
function pCancel(cancelText = 'Operation cancelled.') {
|
|
384
476
|
p.cancel(cancelText)
|
|
385
477
|
process.exit(1)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-houdini",
|
|
3
|
-
"version": "2.0.0
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "A CLI for creating new Houdini projects",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -8,16 +8,15 @@
|
|
|
8
8
|
},
|
|
9
9
|
"license": "MIT",
|
|
10
10
|
"homepage": "https://houdinigraphql.com/",
|
|
11
|
-
"bin": "./bin.js",
|
|
12
11
|
"dependencies": {
|
|
13
|
-
"@clack/prompts": "^
|
|
14
|
-
"commander": "^
|
|
15
|
-
"graphql": "16.
|
|
12
|
+
"@clack/prompts": "^1.5.1",
|
|
13
|
+
"commander": "^15.0.0",
|
|
14
|
+
"graphql": "16.14.1",
|
|
16
15
|
"kleur": "^4.1.5"
|
|
17
16
|
},
|
|
18
17
|
"devDependencies": {
|
|
19
|
-
"@types/node": "^
|
|
20
|
-
"prettier": "^
|
|
18
|
+
"@types/node": "^25.9.1",
|
|
19
|
+
"prettier": "^3.8.3"
|
|
21
20
|
},
|
|
22
21
|
"files": [
|
|
23
22
|
"fragments",
|
|
@@ -33,5 +32,8 @@
|
|
|
33
32
|
"check": "tsc",
|
|
34
33
|
"lint": "prettier --check . --config ../../.prettierrc --ignore-path ../../.gitignore --ignore-path .gitignore --plugin prettier-plugin-svelte --plugin-search-dir=.",
|
|
35
34
|
"format": "pnpm lint --write"
|
|
35
|
+
},
|
|
36
|
+
"bin": {
|
|
37
|
+
"create-houdini": "./bin.js"
|
|
36
38
|
}
|
|
37
39
|
}
|
|
@@ -10,20 +10,20 @@
|
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"houdini": "^HOUDINI_VERSION",
|
|
13
|
-
"houdini-react": "^
|
|
14
|
-
"houdini-adapter-auto": "^
|
|
13
|
+
"houdini-react": "^HOUDINI_REACT_VERSION",
|
|
14
|
+
"houdini-adapter-auto": "^HOUDINI_ADAPTER_VERSION",
|
|
15
15
|
"react": "^19.0.0",
|
|
16
16
|
"react-dom": "^19.0.0",
|
|
17
|
-
"graphql-yoga": "
|
|
18
|
-
"graphql": "
|
|
19
|
-
"@whatwg-node/server": "^0.
|
|
17
|
+
"graphql-yoga": "^5.21.1",
|
|
18
|
+
"graphql": "^16.0.0",
|
|
19
|
+
"@whatwg-node/server": "^0.11.0"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
|
-
"@vitejs/plugin-react": "^
|
|
23
|
-
"vite": "^
|
|
22
|
+
"@vitejs/plugin-react": "^6.0.2",
|
|
23
|
+
"vite": "^8.0.0"
|
|
24
24
|
},
|
|
25
25
|
"resolutions": {
|
|
26
|
-
"graphql": "
|
|
26
|
+
"graphql": "^16.0.0",
|
|
27
27
|
"react": "^19.0.0",
|
|
28
28
|
"react-dom": "^19.0.0"
|
|
29
29
|
}
|
|
@@ -10,23 +10,23 @@
|
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"houdini": "^HOUDINI_VERSION",
|
|
13
|
-
"houdini-react": "^
|
|
14
|
-
"houdini-adapter-auto": "^
|
|
13
|
+
"houdini-react": "^HOUDINI_REACT_VERSION",
|
|
14
|
+
"houdini-adapter-auto": "^HOUDINI_ADAPTER_VERSION",
|
|
15
15
|
"react": "^19.0.0",
|
|
16
16
|
"react-dom": "^19.0.0",
|
|
17
|
-
"graphql-yoga": "
|
|
18
|
-
"graphql": "
|
|
19
|
-
"@whatwg-node/server": "^0.
|
|
17
|
+
"graphql-yoga": "^5.21.1",
|
|
18
|
+
"graphql": "^16.0.0",
|
|
19
|
+
"@whatwg-node/server": "^0.11.0"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
22
|
"@types/react": "^19.0.7",
|
|
23
23
|
"@types/react-dom": "^19.0.3",
|
|
24
|
-
"@vitejs/plugin-react": "^
|
|
25
|
-
"typescript": "^
|
|
26
|
-
"vite": "^
|
|
24
|
+
"@vitejs/plugin-react": "^6.0.2",
|
|
25
|
+
"typescript": "^6.0.0",
|
|
26
|
+
"vite": "^8.0.0"
|
|
27
27
|
},
|
|
28
28
|
"resolutions": {
|
|
29
|
-
"graphql": "
|
|
29
|
+
"graphql": "^16.0.0",
|
|
30
30
|
"react": "^19.0.0",
|
|
31
31
|
"react-dom": "^19.0.0"
|
|
32
32
|
}
|
|
File without changes
|
|
File without changes
|