create-glion 0.1.0 → 0.2.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/README.md CHANGED
@@ -36,7 +36,6 @@ pnpm create glion my-app --example
36
36
  | `starter` | Starter Glion — minimal HL7v2 MLLP server. The default scaffold. |
37
37
  | `mllp-server` | HL7v2 MLLP server with route handlers (Node.js). |
38
38
  | `mllp-server-bun` | HL7v2 MLLP server with route handlers (Bun). |
39
- | `mllp-client` | MLLP client sending sample messages — companion to the server. |
40
39
 
41
40
  Each example is fetched from `github:rethinkhealth/glion/examples/<name>` via [`giget`](https://github.com/unjs/giget).
42
41
 
package/dist/index.js CHANGED
@@ -23,11 +23,6 @@ const EXAMPLES = [
23
23
  hint: "HL7v2 MLLP server with route handlers (Bun)",
24
24
  label: "mllp-server-bun",
25
25
  value: "mllp-server-bun"
26
- },
27
- {
28
- hint: "MLLP client sending sample messages",
29
- label: "mllp-client",
30
- value: "mllp-client"
31
26
  }
32
27
  ];
33
28
  const HELP = `Usage: create-glion [dir] [--example [name]]
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { existsSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { parseArgs } from \"node:util\";\n\nimport * as p from \"@clack/prompts\";\nimport { downloadTemplate } from \"giget\";\n\nconst REPO = \"github:rethinkhealth/glion\";\nconst DEFAULT_DIR = \"./my-glion-app\";\nconst DEFAULT_EXAMPLE = \"starter\";\n\nconst EXAMPLES = [\n {\n hint: \"Starter Glion — minimal HL7v2 MLLP server (default)\",\n label: \"starter\",\n value: \"starter\",\n },\n {\n hint: \"HL7v2 MLLP server with route handlers (Node.js)\",\n label: \"mllp-server\",\n value: \"mllp-server\",\n },\n {\n hint: \"HL7v2 MLLP server with route handlers (Bun)\",\n label: \"mllp-server-bun\",\n value: \"mllp-server-bun\",\n },\n {\n hint: \"MLLP client sending sample messages\",\n label: \"mllp-client\",\n value: \"mllp-client\",\n },\n] as const;\n\ntype ExampleId = (typeof EXAMPLES)[number][\"value\"];\n\nconst HELP = `Usage: create-glion [dir] [--example [name]]\n\nOptions:\n -e, --example [name] Example to clone from examples/. Pass a name to use it\n directly, or pass the flag with no value to open the\n interactive picker. Omit entirely to use the default\n (${DEFAULT_EXAMPLE}).\n -h, --help Show this message\n\nExamples:\n${EXAMPLES.map((e) => ` ${e.value.padEnd(18)} ${e.hint}`).join(\"\\n\")}\n`;\n\nfunction isExampleId(value: string): value is ExampleId {\n return EXAMPLES.some((e) => e.value === value);\n}\n\nfunction abort(message = \"Aborted.\"): never {\n p.cancel(message);\n process.exit(0);\n}\n\n// Detect bare `--example` / `-e` (no value) and `--example=` / `-e=` and strip\n// them from argv so that parseArgs (which requires a value for string options)\n// does not error. The bare form opts into the interactive picker.\nfunction extractPickerFlag(args: string[]): {\n args: string[];\n wantsPicker: boolean;\n} {\n const out: string[] = [];\n let wantsPicker = false;\n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n if (arg === undefined) {\n continue;\n }\n if (arg === \"--example\" || arg === \"-e\") {\n const next = args[i + 1];\n if (next === undefined || next.startsWith(\"-\")) {\n wantsPicker = true;\n continue;\n }\n out.push(arg);\n continue;\n }\n if (arg === \"--example=\" || arg === \"-e=\") {\n wantsPicker = true;\n continue;\n }\n out.push(arg);\n }\n return { args: out, wantsPicker };\n}\n\nasync function run(): Promise<void> {\n const { args: cleanArgs, wantsPicker } = extractPickerFlag(\n process.argv.slice(2)\n );\n const { values, positionals } = parseArgs({\n allowPositionals: true,\n args: cleanArgs,\n options: {\n example: { short: \"e\", type: \"string\" },\n help: { short: \"h\", type: \"boolean\" },\n },\n });\n\n if (values.help) {\n process.stdout.write(`${HELP}\\n`);\n return;\n }\n\n p.intro(\"create-glion\");\n\n let dir = positionals[0];\n if (!dir) {\n const answer = await p.text({\n defaultValue: DEFAULT_DIR,\n message: \"Where should we scaffold your project?\",\n placeholder: DEFAULT_DIR,\n });\n if (p.isCancel(answer)) {\n abort();\n }\n dir = answer.trim().length === 0 ? DEFAULT_DIR : answer;\n }\n\n const target = resolve(process.cwd(), dir);\n\n if (existsSync(target)) {\n const proceed = await p.confirm({\n initialValue: false,\n message: `${target} already exists. Continue and overwrite?`,\n });\n if (p.isCancel(proceed) || !proceed) {\n abort();\n }\n }\n\n let example = values.example;\n if (example && !isExampleId(example)) {\n p.cancel(\n `Unknown example: ${example}. Available: ${EXAMPLES.map((e) => e.value).join(\", \")}`\n );\n process.exit(1);\n }\n\n if (!example) {\n if (wantsPicker) {\n const choice = await p.select({\n initialValue: DEFAULT_EXAMPLE,\n message: \"Choose an example\",\n options: EXAMPLES.map((e) => ({\n hint: e.hint,\n label: e.label,\n value: e.value,\n })),\n });\n if (p.isCancel(choice)) {\n abort();\n }\n example = choice;\n } else {\n example = DEFAULT_EXAMPLE;\n }\n }\n\n const spinner = p.spinner();\n spinner.start(`Downloading example: ${example}`);\n await downloadTemplate(`${REPO}/examples/${example}`, {\n dir: target,\n force: true,\n });\n spinner.stop(`Scaffolded ${example} → ${target}`);\n\n p.note(`cd ${dir}\\npnpm install\\npnpm dev`, \"Next steps\");\n p.outro(\"Happy hacking!\");\n}\n\ntry {\n await run();\n} catch (error: unknown) {\n p.cancel(error instanceof Error ? error.message : String(error));\n process.exit(1);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { existsSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { parseArgs } from \"node:util\";\n\nimport * as p from \"@clack/prompts\";\nimport { downloadTemplate } from \"giget\";\n\nconst REPO = \"github:rethinkhealth/glion\";\nconst DEFAULT_DIR = \"./my-glion-app\";\nconst DEFAULT_EXAMPLE = \"starter\";\n\nconst EXAMPLES = [\n {\n hint: \"Starter Glion — minimal HL7v2 MLLP server (default)\",\n label: \"starter\",\n value: \"starter\",\n },\n {\n hint: \"HL7v2 MLLP server with route handlers (Node.js)\",\n label: \"mllp-server\",\n value: \"mllp-server\",\n },\n {\n hint: \"HL7v2 MLLP server with route handlers (Bun)\",\n label: \"mllp-server-bun\",\n value: \"mllp-server-bun\",\n },\n] as const;\n\ntype ExampleId = (typeof EXAMPLES)[number][\"value\"];\n\nconst HELP = `Usage: create-glion [dir] [--example [name]]\n\nOptions:\n -e, --example [name] Example to clone from examples/. Pass a name to use it\n directly, or pass the flag with no value to open the\n interactive picker. Omit entirely to use the default\n (${DEFAULT_EXAMPLE}).\n -h, --help Show this message\n\nExamples:\n${EXAMPLES.map((e) => ` ${e.value.padEnd(18)} ${e.hint}`).join(\"\\n\")}\n`;\n\nfunction isExampleId(value: string): value is ExampleId {\n return EXAMPLES.some((e) => e.value === value);\n}\n\nfunction abort(message = \"Aborted.\"): never {\n p.cancel(message);\n process.exit(0);\n}\n\n// Detect bare `--example` / `-e` (no value) and `--example=` / `-e=` and strip\n// them from argv so that parseArgs (which requires a value for string options)\n// does not error. The bare form opts into the interactive picker.\nfunction extractPickerFlag(args: string[]): {\n args: string[];\n wantsPicker: boolean;\n} {\n const out: string[] = [];\n let wantsPicker = false;\n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n if (arg === undefined) {\n continue;\n }\n if (arg === \"--example\" || arg === \"-e\") {\n const next = args[i + 1];\n if (next === undefined || next.startsWith(\"-\")) {\n wantsPicker = true;\n continue;\n }\n out.push(arg);\n continue;\n }\n if (arg === \"--example=\" || arg === \"-e=\") {\n wantsPicker = true;\n continue;\n }\n out.push(arg);\n }\n return { args: out, wantsPicker };\n}\n\nasync function run(): Promise<void> {\n const { args: cleanArgs, wantsPicker } = extractPickerFlag(\n process.argv.slice(2)\n );\n const { values, positionals } = parseArgs({\n allowPositionals: true,\n args: cleanArgs,\n options: {\n example: { short: \"e\", type: \"string\" },\n help: { short: \"h\", type: \"boolean\" },\n },\n });\n\n if (values.help) {\n process.stdout.write(`${HELP}\\n`);\n return;\n }\n\n p.intro(\"create-glion\");\n\n let dir = positionals[0];\n if (!dir) {\n const answer = await p.text({\n defaultValue: DEFAULT_DIR,\n message: \"Where should we scaffold your project?\",\n placeholder: DEFAULT_DIR,\n });\n if (p.isCancel(answer)) {\n abort();\n }\n dir = answer.trim().length === 0 ? DEFAULT_DIR : answer;\n }\n\n const target = resolve(process.cwd(), dir);\n\n if (existsSync(target)) {\n const proceed = await p.confirm({\n initialValue: false,\n message: `${target} already exists. Continue and overwrite?`,\n });\n if (p.isCancel(proceed) || !proceed) {\n abort();\n }\n }\n\n let example = values.example;\n if (example && !isExampleId(example)) {\n p.cancel(\n `Unknown example: ${example}. Available: ${EXAMPLES.map((e) => e.value).join(\", \")}`\n );\n process.exit(1);\n }\n\n if (!example) {\n if (wantsPicker) {\n const choice = await p.select({\n initialValue: DEFAULT_EXAMPLE,\n message: \"Choose an example\",\n options: EXAMPLES.map((e) => ({\n hint: e.hint,\n label: e.label,\n value: e.value,\n })),\n });\n if (p.isCancel(choice)) {\n abort();\n }\n example = choice;\n } else {\n example = DEFAULT_EXAMPLE;\n }\n }\n\n const spinner = p.spinner();\n spinner.start(`Downloading example: ${example}`);\n await downloadTemplate(`${REPO}/examples/${example}`, {\n dir: target,\n force: true,\n });\n spinner.stop(`Scaffolded ${example} → ${target}`);\n\n p.note(`cd ${dir}\\npnpm install\\npnpm dev`, \"Next steps\");\n p.outro(\"Happy hacking!\");\n}\n\ntry {\n await run();\n} catch (error: unknown) {\n p.cancel(error instanceof Error ? error.message : String(error));\n process.exit(1);\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-glion",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Scaffold a new Glion app from an example.",
5
5
  "keywords": [
6
6
  "create",
@@ -42,12 +42,12 @@
42
42
  "publint": "0.3.18",
43
43
  "tsdown": "0.21.10",
44
44
  "typescript": "6.0.3",
45
- "vitest": "4.1.5",
46
- "@glion/testing": "0.16.0",
47
- "@glion/tsconfig": "0.16.0"
45
+ "vitest": "4.1.11",
46
+ "@glion/testing": "0.18.0",
47
+ "@glion/tsconfig": "0.18.0"
48
48
  },
49
49
  "engines": {
50
- "node": ">=20"
50
+ "node": ">=22"
51
51
  },
52
52
  "scripts": {
53
53
  "build": "tsdown",