@next-core/yo 1.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/bin/yo.js ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import "../src/index.js";
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@next-core/yo",
3
+ "version": "1.1.0",
4
+ "description": "Generator for next v3",
5
+ "homepage": "https://github.com/easyops-cn/next-core/tree/v3/packages/yo",
6
+ "license": "GPL-3.0",
7
+ "type": "module",
8
+ "bin": {
9
+ "yo": "./bin/yo.js"
10
+ },
11
+ "files": [
12
+ "bin",
13
+ "src"
14
+ ],
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git@github.com:easyops-cn/next-core.git"
18
+ },
19
+ "engines": {
20
+ "node": ">=16"
21
+ },
22
+ "dependencies": {
23
+ "minimist": "^1.2.8",
24
+ "plop": "^3.1.2"
25
+ },
26
+ "devDependencies": {
27
+ "@next-core/build-next-bricks": "^1.7.2",
28
+ "@next-core/element": "^1.0.6",
29
+ "@next-core/i18n": "^1.0.19",
30
+ "@next-core/react-element": "^1.0.7",
31
+ "@next-core/test-next": "^1.0.6",
32
+ "@next-core/theme": "^1.1.1",
33
+ "react": "0.0.0-experimental-ee8509801-20230117"
34
+ },
35
+ "gitHead": "42ca2e08c31d805ee00f8fd010dfb1dc52bfa50b"
36
+ }
package/src/index.js ADDED
@@ -0,0 +1,30 @@
1
+ import path from "node:path";
2
+ import { fileURLToPath } from "node:url";
3
+ import minimist from "minimist";
4
+ import { Plop, run } from "plop";
5
+
6
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
7
+
8
+ const args = process.argv.slice(2);
9
+ const argv = minimist(args);
10
+
11
+ Plop.prepare(
12
+ {
13
+ cwd: argv.cwd,
14
+ configPath: path.join(__dirname, "plopfile.js"),
15
+ preload: argv.preload || [],
16
+ completion: argv.completion,
17
+ },
18
+ (env) =>
19
+ Plop.execute(env, (options) =>
20
+ run(
21
+ {
22
+ ...options,
23
+ // this will make the destination path to be based on the cwd when calling the wrapper
24
+ dest: process.cwd(),
25
+ },
26
+ undefined,
27
+ true
28
+ )
29
+ )
30
+ );
@@ -0,0 +1,225 @@
1
+ import path from "node:path";
2
+ import { existsSync } from "node:fs";
3
+ import { readFile, readdir } from "node:fs/promises";
4
+ import { fileURLToPath } from "node:url";
5
+
6
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
7
+
8
+ const validPkgName = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;
9
+ const validBrickName = /^[a-z][a-z0-9]*(-[a-z0-9]+)+$/;
10
+
11
+ const rootDir = process.cwd();
12
+ const bricksDir = path.join(rootDir, "bricks");
13
+
14
+ const packageJson = JSON.parse(
15
+ await readFile(path.join(rootDir, "package.json"))
16
+ );
17
+ const yoPackageJson = JSON.parse(
18
+ await readFile(path.join(__dirname, "../package.json"))
19
+ );
20
+
21
+ export default function (
22
+ /** @type {import('plop').NodePlopAPI} */
23
+ plop
24
+ ) {
25
+ const isOnGitHub = packageJson.homepage.includes("github.com");
26
+ const dependencies = {};
27
+ const devDependencies = {};
28
+ for (const [dep, version] of Object.entries(yoPackageJson.devDependencies)) {
29
+ switch (dep) {
30
+ case "@next-core/build-next-bricks":
31
+ case "@next-core/test-next":
32
+ devDependencies[dep] = version;
33
+ break;
34
+ default:
35
+ dependencies[dep] = version;
36
+ }
37
+ }
38
+
39
+ plop.setPartial("scope", isOnGitHub ? "@next-bricks" : "@bricks");
40
+ plop.setPartial("homepage", packageJson.homepage.replace(/\/$/, ""));
41
+ plop.setPartial(
42
+ "repository",
43
+ getObjectPartialInPackageJson(packageJson.repository)
44
+ );
45
+ plop.setPartial(
46
+ "license",
47
+ packageJson.license ?? (isOnGitHub ? "GPL-3.0" : "UNLICENSED")
48
+ );
49
+ plop.setPartial("dependencies", getObjectPartialInPackageJson(dependencies));
50
+ plop.setPartial(
51
+ "devDependencies",
52
+ getObjectPartialInPackageJson(devDependencies)
53
+ );
54
+
55
+ // create your generators here
56
+ plop.setGenerator("basics", {
57
+ description: "application controller logic",
58
+ prompts: [
59
+ {
60
+ type: "list",
61
+ name: "type",
62
+ message: "What do you want to do?",
63
+ choices: [
64
+ {
65
+ name: "Add a new brick",
66
+ value: "brick",
67
+ },
68
+ {
69
+ name: "Add a new provider",
70
+ value: "provider",
71
+ },
72
+ {
73
+ name: "Create a new brick package",
74
+ value: "bricks",
75
+ },
76
+ ],
77
+ },
78
+ {
79
+ type: "input",
80
+ name: "pkgName",
81
+ message: "Your package name:",
82
+ when(data) {
83
+ return data.type === "bricks";
84
+ },
85
+ validate(value) {
86
+ if (!validPkgName.test(value)) {
87
+ return "Please enter a lower-kebab-case package name.";
88
+ }
89
+
90
+ if (value.startsWith("providers-of-")) {
91
+ return "`providers-of-*` is reserved, please enter another name.";
92
+ }
93
+
94
+ if (existsSync(path.join(bricksDir, value))) {
95
+ return `Package "${value}" exists, please enter another name.`;
96
+ }
97
+
98
+ return true;
99
+ },
100
+ },
101
+ {
102
+ type: "list",
103
+ name: "pkgName",
104
+ message: "Select your package first:",
105
+ when(data) {
106
+ return data.type === "brick" || data.type === "provider";
107
+ },
108
+ choices: async () => {
109
+ const dirs = await readdir(bricksDir, { withFileTypes: true });
110
+ return dirs
111
+ .filter(
112
+ (dir) =>
113
+ dir.isDirectory() &&
114
+ existsSync(path.join(bricksDir, dir.name, "package.json"))
115
+ )
116
+ .map((dir) => dir.name)
117
+ .sort();
118
+ },
119
+ },
120
+ {
121
+ type: "input",
122
+ name: "brickName",
123
+ message: "Your brick name:",
124
+ when(data) {
125
+ return data.type === "brick";
126
+ },
127
+ validate(value, data) {
128
+ if (!validBrickName.test(value)) {
129
+ return "Please enter a lower-kebab-case brick name.";
130
+ }
131
+
132
+ if (existsSync(path.join(bricksDir, data.pkgName, "src", value))) {
133
+ return `Brick "${value}" seems to be existed, please enter another name.`;
134
+ }
135
+
136
+ return true;
137
+ },
138
+ },
139
+ {
140
+ type: "input",
141
+ name: "providerName",
142
+ message: "Your provider name:",
143
+ when(data) {
144
+ return data.type === "provider";
145
+ },
146
+ validate(value, data) {
147
+ if (!validBrickName.test(value)) {
148
+ return "Please enter a lower-kebab-case provider name.";
149
+ }
150
+
151
+ if (
152
+ existsSync(
153
+ path.join(
154
+ bricksDir,
155
+ data.pkgName,
156
+ "src/data-providers",
157
+ `${value}.ts`
158
+ )
159
+ )
160
+ ) {
161
+ return `Provider "${value}" seems to be existed, please enter another name.`;
162
+ }
163
+
164
+ return true;
165
+ },
166
+ },
167
+ ],
168
+ actions(data) {
169
+ if (data.type === "brick") {
170
+ return [
171
+ {
172
+ type: "addMany",
173
+ destination: "bricks/{{pkgName}}/src/{{brickName}}",
174
+ base: "templates/brick",
175
+ templateFiles: "templates/brick",
176
+ },
177
+ {
178
+ type: "append",
179
+ path: "bricks/{{pkgName}}/src/bootstrap.ts",
180
+ template: 'import "./{{brickName}}/index.js";\n',
181
+ separator: "",
182
+ },
183
+ {
184
+ type: "add",
185
+ path: "bricks/{{pkgName}}/docs/{{brickName}}.md",
186
+ templateFile: "templates/brick.md.hbs",
187
+ },
188
+ ];
189
+ } else if (data.type === "provider") {
190
+ return [
191
+ {
192
+ type: "add",
193
+ path: "bricks/{{pkgName}}/src/data-providers/{{providerName}}.ts",
194
+ templateFile: "templates/provider/provider.ts.hbs",
195
+ },
196
+ {
197
+ type: "add",
198
+ path: "bricks/{{pkgName}}/src/data-providers/{{providerName}}.spec.ts",
199
+ templateFile: "templates/provider/provider.spec.ts.hbs",
200
+ },
201
+ {
202
+ type: "append",
203
+ path: "bricks/{{pkgName}}/src/bootstrap.ts",
204
+ template: 'import "./data-providers/{{providerName}}.js";\n',
205
+ separator: "",
206
+ },
207
+ ];
208
+ } else if (data.type === "bricks") {
209
+ return [
210
+ {
211
+ type: "addMany",
212
+ destination: "bricks/{{pkgName}}",
213
+ base: "templates/bricks",
214
+ templateFiles: "templates/bricks",
215
+ },
216
+ ];
217
+ }
218
+ return [];
219
+ },
220
+ });
221
+ }
222
+
223
+ function getObjectPartialInPackageJson(object) {
224
+ return JSON.stringify(object, null, 4).replace(/\}\s*$/, " }");
225
+ }
@@ -0,0 +1,16 @@
1
+ export enum K {}
2
+ // HELLO = "HELLO",
3
+
4
+ const en: Locale = {
5
+ // HELLO: "Hello",
6
+ };
7
+
8
+ const zh: Locale = {
9
+ // HELLO: "你好",
10
+ };
11
+
12
+ export const NS = "bricks/{{pkgName}}/{{brickName}}";
13
+
14
+ export const locales = { en, zh };
15
+
16
+ type Locale = { [key in K]: string };
@@ -0,0 +1,24 @@
1
+ import { describe, test, expect, jest } from "@jest/globals";
2
+ import { act } from "react-dom/test-utils";
3
+ import "./";
4
+ import { {{pascalCase brickName}} } from "./index.js";
5
+
6
+ jest.mock("@next-core/theme", () => ({}));
7
+
8
+ describe("{{pkgName}}.{{brickName}}", () => {
9
+ test("basic usage", async () => {
10
+ const element = document.createElement("{{pkgName}}.{{brickName}}") as {{pascalCase brickName}};
11
+
12
+ expect(element.shadowRoot).toBeFalsy();
13
+
14
+ act(() => {
15
+ document.body.appendChild(element);
16
+ });
17
+ expect(element.shadowRoot?.childNodes.length).toBeGreaterThan(1);
18
+
19
+ act(() => {
20
+ document.body.removeChild(element);
21
+ });
22
+ expect(element.shadowRoot?.childNodes.length).toBe(0);
23
+ });
24
+ });
@@ -0,0 +1,33 @@
1
+ import React from "react";
2
+ import { createDecorators } from "@next-core/element";
3
+ import { ReactNextElement } from "@next-core/react-element";
4
+ import "@next-core/theme";
5
+ import styleText from "./styles.shadow.css";
6
+
7
+ // --- NOTE: uncomment these lines below to enable i18n for your brick ---
8
+ // import { useTranslation, initializeReactI18n } from "@next-core/i18n/react";
9
+ // import { K, NS, locales } from "./i18n.js";
10
+ // initializeReactI18n(NS, locales);
11
+
12
+ const { defineElement, property } = createDecorators();
13
+
14
+ /**
15
+ * 构件 {{brickName}}
16
+ */
17
+ export
18
+ @defineElement("{{pkgName}}.{{brickName}}", {
19
+ styleTexts: [styleText],
20
+ })
21
+ class {{pascalCase brickName}} extends ReactNextElement {
22
+ render() {
23
+ return (
24
+ <{{pascalCase brickName}}Component />
25
+ );
26
+ }
27
+ }
28
+
29
+ export function {{pascalCase brickName}}Component() {
30
+ // const { t } = useTranslation(NS);
31
+ // const hello = t(K.HELLO);
32
+ return <div>It works!</div>;
33
+ }
@@ -0,0 +1,7 @@
1
+ :host {
2
+ display: inline-block;
3
+ }
4
+
5
+ :host([hidden]) {
6
+ display: none;
7
+ }
@@ -0,0 +1,9 @@
1
+ 构件 {{brickName}}
2
+
3
+ ## Examples
4
+
5
+ ### Basic
6
+
7
+ ```html preview
8
+ <{{pkgName}}.{{brickName}}>Hello world</{{pkgName}}.{{brickName}}>
9
+ ```
@@ -0,0 +1,3 @@
1
+ // @ts-check
2
+ /** @type {import("@next-core/build-next-bricks").BuildNextBricksConfig} */
3
+ export default {};
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "{{> scope }}/{{pkgName}}",
3
+ "version": "0.0.0",
4
+ "homepage": "{{> homepage }}/tree/master/bricks/{{pkgName}}",
5
+ "repository": {{> repository }},
6
+ "license": "{{> license}}",
7
+ "type": "module",
8
+ "sideEffects": true,
9
+ "files": [
10
+ "dist",
11
+ "dist-types",
12
+ "docs"
13
+ ],
14
+ "exports": {
15
+ "./package.json": "./package.json",
16
+ "./dist/bricks.json": "./dist/bricks.json",
17
+ "./dist/manifest.json": "./dist/manifest.json",
18
+ "./*": {
19
+ "types": "./dist-types/*/index.d.ts"
20
+ }
21
+ },
22
+ "scripts": {
23
+ "start": "cross-env NODE_ENV=development build-next-bricks --watch",
24
+ "build": "npm run build:main && npm run build:types",
25
+ "build:main": "cross-env NODE_ENV=production build-next-bricks",
26
+ "build:types": "tsc --emitDeclarationOnly --declaration --declarationDir dist-types --project tsconfig.json",
27
+ "build:manifest": "cross-env NODE_ENV=production build-next-bricks --manifest-only",
28
+ "test": "cross-env NODE_ENV='test' test-next",
29
+ "test:ci": "cross-env NODE_ENV='test' CI=true test-next",
30
+ "prepublishOnly": "cp package.json package.json.bak && npm pkg delete dependencies",
31
+ "postpublish": "mv package.json.bak package.json"
32
+ },
33
+ "dependencies": {{> dependencies }},
34
+ "devDependencies": {{> devDependencies }}
35
+ }
File without changes
@@ -0,0 +1 @@
1
+ import("./bootstrap.js");
@@ -0,0 +1,4 @@
1
+ {
2
+ "extends": "../../tsconfig.module.json",
3
+ "include": ["./src", "../../declarations"]
4
+ }
@@ -0,0 +1,8 @@
1
+ import { describe, test, expect } from "@jest/globals";
2
+ import { {{camelCase providerName}} } from "./{{providerName}}.js";
3
+
4
+ describe("{{camelCase providerName}}", () => {
5
+ test("should work", async () => {
6
+ expect(await {{camelCase providerName}}()).toBe(undefined);
7
+ });
8
+ });
@@ -0,0 +1,10 @@
1
+ import { createProviderClass } from "@next-core/utils/general";
2
+
3
+ export async function {{camelCase providerName}}(): Promise<unknown> {
4
+ //
5
+ }
6
+
7
+ customElements.define(
8
+ "{{pkgName}}.{{providerName}}",
9
+ createProviderClass({{camelCase providerName}})
10
+ );