jaypie 0.1.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/.eslintrc.cjs +40 -0
- package/.github/workflows/npm-deploy.yml +55 -0
- package/.vscode/settings.json +23 -0
- package/README.md +69 -0
- package/_templates/jaypie/hygen/jest.command.ejs.t +14 -0
- package/_templates/jaypie/hygen/new.ejs.t +31 -0
- package/_templates/jaypie/hygen/prompt.cjs +37 -0
- package/_templates/jaypie/hygen/prompt.ejs.t +44 -0
- package/_templates/jaypie/hygen/test.ejs.t +52 -0
- package/_templates/jaypie/vite/new.ejs.t +28 -0
- package/_templates/jaypie/vite/prompt.cjs +35 -0
- package/_templates/jaypie/vite/test.ejs.t +49 -0
- package/_templates/jaypie/vite/vitest.command.ejs.t +11 -0
- package/_templates/jaypie/vitest/jest.command.ejs.t +11 -0
- package/_templates/jaypie/vitest/prompt.cjs +41 -0
- package/_templates/jaypie/vitest/test.ejs.t +49 -0
- package/_templates/jaypie/workflow-npm/npm-deploy.ejs.t +58 -0
- package/_templates/jaypie/workflow-npm/prompt.cjs +32 -0
- package/package.json +32 -0
- package/src/__tests__/index.spec.js +41 -0
- package/src/index.js +6 -0
- package/testSetup.js +3 -0
- package/vite.config.js +10 -0
package/.eslintrc.cjs
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
root: true,
|
|
3
|
+
env: {
|
|
4
|
+
es6: true,
|
|
5
|
+
node: true,
|
|
6
|
+
},
|
|
7
|
+
extends: [
|
|
8
|
+
"eslint:recommended",
|
|
9
|
+
"plugin:import/errors",
|
|
10
|
+
// "Add plugin:prettier/recommended as the last item in the extends array in your .eslintrc* config file, so that eslint-config-prettier has the opportunity to override other configs"
|
|
11
|
+
"plugin:prettier/recommended",
|
|
12
|
+
],
|
|
13
|
+
overrides: [
|
|
14
|
+
{
|
|
15
|
+
files: ["__tests__/**", "**/*.spec.js", "**/*.test.js"],
|
|
16
|
+
plugins: ["vitest"],
|
|
17
|
+
extends: ["plugin:vitest/recommended"],
|
|
18
|
+
rules: {
|
|
19
|
+
"vitest/no-focused-tests": "error",
|
|
20
|
+
"vitest/no-disabled-tests": "warn",
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
files: ["*.cjs"],
|
|
25
|
+
rules: {
|
|
26
|
+
"import/no-commonjs": "off",
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
parserOptions: {
|
|
31
|
+
ecmaVersion: "latest",
|
|
32
|
+
sourceType: "module",
|
|
33
|
+
},
|
|
34
|
+
plugins: ["prettier"],
|
|
35
|
+
rules: {
|
|
36
|
+
"import/extensions": ["error", "ignorePackages"],
|
|
37
|
+
"import/no-commonjs": "error",
|
|
38
|
+
"no-console": "warn",
|
|
39
|
+
},
|
|
40
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
name: NPM Deploy
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- v*
|
|
7
|
+
|
|
8
|
+
env:
|
|
9
|
+
PROJECT_ENV: meta
|
|
10
|
+
PROJECT_SERVICE: libraries
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
deploy:
|
|
14
|
+
name: NPM Deploy
|
|
15
|
+
permissions:
|
|
16
|
+
id-token: write # for aws-actions/configure-aws-credentials
|
|
17
|
+
contents: read # for actions/checkout
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
steps:
|
|
20
|
+
- name: Checkout Code
|
|
21
|
+
uses: actions/checkout@v4
|
|
22
|
+
- name: NPM Install (`npm install`)
|
|
23
|
+
run: npm install
|
|
24
|
+
- name: NPM Deploy
|
|
25
|
+
run: |
|
|
26
|
+
npm config set //registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}
|
|
27
|
+
npm publish --access public
|
|
28
|
+
lint:
|
|
29
|
+
name: Lint (in parallel)
|
|
30
|
+
runs-on: ubuntu-latest
|
|
31
|
+
steps:
|
|
32
|
+
- name: Checkout code
|
|
33
|
+
uses: actions/checkout@v4
|
|
34
|
+
- name: Install dependencies
|
|
35
|
+
run: npm ci
|
|
36
|
+
- name: Run ESLint
|
|
37
|
+
run: npm run lint
|
|
38
|
+
# run: npx eslint . --max-warnings=0
|
|
39
|
+
test:
|
|
40
|
+
name: Unit Test (in parallel)
|
|
41
|
+
runs-on: ubuntu-latest
|
|
42
|
+
strategy:
|
|
43
|
+
matrix:
|
|
44
|
+
node-version: [18.x, 20.x]
|
|
45
|
+
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
|
|
46
|
+
steps:
|
|
47
|
+
- uses: actions/checkout@v4
|
|
48
|
+
- name: Use Node.js ${{ matrix.node-version }}
|
|
49
|
+
uses: actions/setup-node@v4
|
|
50
|
+
with:
|
|
51
|
+
node-version: ${{ matrix.node-version }}
|
|
52
|
+
cache: 'npm'
|
|
53
|
+
- run: npm ci
|
|
54
|
+
- run: |
|
|
55
|
+
npm test
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cSpell.words": [
|
|
3
|
+
"certificatemanager",
|
|
4
|
+
"clonedeep",
|
|
5
|
+
"composables",
|
|
6
|
+
"ejectability",
|
|
7
|
+
"Finlayson",
|
|
8
|
+
"fontface",
|
|
9
|
+
"hygen",
|
|
10
|
+
"iconsets",
|
|
11
|
+
"initzero",
|
|
12
|
+
"jaypie",
|
|
13
|
+
"knowdev",
|
|
14
|
+
"oidc",
|
|
15
|
+
"pinia",
|
|
16
|
+
"roboto",
|
|
17
|
+
"unplugin",
|
|
18
|
+
"vendia",
|
|
19
|
+
"vuekit",
|
|
20
|
+
"vuetify",
|
|
21
|
+
"wght"
|
|
22
|
+
]
|
|
23
|
+
}
|
package/README.md
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Jaypie 🐦⬛
|
|
2
|
+
|
|
3
|
+
Event-driven fullstack architecture centered around JavaScript, AWS, and the JSON:API specification
|
|
4
|
+
|
|
5
|
+
"JavaScript on both sides and underneath"
|
|
6
|
+
|
|
7
|
+
## 🐦⬛ Introduction
|
|
8
|
+
|
|
9
|
+
Jaypie is an opinionated approach to application development centered around JavaScript and the JSON:API specification in an event-driven architecture.
|
|
10
|
+
|
|
11
|
+
Jaypie is suited for applications that require custom infrastructure beyond HTTP requests (e.g., message queues). Without custom infrastructure, fullstack hosts like Vercel or Netlify are recommended.
|
|
12
|
+
|
|
13
|
+
### "Jaypie Stack"
|
|
14
|
+
|
|
15
|
+
* AWS infrastructure managed by CDK in Node.js
|
|
16
|
+
* Express server running on AWS Lambda
|
|
17
|
+
* Node.js worker processes running on AWS Lambda
|
|
18
|
+
* MongoDB via Mongoose
|
|
19
|
+
* Vue ecosystem frontend: Vue 3 composition, Vuetify, Pinia
|
|
20
|
+
* Vitest for testing
|
|
21
|
+
* ES6 syntax enforced via ESLint
|
|
22
|
+
* Prettier formatting
|
|
23
|
+
* JSON logging with custom metadata
|
|
24
|
+
|
|
25
|
+
### Philosophy
|
|
26
|
+
|
|
27
|
+
Jaypie is for building fullstack JavaScript applications.
|
|
28
|
+
|
|
29
|
+
#### JavaScript Only 💛
|
|
30
|
+
|
|
31
|
+
Jaypie uses the AWS Cloud Development Kit (CDK) to manage infrastructure, which is written in Node.js. This makes managing infrastructure accessible to the fullstack developer without learning a new syntax and living without language constructs like loops and inheritance.
|
|
32
|
+
|
|
33
|
+
Does NOT use Kubernetes, Docker, Terraform, or the "Serverless" framework.
|
|
34
|
+
|
|
35
|
+
#### Eject Anything ⏏️
|
|
36
|
+
|
|
37
|
+
Jaypie embraces "ejectability," the philosophy that any part of the framework can be removed (and therefore replaced) without disturbing the whole.
|
|
38
|
+
|
|
39
|
+
#### Mock Everywhere 🎴
|
|
40
|
+
|
|
41
|
+
Jaypie strives to be "mockable-first" meaning all components should be easily tested via default or provided mocks.
|
|
42
|
+
|
|
43
|
+
## 📋 Usage
|
|
44
|
+
|
|
45
|
+
### Installation
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
npm install jaypie
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
TODO: need to document peer dependencies
|
|
52
|
+
|
|
53
|
+
### Example
|
|
54
|
+
|
|
55
|
+
TODO: Example should include one trivial and possibly one thorough example of using the library
|
|
56
|
+
|
|
57
|
+
## 📖 Reference
|
|
58
|
+
|
|
59
|
+
TODO: Reference should be a complete list of everything in the package
|
|
60
|
+
|
|
61
|
+
## 📝 Changelog
|
|
62
|
+
|
|
63
|
+
| Date | Version | Summary |
|
|
64
|
+
| ---------- | ------- | -------------- |
|
|
65
|
+
| 3/15/2024 | 0.0.1 | Initial commit |
|
|
66
|
+
|
|
67
|
+
## 📜 License
|
|
68
|
+
|
|
69
|
+
Published by Finlayson Studio. All rights reserved
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
to: <%= hygen %>/<%= generator %>/<%= action %>/jest.command.ejs.t
|
|
3
|
+
---
|
|
4
|
+
---
|
|
5
|
+
inject: true
|
|
6
|
+
to: package.json
|
|
7
|
+
after: scripts
|
|
8
|
+
skip_if: spec<%- '<' %>%= colonSubspec %<%- '>' %>.+<%- '<' %>%= path %<%- '>' %>/__tests__/<%- '<' %>%= name %<%- '>' %><%- '<' %>%= dotSubtype %<%- '>' %>.spec.js
|
|
9
|
+
sh: |
|
|
10
|
+
if jq -e '.scripts["format:package"]' package.json <%- '>' %> /dev/null; then
|
|
11
|
+
npm run format:package 2<%- '>' %> /dev/null || true
|
|
12
|
+
fi
|
|
13
|
+
---
|
|
14
|
+
"test:spec<%- '<' %>%= colonSubspec %<%- '>' %>:<%- '<' %>%= name %<%- '>' %><%- '<' %>%= dotSubtype %<%- '>' %>": "vitest run ./<%- '<' %>%= path %<%- '>' %>/__tests__/<%- '<' %>%= name %<%- '>' %><%- '<' %>%= dotSubtype %<%- '>' %>.spec.js",
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
to: <%= hygen %>/<%= generator %>/<%= action %>/new.ejs.t
|
|
3
|
+
---
|
|
4
|
+
---
|
|
5
|
+
to: <%- '<' %>%= path %<%- '>' %>/<%- '<' %>%= name %<%- '>' %><%- '<' %>%= dotSubtype %<%- '>' %>.js
|
|
6
|
+
---
|
|
7
|
+
//
|
|
8
|
+
//
|
|
9
|
+
// Constants
|
|
10
|
+
//
|
|
11
|
+
|
|
12
|
+
//
|
|
13
|
+
//
|
|
14
|
+
// Helper Functions
|
|
15
|
+
//
|
|
16
|
+
|
|
17
|
+
//
|
|
18
|
+
//
|
|
19
|
+
// Main
|
|
20
|
+
//
|
|
21
|
+
|
|
22
|
+
const <%- '<' %>%= name %<%- '>' %> = () =<%- '>' %> {
|
|
23
|
+
//
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
//
|
|
27
|
+
//
|
|
28
|
+
// Export
|
|
29
|
+
//
|
|
30
|
+
|
|
31
|
+
export default <%- '<' %>%= name %<%- '>' %>;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// see types of prompts:
|
|
2
|
+
// https://github.com/enquirer/enquirer/tree/master/examples
|
|
3
|
+
//
|
|
4
|
+
module.exports = [
|
|
5
|
+
{
|
|
6
|
+
type: "input",
|
|
7
|
+
name: "actionInput",
|
|
8
|
+
message: "Action name (e.g., 'file'):",
|
|
9
|
+
onSubmit: (name, value, input) => {
|
|
10
|
+
// Remove leading './' and trailing '/'
|
|
11
|
+
value = value.replace(/^\.?\/|\/$/g, "");
|
|
12
|
+
input.state.answers.action = value;
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
type: "input",
|
|
17
|
+
name: "generatorInput",
|
|
18
|
+
initial: "project",
|
|
19
|
+
message: "Hygen generator directory (e.g., 'jaypie'):",
|
|
20
|
+
onSubmit: (name, value, input) => {
|
|
21
|
+
// Remove leading './' and trailing '/'
|
|
22
|
+
value = value.replace(/^\.?\/|\/$/g, "");
|
|
23
|
+
input.state.answers.generator = value;
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
type: "input",
|
|
28
|
+
name: "hygenInput",
|
|
29
|
+
initial: "_templates",
|
|
30
|
+
message: "Hygen template directory (always '_templates'):",
|
|
31
|
+
onSubmit: (name, value, input) => {
|
|
32
|
+
// Remove leading './' and trailing '/'
|
|
33
|
+
value = value.replace(/^\.?\/|\/$/g, "");
|
|
34
|
+
input.state.answers.hygen = value;
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
];
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
to: <%= hygen %>/<%= generator %>/<%= action %>/prompt.cjs
|
|
3
|
+
---
|
|
4
|
+
// see types of prompts:
|
|
5
|
+
// https://github.com/enquirer/enquirer/tree/master/examples
|
|
6
|
+
//
|
|
7
|
+
module.exports = [
|
|
8
|
+
{
|
|
9
|
+
type: "input",
|
|
10
|
+
name: "pathInput",
|
|
11
|
+
initial: "src/util",
|
|
12
|
+
message: "Path (e.g., 'cdk/lib'):",
|
|
13
|
+
onSubmit: (name, value, input) =<%- '>' %> {
|
|
14
|
+
input.state.answers.path = value;
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
type: "input",
|
|
19
|
+
name: "nameInput",
|
|
20
|
+
message: "File name (e.g., 'sum'):",
|
|
21
|
+
onSubmit: (name, value, input) =<%- '>' %> {
|
|
22
|
+
input.state.answers.name = value;
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
type: "input",
|
|
27
|
+
name: "subtypeInput",
|
|
28
|
+
message: "Subtype (optional; e.g., 'function'):",
|
|
29
|
+
onSubmit: (name, value, input) =<%- '>' %> {
|
|
30
|
+
input.state.answers.subtype = value;
|
|
31
|
+
input.state.answers.dotSubtype = value ? `.${value}` : "";
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
type: "input",
|
|
36
|
+
name: "subspecInput",
|
|
37
|
+
message:
|
|
38
|
+
"Sub-spec test, for `npm run test:spec:SUBSPEC:sum.function` command (e.g., 'express' or 'lib:project'):",
|
|
39
|
+
onSubmit: (name, value, input) =<%- '>' %> {
|
|
40
|
+
input.state.answers.subspec = value;
|
|
41
|
+
input.state.answers.colonSubspec = value ? `:${value}` : "";
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
];
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
---
|
|
2
|
+
to: <%= hygen %>/<%= generator %>/<%= action %>/test.ejs.t
|
|
3
|
+
---
|
|
4
|
+
---
|
|
5
|
+
to: <%- '<' %>%= path %<%- '>' %>/__tests__/<%- '<' %>%= name %<%- '>' %><%- '<' %>%= dotSubtype %<%- '>' %>.spec.js
|
|
6
|
+
---
|
|
7
|
+
// eslint-disable-next-line no-unused-vars
|
|
8
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
9
|
+
|
|
10
|
+
// Subject
|
|
11
|
+
import <%- '<' %>%= name %<%- '>' %> from "../<%- '<' %>%= name %<%- '>' %><%- '<' %>%= dotSubtype %<%- '>' %>.js";
|
|
12
|
+
|
|
13
|
+
//
|
|
14
|
+
//
|
|
15
|
+
// Mock constants
|
|
16
|
+
//
|
|
17
|
+
|
|
18
|
+
//
|
|
19
|
+
//
|
|
20
|
+
// Mock modules
|
|
21
|
+
//
|
|
22
|
+
|
|
23
|
+
//
|
|
24
|
+
//
|
|
25
|
+
// Mock environment
|
|
26
|
+
//
|
|
27
|
+
|
|
28
|
+
const DEFAULT_ENV = process.env;
|
|
29
|
+
beforeEach(() =<%- '>' %> {
|
|
30
|
+
process.env = { ...process.env };
|
|
31
|
+
});
|
|
32
|
+
afterEach(() =<%- '>' %> {
|
|
33
|
+
process.env = DEFAULT_ENV;
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
//
|
|
37
|
+
//
|
|
38
|
+
// Run tests
|
|
39
|
+
//
|
|
40
|
+
|
|
41
|
+
<%- '<' %>%_
|
|
42
|
+
let Subtype = "";
|
|
43
|
+
// If subtype is defined, capitalize the first letter
|
|
44
|
+
if(subtype) Subtype = " " + subtype.charAt(0).toUpperCase() + subtype.slice(1);
|
|
45
|
+
_%<%- '>' %>
|
|
46
|
+
describe("<%- '<' %>%= Name %<%- '>' %><%- '<' %>%= Subtype %<%- '>' %>", () =<%- '>' %> {
|
|
47
|
+
it("Works", () =<%- '>' %> {
|
|
48
|
+
const response = <%- '<' %>%= name %<%- '>' %>();
|
|
49
|
+
console.log("response :<%- '>' %><%- '>' %> ", response);
|
|
50
|
+
expect(response).not.toBeUndefined();
|
|
51
|
+
});
|
|
52
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
to: <%= path %>/<%= name %><%= dotSubtype %>.js
|
|
3
|
+
---
|
|
4
|
+
//
|
|
5
|
+
//
|
|
6
|
+
// Constants
|
|
7
|
+
//
|
|
8
|
+
|
|
9
|
+
//
|
|
10
|
+
//
|
|
11
|
+
// Helper Functions
|
|
12
|
+
//
|
|
13
|
+
|
|
14
|
+
//
|
|
15
|
+
//
|
|
16
|
+
// Main
|
|
17
|
+
//
|
|
18
|
+
|
|
19
|
+
const <%= name %> = () => {
|
|
20
|
+
//
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
//
|
|
24
|
+
//
|
|
25
|
+
// Export
|
|
26
|
+
//
|
|
27
|
+
|
|
28
|
+
export default <%= name %>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// see types of prompts:
|
|
2
|
+
// https://github.com/enquirer/enquirer/tree/master/examples
|
|
3
|
+
//
|
|
4
|
+
module.exports = [
|
|
5
|
+
{
|
|
6
|
+
type: "input",
|
|
7
|
+
name: "path",
|
|
8
|
+
initial: "src",
|
|
9
|
+
message: "Path (e.g., 'src/util' no leading './' or trailing '/'):",
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
type: "input",
|
|
13
|
+
name: "name",
|
|
14
|
+
message: "File name (e.g., 'sum' not 'sum.function'):",
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
type: "input",
|
|
18
|
+
name: "subtype",
|
|
19
|
+
message: "Subtype (optional; e.g., 'function'):",
|
|
20
|
+
onSubmit: (name, value, input) => {
|
|
21
|
+
// eslint-disable-next-line no-param-reassign
|
|
22
|
+
input.state.answers.dotSubtype = value ? `.${value}` : "";
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
type: "input",
|
|
27
|
+
name: "subspec",
|
|
28
|
+
message:
|
|
29
|
+
"Sub-spec test, for `npm run test:spec:SUBSPEC:sum.function` command (e.g., 'express'):",
|
|
30
|
+
onSubmit: (name, value, input) => {
|
|
31
|
+
// eslint-disable-next-line no-param-reassign
|
|
32
|
+
input.state.answers.colonSubspec = value ? `:${value}` : "";
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
];
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
to: <%= path %>/__tests__/<%= name %><%= dotSubtype %>.spec.js
|
|
3
|
+
---
|
|
4
|
+
// eslint-disable-next-line no-unused-vars
|
|
5
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
6
|
+
|
|
7
|
+
// Subject
|
|
8
|
+
import <%= name %> from "../<%= name %><%= dotSubtype %>.js";
|
|
9
|
+
|
|
10
|
+
//
|
|
11
|
+
//
|
|
12
|
+
// Mock constants
|
|
13
|
+
//
|
|
14
|
+
|
|
15
|
+
//
|
|
16
|
+
//
|
|
17
|
+
// Mock modules
|
|
18
|
+
//
|
|
19
|
+
|
|
20
|
+
//
|
|
21
|
+
//
|
|
22
|
+
// Mock environment
|
|
23
|
+
//
|
|
24
|
+
|
|
25
|
+
const DEFAULT_ENV = process.env;
|
|
26
|
+
beforeEach(() => {
|
|
27
|
+
process.env = { ...process.env };
|
|
28
|
+
});
|
|
29
|
+
afterEach(() => {
|
|
30
|
+
process.env = DEFAULT_ENV;
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
//
|
|
34
|
+
//
|
|
35
|
+
// Run tests
|
|
36
|
+
//
|
|
37
|
+
|
|
38
|
+
<%_
|
|
39
|
+
let Subtype = "";
|
|
40
|
+
// If subtype is defined, capitalize the first letter
|
|
41
|
+
if(subtype) Subtype = " " + subtype.charAt(0).toUpperCase() + subtype.slice(1);
|
|
42
|
+
_%>
|
|
43
|
+
describe("<%= Name %><%= Subtype %>", () => {
|
|
44
|
+
it("Works", () => {
|
|
45
|
+
const response = <%= name %>();
|
|
46
|
+
console.log("response :>> ", response);
|
|
47
|
+
expect(response).not.toBeUndefined();
|
|
48
|
+
});
|
|
49
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
inject: true
|
|
3
|
+
to: package.json
|
|
4
|
+
after: scripts
|
|
5
|
+
skip_if: spec<%= colonSubspec %>.+<%= path %>/__tests__/<%= name %><%= dotSubtype %>.spec.js
|
|
6
|
+
sh: |
|
|
7
|
+
if jq -e '.scripts["format:package"]' package.json > /dev/null; then
|
|
8
|
+
npm run format:package 2> /dev/null || true
|
|
9
|
+
fi
|
|
10
|
+
---
|
|
11
|
+
"test:spec<%= colonSubspec %>:<%= name %><%= dotSubtype %>": "vitest run ./<%= path %>/__tests__/<%= name %><%= dotSubtype %>.spec.js",
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
inject: true
|
|
3
|
+
to: package.json
|
|
4
|
+
after: scripts
|
|
5
|
+
skip_if: spec<%= colonSubspec %>.+<%= path %>/__tests__/<%= name %><%= dotSubtype %>.spec.js
|
|
6
|
+
sh: |
|
|
7
|
+
if jq -e '.scripts["format:package"]' package.json > /dev/null; then
|
|
8
|
+
npm run format:package 2> /dev/null || true
|
|
9
|
+
fi
|
|
10
|
+
---
|
|
11
|
+
"test:spec<%= colonSubspec %>:<%= name %><%= dotSubtype %>": "vitest run ./<%= path %>/__tests__/<%= name %><%= dotSubtype %>.spec.js",
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// see types of prompts:
|
|
2
|
+
// https://github.com/enquirer/enquirer/tree/master/examples
|
|
3
|
+
//
|
|
4
|
+
module.exports = [
|
|
5
|
+
{
|
|
6
|
+
type: "input",
|
|
7
|
+
name: "pathInput",
|
|
8
|
+
initial: "src",
|
|
9
|
+
message: "Path (e.g., 'src/util'):",
|
|
10
|
+
onSubmit: (name, value, input) => {
|
|
11
|
+
input.state.answers.path = value;
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
type: "input",
|
|
16
|
+
name: "nameInput",
|
|
17
|
+
message: "File name (e.g., 'sum'):",
|
|
18
|
+
onSubmit: (name, value, input) => {
|
|
19
|
+
input.state.answers.name = value;
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
type: "input",
|
|
24
|
+
name: "subtypeInput",
|
|
25
|
+
message: "Subtype (optional; e.g., 'function'):",
|
|
26
|
+
onSubmit: (name, value, input) => {
|
|
27
|
+
input.state.answers.subtype = value;
|
|
28
|
+
input.state.answers.dotSubtype = value ? `.${value}` : "";
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
type: "input",
|
|
33
|
+
name: "subspecInput",
|
|
34
|
+
message:
|
|
35
|
+
"Sub-spec test, for `npm run test:spec:SUBSPEC:sum.function` command (e.g., 'express' or 'lib:project'):",
|
|
36
|
+
onSubmit: (name, value, input) => {
|
|
37
|
+
input.state.answers.subspec = value;
|
|
38
|
+
input.state.answers.colonSubspec = value ? `:${value}` : "";
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
];
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
to: <%= path %>/__tests__/<%= name %><%= dotSubtype %>.spec.js
|
|
3
|
+
---
|
|
4
|
+
// eslint-disable-next-line no-unused-vars
|
|
5
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
6
|
+
|
|
7
|
+
// Subject
|
|
8
|
+
import <%= name %> from "../<%= name %><%= dotSubtype %>.js";
|
|
9
|
+
|
|
10
|
+
//
|
|
11
|
+
//
|
|
12
|
+
// Mock constants
|
|
13
|
+
//
|
|
14
|
+
|
|
15
|
+
//
|
|
16
|
+
//
|
|
17
|
+
// Mock modules
|
|
18
|
+
//
|
|
19
|
+
|
|
20
|
+
//
|
|
21
|
+
//
|
|
22
|
+
// Mock environment
|
|
23
|
+
//
|
|
24
|
+
|
|
25
|
+
const DEFAULT_ENV = process.env;
|
|
26
|
+
beforeEach(() => {
|
|
27
|
+
process.env = { ...process.env };
|
|
28
|
+
});
|
|
29
|
+
afterEach(() => {
|
|
30
|
+
process.env = DEFAULT_ENV;
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
//
|
|
34
|
+
//
|
|
35
|
+
// Run tests
|
|
36
|
+
//
|
|
37
|
+
|
|
38
|
+
<%_
|
|
39
|
+
let Subtype = "";
|
|
40
|
+
// If subtype is defined, capitalize the first letter
|
|
41
|
+
if(subtype) Subtype = " " + subtype.charAt(0).toUpperCase() + subtype.slice(1);
|
|
42
|
+
_%>
|
|
43
|
+
describe("<%= Name %><%= Subtype %>", () => {
|
|
44
|
+
it("Works", () => {
|
|
45
|
+
const response = <%= name %>();
|
|
46
|
+
console.log("response :>> ", response);
|
|
47
|
+
expect(response).not.toBeUndefined();
|
|
48
|
+
});
|
|
49
|
+
});
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
---
|
|
2
|
+
to: <%= path %>/<%= name %>.yml
|
|
3
|
+
---
|
|
4
|
+
name: NPM Deploy
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
push:
|
|
8
|
+
tags:
|
|
9
|
+
- v*
|
|
10
|
+
|
|
11
|
+
env:
|
|
12
|
+
PROJECT_ENV: meta
|
|
13
|
+
PROJECT_SERVICE: libraries
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
deploy:
|
|
17
|
+
name: NPM Deploy
|
|
18
|
+
permissions:
|
|
19
|
+
id-token: write # for aws-actions/configure-aws-credentials
|
|
20
|
+
contents: read # for actions/checkout
|
|
21
|
+
runs-on: ubuntu-latest
|
|
22
|
+
steps:
|
|
23
|
+
- name: Checkout Code
|
|
24
|
+
uses: actions/checkout@v4
|
|
25
|
+
- name: NPM Install (`npm install`)
|
|
26
|
+
run: npm install
|
|
27
|
+
- name: NPM Deploy
|
|
28
|
+
run: |
|
|
29
|
+
npm config set //registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}
|
|
30
|
+
npm publish --access <%= access %>
|
|
31
|
+
lint:
|
|
32
|
+
name: Lint (in parallel)
|
|
33
|
+
runs-on: ubuntu-latest
|
|
34
|
+
steps:
|
|
35
|
+
- name: Checkout code
|
|
36
|
+
uses: actions/checkout@v4
|
|
37
|
+
- name: Install dependencies
|
|
38
|
+
run: npm ci
|
|
39
|
+
- name: Run ESLint
|
|
40
|
+
run: npm run lint
|
|
41
|
+
# run: npx eslint . --max-warnings=0
|
|
42
|
+
test:
|
|
43
|
+
name: Unit Test (in parallel)
|
|
44
|
+
runs-on: ubuntu-latest
|
|
45
|
+
strategy:
|
|
46
|
+
matrix:
|
|
47
|
+
node-version: [18.x, 20.x]
|
|
48
|
+
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
|
|
49
|
+
steps:
|
|
50
|
+
- uses: actions/checkout@v4
|
|
51
|
+
- name: Use Node.js ${{ matrix.node-version }}
|
|
52
|
+
uses: actions/setup-node@v4
|
|
53
|
+
with:
|
|
54
|
+
node-version: ${{ matrix.node-version }}
|
|
55
|
+
cache: 'npm'
|
|
56
|
+
- run: npm ci
|
|
57
|
+
- run: |
|
|
58
|
+
npm test
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// see types of prompts:
|
|
2
|
+
// https://github.com/enquirer/enquirer/tree/master/examples
|
|
3
|
+
//
|
|
4
|
+
module.exports = [
|
|
5
|
+
{
|
|
6
|
+
type: "input",
|
|
7
|
+
name: "accessInput",
|
|
8
|
+
initial: "public",
|
|
9
|
+
message: "Access ('public' or 'restricted'):",
|
|
10
|
+
onSubmit: (name, value, input) => {
|
|
11
|
+
input.state.answers.access = value;
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
type: "input",
|
|
16
|
+
name: "pathInput",
|
|
17
|
+
initial: ".github/workflows",
|
|
18
|
+
message: "Path (always '.github/workflows'):",
|
|
19
|
+
onSubmit: (name, value, input) => {
|
|
20
|
+
input.state.answers.path = value;
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
type: "input",
|
|
25
|
+
name: "nameInput",
|
|
26
|
+
initial: "npm-deploy",
|
|
27
|
+
message: "File name, no extension (always 'npm-deploy'):",
|
|
28
|
+
onSubmit: (name, value, input) => {
|
|
29
|
+
input.state.answers.name = value;
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
];
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "jaypie",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"author": "Finlayson Studio",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "src/index.js",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"format": "npm run format:package && npm run format:lint",
|
|
9
|
+
"format:lint": "eslint --fix .",
|
|
10
|
+
"format:package": "sort-package-json ./package.json",
|
|
11
|
+
"init:deploy": "hygen jaypie workflow-npm",
|
|
12
|
+
"lint": "eslint .",
|
|
13
|
+
"new": "hygen jaypie vite",
|
|
14
|
+
"test": "vitest",
|
|
15
|
+
"test:spec:index": "vitest run ./src/__tests__/index.spec.js"
|
|
16
|
+
},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"@jaypie/core": "^0.3.3"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"eslint": "^8.57.0",
|
|
22
|
+
"eslint-config-prettier": "^9.1.0",
|
|
23
|
+
"eslint-plugin-import": "^2.29.1",
|
|
24
|
+
"eslint-plugin-prettier": "^5.1.3",
|
|
25
|
+
"eslint-plugin-vitest": "^0.3.26",
|
|
26
|
+
"hygen": "^6.2.11",
|
|
27
|
+
"jest-extended": "^4.0.2",
|
|
28
|
+
"prettier": "^3.2.5",
|
|
29
|
+
"sort-package-json": "^2.8.0",
|
|
30
|
+
"vitest": "^1.4.0"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// eslint-disable-next-line no-unused-vars
|
|
2
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
3
|
+
|
|
4
|
+
// Subject
|
|
5
|
+
import { PROJECT } from "../index.js";
|
|
6
|
+
|
|
7
|
+
//
|
|
8
|
+
//
|
|
9
|
+
// Mock constants
|
|
10
|
+
//
|
|
11
|
+
|
|
12
|
+
//
|
|
13
|
+
//
|
|
14
|
+
// Mock modules
|
|
15
|
+
//
|
|
16
|
+
|
|
17
|
+
//
|
|
18
|
+
//
|
|
19
|
+
// Mock environment
|
|
20
|
+
//
|
|
21
|
+
|
|
22
|
+
const DEFAULT_ENV = process.env;
|
|
23
|
+
beforeEach(() => {
|
|
24
|
+
process.env = { ...process.env };
|
|
25
|
+
});
|
|
26
|
+
afterEach(() => {
|
|
27
|
+
process.env = DEFAULT_ENV;
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
//
|
|
31
|
+
//
|
|
32
|
+
// Run tests
|
|
33
|
+
//
|
|
34
|
+
|
|
35
|
+
describe("Index", () => {
|
|
36
|
+
it("Works", () => {
|
|
37
|
+
expect(PROJECT).not.toBeUndefined();
|
|
38
|
+
expect(PROJECT.SPONSOR).not.toBeUndefined();
|
|
39
|
+
expect(PROJECT.SPONSOR.JAYPIE).toBeString();
|
|
40
|
+
});
|
|
41
|
+
});
|
package/src/index.js
ADDED
package/testSetup.js
ADDED