create-harper 1.8.1 → 1.9.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.
@@ -1,4 +1,5 @@
1
1
  import colors from 'picocolors';
2
+ import { templates } from './templates.js';
2
3
 
3
4
  const {
4
5
  blue,
@@ -22,80 +23,47 @@ const {
22
23
  * @property {Variant[]} variants - The available variants for this framework.
23
24
  */
24
25
 
26
+ /** Display name and color for each framework family. */
27
+ const frameworkMeta = {
28
+ vanilla: { display: 'Vanilla', color: yellow },
29
+ react: { display: 'React', color: cyan },
30
+ vue: { display: 'Vue', color: green },
31
+ };
32
+
25
33
  /**
26
- * The list of supported frameworks and their variants.
34
+ * The list of supported frameworks and their variants, derived from the template catalog so the
35
+ * interactive picker stays in sync with the single source of truth.
27
36
  * @type {Framework[]}
28
37
  */
29
- export const frameworks = [
30
- {
31
- name: 'vanilla',
32
- display: 'Vanilla',
33
- color: yellow,
34
- variants: [
35
- {
36
- name: 'vanilla-ts',
37
- display: 'TypeScript',
38
- color: blue,
39
- },
40
- {
41
- name: 'vanilla',
42
- display: 'JavaScript',
43
- color: yellow,
44
- },
45
- ],
46
- },
47
- {
48
- name: 'react',
49
- display: 'React',
50
- color: cyan,
51
- variants: [
52
- {
53
- name: 'react-ts',
54
- display: 'TypeScript',
55
- color: blue,
56
- },
57
- {
58
- name: 'react',
59
- display: 'JavaScript',
60
- color: yellow,
61
- },
62
- {
63
- name: 'react-ts-ssr',
64
- display: 'TypeScript + SSR',
65
- color: blue,
66
- },
67
- {
68
- name: 'react-ssr',
69
- display: 'JavaScript + SSR',
70
- color: yellow,
71
- },
72
- ],
73
- },
74
- {
75
- name: 'vue',
76
- display: 'Vue',
77
- color: green,
78
- variants: [
79
- {
80
- name: 'vue-ts',
81
- display: 'TypeScript',
82
- color: blue,
83
- },
84
- {
85
- name: 'vue',
86
- display: 'JavaScript',
87
- color: yellow,
88
- },
89
- {
90
- name: 'vue-ts-ssr',
91
- display: 'TypeScript + SSR',
92
- color: blue,
93
- },
94
- {
95
- name: 'vue-ssr',
96
- display: 'JavaScript + SSR',
97
- color: yellow,
98
- },
99
- ],
100
- },
101
- ];
38
+ export const frameworks = (() => {
39
+ /** @type {Framework[]} */
40
+ const grouped = [];
41
+ const byName = new Map();
42
+
43
+ for (const t of templates) {
44
+ let framework = byName.get(t.framework);
45
+ if (!framework) {
46
+ const meta = frameworkMeta[t.framework];
47
+ if (!meta) {
48
+ throw new Error(
49
+ `Missing framework metadata for "${t.framework}". Please add it to frameworkMeta in frameworks.js.`,
50
+ );
51
+ }
52
+ framework = {
53
+ name: t.framework,
54
+ display: meta.display,
55
+ color: meta.color,
56
+ variants: [],
57
+ };
58
+ byName.set(t.framework, framework);
59
+ grouped.push(framework);
60
+ }
61
+ framework.variants.push({
62
+ name: t.name,
63
+ display: `${t.typescript ? 'TypeScript' : 'JavaScript'}${t.ssr ? ' + SSR' : ''}`,
64
+ color: t.typescript ? blue : yellow,
65
+ });
66
+ }
67
+
68
+ return grouped;
69
+ })();
@@ -1,10 +1,19 @@
1
- import colors from 'picocolors';
1
+ import { frameworks } from './frameworks.js';
2
2
 
3
- const {
4
- cyan,
5
- green,
6
- yellow,
7
- } = colors;
3
+ /** Width of each template-name column in the "Available templates" list. */
4
+ const COLUMN_WIDTH = 20;
5
+
6
+ /**
7
+ * One color-coded line per framework, listing its variants in aligned columns. Derived from the
8
+ * template catalog (via {@link frameworks}) so new templates appear in `--help` automatically.
9
+ */
10
+ const availableTemplates = frameworks
11
+ .map((framework) =>
12
+ framework.color(
13
+ framework.variants.map((variant) => variant.name.padEnd(COLUMN_WIDTH)).join('').trimEnd(),
14
+ )
15
+ )
16
+ .join('\n');
8
17
 
9
18
  /**
10
19
  * The help message displayed when using the --help flag or on invalid input.
@@ -30,6 +39,4 @@ If you are going to deploy your application to https://fabric.harper.fast/, you
30
39
  For authentication, use "harper login" in your project directory.
31
40
 
32
41
  Available templates:
33
- ${yellow('vanilla-ts vanilla')}
34
- ${cyan('react-ts react react-ts-ssr react-ssr')}
35
- ${green('vue-ts vue vue-ts-ssr vue-ssr')}`;
42
+ ${availableTemplates}`;
@@ -0,0 +1,54 @@
1
+ export type Framework = 'vanilla' | 'react' | 'vue';
2
+
3
+ export type TemplateName =
4
+ | 'vanilla-ts'
5
+ | 'vanilla'
6
+ | 'react-ts'
7
+ | 'react'
8
+ | 'react-ts-ssr'
9
+ | 'react-ssr'
10
+ | 'vue-ts'
11
+ | 'vue'
12
+ | 'vue-ts-ssr'
13
+ | 'vue-ssr';
14
+
15
+ export interface TemplateInfo {
16
+ /** The canonical template name (e.g. 'vanilla', 'react-ts'). Used to scaffold. */
17
+ name: TemplateName;
18
+ /** The framework family this template belongs to. */
19
+ framework: Framework;
20
+ /** A human-friendly display title. */
21
+ title: string;
22
+ /** A short description of the template. */
23
+ description: string;
24
+ /** Tags describing the template's stack. */
25
+ tags: string[];
26
+ /** Whether the template uses TypeScript. */
27
+ typescript: boolean;
28
+ /** Whether the template is server-side rendered. */
29
+ ssr: boolean;
30
+ /** The published Studio template package for this template. */
31
+ npmPackage: string;
32
+ /** A link to the template's source on GitHub. */
33
+ githubUrl: string;
34
+ }
35
+
36
+ /** The catalog of every template create-harper can scaffold, in display order. */
37
+ export declare const templates: readonly TemplateInfo[];
38
+
39
+ /**
40
+ * The flat list of every template name, in catalog order, typed as a non-empty tuple of string
41
+ * literals so it can be passed straight to `z.enum(...)` and yield a literal union.
42
+ */
43
+ export declare const templateNames: readonly [
44
+ 'vanilla-ts',
45
+ 'vanilla',
46
+ 'react-ts',
47
+ 'react',
48
+ 'react-ts-ssr',
49
+ 'react-ssr',
50
+ 'vue-ts',
51
+ 'vue',
52
+ 'vue-ts-ssr',
53
+ 'vue-ssr',
54
+ ];
@@ -1,10 +1,142 @@
1
- import { frameworks } from './frameworks.js';
1
+ const CREATE_HARPER_TREE = 'https://github.com/HarperFast/create-harper/tree/main';
2
2
 
3
3
  /**
4
- * A list of all available template names derived from the frameworks and their variants.
4
+ * @typedef {'vanilla' | 'react' | 'vue'} Framework
5
+ */
6
+
7
+ /**
8
+ * @typedef {Object} TemplateInfo
9
+ * @property {string} name - The canonical template name (e.g. 'vanilla', 'react-ts'). Used to scaffold.
10
+ * @property {Framework} framework - The framework family this template belongs to.
11
+ * @property {string} title - A human-friendly display title.
12
+ * @property {string} description - A short description of the template.
13
+ * @property {string[]} tags - Tags describing the template's stack.
14
+ * @property {boolean} typescript - Whether the template uses TypeScript.
15
+ * @property {boolean} ssr - Whether the template is server-side rendered.
16
+ * @property {string} npmPackage - The published Studio template package for this template.
17
+ * @property {string} githubUrl - A link to the template's source on GitHub.
18
+ */
19
+
20
+ /**
21
+ * Build a {@link TemplateInfo} entry, deriving the npm package and GitHub URL from the template name.
22
+ *
23
+ * @param {Omit<TemplateInfo, 'npmPackage' | 'githubUrl'>} info
24
+ * @returns {TemplateInfo}
25
+ */
26
+ function template(info) {
27
+ return {
28
+ ...info,
29
+ npmPackage: `@harperfast/template-${info.name}-studio`,
30
+ githubUrl: `${CREATE_HARPER_TREE}/template-${info.name}`,
31
+ };
32
+ }
33
+
34
+ /**
35
+ * The catalog of every template create-harper can scaffold. This is the single source of truth from
36
+ * which {@link templateNames} (the flat name list) and
37
+ * {@link import('./frameworks.js').frameworks} (the interactive picker) are derived.
38
+ *
39
+ * Order is significant: it determines the order of the flat name list and the CLI picker.
40
+ *
41
+ * @type {TemplateInfo[]}
42
+ */
43
+ export const templates = [
44
+ template({
45
+ name: 'vanilla-ts',
46
+ framework: 'vanilla',
47
+ title: 'Vanilla + TypeScript',
48
+ description: 'The same Web + REST ORM from the first template, but with TypeScript sprinkled in.',
49
+ tags: ['Vanilla', 'TypeScript', 'GraphQL'],
50
+ typescript: true,
51
+ ssr: false,
52
+ }),
53
+ template({
54
+ name: 'vanilla',
55
+ framework: 'vanilla',
56
+ title: 'Vanilla JS',
57
+ description: "Define your entities in schema.graphql, add your HTML/CSS/JS in web, and you're cooking!",
58
+ tags: ['Vanilla', 'REST', 'GraphQL', 'ORM'],
59
+ typescript: false,
60
+ ssr: false,
61
+ }),
62
+ template({
63
+ name: 'react-ts',
64
+ framework: 'react',
65
+ title: 'React + TypeScript',
66
+ description: 'The same Vite-powered React app, with end-to-end type safety from TypeScript.',
67
+ tags: ['React', 'TypeScript', 'Vite', 'SPA'],
68
+ typescript: true,
69
+ ssr: false,
70
+ }),
71
+ template({
72
+ name: 'react',
73
+ framework: 'react',
74
+ title: 'React',
75
+ description: "A Vite-powered React single-page app, wired up to Harper's REST + GraphQL APIs out of the box.",
76
+ tags: ['React', 'Vite', 'SPA', 'GraphQL'],
77
+ typescript: false,
78
+ ssr: false,
79
+ }),
80
+ template({
81
+ name: 'react-ts-ssr',
82
+ framework: 'react',
83
+ title: 'React + TypeScript + SSR',
84
+ description: 'Server-rendered React with Vite and TypeScript for type-safe, SEO-friendly pages on Harper.',
85
+ tags: ['React', 'TypeScript', 'SSR', 'Vite'],
86
+ typescript: true,
87
+ ssr: true,
88
+ }),
89
+ template({
90
+ name: 'react-ssr',
91
+ framework: 'react',
92
+ title: 'React + SSR',
93
+ description: 'Server-rendered React with Vite for fast first paints, hydrating into a full SPA on Harper.',
94
+ tags: ['React', 'SSR', 'Vite', 'GraphQL'],
95
+ typescript: false,
96
+ ssr: true,
97
+ }),
98
+ template({
99
+ name: 'vue-ts',
100
+ framework: 'vue',
101
+ title: 'Vue + TypeScript',
102
+ description: 'The same Vite-powered Vue app, with end-to-end type safety from TypeScript.',
103
+ tags: ['Vue', 'TypeScript', 'Vite', 'SPA'],
104
+ typescript: true,
105
+ ssr: false,
106
+ }),
107
+ template({
108
+ name: 'vue',
109
+ framework: 'vue',
110
+ title: 'Vue',
111
+ description: "A Vite-powered Vue single-page app, wired up to Harper's REST + GraphQL APIs out of the box.",
112
+ tags: ['Vue', 'Vite', 'SPA', 'GraphQL'],
113
+ typescript: false,
114
+ ssr: false,
115
+ }),
116
+ template({
117
+ name: 'vue-ts-ssr',
118
+ framework: 'vue',
119
+ title: 'Vue + TypeScript + SSR',
120
+ description: 'Server-rendered Vue with Vite and TypeScript for type-safe, SEO-friendly pages on Harper.',
121
+ tags: ['Vue', 'TypeScript', 'SSR', 'Vite'],
122
+ typescript: true,
123
+ ssr: true,
124
+ }),
125
+ template({
126
+ name: 'vue-ssr',
127
+ framework: 'vue',
128
+ title: 'Vue + SSR',
129
+ description: 'Server-rendered Vue with Vite for fast first paints, hydrating into a full SPA on Harper.',
130
+ tags: ['Vue', 'SSR', 'Vite', 'GraphQL'],
131
+ typescript: false,
132
+ ssr: true,
133
+ }),
134
+ ];
135
+
136
+ /**
137
+ * The flat list of every template name, in catalog order. This is the canonical, dependency-free list
138
+ * other tools can import to validate or enumerate templates.
139
+ *
5
140
  * @type {string[]}
6
141
  */
7
- export const templates = frameworks.map((f) => f.variants.map((v) => v.name)).reduce(
8
- (a, b) => a.concat(b),
9
- [],
10
- );
142
+ export const templateNames = templates.map((t) => t.name);
@@ -1,6 +1,6 @@
1
1
  import * as prompts from '@clack/prompts';
2
2
  import { frameworks } from '../constants/frameworks.js';
3
- import { templates } from '../constants/templates.js';
3
+ import { templateNames } from '../constants/templates.js';
4
4
 
5
5
  /**
6
6
  * Step 4: Choose a project template (framework and variant).
@@ -13,7 +13,7 @@ export async function getTemplate(argTemplate, interactive) {
13
13
  let template = argTemplate;
14
14
  let hasInvalidArgTemplate = false;
15
15
 
16
- if (argTemplate && !templates.includes(argTemplate)) {
16
+ if (argTemplate && !templateNames.includes(argTemplate)) {
17
17
  template = undefined;
18
18
  hasInvalidArgTemplate = true;
19
19
  }
package/package.json CHANGED
@@ -1,8 +1,15 @@
1
1
  {
2
2
  "name": "create-harper",
3
3
  "description": "Scaffold a new Harper project in JavaScript or TypeScript.",
4
- "version": "1.8.1",
4
+ "version": "1.9.0",
5
5
  "type": "module",
6
+ "sideEffects": false,
7
+ "exports": {
8
+ "./templates": {
9
+ "types": "./lib/constants/templates.d.ts",
10
+ "import": "./lib/constants/templates.js"
11
+ }
12
+ },
6
13
  "author": {
7
14
  "name": "HarperDB",
8
15
  "email": "support@harperdb.io"