create-glion 0.0.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 +18 -12
- package/dist/index.js +46 -13
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -5,31 +5,37 @@ Scaffold a new Glion app from an example in [`rethinkhealth/glion`](https://gith
|
|
|
5
5
|
## Usage
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
#
|
|
8
|
+
# Default: prompts for a directory only, then scaffolds the `starter` template.
|
|
9
9
|
pnpm create glion
|
|
10
10
|
npm create glion
|
|
11
11
|
yarn create glion
|
|
12
12
|
bun create glion
|
|
13
13
|
|
|
14
|
-
#
|
|
14
|
+
# Skip every prompt — directory and starter template are both fixed.
|
|
15
|
+
pnpm create glion my-app
|
|
16
|
+
|
|
17
|
+
# Pick a non-default template up front.
|
|
15
18
|
pnpm create glion my-app --example mllp-server
|
|
19
|
+
|
|
20
|
+
# Open the interactive template picker (pass --example with no value).
|
|
21
|
+
pnpm create glion my-app --example
|
|
16
22
|
```
|
|
17
23
|
|
|
18
24
|
## Options
|
|
19
25
|
|
|
20
|
-
| Flag
|
|
21
|
-
|
|
|
22
|
-
| `[dir]` (positional)
|
|
23
|
-
| `-e, --example <name
|
|
24
|
-
| `-h, --help`
|
|
26
|
+
| Flag | Description |
|
|
27
|
+
| ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
28
|
+
| `[dir]` (positional) | Target directory. Prompts when omitted; defaults to `./my-glion-app`. |
|
|
29
|
+
| `-e, --example [<name>]` | Example to clone from `examples/`. Pass a name to use it directly, or pass the flag with no value to open the interactive picker. Omit to use `starter`. |
|
|
30
|
+
| `-h, --help` | Print usage and exit. |
|
|
25
31
|
|
|
26
32
|
## Examples
|
|
27
33
|
|
|
28
|
-
| Name | Description
|
|
29
|
-
| ----------------- |
|
|
30
|
-
| `
|
|
31
|
-
| `mllp-server
|
|
32
|
-
| `mllp-
|
|
34
|
+
| Name | Description |
|
|
35
|
+
| ----------------- | ---------------------------------------------------------------- |
|
|
36
|
+
| `starter` | Starter Glion — minimal HL7v2 MLLP server. The default scaffold. |
|
|
37
|
+
| `mllp-server` | HL7v2 MLLP server with route handlers (Node.js). |
|
|
38
|
+
| `mllp-server-bun` | HL7v2 MLLP server with route handlers (Bun). |
|
|
33
39
|
|
|
34
40
|
Each example is fetched from `github:rethinkhealth/glion/examples/<name>` via [`giget`](https://github.com/unjs/giget).
|
|
35
41
|
|
package/dist/index.js
CHANGED
|
@@ -6,7 +6,14 @@ import * as p from "@clack/prompts";
|
|
|
6
6
|
import { downloadTemplate } from "giget";
|
|
7
7
|
//#region src/index.ts
|
|
8
8
|
const REPO = "github:rethinkhealth/glion";
|
|
9
|
+
const DEFAULT_DIR = "./my-glion-app";
|
|
10
|
+
const DEFAULT_EXAMPLE = "starter";
|
|
9
11
|
const EXAMPLES = [
|
|
12
|
+
{
|
|
13
|
+
hint: "Starter Glion — minimal HL7v2 MLLP server (default)",
|
|
14
|
+
label: "starter",
|
|
15
|
+
value: "starter"
|
|
16
|
+
},
|
|
10
17
|
{
|
|
11
18
|
hint: "HL7v2 MLLP server with route handlers (Node.js)",
|
|
12
19
|
label: "mllp-server",
|
|
@@ -16,17 +23,15 @@ const EXAMPLES = [
|
|
|
16
23
|
hint: "HL7v2 MLLP server with route handlers (Bun)",
|
|
17
24
|
label: "mllp-server-bun",
|
|
18
25
|
value: "mllp-server-bun"
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
hint: "MLLP client sending sample messages",
|
|
22
|
-
label: "mllp-client",
|
|
23
|
-
value: "mllp-client"
|
|
24
26
|
}
|
|
25
27
|
];
|
|
26
|
-
const HELP = `Usage: create-glion [dir] [--example
|
|
28
|
+
const HELP = `Usage: create-glion [dir] [--example [name]]
|
|
27
29
|
|
|
28
30
|
Options:
|
|
29
|
-
-e, --example
|
|
31
|
+
-e, --example [name] Example to clone from examples/. Pass a name to use it
|
|
32
|
+
directly, or pass the flag with no value to open the
|
|
33
|
+
interactive picker. Omit entirely to use the default
|
|
34
|
+
(${DEFAULT_EXAMPLE}).
|
|
30
35
|
-h, --help Show this message
|
|
31
36
|
|
|
32
37
|
Examples:
|
|
@@ -39,10 +44,37 @@ function abort(message = "Aborted.") {
|
|
|
39
44
|
p.cancel(message);
|
|
40
45
|
process.exit(0);
|
|
41
46
|
}
|
|
47
|
+
function extractPickerFlag(args) {
|
|
48
|
+
const out = [];
|
|
49
|
+
let wantsPicker = false;
|
|
50
|
+
for (let i = 0; i < args.length; i++) {
|
|
51
|
+
const arg = args[i];
|
|
52
|
+
if (arg === void 0) continue;
|
|
53
|
+
if (arg === "--example" || arg === "-e") {
|
|
54
|
+
const next = args[i + 1];
|
|
55
|
+
if (next === void 0 || next.startsWith("-")) {
|
|
56
|
+
wantsPicker = true;
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
out.push(arg);
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
if (arg === "--example=" || arg === "-e=") {
|
|
63
|
+
wantsPicker = true;
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
out.push(arg);
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
args: out,
|
|
70
|
+
wantsPicker
|
|
71
|
+
};
|
|
72
|
+
}
|
|
42
73
|
async function run() {
|
|
74
|
+
const { args: cleanArgs, wantsPicker } = extractPickerFlag(process.argv.slice(2));
|
|
43
75
|
const { values, positionals } = parseArgs({
|
|
44
76
|
allowPositionals: true,
|
|
45
|
-
args:
|
|
77
|
+
args: cleanArgs,
|
|
46
78
|
options: {
|
|
47
79
|
example: {
|
|
48
80
|
short: "e",
|
|
@@ -62,12 +94,12 @@ async function run() {
|
|
|
62
94
|
let dir = positionals[0];
|
|
63
95
|
if (!dir) {
|
|
64
96
|
const answer = await p.text({
|
|
97
|
+
defaultValue: DEFAULT_DIR,
|
|
65
98
|
message: "Where should we scaffold your project?",
|
|
66
|
-
placeholder:
|
|
67
|
-
validate: (value) => value.trim().length === 0 ? "Please enter a directory." : void 0
|
|
99
|
+
placeholder: DEFAULT_DIR
|
|
68
100
|
});
|
|
69
101
|
if (p.isCancel(answer)) abort();
|
|
70
|
-
dir = answer;
|
|
102
|
+
dir = answer.trim().length === 0 ? DEFAULT_DIR : answer;
|
|
71
103
|
}
|
|
72
104
|
const target = resolve(process.cwd(), dir);
|
|
73
105
|
if (existsSync(target)) {
|
|
@@ -82,8 +114,9 @@ async function run() {
|
|
|
82
114
|
p.cancel(`Unknown example: ${example}. Available: ${EXAMPLES.map((e) => e.value).join(", ")}`);
|
|
83
115
|
process.exit(1);
|
|
84
116
|
}
|
|
85
|
-
if (!example) {
|
|
117
|
+
if (!example) if (wantsPicker) {
|
|
86
118
|
const choice = await p.select({
|
|
119
|
+
initialValue: DEFAULT_EXAMPLE,
|
|
87
120
|
message: "Choose an example",
|
|
88
121
|
options: EXAMPLES.map((e) => ({
|
|
89
122
|
hint: e.hint,
|
|
@@ -93,7 +126,7 @@ async function run() {
|
|
|
93
126
|
});
|
|
94
127
|
if (p.isCancel(choice)) abort();
|
|
95
128
|
example = choice;
|
|
96
|
-
}
|
|
129
|
+
} else example = DEFAULT_EXAMPLE;
|
|
97
130
|
const spinner = p.spinner();
|
|
98
131
|
spinner.start(`Downloading example: ${example}`);
|
|
99
132
|
await downloadTemplate(`${REPO}/examples/${example}`, {
|
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\";\n\nconst EXAMPLES = [\n {\n hint: \"HL7v2 MLLP server
|
|
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.
|
|
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.
|
|
46
|
-
"@glion/testing": "0.
|
|
47
|
-
"@glion/tsconfig": "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": ">=
|
|
50
|
+
"node": ">=22"
|
|
51
51
|
},
|
|
52
52
|
"scripts": {
|
|
53
53
|
"build": "tsdown",
|