create-pylon 1.1.4 → 1.1.5-canary-20250521152654.16fa11a497399c04d3766e666e5ed5212e5ae309

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/dist/index.js CHANGED
@@ -1,16 +1,881 @@
1
1
  #!/usr/bin/env node
2
- import{Option as k,program as J}from"commander";import u from"consola";import{input as E,select as W,confirm as N}from"@inquirer/prompts";import c from"path";import m from"chalk";import*as r from"fs";import*as L from"@getcronit/pylon-telemetry";import{fileURLToPath as ne}from"url";import{dirname as re}from"path";import{spawnSync as ce}from"child_process";import*as y from"node:fs";import*as h from"node:path";import M from"node:process";import{execSync as X}from"node:child_process";import I from"consola";function x(e){try{return X(`${e} --version`,{stdio:"ignore"}),!0}catch(a){return console.error(a),!1}}function z(){return typeof Bun<"u"&&x("bun")}function G(){return M.env.npm_execpath?.includes("npm")??!1}function Q(){return M.env.npm_execpath?.includes("yarn")??!1}function Z(){return typeof Deno<"u"&&x("deno")}function ee(){return M.env.npm_execpath?.includes("pnpm")??!1}function te(e){return y.existsSync(h.join(e,"bun.lockb"))?"bun":y.existsSync(h.join(e,"package-lock.json"))?"npm":y.existsSync(h.join(e,"yarn.lock"))?"yarn":y.existsSync(h.join(e,"deno.json"))||y.existsSync(h.join(e,"deno.lock"))?"deno":y.existsSync(h.join(e,"pnpm-lock.yaml"))?"pnpm":null}function R({preferredPm:e,cwd:a=M.cwd()}){if(e&&x(e))return e;if(z())return"bun";if(G())return"npm";if(ee())return"pnpm";if(Z())return"deno";if(Q())return"yarn";let n=te(a);if(n){if(I.info(`Detected package manager by lock file: ${n}`),x(n))return n;I.warn(`Lock file detected, but ${n} is not installed.`)}return"unknown"}function T(e){switch(e){case"bun":return"bun";case"npm":return"npm run";case"yarn":return"yarn";case"pnpm":return"pnpm run";case"deno":return"deno task";default:throw new Error("Unknown package manager")}}var ae=ne(import.meta.url),A=re(ae),U=JSON.parse(r.readFileSync(c.join(A,"..","package.json"),"utf-8")).version;function ie(e){try{r.mkdirSync(e,{recursive:!0})}catch(a){if(a instanceof Error&&"code"in a&&a.code==="EEXIST")return;throw a}}var D=[{key:"bun",name:"Bun.js",website:"https://bunjs.dev",templates:["default"]},{key:"node",name:"Node.js",website:"https://nodejs.org",templates:["default"]},{key:"cf-workers",name:"Cloudflare Workers",website:"https://workers.cloudflare.com",templates:["default"]},{key:"deno",name:"Deno",website:"https://deno.land",templates:["default"]}],q=[{key:"default",name:"Default",description:"Default template"},{key:"database",name:"Database (Prisma)",description:"Template with Prisma ORM"}],se=(e,a)=>{let n=e;return Object.entries(a).forEach(([i,f])=>{n=n.replaceAll(i,f)}),n},B=e=>{let a=n=>{let i=[];return r.readdirSync(n).forEach(b=>{let l=c.join(n,b);r.statSync(l).isDirectory()&&i.push(...a(l)),r.statSync(l).isFile()&&i.push(l)}),i};return a(e).map(n=>n.replace(e,"."))},oe=async e=>{let{runtime:a,template:n,target:i}=e,f=D.find(({key:t})=>t===a)?.name,b=q.find(({key:t})=>t===n)?.name;if(!f)throw new Error(`Invalid runtime: ${a}`);if(!b)throw new Error(`Invalid template: ${n}`);let l=c.join(A,"..","templates","shared");if(!r.existsSync(l))throw new Error(`Shared templates not found: ${l}`);let w=c.join(A,"..","templates",a,n);if(!r.existsSync(w))throw new Error(`Template not found: ${w}`);let P=c.join(process.cwd(),i);u.start(`Creating pylon in ${P}`);let v=t=>se(t,{__PYLON_NAME__:e.name});B(l).forEach(t=>{let d=c.join(l,t),s=c.join(P,t),p=c.dirname(s);if(a==="cf-workers"&&d.includes(".github/workflows/publish.yaml"))return;r.existsSync(p)||r.mkdirSync(p,{recursive:!0}),s.endsWith(".example")&&(s=s.replace(".example",""));let g=v(r.readFileSync(d,"utf-8"));r.writeFileSync(s,g)}),B(w).forEach(t=>{let d=c.join(w,t),s=c.join(P,t),p=c.dirname(s);r.existsSync(p)||r.mkdirSync(p,{recursive:!0}),s.endsWith(".example")&&(s=s.replace(".example",""));let g=v(r.readFileSync(d,"utf-8"));r.writeFileSync(s,g)}),u.success("Pylon created")},le=async e=>{let a=c.resolve(e.target),n=e.packageManager,i="";switch(n){case"yarn":i="yarn";break;case"npm":i="npm install";break;case"pnpm":i="pnpm install";break;case"bun":i="bun install";break;case"deno":i="deno install";break;default:throw new Error(`Invalid package manager: ${n}`)}if(u.start(`Installing dependencies using ${n}`),ce(i,{cwd:a,shell:!0,stdio:"inherit"}).status!==0)throw new Error("Failed to install dependencies");u.success("Dependencies installed")};J.name("create-pylon").version(U).arguments("[target]").addOption(new k("-i, --install","Install dependencies")).addOption(new k("-r, --runtime <runtime>","Runtime").choices(D.map(({key:e})=>e))).addOption(new k("-t, --template <template>","Template")).addOption(new k("-pm, --package-manager <packageManager>","Package manager")).addOption(new k("--client","Enable client generation (https://pylon.cronit.io/docs/integrations/gqty)")).addOption(new k("--client-path <clientPath>","Client path")).addOption(new k("--client-port <clientPort>","Client port")).action(me);var pe=e=>{if(e==="bun")return"bun";if(e==="deno")return"deno"};async function me(e,a,n){try{u.log(`${n.name()} version ${n.version()}`);let{install:i,runtime:f,template:b,packageManager:l,client:w,clientPath:P,clientPort:v}=a,t="";e?(t=e,u.success(`Using target directory \u2026 ${t}`)):t=await E({message:"Target directory",default:"my-pylon"});let d="";t==="."?d=c.basename(process.cwd()):d=c.basename(t);let s=f||await W({message:"Which runtime would you like to use?",choices:D.map(o=>({name:`${o.name} (${o.website})`,value:o.key})),default:0});if(!s)throw new Error("No runtime selected");let p=D.find(({key:o})=>o===s);if(!p)throw new Error(`Invalid runtime selected: ${s}`);let g=b||await W({message:"Which template would you like to use?",choices:q.filter(o=>p.templates?.includes(o.key)).map(o=>({name:o.name,value:o.key})),default:0});if(!g)throw new Error("No template selected");r.existsSync(t)?r.readdirSync(t).length>0&&(await N({message:"Directory not empty. Continue?",default:!1})||process.exit(1)):ie(t);let V=i||await N({message:"Would you like to install dependencies?"});await oe({name:d,runtime:s,template:g,target:t});let F=R({preferredPm:pe(p.key),cwd:t});V&&await le({target:t,packageManager:F});let Y=w||await N({message:"Would you like to enable client generation? (https://pylon.cronit.io/docs/integrations/gqty)",default:!1}),j="",C="",O="";if(Y){P||(j=await E({message:"Path to the root where the client should be generated",default:"."}),C=await E({message:"Path to generate the client to",default:c.join(j,"gqty/index.ts"),validate:K=>K.startsWith(j==="."?"":j)?!0:"Path must start with the client root"})),O=v||await E({message:"Port of the pylon server to generate the client from",default:"3000"}),u.start("Updating pylon dev script to generate client");let o,S;p.key==="deno"?(o=c.join(t,"deno.json"),S="tasks"):(o=c.join(t,"package.json"),S="scripts");let $=JSON.parse(r.readFileSync(o,"utf-8"));$[S]={...$[S],dev:$[S].dev+` --client --client-port ${O} --client-path ${C}`},r.writeFileSync(o,JSON.stringify($,null,2)),u.success("Pylon dev script updated")}let _=T(F),H=`
3
- \u{1F389} ${m.green.bold("Pylon created successfully.")}
2
+ import i from"chalk";import{Option as h,program as D}from"commander";import c from"consola";import*as y from"fs";import N from"path";import w from"fs/promises";import _ from"path";var u="^2.0.0",g="^1.0.0",b={ALL:[{path:".gitignore",content:`# Logs
4
3
 
5
- \u{1F4BB} ${m.cyan.bold("Continue Developing")}
6
- ${m.yellow("Change directories:")} cd ${m.blue(t)}
7
- ${m.yellow("Start dev server:")} ${_} dev
8
- ${m.yellow("Deploy:")} ${_} deploy
4
+ logs
5
+ _.log
6
+ npm-debug.log_
7
+ yarn-debug.log*
8
+ yarn-error.log*
9
+ lerna-debug.log*
10
+ .pnpm-debug.log*
9
11
 
10
- \u{1F4D6} ${m.cyan.bold("Explore Documentation")}
11
- ${m.underline.blue("https://pylon.cronit.io/docs")}
12
+ # Diagnostic reports (https://nodejs.org/api/report.html)
12
13
 
13
- \u{1F4AC} ${m.cyan.bold("Join our Community")}
14
- ${m.underline.blue("https://discord.gg/cbJjkVrnHe")}
15
- `;await L.sendCreateEvent({name:d,pylonCreateVersion:U,runtime:s,template:g,clientPath:C||void 0,clientPort:parseInt(O)||void 0}),u.box(H)}catch(i){u.error(i)}}J.parse();
14
+ report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
15
+
16
+ # Runtime data
17
+
18
+ pids
19
+ _.pid
20
+ _.seed
21
+ *.pid.lock
22
+
23
+ # Directory for instrumented libs generated by jscoverage/JSCover
24
+
25
+ lib-cov
26
+
27
+ # Coverage directory used by tools like istanbul
28
+
29
+ coverage
30
+ *.lcov
31
+
32
+ # nyc test coverage
33
+
34
+ .nyc_output
35
+
36
+ # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
37
+
38
+ .grunt
39
+
40
+ # Bower dependency directory (https://bower.io/)
41
+
42
+ bower_components
43
+
44
+ # node-waf configuration
45
+
46
+ .lock-wscript
47
+
48
+ # Compiled binary addons (https://nodejs.org/api/addons.html)
49
+
50
+ build/Release
51
+
52
+ # Dependency directories
53
+
54
+ node_modules/
55
+ jspm_packages/
56
+
57
+ # Snowpack dependency directory (https://snowpack.dev/)
58
+
59
+ web_modules/
60
+
61
+ # TypeScript cache
62
+
63
+ *.tsbuildinfo
64
+
65
+ # Optional npm cache directory
66
+
67
+ .npm
68
+
69
+ # Optional eslint cache
70
+
71
+ .eslintcache
72
+
73
+ # Optional stylelint cache
74
+
75
+ .stylelintcache
76
+
77
+ # Microbundle cache
78
+
79
+ .rpt2_cache/
80
+ .rts2_cache_cjs/
81
+ .rts2_cache_es/
82
+ .rts2_cache_umd/
83
+
84
+ # Optional REPL history
85
+
86
+ .node_repl_history
87
+
88
+ # Output of 'npm pack'
89
+
90
+ *.tgz
91
+
92
+ # Yarn Integrity file
93
+
94
+ .yarn-integrity
95
+
96
+ # dotenv environment variable files
97
+
98
+ .env
99
+ .env.development.local
100
+ .env.test.local
101
+ .env.production.local
102
+ .env.local
103
+
104
+ # parcel-bundler cache (https://parceljs.org/)
105
+
106
+ .cache
107
+ .parcel-cache
108
+
109
+ # Next.js build output
110
+
111
+ .next
112
+ out
113
+
114
+ # Nuxt.js build / generate output
115
+
116
+ .nuxt
117
+ dist
118
+
119
+ # Gatsby files
120
+
121
+ .cache/
122
+
123
+ # Comment in the public line in if your project uses Gatsby and not Next.js
124
+
125
+ # https://nextjs.org/blog/next-9-1#public-directory-support
126
+
127
+ # public
128
+
129
+ # vuepress build output
130
+
131
+ .vuepress/dist
132
+
133
+ # vuepress v2.x temp and cache directory
134
+
135
+ .temp
136
+ .cache
137
+
138
+ # Docusaurus cache and generated files
139
+
140
+ .docusaurus
141
+
142
+ # Serverless directories
143
+
144
+ .serverless/
145
+
146
+ # FuseBox cache
147
+
148
+ .fusebox/
149
+
150
+ # DynamoDB Local files
151
+
152
+ .dynamodb/
153
+
154
+ # TernJS port file
155
+
156
+ .tern-port
157
+
158
+ # Stores VSCode versions used for testing VSCode extensions
159
+
160
+ .vscode-test
161
+
162
+ # yarn v2
163
+
164
+ .yarn/cache
165
+ .yarn/unplugged
166
+ .yarn/build-state.yml
167
+ .yarn/install-state.gz
168
+ .pnp.*
169
+
170
+ # wrangler project
171
+
172
+ .dev.vars
173
+ .wrangler/
174
+
175
+ # Pylon project
176
+ .pylon
177
+ `},{path:".dockerignore",content:`node_modules
178
+ Dockerfile*
179
+ docker-compose*
180
+ .dockerignore
181
+ .git
182
+ .gitignore
183
+ README.md
184
+ LICENSE
185
+ .vscode
186
+ Makefile
187
+ helm-charts
188
+ .env
189
+ .editorconfig
190
+ .idea
191
+ coverage*
192
+ `,specificRuntimes:["node","bun"]},{path:".github/workflows/publish.yml",content:`name: publish
193
+
194
+ on: [push]
195
+ env:
196
+ IMAGE_NAME: __PYLON_NAME__
197
+
198
+ jobs:
199
+ # Push image to GitHub Packages.
200
+ # See also https://docs.docker.com/docker-hub/builds/
201
+ publish-container:
202
+ runs-on: ubuntu-latest
203
+ permissions:
204
+ packages: write
205
+ contents: read
206
+
207
+ steps:
208
+ - uses: actions/checkout@v4
209
+
210
+ - name: Build image
211
+ run: docker build . --file Dockerfile --tag $IMAGE_NAME
212
+
213
+ - name: Log into registry
214
+ run: echo "\${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u \${{ github.actor }} --password-stdin
215
+
216
+ - name: Push image
217
+ run: |
218
+ IMAGE_ID=ghcr.io/\${{ github.repository_owner }}/$IMAGE_NAME
219
+
220
+ # Change all uppercase to lowercase
221
+ IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]')
222
+ # Strip git ref prefix from version
223
+ VERSION=$(echo "\${{ github.ref }}" | sed -e 's,.*/\\(.*\\),\\1,')
224
+ # Strip "v" prefix from tag name
225
+ [[ "\${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')
226
+ # Use Docker \`latest\` tag convention
227
+ [ "$VERSION" == "main" ] && VERSION=latest
228
+ echo IMAGE_ID=$IMAGE_ID
229
+ echo VERSION=$VERSION
230
+ docker tag $IMAGE_NAME $IMAGE_ID:$VERSION
231
+ docker push $IMAGE_ID:$VERSION
232
+
233
+ # SPDX-License-Identifier: (EUPL-1.2)
234
+ # Copyright \xA9 2024 cronit KG`,specificRuntimes:["node","bun"]}],bun:[{path:"package.json",content:`{
235
+ "name": "__PYLON_NAME__",
236
+ "private": true,
237
+ "version": "0.0.1",
238
+ "type": "module",
239
+ "description": "Generated with \`npm create pylon\`",
240
+ "scripts": {
241
+ "dev": "pylon dev -c \\"bun run .pylon/index.js\\"",
242
+ "build": "pylon build"
243
+ },
244
+ "dependencies": {
245
+ "@getcronit/pylon": "${u}",
246
+ },
247
+ "devDependencies": {
248
+ "@getcronit/pylon-dev": "${g}",
249
+ "@types/bun": "^1.0.0"
250
+ },
251
+ "repository": {
252
+ "type": "git",
253
+ "url": "https://github.com/getcronit/pylon.git"
254
+ },
255
+ "homepage": "https://pylon.cronit.io",
256
+ "packageManager": "bun"
257
+ }
258
+ `},{path:"Dockerfile",content:`# use the official Bun image
259
+ # see all versions at https://hub.docker.com/r/oven/bun/tags
260
+ FROM oven/bun:1 as base
261
+
262
+ LABEL description="Offical docker image for Pylon services (Bun)"
263
+ LABEL org.opencontainers.image.source="https://github.com/getcronit/pylon"
264
+ LABEL maintainer="office@cronit.io"
265
+
266
+ WORKDIR /usr/src/pylon
267
+
268
+
269
+ # install dependencies into temp directory
270
+ # this will cache them and speed up future builds
271
+ FROM base AS install
272
+ RUN mkdir -p /temp/dev
273
+ COPY package.json bun.lockb /temp/dev/
274
+ RUN cd /temp/dev && bun install --frozen-lockfile
275
+
276
+ # install with --production (exclude devDependencies)
277
+ RUN mkdir -p /temp/prod
278
+ COPY package.json bun.lockb /temp/prod/
279
+ RUN cd /temp/prod && bun install --frozen-lockfile --production
280
+
281
+ # copy node_modules from temp directory
282
+ # then copy all (non-ignored) project files into the image
283
+ FROM install AS prerelease
284
+ COPY --from=install /temp/dev/node_modules node_modules
285
+ COPY . .
286
+
287
+ # [optional] tests & build
288
+ ENV NODE_ENV=production
289
+
290
+ # Create .pylon folder (mkdir)
291
+ RUN mkdir -p .pylon
292
+ # RUN bun test
293
+ RUN bun run pylon build
294
+
295
+ # copy production dependencies and source code into final image
296
+ FROM base AS release
297
+ COPY --from=install /temp/prod/node_modules node_modules
298
+ COPY --from=prerelease /usr/src/pylon/.pylon .pylon
299
+ COPY --from=prerelease /usr/src/pylon/package.json .
300
+
301
+ # run the app
302
+ USER bun
303
+ EXPOSE 3000/tcp
304
+ ENTRYPOINT [ "bun", "run", "/usr/src/pylon/.pylon/index.js" ]
305
+ `}],node:[{path:"package.json",content:`{
306
+ "name": "__PYLON_NAME__",
307
+ "private": true,
308
+ "version": "0.0.1",
309
+ "type": "module",
310
+ "description": "Generated with \`npm create pylon\`",
311
+ "scripts": {
312
+ "dev": "pylon dev -c \\"node --enable-source-maps .pylon/index.js\\"",
313
+ "build": "pylon build"
314
+ },
315
+ "dependencies": {
316
+ "@getcronit/pylon": "${u}",
317
+ "@hono/node-server": "^1.12.2"
318
+ },
319
+ "devDependencies": {
320
+ "@getcronit/pylon-dev": "${g}"
321
+ },
322
+ "repository": {
323
+ "type": "git",
324
+ "url": "https://github.com/getcronit/pylon.git"
325
+ },
326
+ "homepage": "https://pylon.cronit.io"
327
+ }
328
+ `},{path:"Dockerfile",content:`# Use the official Node.js 20 image as the base
329
+ FROM node:20-alpine as base
330
+
331
+ LABEL description="Offical docker image for Pylon services (Node.js)"
332
+ LABEL org.opencontainers.image.source="https://github.com/getcronit/pylon"
333
+ LABEL maintainer="office@cronit.io"
334
+
335
+ WORKDIR /usr/src/pylon
336
+
337
+ # install dependencies into a temp directory
338
+ # this will cache them and speed up future builds
339
+ FROM base AS install
340
+ RUN mkdir -p /temp/dev
341
+ COPY package.json package-lock.json /temp/dev/
342
+ RUN cd /temp/dev && npm ci
343
+
344
+ # install with --production (exclude devDependencies)
345
+ RUN mkdir -p /temp/prod
346
+ COPY package.json package-lock.json /temp/prod/
347
+ RUN cd /temp/prod && npm ci --only=production
348
+
349
+ # copy node_modules from temp directory
350
+ # then copy all (non-ignored) project files into the image
351
+ FROM install AS prerelease
352
+ COPY --from=install /temp/dev/node_modules node_modules
353
+ COPY . .
354
+
355
+ # [optional] tests & build
356
+ ENV NODE_ENV=production
357
+
358
+ # Create .pylon folder (mkdir)
359
+ RUN mkdir -p .pylon
360
+ # RUN npm test
361
+ RUN npm run pylon build
362
+
363
+ # copy production dependencies and source code into final image
364
+ FROM base AS release
365
+ COPY --from=install /temp/prod/node_modules node_modules
366
+ COPY --from=prerelease /usr/src/pylon/.pylon .pylon
367
+ COPY --from=prerelease /usr/src/pylon/package.json .
368
+
369
+ # run the app
370
+ USER node
371
+ EXPOSE 3000/tcp
372
+ ENTRYPOINT [ "node", "/usr/src/pylon/.pylon/index.js" ]
373
+ `}],"cf-workers":[{path:"package.json",content:`{
374
+ "name": "__PYLON_NAME__",
375
+ "type": "module",
376
+ "description": "Generated with \`npm create pylon\`",
377
+ "version": "0.0.1",
378
+ "private": true,
379
+ "scripts": {
380
+ "deploy": "pylon build && wrangler deploy",
381
+ "dev": "pylon dev -c \\"wrangler dev\\"",
382
+ "cf-typegen": "wrangler types"
383
+ },
384
+ "dependencies": {
385
+ "@getcronit/pylon": "${u}",
386
+ },
387
+ "devDependencies": {
388
+ "@getcronit/pylon-dev": "${g}",
389
+ "@cloudflare/vitest-pool-workers": "^0.4.5",
390
+ "@cloudflare/workers-types": "^4.20240903.0",
391
+ "typescript": "^5.5.2",
392
+ "wrangler": "^3.60.3"
393
+ },
394
+ "repository": {
395
+ "type": "git",
396
+ "url": "https://github.com/getcronit/pylon.git"
397
+ },
398
+ "homepage": "https://pylon.cronit.io"
399
+ }
400
+ `},{path:"wrangler.toml",content:`#:schema node_modules/wrangler/config-schema.json
401
+ name = "__PYLON_NAME__"
402
+ main = ".pylon/index.js"
403
+ compatibility_date = "2024-09-03"
404
+ compatibility_flags = ["nodejs_compat_v2"]
405
+
406
+ # Automatically place your workloads in an optimal location to minimize latency.
407
+ # If you are running back-end logic in a Worker, running it closer to your back-end infrastructure
408
+ # rather than the end user may result in better performance.
409
+ # Docs: https://developers.cloudflare.com/workers/configuration/smart-placement/#smart-placement
410
+ # [placement]
411
+ # mode = "smart"
412
+
413
+ # Variable bindings. These are arbitrary, plaintext strings (similar to environment variables)
414
+ # Docs:
415
+ # - https://developers.cloudflare.com/workers/wrangler/configuration/#environment-variables
416
+ # Note: Use secrets to store sensitive data.
417
+ # - https://developers.cloudflare.com/workers/configuration/secrets/
418
+ # [vars]
419
+ # MY_VARIABLE = "production_value"
420
+
421
+ # Bind the Workers AI model catalog. Run machine learning models, powered by serverless GPUs, on Cloudflare\u2019s global network
422
+ # Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#workers-ai
423
+ # [ai]
424
+ # binding = "AI"
425
+
426
+ # Bind an Analytics Engine dataset. Use Analytics Engine to write analytics within your Pages Function.
427
+ # Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#analytics-engine-datasets
428
+ # [[analytics_engine_datasets]]
429
+ # binding = "MY_DATASET"
430
+
431
+ # Bind a headless browser instance running on Cloudflare's global network.
432
+ # Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#browser-rendering
433
+ # [browser]
434
+ # binding = "MY_BROWSER"
435
+
436
+ # Bind a D1 database. D1 is Cloudflare\u2019s native serverless SQL database.
437
+ # Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#d1-databases
438
+ # [[d1_databases]]
439
+ # binding = "MY_DB"
440
+ # database_name = "my-database"
441
+ # database_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
442
+
443
+ # Bind a dispatch namespace. Use Workers for Platforms to deploy serverless functions programmatically on behalf of your customers.
444
+ # Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#dispatch-namespace-bindings-workers-for-platforms
445
+ # [[dispatch_namespaces]]
446
+ # binding = "MY_DISPATCHER"
447
+ # namespace = "my-namespace"
448
+
449
+ # Bind a Durable Object. Durable objects are a scale-to-zero compute primitive based on the actor model.
450
+ # Durable Objects can live for as long as needed. Use these when you need a long-running "server", such as in realtime apps.
451
+ # Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects
452
+ # [[durable_objects.bindings]]
453
+ # name = "MY_DURABLE_OBJECT"
454
+ # class_name = "MyDurableObject"
455
+
456
+ # Durable Object migrations.
457
+ # Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#migrations
458
+ # [[migrations]]
459
+ # tag = "v1"
460
+ # new_classes = ["MyDurableObject"]
461
+
462
+ # Bind a Hyperdrive configuration. Use to accelerate access to your existing databases from Cloudflare Workers.
463
+ # Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#hyperdrive
464
+ # [[hyperdrive]]
465
+ # binding = "MY_HYPERDRIVE"
466
+ # id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
467
+
468
+ # Bind a KV Namespace. Use KV as persistent storage for small key-value pairs.
469
+ # Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#kv-namespaces
470
+ # [[kv_namespaces]]
471
+ # binding = "MY_KV_NAMESPACE"
472
+ # id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
473
+
474
+ # Bind an mTLS certificate. Use to present a client certificate when communicating with another service.
475
+ # Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#mtls-certificates
476
+ # [[mtls_certificates]]
477
+ # binding = "MY_CERTIFICATE"
478
+ # certificate_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
479
+
480
+ # Bind a Queue producer. Use this binding to schedule an arbitrary task that may be processed later by a Queue consumer.
481
+ # Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#queues
482
+ # [[queues.producers]]
483
+ # binding = "MY_QUEUE"
484
+ # queue = "my-queue"
485
+
486
+ # Bind a Queue consumer. Queue Consumers can retrieve tasks scheduled by Producers to act on them.
487
+ # Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#queues
488
+ # [[queues.consumers]]
489
+ # queue = "my-queue"
490
+
491
+ # Bind an R2 Bucket. Use R2 to store arbitrarily large blobs of data, such as files.
492
+ # Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#r2-buckets
493
+ # [[r2_buckets]]
494
+ # binding = "MY_BUCKET"
495
+ # bucket_name = "my-bucket"
496
+
497
+ # Bind another Worker service. Use this binding to call another Worker without network overhead.
498
+ # Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#service-bindings
499
+ # [[services]]
500
+ # binding = "MY_SERVICE"
501
+ # service = "my-service"
502
+
503
+ # Bind a Vectorize index. Use to store and query vector embeddings for semantic search, classification and other vector search use-cases.
504
+ # Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#vectorize-indexes
505
+ # [[vectorize]]
506
+ # binding = "MY_INDEX"
507
+ # index_name = "my-index"
508
+ `}],deno:[{path:".vscode/settings.json",content:`{
509
+ "deno.enablePaths": [
510
+ "./"
511
+ ],
512
+ "editor.inlayHints.enabled": "off"
513
+ }`},{path:".vscode/extensions.json",content:`{
514
+ "recommendations": [
515
+ "denoland.vscode-deno"
516
+ ]
517
+ }`},{path:"deno.json",content:`{
518
+ "imports": {
519
+ "@getcronit/pylon-dev": "npm:@getcronit/pylon-dev@${g}",
520
+ "@getcronit/pylon": "npm:@getcronit/pylon@${u}"
521
+ },
522
+ "tasks": {
523
+ "dev": "pylon dev -c \\"deno run -A .pylon/index.js --config tsconfig.json\\"",
524
+ "build": "pylon build"
525
+ },
526
+ "compilerOptions": {
527
+ "jsx": "precompile",
528
+ "jsxImportSource": "hono/jsx"
529
+ },
530
+ "nodeModulesDir": "auto",
531
+ "packageManager": "deno"
532
+ }
533
+ `}]};var m=[{key:"bun",name:"Bun.js",website:"https://bunjs.dev",supportedFeatures:["auth","pages"]},{key:"node",name:"Node.js",website:"https://nodejs.org",supportedFeatures:["auth","pages"]},{key:"cf-workers",name:"Cloudflare Workers",website:"https://workers.cloudflare.com",supportedFeatures:["auth"]},{key:"deno",name:"Deno",website:"https://deno.land"}],v=[{key:"auth",name:"Authentication",website:"https://pylon.cronit.io/docs/authentication"},{key:"pages",name:"Pages",website:"https://pylon.cronit.io/docs/pages"}],A=(e,r)=>{let o=["app","PylonConfig"],t=[];r.includes("auth")&&(o.push("useAuth"),t.push("useAuth({issuer: 'https://test-0o6zvq.zitadel.cloud'})")),r.includes("pages")&&(o.push("usePages"),t.push("usePages()"));let n="";return n+=`import {${o.join(", ")}} from '@getcronit/pylon'
534
+
535
+ `,e==="node"&&(n+=`import {serve} from '@hono/node-server'
536
+ `),n+=`
537
+
538
+ `,n+=`export const graphql = {
539
+ Query: {
540
+ hello: () => {
541
+ return 'Hello, world!'
542
+ }
543
+ },
544
+ Mutation: {}
545
+ }`,n+=`
546
+
547
+ `,e==="bun"||e==="cf-workers"?n+="export default app":e==="node"?n+="serve(app, info => {\n console.log(`Server running at ${info.port}`)\n})":e==="deno"&&(n+=`Deno.serve({port: 3000}, app.fetch)
548
+ `),n+=`
549
+
550
+ `,n+=`export const config: PylonConfig = {
551
+ plugins: [${t.join(", ")}]
552
+ }`,n},M=async(e,r)=>{let o=`import '@getcronit/pylon'
553
+
554
+ declare module '@getcronit/pylon' {
555
+ interface Bindings {}
556
+
557
+ interface Variables {}
558
+ }
559
+
560
+
561
+ `;return r.includes("pages")&&(o+=`import {useQuery} from './.pylon/client'
562
+
563
+ declare module '@getcronit/pylon/pages' {
564
+ interface PageData extends ReturnType<typeof useQuery> {}
565
+ }`),o},I=async(e,r)=>{let o={extends:"@getcronit/pylon/tsconfig.pylon.json",include:["pylon.d.ts","src/**/*.ts"]};return e==="cf-workers"&&o.include.push("worker-configuration.d.ts"),r.includes("pages")&&(o.compilerOptions={baseUrl:".",paths:{"@/*":["./*"]},jsx:"react-jsx"},o.include.push("pages","components",".pylon")),JSON.stringify(o,null,2)},S=async e=>{let r=[{path:"pages/layout.tsx",content:`import '../globals.css'
566
+
567
+ export default function RootLayout({children}: {children: React.ReactNode}) {
568
+ return (
569
+ <html lang="en">
570
+ <body>{children}</body>
571
+ </html>
572
+ )
573
+ }
574
+ `},{path:"pages/page.tsx",content:`import { Button } from '@/components/ui/button'
575
+ import { PageProps } from '@getcronit/pylon/pages'
576
+
577
+ const Page: React.FC<PageProps> = props => {
578
+ return (
579
+ <div className="container">
580
+ <title>{props.data.hello}</title>
581
+ <Button>Hello {props.data.hello}</Button>
582
+ </div>
583
+ )
584
+ }
585
+
586
+ export default Page
587
+ `},{path:"globals.css",content:`@import 'tailwindcss';
588
+
589
+ @plugin 'tailwindcss-animate';
590
+
591
+ @custom-variant dark (&:is(.dark *));
592
+
593
+ @theme {
594
+ --color-background: hsl(var(--background));
595
+ --color-foreground: hsl(var(--foreground));
596
+
597
+ --color-card: hsl(var(--card));
598
+ --color-card-foreground: hsl(var(--card-foreground));
599
+
600
+ --color-popover: hsl(var(--popover));
601
+ --color-popover-foreground: hsl(var(--popover-foreground));
602
+
603
+ --color-primary: hsl(var(--primary));
604
+ --color-primary-foreground: hsl(var(--primary-foreground));
605
+
606
+ --color-secondary: hsl(var(--secondary));
607
+ --color-secondary-foreground: hsl(var(--secondary-foreground));
608
+
609
+ --color-muted: hsl(var(--muted));
610
+ --color-muted-foreground: hsl(var(--muted-foreground));
611
+
612
+ --color-accent: hsl(var(--accent));
613
+ --color-accent-foreground: hsl(var(--accent-foreground));
614
+
615
+ --color-destructive: hsl(var(--destructive));
616
+ --color-destructive-foreground: hsl(var(--destructive-foreground));
617
+
618
+ --color-border: hsl(var(--border));
619
+ --color-input: hsl(var(--input));
620
+ --color-ring: hsl(var(--ring));
621
+
622
+ --color-chart-1: hsl(var(--chart-1));
623
+ --color-chart-2: hsl(var(--chart-2));
624
+ --color-chart-3: hsl(var(--chart-3));
625
+ --color-chart-4: hsl(var(--chart-4));
626
+ --color-chart-5: hsl(var(--chart-5));
627
+
628
+ --color-sidebar: hsl(var(--sidebar-background));
629
+ --color-sidebar-foreground: hsl(var(--sidebar-foreground));
630
+ --color-sidebar-primary: hsl(var(--sidebar-primary));
631
+ --color-sidebar-primary-foreground: hsl(var(--sidebar-primary-foreground));
632
+ --color-sidebar-accent: hsl(var(--sidebar-accent));
633
+ --color-sidebar-accent-foreground: hsl(var(--sidebar-accent-foreground));
634
+ --color-sidebar-border: hsl(var(--sidebar-border));
635
+ --color-sidebar-ring: hsl(var(--sidebar-ring));
636
+
637
+ --radius-lg: var(--radius);
638
+ --radius-md: calc(var(--radius) - 2px);
639
+ --radius-sm: calc(var(--radius) - 4px);
640
+
641
+ --animate-accordion-down: accordion-down 0.2s ease-out;
642
+ --animate-accordion-up: accordion-up 0.2s ease-out;
643
+
644
+ @keyframes accordion-down {
645
+ from {
646
+ height: 0;
647
+ }
648
+ to {
649
+ height: var(--radix-accordion-content-height);
650
+ }
651
+ }
652
+ @keyframes accordion-up {
653
+ from {
654
+ height: var(--radix-accordion-content-height);
655
+ }
656
+ to {
657
+ height: 0;
658
+ }
659
+ }
660
+ }
661
+
662
+ /*
663
+ The default border color has changed to \`currentColor\` in Tailwind CSS v4,
664
+ so we've added these compatibility styles to make sure everything still
665
+ looks the same as it did with Tailwind CSS v3.
666
+
667
+ If we ever want to remove these styles, we need to add an explicit border
668
+ color utility to any element that depends on these defaults.
669
+ */
670
+ @layer base {
671
+ *,
672
+ ::after,
673
+ ::before,
674
+ ::backdrop,
675
+ ::file-selector-button {
676
+ border-color: var(--color-gray-200, currentColor);
677
+ }
678
+ }
679
+
680
+ @layer utilities {
681
+ body {
682
+ font-family: Arial, Helvetica, sans-serif;
683
+ }
684
+ }
685
+
686
+ @layer base {
687
+ :root {
688
+ --background: 0 0% 100%;
689
+ --foreground: 0 0% 3.9%;
690
+ --card: 0 0% 100%;
691
+ --card-foreground: 0 0% 3.9%;
692
+ --popover: 0 0% 100%;
693
+ --popover-foreground: 0 0% 3.9%;
694
+ --primary: 0 0% 9%;
695
+ --primary-foreground: 0 0% 98%;
696
+ --secondary: 0 0% 96.1%;
697
+ --secondary-foreground: 0 0% 9%;
698
+ --muted: 0 0% 96.1%;
699
+ --muted-foreground: 0 0% 45.1%;
700
+ --accent: 0 0% 96.1%;
701
+ --accent-foreground: 0 0% 9%;
702
+ --destructive: 0 84.2% 60.2%;
703
+ --destructive-foreground: 0 0% 98%;
704
+ --border: 0 0% 89.8%;
705
+ --input: 0 0% 89.8%;
706
+ --ring: 0 0% 3.9%;
707
+ --chart-1: 12 76% 61%;
708
+ --chart-2: 173 58% 39%;
709
+ --chart-3: 197 37% 24%;
710
+ --chart-4: 43 74% 66%;
711
+ --chart-5: 27 87% 67%;
712
+ --radius: 0.5rem;
713
+ --sidebar-background: 0 0% 98%;
714
+ --sidebar-foreground: 240 5.3% 26.1%;
715
+ --sidebar-primary: 240 5.9% 10%;
716
+ --sidebar-primary-foreground: 0 0% 98%;
717
+ --sidebar-accent: 240 4.8% 95.9%;
718
+ --sidebar-accent-foreground: 240 5.9% 10%;
719
+ --sidebar-border: 220 13% 91%;
720
+ --sidebar-ring: 217.2 91.2% 59.8%;
721
+ }
722
+ .dark {
723
+ --background: 0 0% 3.9%;
724
+ --foreground: 0 0% 98%;
725
+ --card: 0 0% 3.9%;
726
+ --card-foreground: 0 0% 98%;
727
+ --popover: 0 0% 3.9%;
728
+ --popover-foreground: 0 0% 98%;
729
+ --primary: 0 0% 98%;
730
+ --primary-foreground: 0 0% 9%;
731
+ --secondary: 0 0% 14.9%;
732
+ --secondary-foreground: 0 0% 98%;
733
+ --muted: 0 0% 14.9%;
734
+ --muted-foreground: 0 0% 63.9%;
735
+ --accent: 0 0% 14.9%;
736
+ --accent-foreground: 0 0% 98%;
737
+ --destructive: 0 62.8% 30.6%;
738
+ --destructive-foreground: 0 0% 98%;
739
+ --border: 0 0% 14.9%;
740
+ --input: 0 0% 14.9%;
741
+ --ring: 0 0% 83.1%;
742
+ --chart-1: 220 70% 50%;
743
+ --chart-2: 160 60% 45%;
744
+ --chart-3: 30 80% 55%;
745
+ --chart-4: 280 65% 60%;
746
+ --chart-5: 340 75% 55%;
747
+ --sidebar-background: 240 5.9% 10%;
748
+ --sidebar-foreground: 240 4.8% 95.9%;
749
+ --sidebar-primary: 224.3 76.3% 48%;
750
+ --sidebar-primary-foreground: 0 0% 100%;
751
+ --sidebar-accent: 240 3.7% 15.9%;
752
+ --sidebar-accent-foreground: 240 4.8% 95.9%;
753
+ --sidebar-border: 240 3.7% 15.9%;
754
+ --sidebar-ring: 217.2 91.2% 59.8%;
755
+ }
756
+ }
757
+
758
+ @layer base {
759
+ * {
760
+ @apply border-border;
761
+ }
762
+ body {
763
+ @apply bg-background text-foreground;
764
+ }
765
+ }
766
+
767
+ /*
768
+ ---break---
769
+ */
770
+
771
+ @layer base {
772
+ * {
773
+ @apply border-border outline-ring/50;
774
+ }
775
+ body {
776
+ @apply bg-background text-foreground;
777
+ }
778
+ }
779
+ `},{path:"postcss.config.js",content:`import tailwindPostCss from '@tailwindcss/postcss'
780
+
781
+ export default {
782
+ plugins: [tailwindPostCss]
783
+ }
784
+ `},{path:"components.json",content:`{
785
+ "$schema": "https://ui.shadcn.com/schema.json",
786
+ "style": "new-york",
787
+ "rsc": false,
788
+ "tsx": true,
789
+ "tailwind": {
790
+ "config": "tailwind.config.js",
791
+ "css": "globals.css",
792
+ "baseColor": "zinc",
793
+ "cssVariables": true,
794
+ "prefix": ""
795
+ },
796
+ "aliases": {
797
+ "components": "@/components",
798
+ "utils": "@/lib/utils",
799
+ "ui": "@/components/ui",
800
+ "lib": "@/lib",
801
+ "hooks": "@/hooks"
802
+ },
803
+ "iconLibrary": "lucide"
804
+ }`},{path:"lib/utils.ts",content:`import {clsx, type ClassValue} from 'clsx'
805
+ import {twMerge} from 'tailwind-merge'
806
+
807
+ export function cn(...inputs: ClassValue[]) {
808
+ return twMerge(clsx(inputs))
809
+ }`},{path:"components/ui/button.tsx",content:`import * as React from 'react'
810
+ import {Slot} from '@radix-ui/react-slot'
811
+ import {cva, type VariantProps} from 'class-variance-authority'
812
+
813
+ import {cn} from '@/lib/utils'
814
+
815
+ const buttonVariants = cva(
816
+ "inline-flexxx items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-[color,box-shadow] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0 ring-ring/10 dark:ring-ring/20 dark:outline-ring/40 outline-ring/50 focus-visible:ring-4 focus-visible:outline-1 aria-invalid:focus-visible:ring-0",
817
+ {
818
+ variants: {
819
+ variant: {
820
+ default:
821
+ 'bg-primary text-primary-foreground shadow-sm hover:bg-primary/90',
822
+ destructive:
823
+ 'bg-destructive text-destructive-foreground shadow-xs hover:bg-destructive/90',
824
+ outline:
825
+ 'border border-input bg-background shadow-xs hover:bg-accent hover:text-accent-foreground',
826
+ secondary:
827
+ 'bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80',
828
+ ghost: 'hover:bg-accent hover:text-accent-foreground',
829
+ link: 'text-primary underline-offset-4 hover:underline'
830
+ },
831
+ size: {
832
+ default: 'h-9 px-4 py-2 has-[>svg]:px-3',
833
+ sm: 'h-8 rounded-md px-3 has-[>svg]:px-2.5',
834
+ lg: 'h-10 rounded-md px-6 has-[>svg]:px-4',
835
+ icon: 'size-9'
836
+ }
837
+ },
838
+ defaultVariants: {
839
+ variant: 'default',
840
+ size: 'default'
841
+ }
842
+ }
843
+ )
844
+
845
+ function Button({
846
+ className,
847
+ variant,
848
+ size,
849
+ asChild = false,
850
+ ...props
851
+ }: React.ComponentProps<'button'> &
852
+ VariantProps<typeof buttonVariants> & {
853
+ asChild?: boolean
854
+ }) {
855
+ const Comp = asChild ? Slot : 'button'
856
+
857
+ return (
858
+ <Comp
859
+ data-slot="button"
860
+ className={cn(buttonVariants({variant, size, className}))}
861
+ {...props}
862
+ />
863
+ )
864
+ }
865
+
866
+ export {Button, buttonVariants}
867
+ `}];e.push(...r);let o=e.find(t=>t.path==="package.json");if(o){let t=JSON.parse(o.content);t.dependencies={...t.dependencies,"@gqty/react":"^3.1.0",gqty:"^3.4.0","@radix-ui/react-slot":"^1.1.2","class-variance-authority":"^0.7.1",clsx:"^2.1.1","lucide-react":"^0.474.0",react:"^19.0.0","react-dom":"^19.0.0","tailwind-merge":"^3.0.1",tailwindcss:"^4.0.4","tailwindcss-animate":"^1.0.7"},t.devDependencies={...t.devDependencies,"@tailwindcss/postcss":"^4.0.6","@types/react":"^19.0.8"},o.content=JSON.stringify(t,null,2)}return e},$=(e,r)=>{let o=e;return Object.entries(r).forEach(([t,n])=>{o=o.replaceAll(t,n)}),o},j=async e=>{let{destination:r,runtime:o,features:t}=e,n=b.ALL.concat(b[o]||[]).filter(l=>l.specificRuntimes?l.specificRuntimes.includes(o):!0),k=A(o,t),d=await I(o,t),p=await M(o,t);n.push({path:"tsconfig.json",content:d},{path:"pylon.d.ts",content:p},{path:"src/index.ts",content:k}),t.includes("pages")&&(n=await S(n));for(let l of n){let a=_.join(r,l.path);await w.mkdir(_.dirname(a),{recursive:!0}),await w.writeFile(a,$(l.content,e.variables))}};import B from"node:process";import{detect as L}from"package-manager-detector/detect";import U from"consola";async function f(e=B.cwd()){return(await L({cwd:e,onUnknown(o){U.warn("Unknown packageManager:",o)}}))?.agent||null}function E(e){if(e===null)return null;let[r]=e.split("@");switch(r){case"bun":return"bun";case"npm":return"npm run";case"yarn":return"yarn";case"pnpm":return"pnpm run";case"deno":return"deno task";default:return null}}import{existsSync as Y}from"node:fs";import{resolve as V}from"node:path";import F from"node:process";import{x as T}from"tinyexec";async function P(e,r={}){let o=r.packageManager||await f(r.cwd)||"npm",[t]=o.split("@");Array.isArray(e)||(e=[e]);let n=(typeof r.additionalArgs=="function"?r.additionalArgs(t,o):r.additionalArgs)||[];return r.preferOffline&&(o==="yarn@berry"?n.unshift("--cached"):n.unshift("--prefer-offline")),t==="pnpm"&&Y(V(r.cwd??F.cwd(),"pnpm-workspace.yaml"))&&n.unshift("-w","--prod=false"),T(t,[t==="yarn"?"add":"install",r.dev?"-D":"",...n,...e].filter(Boolean),{nodeOptions:{stdio:r.silent?"ignore":"inherit",cwd:r.cwd},throwOnError:!0})}import{PostHog as G}from"posthog-node";import z from"conf";import{readFileSync as q}from"fs";import{randomUUID as O}from"crypto";var J={distinctId:{type:"string",default:O()}},W=new z({projectName:"pylon",schema:J}),R=W.get("distinctId"),xe=O(),x=new G("phc_KN4qCOcCdkXp6sHLIuMWGRfzZWuNht69oqv5Kw5rGxj",{host:"https://eu.i.posthog.com",disabled:process.env.PYLON_DISABLE_TELEMETRY==="true"}),H=()=>{let e;try{e=JSON.parse(q("./package.json","utf8"))}catch{e={}}let r=e.dependencies||{},o=e.devDependencies||{},t=e.peerDependencies||{};return{dependencies:r,devDependencies:o,peerDependencies:t}},ke=H();var C="1.1.5-canary-20250521152654.16fa11a497399c04d3766e666e5ed5212e5ae309";D.name("create-pylon").version(C).arguments("[target]").addOption(new h("-i, --install","Install dependencies")).addOption(new h("-r, --runtime <runtime>","Runtime").choices(m.map(({key:e})=>e))).addOption(new h("--features [features...]","Features").choices(v.map(({key:e})=>e))).addOption(new h("-pm, --package-manager <packageManager>","Package manager")).action(Q);async function Q(e,r,o){c.log(`${o.name()} version ${o.version()}`);try{e||(e=await c.prompt("Where should the project be created?",{default:"./my-pylon",placeholder:"./my-pylon",cancel:"reject"}));let t="";if(e==="."?t=N.basename(process.cwd()):t=N.basename(e),!r.runtime){let a=await c.prompt("Select a runtime environment:",{type:"select",options:m.map(s=>({label:s.name,value:s.key,hint:s.website})),cancel:"reject"});r.runtime=a}let n=m.find(a=>a.key===r.runtime);if(!n)throw new Error(`Invalid runtime selected: ${r.runtime}`);if(!r.features){let a=await c.prompt("Configure features:",{type:"multiselect",options:v.filter(s=>n.supportedFeatures?.includes(s.key)).map(s=>({label:s.name,value:s.key,hint:s.website})),required:!1,cancel:"reject"});r.features=a}for(let a of r.features)if(!n.supportedFeatures?.includes(a))throw new Error(`Invalid feature selected: ${a}`);if(!await c.prompt(`Ready to create the project in ${i.blue(e)}?`,{type:"confirm",initial:!0,cancel:"reject"})){let a=new Error("Prompt cancelled.");throw a.name="ConsolaPromptCancelledError",a}if(y.existsSync(e)&&y.readdirSync(e).length>0&&!await c.prompt("Directory not empty. Continue?",{type:"confirm",cancel:"reject"})){let s=new Error("Prompt cancelled.");throw s.name="ConsolaPromptCancelledError",s}await j({variables:{__PYLON_NAME__:t},runtime:n.key,features:r.features,destination:e});let d=r.packageManager||await f(e)||"npm";r.install===void 0&&(r.install=await c.prompt(`Installed dependencies with ${d} now? You can also do this later.`,{type:"confirm",initial:!0,cancel:"reject"})),r.install&&await P([]),x.capture({distinctId:R,event:"create-pylon",properties:{runtime:n.key,features:r.features,packageManager:d,install:r.install}});let p=E(d),l=`
868
+ \u{1F389} ${i.green.bold("Pylon created successfully.")}
869
+
870
+ \u{1F4BB} ${i.cyan.bold("Continue Developing")}
871
+ ${i.yellow("Change directories:")} cd ${i.blue(e)}
872
+ ${i.yellow("Start dev server:")} ${p} dev
873
+ ${n.key==="cf-workers"?`${i.yellow("Deploy:")} ${p} deploy`:""}
874
+
875
+ \u{1F4D6} ${i.cyan.bold("Explore Documentation")}
876
+ ${i.underline.blue("https://pylon.cronit.io/docs")}
877
+
878
+ \u{1F4AC} ${i.cyan.bold("Join our Community")}
879
+ ${i.underline.blue("https://discord.gg/cbJjkVrnHe")}
880
+ `;c.box(l)}catch(t){c.error(t)}finally{await x.shutdown()}}D.parse();
16
881
  //# sourceMappingURL=index.js.map