create-harper 0.0.1 → 0.0.3

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.
Files changed (137) hide show
  1. package/README.md +5 -0
  2. package/index.js +37 -214
  3. package/lib/constants/defaultTargetDir.js +1 -0
  4. package/lib/constants/frameworks.js +75 -0
  5. package/lib/constants/helpMessage.js +23 -0
  6. package/lib/constants/renameFiles.js +7 -0
  7. package/lib/constants/templates.js +6 -0
  8. package/lib/fs/applyAndWriteTemplateFile.js +9 -0
  9. package/lib/fs/copy.js +11 -0
  10. package/lib/fs/copyDir.js +12 -0
  11. package/lib/fs/crawlTemplateDir.js +18 -0
  12. package/lib/fs/emptyDir.js +14 -0
  13. package/lib/fs/formatTargetDir.js +3 -0
  14. package/lib/fs/isEmpty.js +6 -0
  15. package/lib/install.js +17 -0
  16. package/lib/pkg/getInstallCommand.js +6 -0
  17. package/lib/pkg/getRunCommand.js +12 -0
  18. package/lib/pkg/isValidPackageName.js +5 -0
  19. package/lib/pkg/pkgFromUserAgent.js +9 -0
  20. package/lib/pkg/toValidPackageName.js +9 -0
  21. package/lib/run.js +14 -0
  22. package/lib/start.js +15 -0
  23. package/lib/steps/getEnvVars.js +79 -0
  24. package/lib/steps/getImmediate.js +29 -0
  25. package/lib/steps/getPackageName.js +38 -0
  26. package/lib/steps/getProjectName.js +40 -0
  27. package/lib/steps/getTemplate.js +65 -0
  28. package/lib/steps/handleExistingDir.js +61 -0
  29. package/lib/steps/scaffoldProject.js +40 -0
  30. package/lib/steps/showOutro.js +30 -0
  31. package/package.json +20 -8
  32. package/template-barebones/README.md +7 -0
  33. package/template-barebones/_aiignore +1 -0
  34. package/template-barebones/_env +3 -0
  35. package/template-barebones/_env.example +3 -0
  36. package/template-barebones/_gitignore +147 -0
  37. package/template-barebones/config.yaml +7 -0
  38. package/template-barebones/graphql.config.yml +3 -0
  39. package/template-barebones/package.json +14 -0
  40. package/template-barebones/schema.graphql +1 -0
  41. package/template-react/README.md +45 -0
  42. package/template-react/_aiignore +1 -0
  43. package/template-react/_env +3 -0
  44. package/template-react/_env.example +3 -0
  45. package/template-react/_github/workflow/deploy.yaml +40 -0
  46. package/template-react/_gitignore +147 -0
  47. package/template-react/config.yaml +23 -0
  48. package/template-react/deploy-template/config.yaml +2 -0
  49. package/template-react/deploy-template/fastify/static.js +14 -0
  50. package/template-react/deploy-template/package.json +5 -0
  51. package/template-react/graphql.config.yml +3 -0
  52. package/template-react/index.html +13 -0
  53. package/template-react/package.json +25 -0
  54. package/template-react/public/react.svg +14 -0
  55. package/template-react/public/typescript.svg +16 -0
  56. package/template-react/public/vite.svg +42 -0
  57. package/template-react/resources.js +27 -0
  58. package/template-react/schema.graphql +5 -0
  59. package/template-react/src/App.jsx +34 -0
  60. package/template-react/src/main.jsx +13 -0
  61. package/template-react/src/style.css +96 -0
  62. package/template-react/src/vite-env.d.ts +9 -0
  63. package/template-react/vite.config.js +22 -0
  64. package/template-react-ts/README.md +45 -0
  65. package/template-react-ts/_aiignore +1 -0
  66. package/template-react-ts/_env +3 -0
  67. package/template-react-ts/_env.example +3 -0
  68. package/template-react-ts/_github/workflow/deploy.yaml +40 -0
  69. package/template-react-ts/_gitignore +147 -0
  70. package/template-react-ts/config.yaml +23 -0
  71. package/template-react-ts/deploy-template/config.yaml +2 -0
  72. package/template-react-ts/deploy-template/fastify/static.js +14 -0
  73. package/template-react-ts/deploy-template/package.json +5 -0
  74. package/template-react-ts/graphql.config.yml +3 -0
  75. package/template-react-ts/index.html +13 -0
  76. package/template-react-ts/package.json +29 -0
  77. package/template-react-ts/public/react.svg +14 -0
  78. package/template-react-ts/public/typescript.svg +16 -0
  79. package/template-react-ts/public/vite.svg +42 -0
  80. package/template-react-ts/resources.ts +52 -0
  81. package/template-react-ts/schema.graphql +5 -0
  82. package/template-react-ts/src/App.tsx +34 -0
  83. package/template-react-ts/src/main.tsx +13 -0
  84. package/template-react-ts/src/style.css +96 -0
  85. package/template-react-ts/src/vite-env.d.ts +9 -0
  86. package/template-react-ts/tsconfig.json +34 -0
  87. package/template-react-ts/vite.config.ts +22 -0
  88. package/template-studio/README.md +34 -0
  89. package/template-studio/_aiignore +1 -0
  90. package/template-studio/_gitignore +147 -0
  91. package/template-studio/config.yaml +24 -0
  92. package/template-studio/graphql.config.yml +3 -0
  93. package/template-studio/package.json +14 -0
  94. package/template-studio/resources.js +27 -0
  95. package/template-studio/schema.graphql +7 -0
  96. package/template-studio/web/index.html +28 -0
  97. package/template-studio/web/index.js +18 -0
  98. package/template-studio/web/styles.css +57 -0
  99. package/template-studio-ts/README.md +34 -0
  100. package/template-studio-ts/_aiignore +1 -0
  101. package/template-studio-ts/_gitignore +147 -0
  102. package/template-studio-ts/config.yaml +24 -0
  103. package/template-studio-ts/graphql.config.yml +3 -0
  104. package/template-studio-ts/package.json +14 -0
  105. package/template-studio-ts/resources.ts +52 -0
  106. package/template-studio-ts/schema.graphql +7 -0
  107. package/template-studio-ts/tsconfig.json +10 -0
  108. package/template-studio-ts/web/index.html +28 -0
  109. package/template-studio-ts/web/index.js +18 -0
  110. package/template-studio-ts/web/styles.css +57 -0
  111. package/template-vanilla/README.md +57 -0
  112. package/template-vanilla/_aiignore +1 -0
  113. package/template-vanilla/_env +3 -0
  114. package/template-vanilla/_env.example +3 -0
  115. package/template-vanilla/_gitignore +147 -0
  116. package/template-vanilla/config.yaml +24 -0
  117. package/template-vanilla/graphql.config.yml +3 -0
  118. package/template-vanilla/package.json +14 -0
  119. package/template-vanilla/resources.js +27 -0
  120. package/template-vanilla/schema.graphql +7 -0
  121. package/template-vanilla/web/index.html +28 -0
  122. package/template-vanilla/web/index.js +18 -0
  123. package/template-vanilla/web/styles.css +57 -0
  124. package/template-vanilla-ts/README.md +57 -0
  125. package/template-vanilla-ts/_aiignore +1 -0
  126. package/template-vanilla-ts/_env +3 -0
  127. package/template-vanilla-ts/_env.example +3 -0
  128. package/template-vanilla-ts/_gitignore +147 -0
  129. package/template-vanilla-ts/config.yaml +24 -0
  130. package/template-vanilla-ts/graphql.config.yml +3 -0
  131. package/template-vanilla-ts/package.json +14 -0
  132. package/template-vanilla-ts/resources.ts +52 -0
  133. package/template-vanilla-ts/schema.graphql +7 -0
  134. package/template-vanilla-ts/tsconfig.json +10 -0
  135. package/template-vanilla-ts/web/index.html +28 -0
  136. package/template-vanilla-ts/web/index.js +18 -0
  137. package/template-vanilla-ts/web/styles.css +57 -0
@@ -0,0 +1,29 @@
1
+ import * as prompts from '@clack/prompts';
2
+
3
+ /**
4
+ * Step 5: Ask about immediate install and package manager
5
+ * @param {boolean | undefined} argImmediate
6
+ * @param {boolean} interactive
7
+ * @param {string} pkgManager
8
+ * @returns {Promise<{immediate: boolean, cancelled: boolean}>}
9
+ */
10
+ export async function getImmediate(argImmediate, interactive, pkgManager) {
11
+ let immediate = argImmediate;
12
+
13
+ if (immediate === undefined) {
14
+ if (interactive) {
15
+ const immediateResult = await prompts.confirm({
16
+ message: `Install with ${pkgManager} and start now?`,
17
+ });
18
+
19
+ if (prompts.isCancel(immediateResult)) {
20
+ return { immediate: false, cancelled: true };
21
+ }
22
+ immediate = immediateResult;
23
+ } else {
24
+ immediate = false;
25
+ }
26
+ }
27
+
28
+ return { immediate, cancelled: false };
29
+ }
@@ -0,0 +1,38 @@
1
+ import * as prompts from '@clack/prompts';
2
+ import path from 'node:path';
3
+ import { isValidPackageName } from '../pkg/isValidPackageName.js';
4
+ import { toValidPackageName } from '../pkg/toValidPackageName.js';
5
+
6
+ /**
7
+ * Step 3: Get package name
8
+ * @param {string} targetDir
9
+ * @param {boolean} interactive
10
+ * @returns {Promise<{packageName: string, cancelled: boolean}>}
11
+ */
12
+ export async function getPackageName(targetDir, interactive) {
13
+ let packageName = path.basename(path.resolve(targetDir));
14
+
15
+ if (!isValidPackageName(packageName)) {
16
+ if (interactive) {
17
+ const packageNameResult = await prompts.text({
18
+ message: 'Package name:',
19
+ defaultValue: toValidPackageName(packageName),
20
+ placeholder: toValidPackageName(packageName),
21
+ validate(dir) {
22
+ if (dir && !isValidPackageName(dir)) {
23
+ return 'Invalid package.json name';
24
+ }
25
+ },
26
+ });
27
+
28
+ if (prompts.isCancel(packageNameResult)) {
29
+ return { packageName: '', cancelled: true };
30
+ }
31
+ packageName = packageNameResult;
32
+ } else {
33
+ packageName = toValidPackageName(packageName);
34
+ }
35
+ }
36
+
37
+ return { packageName, cancelled: false };
38
+ }
@@ -0,0 +1,40 @@
1
+ import * as prompts from '@clack/prompts';
2
+ import { defaultTargetDir } from '../constants/defaultTargetDir.js';
3
+ import { formatTargetDir } from '../fs/formatTargetDir.js';
4
+
5
+ /**
6
+ * Step 1: Get project name and target directory
7
+ * @param {string | undefined} argTargetDir
8
+ * @param {boolean} interactive
9
+ * @returns {Promise<{projectName: string, targetDir: string, cancelled: boolean}>}
10
+ */
11
+ export async function getProjectName(argTargetDir, interactive) {
12
+ let targetDir = argTargetDir;
13
+ let projectName = targetDir;
14
+
15
+ if (!targetDir) {
16
+ if (interactive) {
17
+ projectName = await prompts.text({
18
+ message: 'Project name:',
19
+ defaultValue: defaultTargetDir,
20
+ placeholder: defaultTargetDir,
21
+ validate: (value) => {
22
+ return !value || formatTargetDir(value).length > 0
23
+ ? undefined
24
+ : 'Invalid project name';
25
+ },
26
+ });
27
+
28
+ if (prompts.isCancel(projectName)) {
29
+ return { projectName: '', targetDir: '', cancelled: true };
30
+ }
31
+
32
+ targetDir = formatTargetDir(projectName);
33
+ } else {
34
+ targetDir = defaultTargetDir;
35
+ projectName = targetDir;
36
+ }
37
+ }
38
+
39
+ return { projectName, targetDir, cancelled: false };
40
+ }
@@ -0,0 +1,65 @@
1
+ import * as prompts from '@clack/prompts';
2
+ import { FRAMEWORKS } from '../constants/frameworks.js';
3
+ import { TEMPLATES } from '../constants/templates.js';
4
+
5
+ /**
6
+ * Step 4: Choose a framework and variant
7
+ * @param {string | undefined} argTemplate
8
+ * @param {boolean} interactive
9
+ * @returns {Promise<{template: string, cancelled: boolean}>}
10
+ */
11
+ export async function getTemplate(argTemplate, interactive) {
12
+ let template = argTemplate;
13
+ let hasInvalidArgTemplate = false;
14
+
15
+ if (argTemplate && !TEMPLATES.includes(argTemplate)) {
16
+ template = undefined;
17
+ hasInvalidArgTemplate = true;
18
+ }
19
+
20
+ if (!template) {
21
+ if (interactive) {
22
+ const framework = await prompts.select({
23
+ message: hasInvalidArgTemplate
24
+ ? `"${argTemplate}" isn't a valid template. Please choose from below: `
25
+ : 'Select a framework:',
26
+ options: FRAMEWORKS
27
+ .filter(framework => !framework.hidden)
28
+ .map((framework) => {
29
+ const frameworkColor = framework.color;
30
+ return {
31
+ label: frameworkColor(framework.display),
32
+ value: framework,
33
+ };
34
+ }),
35
+ });
36
+
37
+ if (prompts.isCancel(framework)) {
38
+ return { template: '', cancelled: true };
39
+ }
40
+
41
+ const variant = framework.variants.length === 1
42
+ ? framework.variants[0].name
43
+ : await prompts.select({
44
+ message: 'Select a variant:',
45
+ options: framework.variants.map((variant) => {
46
+ const variantColor = variant.color;
47
+ return {
48
+ label: variantColor(variant.display || variant.name),
49
+ value: variant.name,
50
+ };
51
+ }),
52
+ });
53
+
54
+ if (prompts.isCancel(variant)) {
55
+ return { template: '', cancelled: true };
56
+ }
57
+
58
+ template = variant;
59
+ } else {
60
+ template = 'vanilla-ts';
61
+ }
62
+ }
63
+
64
+ return { template, cancelled: false };
65
+ }
@@ -0,0 +1,61 @@
1
+ import * as prompts from '@clack/prompts';
2
+ import fs from 'node:fs';
3
+ import { emptyDir } from '../fs/emptyDir.js';
4
+ import { isEmpty } from '../fs/isEmpty.js';
5
+
6
+ /**
7
+ * Step 2: Handle directory if exist and not empty
8
+ * @param {string} targetDir
9
+ * @param {boolean | undefined} argOverwrite
10
+ * @param {boolean} interactive
11
+ * @returns {Promise<{cancelled: boolean}>}
12
+ */
13
+ export async function handleExistingDir(targetDir, argOverwrite, interactive) {
14
+ if (fs.existsSync(targetDir) && !isEmpty(targetDir)) {
15
+ let overwrite = argOverwrite
16
+ ? 'yes'
17
+ : undefined;
18
+
19
+ if (!overwrite) {
20
+ if (interactive) {
21
+ const res = await prompts.select({
22
+ message: (targetDir === '.'
23
+ ? 'Current directory'
24
+ : `Target directory "${targetDir}"`)
25
+ + ` is not empty. Please choose how to proceed:`,
26
+ options: [
27
+ {
28
+ label: 'Cancel operation',
29
+ value: 'no',
30
+ },
31
+ {
32
+ label: 'Remove existing files and continue',
33
+ value: 'yes',
34
+ },
35
+ {
36
+ label: 'Ignore files and continue',
37
+ value: 'ignore',
38
+ },
39
+ ],
40
+ });
41
+
42
+ if (prompts.isCancel(res)) {
43
+ return { cancelled: true };
44
+ }
45
+ overwrite = res;
46
+ } else {
47
+ overwrite = 'no';
48
+ }
49
+ }
50
+
51
+ switch (overwrite) {
52
+ case 'yes':
53
+ emptyDir(targetDir);
54
+ break;
55
+ case 'no':
56
+ return { cancelled: true };
57
+ }
58
+ }
59
+
60
+ return { cancelled: false };
61
+ }
@@ -0,0 +1,40 @@
1
+ import * as prompts from '@clack/prompts';
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+ import { crawlTemplateDir } from '../fs/crawlTemplateDir.js';
6
+
7
+ /**
8
+ * Step 6: Write out the contents based on all prior steps.
9
+ * @param {string} targetDir
10
+ * @param {string} projectName
11
+ * @param {string} packageName
12
+ * @param {string} template
13
+ * @param {{username: string, target: string, password?: string}} envVars
14
+ * @returns {string} The root directory of the project
15
+ */
16
+ export function scaffoldProject(targetDir, projectName, packageName, template, envVars) {
17
+ const cwd = process.cwd();
18
+ const root = path.join(cwd, targetDir);
19
+ fs.mkdirSync(root, { recursive: true });
20
+ prompts.log.step(`Scaffolding project in ${root}...`);
21
+
22
+ const substitutions = {
23
+ 'your-project-name-here': projectName,
24
+ 'your-package-name-here': packageName,
25
+ 'your-cluster-username-here': envVars.username,
26
+ 'your-cluster-password-here': envVars.password,
27
+ 'your-fabric.harper.fast-cluster-url-here': envVars.target,
28
+ };
29
+
30
+ const templateDir = path.resolve(
31
+ fileURLToPath(import.meta.url),
32
+ '..',
33
+ '..',
34
+ '..',
35
+ `template-${template}`,
36
+ );
37
+ crawlTemplateDir(root, templateDir, substitutions);
38
+
39
+ return root;
40
+ }
@@ -0,0 +1,30 @@
1
+ import * as prompts from '@clack/prompts';
2
+ import path from 'node:path';
3
+ import { install } from '../install.js';
4
+ import { getInstallCommand } from '../pkg/getInstallCommand.js';
5
+ import { getRunCommand } from '../pkg/getRunCommand.js';
6
+ import { start } from '../start.js';
7
+
8
+ /**
9
+ * Step 7: Log out the next steps.
10
+ * @param {string} root
11
+ * @param {string} pkgManager
12
+ * @param {boolean} immediate
13
+ */
14
+ export function showOutro(root, pkgManager, immediate) {
15
+ if (immediate) {
16
+ install(root, pkgManager);
17
+ start(root, pkgManager);
18
+ } else {
19
+ let doneMessage = '';
20
+ const cwd = process.cwd();
21
+ const cdProjectName = path.relative(cwd, root);
22
+ doneMessage += `Done. Now run:\n`;
23
+ if (root !== cwd) {
24
+ doneMessage += `\n cd ${cdProjectName.includes(' ') ? `"${cdProjectName}"` : cdProjectName}`;
25
+ }
26
+ doneMessage += `\n ${getInstallCommand(pkgManager).join(' ')}`;
27
+ doneMessage += `\n ${getRunCommand(pkgManager, 'dev').join(' ')}`;
28
+ prompts.outro(doneMessage);
29
+ }
30
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-harper",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "type": "module",
5
5
  "author": {
6
6
  "name": "HarperDB",
@@ -12,15 +12,26 @@
12
12
  },
13
13
  "files": [
14
14
  "index.js",
15
- "template-*"
15
+ "lib/",
16
+ "!lib/**/*.test.js",
17
+ "template-barebones/",
18
+ "template-react/",
19
+ "template-react-ts/",
20
+ "template-studio/",
21
+ "template-studio-ts/",
22
+ "template-vanilla/",
23
+ "template-vanilla-ts/"
16
24
  ],
17
25
  "scripts": {
18
- "lint": "oxlint .",
19
- "lint:fix": "oxlint . --fix",
20
- "format": "dprint check",
26
+ "commitlint": "commitlint --edit",
27
+ "format:check": "dprint check",
21
28
  "format:fix": "dprint fmt",
22
29
  "format:staged": "dprint check --staged",
23
- "test": "vitest"
30
+ "lint:check": "oxlint .",
31
+ "lint:fix": "oxlint . --fix",
32
+ "test": "vitest run",
33
+ "test:coverage": "vitest run --coverage",
34
+ "test:watch": "vitest"
24
35
  },
25
36
  "engines": {
26
37
  "node": "^20.19.0 || >=22.12.0"
@@ -37,13 +48,14 @@
37
48
  "@clack/prompts": "^1.0.0-alpha.9",
38
49
  "@vercel/detect-agent": "^1.0.0",
39
50
  "cross-spawn": "^7.0.6",
40
- "lodash": "^4.17.21",
41
51
  "mri": "^1.2.0",
42
52
  "picocolors": "^1.1.1"
43
53
  },
44
54
  "devDependencies": {
55
+ "@commitlint/cli": "^20.0.0",
56
+ "@commitlint/config-conventional": "^20.0.0",
57
+ "@vitest/coverage-v8": "^4.0.17",
45
58
  "dprint": "^0.51.1",
46
- "harperdb": "^4.7.15",
47
59
  "oxlint": "^1.38.0",
48
60
  "vitest": "^4.0.17"
49
61
  }
@@ -0,0 +1,7 @@
1
+ # your-project-name-here
2
+
3
+ This repository is intended for use alongside the Harper Learn ["Getting Started > Create Your First Application"](https://docs.harperdb.io/learn/getting-started/create-your-first-application) guide.
4
+
5
+ The `main` branch is the starting point for the guide.
6
+
7
+ The `completed` branch is the completed code example if you need to check your work.
@@ -0,0 +1 @@
1
+ .env
@@ -0,0 +1,3 @@
1
+ CLI_TARGET_USERNAME='your-cluster-username-here'
2
+ CLI_TARGET_PASSWORD='your-cluster-password-here'
3
+ CLI_TARGET='your-fabric.harper.fast-cluster-url-here'
@@ -0,0 +1,3 @@
1
+ CLI_TARGET_USERNAME='YOUR_CLUSTER_USERNAME'
2
+ CLI_TARGET_PASSWORD='YOUR_CLUSTER_PASSWORD'
3
+ CLI_TARGET='YOUR_FABRIC.HARPER.FAST_CLUSTER_URL_HERE'
@@ -0,0 +1,147 @@
1
+ .DS_Store
2
+
3
+ #
4
+ # https://raw.githubusercontent.com/github/gitignore/refs/heads/main/Node.gitignore
5
+ #
6
+
7
+ # Logs
8
+ logs
9
+ *.log
10
+ npm-debug.log*
11
+ yarn-debug.log*
12
+ yarn-error.log*
13
+ lerna-debug.log*
14
+
15
+ # Diagnostic reports (https://nodejs.org/api/report.html)
16
+ report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
17
+
18
+ # Runtime data
19
+ pids
20
+ *.pid
21
+ *.seed
22
+ *.pid.lock
23
+
24
+ # Directory for instrumented libs generated by jscoverage/JSCover
25
+ lib-cov
26
+
27
+ # Coverage directory used by tools like istanbul
28
+ coverage
29
+ *.lcov
30
+
31
+ # nyc test coverage
32
+ .nyc_output
33
+
34
+ # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
35
+ .grunt
36
+
37
+ # Bower dependency directory (https://bower.io/)
38
+ bower_components
39
+
40
+ # node-waf configuration
41
+ .lock-wscript
42
+
43
+ # Compiled binary addons (https://nodejs.org/api/addons.html)
44
+ build/Release
45
+
46
+ # Dependency directories
47
+ node_modules/
48
+ jspm_packages/
49
+
50
+ # Snowpack dependency directory (https://snowpack.dev/)
51
+ web_modules/
52
+
53
+ # TypeScript cache
54
+ *.tsbuildinfo
55
+
56
+ # Optional npm cache directory
57
+ .npm
58
+
59
+ # Optional eslint cache
60
+ .eslintcache
61
+
62
+ # Optional stylelint cache
63
+ .stylelintcache
64
+
65
+ # Optional REPL history
66
+ .node_repl_history
67
+
68
+ # Output of 'npm pack'
69
+ *.tgz
70
+
71
+ # Yarn Integrity file
72
+ .yarn-integrity
73
+
74
+ # dotenv environment variable files
75
+ .env
76
+ .env.*
77
+ !.env.example
78
+
79
+ # parcel-bundler cache (https://parceljs.org/)
80
+ .cache
81
+ .parcel-cache
82
+
83
+ # Next.js build output
84
+ .next
85
+ out
86
+
87
+ # Nuxt.js build / generate output
88
+ .nuxt
89
+ dist
90
+ .output
91
+
92
+ # Gatsby files
93
+ .cache/
94
+ # Comment in the public line in if your project uses Gatsby and not Next.js
95
+ # https://nextjs.org/blog/next-9-1#public-directory-support
96
+ # public
97
+
98
+ # vuepress build output
99
+ .vuepress/dist
100
+
101
+ # vuepress v2.x temp and cache directory
102
+ .temp
103
+ .cache
104
+
105
+ # Sveltekit cache directory
106
+ .svelte-kit/
107
+
108
+ # vitepress build output
109
+ **/.vitepress/dist
110
+
111
+ # vitepress cache directory
112
+ **/.vitepress/cache
113
+
114
+ # Docusaurus cache and generated files
115
+ .docusaurus
116
+
117
+ # Serverless directories
118
+ .serverless/
119
+
120
+ # FuseBox cache
121
+ .fusebox/
122
+
123
+ # DynamoDB Local files
124
+ .dynamodb/
125
+
126
+ # Firebase cache directory
127
+ .firebase/
128
+
129
+ # TernJS port file
130
+ .tern-port
131
+
132
+ # Stores VSCode versions used for testing VSCode extensions
133
+ .vscode-test
134
+
135
+ # yarn v3
136
+ .pnp.*
137
+ .yarn/*
138
+ !.yarn/patches
139
+ !.yarn/plugins
140
+ !.yarn/releases
141
+ !.yarn/sdks
142
+ !.yarn/versions
143
+
144
+ # Vite files
145
+ vite.config.js.timestamp-*
146
+ vite.config.ts.timestamp-*
147
+ .vite/
@@ -0,0 +1,7 @@
1
+ # yaml-language-server: $schema=./node_modules/harperdb/config-app.schema.json
2
+
3
+ # This is the configuration file for the application.
4
+ # It specifies built-in Harper components that will load the specified feature and files.
5
+ # For more information, see https://docs.harperdb.io/docs/reference/components/built-in-extensions
6
+
7
+ # Follow along with https://github.com/HarperFast/create-your-first-application to learn more!
@@ -0,0 +1,3 @@
1
+ schema: schema.graphql
2
+ include: node_modules/harperdb/schema.graphql
3
+ documents: '**/*.graphql'
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "your-package-name-here",
3
+ "version": "1.0.0",
4
+ "description": "Your new Harper app",
5
+ "type": "module",
6
+ "scripts": {
7
+ "start": "harperdb run .",
8
+ "dev": "harperdb dev .",
9
+ "deploy": "npx -y dotenv-cli -- harperdb deploy . restart=rolling replicated=true"
10
+ },
11
+ "devDependencies": {
12
+ "harperdb": "^4.7.15"
13
+ }
14
+ }
@@ -0,0 +1 @@
1
+ ## Table Schemas
@@ -0,0 +1,45 @@
1
+ # your-project-name-here
2
+
3
+ ## Installation
4
+
5
+ To get started, make sure you have [installed Harper](https://docs.harperdb.io/docs/deployments/install-harper), which can be done quickly:
6
+
7
+ ```sh
8
+ npm install -g harperdb
9
+ ```
10
+
11
+ ## Development
12
+
13
+ Then you can start your app:
14
+
15
+ ```sh
16
+ npm run dev
17
+ ```
18
+
19
+ Navigate to [http://localhost:9926](http://localhost:9926) in a browser and view the functional web application.
20
+
21
+ For more information about getting started with HarperDB and building applications, see our [getting started guide](https://docs.harperdb.io/docs).
22
+
23
+ For more information on Harper Components, see the [Components documentation](https://docs.harperdb.io/docs/reference/components).
24
+
25
+ Take a look at the [default configuration](./config.yaml), which specifies how files are handled in your application.
26
+
27
+ The [schema.graphql](./schema.graphql) is the table schema definition. This is the main starting point for defining your database schema, specifying which tables you want and what attributes/fields they should have.
28
+
29
+ The [resources.js](resources.ts) provides a template for defining JavaScript resource classes, for customized application logic in your endpoints.
30
+
31
+ ## Deployment
32
+
33
+ When you are ready, head to [https://fabric.harper.fast/](https://fabric.harper.fast/), log in to your account, and create a cluster.
34
+
35
+ Set up your .env file with your secure cluster credentials. Don't commit this file to source control!
36
+
37
+ ```sh
38
+ npm run login
39
+ ```
40
+
41
+ Then you can deploy your app to your cluster:
42
+
43
+ ```sh
44
+ npm run deploy
45
+ ```
@@ -0,0 +1 @@
1
+ .env
@@ -0,0 +1,3 @@
1
+ CLI_TARGET_USERNAME='your-cluster-username-here'
2
+ CLI_TARGET_PASSWORD='your-cluster-password-here'
3
+ CLI_TARGET='your-fabric.harper.fast-cluster-url-here'
@@ -0,0 +1,3 @@
1
+ CLI_TARGET_USERNAME='YOUR_CLUSTER_USERNAME'
2
+ CLI_TARGET_PASSWORD='YOUR_CLUSTER_PASSWORD'
3
+ CLI_TARGET='YOUR_FABRIC.HARPER.FAST_CLUSTER_URL_HERE'
@@ -0,0 +1,40 @@
1
+ name: Deploy to Harper Fabric
2
+ on:
3
+ workflow_dispatch:
4
+ # push:
5
+ # branches:
6
+ # - main
7
+
8
+ concurrency:
9
+ group: main
10
+ cancel-in-progress: false
11
+
12
+ jobs:
13
+ deploy:
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - name: Checkout code
17
+ uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
18
+ with:
19
+ fetch-depth: 0
20
+ fetch-tags: true
21
+ - name: Set up Node.js
22
+ uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
23
+ with:
24
+ cache: 'npm'
25
+ node-version-file: '.nvmrc'
26
+ - name: Install dependencies
27
+ run: npm ci
28
+ - name: Run unit tests
29
+ run: npm test
30
+ - name: Run lint
31
+ run: npm run lint
32
+ - name: Build
33
+ run: npm run build
34
+ - name: Deploy
35
+ run: |
36
+ mkdir deploy
37
+ mv web deploy/
38
+ cp -R deploy-template/* deploy/
39
+ cd deploy
40
+ CLI_TARGET_USERNAME=${{ secrets.CLI_TARGET_USERNAME }} CLI_TARGET_PASSWORD='${{ secrets.CLI_TARGET_PASSWORD }}' harperdb deploy_component project='${{ secrets.CLI_DEPLOY_TARGET_NAME }}' target='${{ secrets.CLI_DEPLOY_TARGET_URL }}' restart=false replicated=true