create-houdini 2.0.0-next.8 → 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 +123 -20
- 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,6 +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 each package to its actual published version
|
|
20
|
+
// independently — packages can be at different versions across a release cycle
|
|
21
|
+
const distTag = version.includes('-') ? version.split('-')[1].split('.')[0] : 'latest'
|
|
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
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const houdiniVersion = resolveVersion('houdini')
|
|
34
|
+
const houdiniReactVersion = resolveVersion('houdini-react')
|
|
35
|
+
const houdiniAdapterVersion = resolveVersion('houdini-adapter-auto')
|
|
36
|
+
|
|
19
37
|
// prepare options
|
|
20
38
|
const templatesDir = sourcePath(`./templates`)
|
|
21
39
|
const options = fs.readdirSync(templatesDir).map((templateDir) => {
|
|
@@ -51,12 +69,11 @@ p.intro('🎩 Welcome to Houdini!')
|
|
|
51
69
|
|
|
52
70
|
// if we weren't given a directory, then we should ask
|
|
53
71
|
if (!projectDir) {
|
|
54
|
-
const dir = await
|
|
72
|
+
const dir = await pathInput({
|
|
55
73
|
message: `Where should we create your project?`,
|
|
56
|
-
placeholder: ' (press Enter to use the current directory)',
|
|
57
74
|
})
|
|
58
75
|
|
|
59
|
-
if (
|
|
76
|
+
if (dir === null) {
|
|
60
77
|
process.exit(1)
|
|
61
78
|
}
|
|
62
79
|
|
|
@@ -130,13 +147,46 @@ let apiUrl = options_cli.schema?.startsWith('http') ? options_cli.schema : templ
|
|
|
130
147
|
if (!localSchema) {
|
|
131
148
|
let pullSchema_content = ''
|
|
132
149
|
if (apiUrl === '') {
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
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
|
+
}
|
|
138
165
|
} else {
|
|
139
|
-
|
|
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'
|
|
140
190
|
}
|
|
141
191
|
} else {
|
|
142
192
|
const pullSchema_content_local = await pullSchema(apiUrl, {})
|
|
@@ -147,22 +197,20 @@ if (!localSchema) {
|
|
|
147
197
|
}
|
|
148
198
|
}
|
|
149
199
|
|
|
150
|
-
|
|
200
|
+
if (pullSchema_content) {
|
|
201
|
+
writeFileSync(path.join(projectDir, 'schema.graphql'), pullSchema_content)
|
|
202
|
+
}
|
|
151
203
|
}
|
|
152
204
|
|
|
153
|
-
// the
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
: `{
|
|
157
|
-
url: '${apiUrl}',
|
|
158
|
-
}`
|
|
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 = ``
|
|
159
208
|
|
|
209
|
+
// a remote api sets the top-level `url` (watchSchema defaults to it), env-switched per build.
|
|
160
210
|
const configFile = localSchema
|
|
161
211
|
? ''
|
|
162
212
|
: `
|
|
163
|
-
|
|
164
|
-
url: '${apiUrl}',
|
|
165
|
-
},
|
|
213
|
+
url: import.meta.env.VITE_API_URL ?? '${apiUrl}',
|
|
166
214
|
`
|
|
167
215
|
|
|
168
216
|
copy(
|
|
@@ -171,7 +219,9 @@ copy(
|
|
|
171
219
|
{
|
|
172
220
|
API_URL: apiUrl,
|
|
173
221
|
PROJECT_NAME: projectName,
|
|
174
|
-
HOUDINI_VERSION:
|
|
222
|
+
HOUDINI_VERSION: houdiniVersion,
|
|
223
|
+
HOUDINI_REACT_VERSION: houdiniReactVersion,
|
|
224
|
+
HOUDINI_ADAPTER_VERSION: houdiniAdapterVersion,
|
|
175
225
|
["'CLIENT_CONFIG'"]: clientConfig,
|
|
176
226
|
["'CONFIG_FILE'"]: configFile,
|
|
177
227
|
},
|
|
@@ -369,6 +419,59 @@ function extractHeadersStr(/** @type {string} */ str) {
|
|
|
369
419
|
return obj
|
|
370
420
|
}
|
|
371
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
|
+
|
|
372
475
|
function pCancel(cancelText = 'Operation cancelled.') {
|
|
373
476
|
p.cancel(cancelText)
|
|
374
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
|