UNPKG

9.63 kBJavaScriptView Raw
1#!/usr/bin/env node
2
3const fs = require("fs");
4const path = require("path");
5
6const argv = process.argv;
7const action = argv[2];
8const name = argv.length === 4? argv[3] : argv[4];
9const repo = argv.length === 4? undefined : argv[4];
10
11switch (action) {
12 case "create":
13 createComponent(name, repo);
14 break;
15 default:
16 console.error(`There is no '${action}' command. Have you misspell?`);
17}
18
19
20function createComponent(componentName, repo) {
21 const componentPath = `components/${componentName.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase()}`;
22 componentName = componentName.split("/").map(s => s[0].toUpperCase() + s.substring(1)).join("");
23
24 if(fs.existsSync(componentPath)) {
25 console.error(`Folder '${path.resolve(componentPath)}' already exists.`);
26 return 1;
27 }
28
29 fs.mkdirSync(componentPath, { recursive: true });
30
31 if(componentName === "Hello") {
32 createIndex();
33 createConfig();
34 addStartScriptToPackageJson();
35 }
36
37 createComponentDeclaration(componentName, componentPath);
38 createControllerDeclaration(componentName, componentPath);
39 if(repo) {
40 createFactoryDeclarationWithRepository(componentName, componentPath);
41 } else {
42 createFactoryDeclaration(componentName, componentPath);
43 }
44 addComponentToProject(componentName, componentPath);
45
46 console.log(`Component '${componentName}' created in ${path.resolve(componentPath)}.`);
47}
48
49function createIndex() {
50 if(fs.existsSync(path.resolve("index.js"))) {
51 return;
52 }
53
54 const projectIndex =
55 `const Server = require("@dominion-framework/dominion");
56
57Server.addComponent(require("@dominion-framework/dominion/components/cors"));
58Server.addComponent(require("@dominion-framework/dominion/components/logging"));
59
60Server.addComponent(require("./components/hello"));
61
62Server.start();
63
64Server.openApiToFile();
65`;
66 fs.writeFileSync(path.resolve("index.js"), projectIndex, 'utf8');
67}
68
69function addStartScriptToPackageJson() {
70 if(!fs.existsSync(path.resolve("package.json"))) {
71 return;
72 }
73 const packageJson =JSON.parse(fs.readFileSync(path.resolve("package.json")).toString());
74 if(!packageJson.scripts) {
75 packageJson.scripts = {};
76 }
77 packageJson.scripts.start = "node index.js";
78 fs.writeFileSync(path.resolve("package.json"), JSON.stringify(packageJson, null, 2), 'utf8');
79}
80
81function createConfig() {
82 if(fs.existsSync(path.resolve("config"))) {
83 return;
84 }
85
86 const indexConfig =
87 `const config = require("./config.dev");
88
89module.exports = config;
90`;
91
92 const projectConfig =
93 `module.exports = {
94 server: {
95 protocol: "http",
96 host: "localhost",
97 port: 7042,
98 // No slash in the end
99 url: "http://localhost:7042"
100 },
101
102 router: {
103 // e.g. api/v2/
104 urlPrefix: "",
105 // e.g. "[a-f\\d]{8}-[a-f\\d]{4}-4[a-f\\d]{3}-[89ab][a-f\\d]{3}-[a-f\\d]{12}"
106 primaryKeyPattern: "\\\\d+"
107 },
108
109 cors: {
110 // e.g. * | ["example.com"] | () => {} (synchronous callback function with Message context returning array of allowed origins)
111 origin: ["http://localhost:7042", "https://editor.swagger.io"],
112 methods: ["OPTIONS", "GET", "POST", "PUT", "DELETE"],
113 headers: ["Content-Type", "Set-Cookies", "Authorization"],
114 credentials: false,
115 maxAge: 5 /* seconds */
116 }
117};
118`;
119 fs.mkdirSync(path.resolve("config"));
120 fs.writeFileSync(path.resolve("config/config.dev.js"), projectConfig, 'utf8');
121 fs.writeFileSync(path.resolve("config/index.js"), indexConfig, 'utf8');
122
123}
124
125function createComponentDeclaration(componentName, componentPath) {
126 const componentDeclaration =
127 `module.exports = {
128 factories: [
129 __dirname + '/factory',
130 ],
131 controllers: [
132 __dirname + '/controller',
133 ],
134 requestInterceptors: [],
135 responseInterceptors: [],
136 bootstrap: []
137};
138`;
139 fs.writeFileSync(path.resolve(componentPath, "index.js"), componentDeclaration, 'utf8');
140}
141
142function createControllerDeclaration(componentName, componentPath) {
143 const controllerDeclaration =
144 `const Factories = require("@dominion-framework/dominion/core/factories");
145
146const ${componentName}Factory = Factories("${componentName}");
147
148
149module.exports = {
150
151 factory: ${componentName}Factory,
152
153 GET: [
154 //${componentName.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase()}?offset=0&limit=10
155 function (offset = 0, limit = 10) {
156 // @summary: ${componentName === "Hello"? "Demo endpoint with optional arguments" : ""}
157 // @description: ${componentName === "Hello"? `Open http://localhost:7042/${componentName.toLowerCase()}?offset=0&limit=10 to see results` : ""}
158
159 ${componentName === "Hello"?
160 "return HelloFactory.new({message: `Welcome to Dominion! Nice to meet you! [${offset}, ${limit}]` });"
161 :
162 "return ;"
163 }
164 }${componentName === "Hello" ?
165 `,
166
167 //${componentName.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase()}/42
168 function (${componentName[0].toLowerCase() + componentName.substring(1)}Id) {
169 // @summary: '@summary' and '@description' annotations will be used for generating OpenApi docs
170 // @description: Open http://localhost:7042/${componentName.toLowerCase()}/42 to see results
171
172 return ${componentName}Factory.new({
173 id: +${componentName.toLowerCase()}Id,
174 email: "my.name@example.com"
175 });
176 }`
177 :
178 ""}
179 ],
180
181 POST: [
182 //${componentName.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase()}
183 function (${componentName === "Hello" ? "id" : ""}) {
184 ${componentName === "Hello"? "// @path: custom\\/url\\/(\\d+)" : ""}
185
186 return ;
187 }
188 ],
189
190 PUT: [
191 //${componentName.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase()}/42
192 function (${componentName[0].toLowerCase() + componentName.substring(1)}Id) {
193
194 return ;
195 }
196 ],
197
198 DELETE: [
199 //${componentName.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase()}/42
200 function (${componentName[0].toLowerCase() + componentName.substring(1)}Id) {
201
202 return ;
203 }
204 ]
205
206};
207`;
208 fs.writeFileSync(path.resolve(componentPath, "controller.js"), controllerDeclaration, 'utf8');
209}
210
211function createFactoryDeclaration(componentName, componentPath) {
212 const factoriesDeclaration =
213 `const Property = require("@dominion-framework/dominion/core/property");
214
215
216module.exports = {
217
218 name: "${componentName}",
219
220 properties: {
221 id: Property.id(),
222 message: Property.string().required(),
223 guid: Property.string().example("123e4567-e89b-12d3-a456-426655440000"),
224 email: Property.string().example("my.name@example.com"),
225 state: Property.enum(["open", "close"]),
226 parentId: Property.model("${componentName}").private(),
227 creationTime: Property.date().private(),
228 modificationTime: Property.date().private()
229 },
230
231 factory: {
232
233 },
234
235 instance: {
236
237 }
238};
239`;
240 fs.writeFileSync(path.resolve(componentPath, "factory.js"), factoriesDeclaration, 'utf8');
241}
242
243function createFactoryDeclarationWithRepository(componentName, componentPath) {
244 const factoriesDeclaration =
245 `const Property = require("@dominion-framework/dominion/core/property");
246const ${componentName}Repository = require("./repository");
247
248
249module.exports = {
250
251 name: "${componentName}",
252
253 repository: ${componentName}Repository,
254
255 properties: {
256 id: Property.id(),
257 message: Property.string().required(),
258 guid: Property.string().example("123e4567-e89b-12d3-a456-426655440000"),
259 email: Property.string().example("my.name@example.com"),
260 state: Property.enum(["open", "close"]),
261 parentId: Property.model("${componentName}").private(),
262 creationTime: Property.date().private(),
263 modificationTime: Property.date().private()
264 },
265
266 factory: {
267
268 },
269
270 instance: {
271
272 }
273};
274`;
275 const repositoryDeclaration =
276 `const Repositories = require("@dominion-framework/repository-mysql");
277
278
279module.exports = Repositories.create('${componentName.toLowerCase()}_table_name', {
280
281});
282`;
283
284 fs.writeFileSync(path.resolve(componentPath, "factory.js"), factoriesDeclaration, 'utf8');
285 fs.writeFileSync(path.resolve(componentPath, "repository.js"), repositoryDeclaration, 'utf8');
286}
287
288function addComponentToProject(componentName, componentPath) {
289 if(!fs.existsSync(path.resolve("index.js"))) {
290 console.error("File `index.js` in project's root doesn't exist. Can't include created component.");
291 return;
292 }
293
294 const indexFile = fs.readFileSync(path.resolve("index.js")).toString().split("\n");
295 const position = indexFile.reverse().findIndex(line => line.indexOf("Server.addComponent") > -1);
296 indexFile.splice(position, 0, `Server.addComponent(require("./${componentPath}"));`);
297 fs.writeFileSync(path.resolve("index.js"), indexFile.reverse().join("\n"));
298}