create-moost 0.4.22 → 0.5.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/dist/index.cjs CHANGED
@@ -51,8 +51,6 @@ async function getPrompts(inputs) {
51
51
  targetDir: inputs.name || '',
52
52
  projectName: inputs.name || '',
53
53
  packageName: inputs.name || '',
54
- prettier: !!inputs.prettier,
55
- eslint: !!inputs.eslint,
56
54
  };
57
55
  try {
58
56
  const results = await prompts([
@@ -101,25 +99,6 @@ async function getPrompts(inputs) {
101
99
  { title: 'CLI Application', value: 'cli' },
102
100
  ],
103
101
  },
104
- {
105
- name: 'bundler',
106
- type: () => {
107
- if (inputs.esbuild && !inputs.rollup) {
108
- predefined.bundler = 'esbuild';
109
- return null;
110
- }
111
- if (!inputs.esbuild && inputs.rollup) {
112
- predefined.bundler = 'rollup';
113
- return null;
114
- }
115
- return 'select';
116
- },
117
- message: 'Bundler:',
118
- choices: [
119
- { title: 'Rollup (recommended)', value: 'rollup' },
120
- { title: 'ESBuild', value: 'esbuild' },
121
- ],
122
- },
123
102
  {
124
103
  name: 'packageName',
125
104
  type: () => (isValidPackageName(predefined.targetDir) ? null : 'text'),
@@ -128,22 +107,17 @@ async function getPrompts(inputs) {
128
107
  validate: (dir) => isValidPackageName(dir) || 'Invalid package.json name',
129
108
  },
130
109
  {
131
- name: 'eslint',
132
- type: () => (inputs.eslint ? null : 'toggle'),
133
- message: 'Add ESLint for code quality?',
110
+ name: 'wf',
111
+ type: () => (inputs.wf ? null : 'toggle'),
112
+ message: 'Add Moost Workflows Example?',
134
113
  initial: false,
135
114
  active: 'Yes',
136
115
  inactive: 'No',
137
116
  },
138
117
  {
139
- name: 'prettier',
140
- type: (prev, values) => {
141
- if (!values.eslint) {
142
- return null;
143
- }
144
- return 'toggle';
145
- },
146
- message: 'Add Prettier for code formatting?',
118
+ name: 'domelint',
119
+ type: () => (inputs.domelint ? null : 'toggle'),
120
+ message: 'Add do-me-lint (smart eslint installer)?',
147
121
  initial: false,
148
122
  active: 'Yes',
149
123
  inactive: 'No',
@@ -191,7 +165,7 @@ function toValidPackageName(projectName) {
191
165
 
192
166
  const rw = new rewrite.ProstoRewrite({
193
167
  textPattern: [
194
- '*.{js,jsx,ts,tsx,txt,json,yml,yaml,md,ini}',
168
+ '*.{js,jsx,ts,tsx,txt,json,jsonc,yml,yaml,md,ini,css,html}',
195
169
  'Dockerfile',
196
170
  '*config',
197
171
  '.gitignore',
@@ -214,19 +188,11 @@ async function scaffold(data) {
214
188
  }
215
189
  const templatePath = path.join(__dirname, '../templates', data.type);
216
190
  const commonPath = path.join(__dirname, '../templates/common');
191
+ const wfPath = path.join(__dirname, '../templates/wf');
217
192
  const context = { ...data, version };
218
193
  const excludeCommon = [];
219
- if (!data.eslint) {
220
- excludeCommon.push('.eslintrc.json');
221
- }
222
- if (!data.prettier) {
223
- excludeCommon.push('.prettierignore', '.prettierrc');
224
- }
225
- if (data.bundler !== 'rollup') {
226
- excludeCommon.push('rollup.config.js');
227
- }
228
- if (data.bundler !== 'esbuild') {
229
- excludeCommon.push('build.js');
194
+ if (!data.domelint) {
195
+ excludeCommon.push('.domelintrc.yml');
230
196
  }
231
197
  await rw.rewriteDir({
232
198
  baseDir: templatePath,
@@ -236,7 +202,19 @@ async function scaffold(data) {
236
202
  baseDir: commonPath,
237
203
  output: projectDir,
238
204
  exclude: excludeCommon,
205
+ renameFile(filename) {
206
+ if (filename.endsWith('.jsonc')) {
207
+ return filename.replace(/c$/, '');
208
+ }
209
+ return filename;
210
+ },
239
211
  }, context);
212
+ if (data.wf) {
213
+ await rw.rewriteDir({
214
+ baseDir: wfPath,
215
+ output: projectDir,
216
+ }, context);
217
+ }
240
218
  }
241
219
  function emptyDirectorySync(directory) {
242
220
  if (fs.existsSync(directory)) {
@@ -264,13 +242,11 @@ let CliController = class CliController extends moost.Moost {
264
242
  eventCli$1.useAutoHelp() && process.exit(0);
265
243
  const prompts = await getPrompts({
266
244
  name,
267
- eslint: !!eventCli$1.useCliOption('eslint'),
268
- prettier: !!eventCli$1.useCliOption('prettier'),
269
245
  http: !!eventCli$1.useCliOption('http'),
270
246
  cli: !!eventCli$1.useCliOption('cli'),
247
+ wf: !!eventCli$1.useCliOption('wf'),
248
+ domelint: !!eventCli$1.useCliOption('domelint'),
271
249
  force: !!eventCli$1.useCliOption('force'),
272
- esbuild: !!eventCli$1.useCliOption('esbuild'),
273
- rollup: !!eventCli$1.useCliOption('rollup'),
274
250
  });
275
251
  console.log('\nScaffolding a new project...');
276
252
  await scaffold(prompts);
@@ -321,11 +297,13 @@ function run() {
321
297
  globalCliOptions: [
322
298
  { keys: ['http'], description: 'Use Moost HTTP', type: Boolean },
323
299
  { keys: ['cli'], description: 'Use Moost CLI', type: Boolean },
324
- { keys: ['eslint'], description: 'Add ESLint', type: Boolean },
325
- { keys: ['prettier'], description: 'Add Prettier', type: Boolean },
300
+ { keys: ['wf'], description: 'Add Workflow Adapter', type: Boolean },
301
+ {
302
+ keys: ['domelint'],
303
+ description: 'Add do-me-lint (smart eslint installer)',
304
+ type: Boolean,
305
+ },
326
306
  { keys: ['force'], description: 'Force Overwrite', type: Boolean },
327
- { keys: ['esbuild'], description: 'Use esbuild for builds', type: Boolean },
328
- { keys: ['rollup'], description: 'Use rollup for builds', type: Boolean },
329
307
  ],
330
308
  }));
331
309
  void app.init();
package/dist/index.mjs CHANGED
@@ -49,8 +49,6 @@ async function getPrompts(inputs) {
49
49
  targetDir: inputs.name || '',
50
50
  projectName: inputs.name || '',
51
51
  packageName: inputs.name || '',
52
- prettier: !!inputs.prettier,
53
- eslint: !!inputs.eslint,
54
52
  };
55
53
  try {
56
54
  const results = await prompts([
@@ -99,25 +97,6 @@ async function getPrompts(inputs) {
99
97
  { title: 'CLI Application', value: 'cli' },
100
98
  ],
101
99
  },
102
- {
103
- name: 'bundler',
104
- type: () => {
105
- if (inputs.esbuild && !inputs.rollup) {
106
- predefined.bundler = 'esbuild';
107
- return null;
108
- }
109
- if (!inputs.esbuild && inputs.rollup) {
110
- predefined.bundler = 'rollup';
111
- return null;
112
- }
113
- return 'select';
114
- },
115
- message: 'Bundler:',
116
- choices: [
117
- { title: 'Rollup (recommended)', value: 'rollup' },
118
- { title: 'ESBuild', value: 'esbuild' },
119
- ],
120
- },
121
100
  {
122
101
  name: 'packageName',
123
102
  type: () => (isValidPackageName(predefined.targetDir) ? null : 'text'),
@@ -126,22 +105,17 @@ async function getPrompts(inputs) {
126
105
  validate: (dir) => isValidPackageName(dir) || 'Invalid package.json name',
127
106
  },
128
107
  {
129
- name: 'eslint',
130
- type: () => (inputs.eslint ? null : 'toggle'),
131
- message: 'Add ESLint for code quality?',
108
+ name: 'wf',
109
+ type: () => (inputs.wf ? null : 'toggle'),
110
+ message: 'Add Moost Workflows Example?',
132
111
  initial: false,
133
112
  active: 'Yes',
134
113
  inactive: 'No',
135
114
  },
136
115
  {
137
- name: 'prettier',
138
- type: (prev, values) => {
139
- if (!values.eslint) {
140
- return null;
141
- }
142
- return 'toggle';
143
- },
144
- message: 'Add Prettier for code formatting?',
116
+ name: 'domelint',
117
+ type: () => (inputs.domelint ? null : 'toggle'),
118
+ message: 'Add do-me-lint (smart eslint installer)?',
145
119
  initial: false,
146
120
  active: 'Yes',
147
121
  inactive: 'No',
@@ -189,7 +163,7 @@ function toValidPackageName(projectName) {
189
163
 
190
164
  const rw = new ProstoRewrite({
191
165
  textPattern: [
192
- '*.{js,jsx,ts,tsx,txt,json,yml,yaml,md,ini}',
166
+ '*.{js,jsx,ts,tsx,txt,json,jsonc,yml,yaml,md,ini,css,html}',
193
167
  'Dockerfile',
194
168
  '*config',
195
169
  '.gitignore',
@@ -212,19 +186,11 @@ async function scaffold(data) {
212
186
  }
213
187
  const templatePath = join(__dirname, '../templates', data.type);
214
188
  const commonPath = join(__dirname, '../templates/common');
189
+ const wfPath = join(__dirname, '../templates/wf');
215
190
  const context = { ...data, version };
216
191
  const excludeCommon = [];
217
- if (!data.eslint) {
218
- excludeCommon.push('.eslintrc.json');
219
- }
220
- if (!data.prettier) {
221
- excludeCommon.push('.prettierignore', '.prettierrc');
222
- }
223
- if (data.bundler !== 'rollup') {
224
- excludeCommon.push('rollup.config.js');
225
- }
226
- if (data.bundler !== 'esbuild') {
227
- excludeCommon.push('build.js');
192
+ if (!data.domelint) {
193
+ excludeCommon.push('.domelintrc.yml');
228
194
  }
229
195
  await rw.rewriteDir({
230
196
  baseDir: templatePath,
@@ -234,7 +200,19 @@ async function scaffold(data) {
234
200
  baseDir: commonPath,
235
201
  output: projectDir,
236
202
  exclude: excludeCommon,
203
+ renameFile(filename) {
204
+ if (filename.endsWith('.jsonc')) {
205
+ return filename.replace(/c$/, '');
206
+ }
207
+ return filename;
208
+ },
237
209
  }, context);
210
+ if (data.wf) {
211
+ await rw.rewriteDir({
212
+ baseDir: wfPath,
213
+ output: projectDir,
214
+ }, context);
215
+ }
238
216
  }
239
217
  function emptyDirectorySync(directory) {
240
218
  if (existsSync(directory)) {
@@ -262,13 +240,11 @@ let CliController = class CliController extends Moost {
262
240
  useAutoHelp() && process.exit(0);
263
241
  const prompts = await getPrompts({
264
242
  name,
265
- eslint: !!useCliOption('eslint'),
266
- prettier: !!useCliOption('prettier'),
267
243
  http: !!useCliOption('http'),
268
244
  cli: !!useCliOption('cli'),
245
+ wf: !!useCliOption('wf'),
246
+ domelint: !!useCliOption('domelint'),
269
247
  force: !!useCliOption('force'),
270
- esbuild: !!useCliOption('esbuild'),
271
- rollup: !!useCliOption('rollup'),
272
248
  });
273
249
  console.log('\nScaffolding a new project...');
274
250
  await scaffold(prompts);
@@ -319,11 +295,13 @@ function run() {
319
295
  globalCliOptions: [
320
296
  { keys: ['http'], description: 'Use Moost HTTP', type: Boolean },
321
297
  { keys: ['cli'], description: 'Use Moost CLI', type: Boolean },
322
- { keys: ['eslint'], description: 'Add ESLint', type: Boolean },
323
- { keys: ['prettier'], description: 'Add Prettier', type: Boolean },
298
+ { keys: ['wf'], description: 'Add Workflow Adapter', type: Boolean },
299
+ {
300
+ keys: ['domelint'],
301
+ description: 'Add do-me-lint (smart eslint installer)',
302
+ type: Boolean,
303
+ },
324
304
  { keys: ['force'], description: 'Force Overwrite', type: Boolean },
325
- { keys: ['esbuild'], description: 'Use esbuild for builds', type: Boolean },
326
- { keys: ['rollup'], description: 'Use rollup for builds', type: Boolean },
327
305
  ],
328
306
  }));
329
307
  void app.init();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-moost",
3
- "version": "0.4.22",
3
+ "version": "0.5.0",
4
4
  "description": "create-moost",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.mjs",
@@ -42,10 +42,10 @@
42
42
  },
43
43
  "homepage": "https://github.com/moostjs/moostjs/tree/main/packages/create-moost#readme",
44
44
  "dependencies": {
45
- "@moostjs/event-cli": "0.4.22",
46
- "@wooksjs/event-cli": "^0.5.16",
45
+ "@moostjs/event-cli": "0.5.0",
46
+ "@wooksjs/event-cli": "^0.5.18",
47
47
  "@prostojs/rewrite": "^0.1.1",
48
- "moost": "0.4.22",
48
+ "moost": "0.5.0",
49
49
  "prompts": "^2.4.2"
50
50
  }
51
51
  }
@@ -0,0 +1,14 @@
1
+ ignoredRules:
2
+ # for Moost controllers: they don't typically use 'this'
3
+ - '@typescript-eslint/class-methods-use-this'
4
+
5
+ # For Moost decorators: it's common to pull url route params from the url
6
+ - max-params
7
+
8
+ # Too strict, hinders readability
9
+ - '@typescript-eslint/strict-boolean-expressions'
10
+
11
+ # Empty class is a valid use case for Moost's controller composition
12
+ - '@typescript-eslint/no-extraneous-class'
13
+
14
+ - '@typescript-eslint/consistent-type-imports'
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "{{ packageName }}",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "main": "dist/main.js",
6
+ "type": "module",
7
+ "scripts": {
8
+ //=IF (domelint)
9
+ "postinstall": "npx do-me-lint",
10
+ //=END IF
11
+ "dev": "vite dev",
12
+ "build": "vite build",
13
+ "test": "echo \"Error: no test specified\" && exit 1"
14
+ },
15
+ "keywords": [],
16
+ "author": "",
17
+ "license": "ISC",
18
+ "dependencies": {
19
+ //=IF (type === 'http')
20
+ "@moostjs/event-http": "^{{ version }}",
21
+ //=END IF
22
+ //=IF (wf)
23
+ "@moostjs/event-wf": "^{{ version }}",
24
+ "@wooksjs/http-static": "^0.5.18",
25
+ //=END IF
26
+ //=IF (type === 'cli')
27
+ "@moostjs/event-cli": "^{{ version }}",
28
+ //=END IF
29
+ "moost": "^{{ version }}"
30
+ },
31
+ "devDependencies": {
32
+ "@moostjs/vite": "^{{ version }}",
33
+ "@types/node": "^22.10.2",
34
+ "typescript": "^5.7.2",
35
+ "unplugin-swc": "^1.5.1",
36
+ "vite": "^6.0.5"
37
+ }
38
+ }
@@ -1,15 +1,21 @@
1
1
  {
2
- "compilerOptions": {
3
- "outDir": "dist",
4
- "emitDecoratorMetadata": true,
5
- "experimentalDecorators": true,
6
- "esModuleInterop": true,
7
- "moduleResolution": "node",
8
- "lib": ["esnext"],
9
- "target": "ESNext",
10
- "downlevelIteration": true,
11
- "strict": true,
12
- "skipLibCheck": true
13
- },
14
- "include": ["src"]
2
+ "compilerOptions": {
3
+ "outDir": "dist",
4
+
5
+ "target": "ESNext",
6
+ "module": "ESNext",
7
+ "moduleResolution": "node",
8
+
9
+ "experimentalDecorators": true,
10
+ "emitDecoratorMetadata": true,
11
+
12
+ "strict": true,
13
+ "esModuleInterop": true,
14
+ "skipLibCheck": true,
15
+
16
+ "isolatedModules": true,
17
+ "useDefineForClassFields": true
18
+ },
19
+ "exclude": ["node_modules", "dist"],
20
+ "include": ["src"]
15
21
  }
@@ -0,0 +1,13 @@
1
+ import { defineConfig, type Plugin } from "vite";
2
+ import swc from 'unplugin-swc';
3
+ import { moostViteDev } from "@moostjs/vite";
4
+
5
+ export default defineConfig({
6
+ plugins: [
7
+ moostViteDev({
8
+ entry: "/src/main.ts",
9
+ }),
10
+ swc.vite(),
11
+ ],
12
+ });
13
+
@@ -1,10 +1,103 @@
1
- import { Get } from '@moostjs/event-http'
2
- import { Controller, Param } from 'moost'
1
+ /**
2
+ * @file Application Controller for Moost HTTP Template
3
+ *
4
+ * This file defines the `AppController` class, which handles HTTP routes within the
5
+ * Moost framework. The controller manages http endpoints.
6
+ *
7
+ * For more information on Moost HTTP, visit https://moost.org/webapp/
8
+ */
3
9
 
10
+ import { Body, Get, Post, SetHeader } from "@moostjs/event-http";
11
+ //=IF (wf)
12
+ import { MoostWf } from "@moostjs/event-wf";
13
+ import { serveFile } from "@wooksjs/http-static";
14
+ //=END IF
15
+ import { Controller, Param } from "moost";
16
+
17
+
18
+ //=IF (wf)
19
+ import type {
20
+ TWfExampleContext,
21
+ TWfExampleInput,
22
+ TWfExampleInputSchema,
23
+ TWfState,
24
+ } from "../workflow/wf.types";
25
+ import { Wf2HtmlPage } from "../workflow/wf2html.interceptor";
26
+ //=END IF
27
+
28
+ /**
29
+ * `AppController` manages the application's HTTP routes.
30
+ */
4
31
  @Controller()
5
32
  export class AppController {
6
- @Get('hello/:name')
7
- greet(@Param('name') name: string) {
8
- return `Hello, ${name}!`
33
+ //=IF (wf)
34
+ constructor(
35
+ private readonly wf: MoostWf<TWfExampleContext, TWfExampleInputSchema>
36
+ ) {}
37
+ //=END IF
38
+
39
+ /**
40
+ * Handles GET requests to the `/hello/:name` endpoint.
41
+ *
42
+ * Responds with a personalized greeting message.
43
+ *
44
+ * **Example:**
45
+ * - Request: `GET /hello/John`
46
+ * - Response: `Hello John`
47
+ *
48
+ * @param {string} name - The name parameter extracted from the URL.
49
+ * @returns {string} A greeting message.
50
+ */
51
+ @Get("hello/:name")
52
+ hello(@Param("name") name: string): string {
53
+ return `Hello ${name}`;
54
+ }
55
+
56
+ //=IF (wf)
57
+ /**
58
+ * Handles both GET and POST requests to the `/wf` endpoint.
59
+ *
60
+ * This endpoint is responsible for starting or resuming workflows based on the
61
+ * provided workflow state and user inputs. It utilizes the `Wf2HtmlPage` interceptor
62
+ * to convert workflow outputs into HTML pages with forms for user interaction.
63
+ *
64
+ * @param {TWfExampleInput | undefined} formInput - The input data from the request body.
65
+ * @returns {Promise<any>} The workflow's response, rendered as an HTML page.
66
+ */
67
+ @Get("wf")
68
+ @Post("wf")
69
+ @SetHeader("content-type", "text/html")
70
+ @Wf2HtmlPage()
71
+ async startWf(@Body() formInput?: TWfExampleInput) {
72
+ const { wfState, ...rest } = formInput || {};
73
+ const input = formInput ? rest : undefined;
74
+
75
+ if (typeof wfState === "object") {
76
+ // Resume an existing workflow with the provided state and input
77
+ return this.wf.resume<TWfExampleInput>(wfState as TWfState, input);
9
78
  }
79
+
80
+ // Start a new workflow with the provided input
81
+ return this.wf.start<TWfExampleInput>("wf-example", {}, input);
82
+ }
83
+
84
+ /**
85
+ * Serves static files from the `/static` directory.
86
+ *
87
+ * Handles GET requests to the `/static/*` endpoint by serving the requested file.
88
+ *
89
+ * **Example:**
90
+ * - Request: `GET /static/wf.css`
91
+ * - Response: Serves the `wf.css` file from the `./src/static/` directory.
92
+ *
93
+ * @param {string} filePath - The path to the static file requested.
94
+ * @returns {Promise<Buffer | string>} The contents of the requested static file.
95
+ */
96
+ @Get("static/*")
97
+ async serveStaticFile(@Param("*") filePath: string) {
98
+ return serveFile(`./src/static/${filePath}`, {
99
+ cacheControl: { maxAge: '1d' },
100
+ });
101
+ }
102
+ //=END IF
10
103
  }
@@ -1,16 +1,49 @@
1
- import { MoostHttp } from '@moostjs/event-http'
2
- import { Moost } from 'moost'
3
- import { AppController } from './controllers/app.controller'
1
+ /**
2
+ * @file Main Entry Point for Moost Application Template
3
+ *
4
+ * This file serves as the primary entry point for the Moost application.
5
+ *
6
+ * For more details on Moost Webapp and Moost Workflows, visit:
7
+ * - Moost Webapp: https://moost.org/webapp/
8
+ * - Moost Workflows: https://moost.org/wf/
9
+ */
4
10
 
5
- const app = new Moost()
11
+ import { MoostHttp } from "@moostjs/event-http";
12
+ //=IF (wf)
13
+ import { MoostWf } from "@moostjs/event-wf";
14
+ //=END IF
15
+ import { Moost } from "moost";
6
16
 
7
- void app.adapter(new MoostHttp()).listen(3000, () => {
8
- app.getLogger('{{ projectName }}').info('Up on port 3000')
9
- })
17
+ import { AppController } from "./controllers/app.controller";
18
+ //=IF (wf)
19
+ import { WfController } from "./workflow/wf.controller";
20
+ //=END IF
10
21
 
11
- void app
12
- .registerControllers(
13
- AppController
14
- // Add more controllers here...
15
- )
16
- .init()
22
+ /**
23
+ * Initializes and configures the Moost application.
24
+ *
25
+ * The application performs the following steps:
26
+ * 1. Creates a new instance of the Moost application.
27
+ * 2. Sets up the moost adapters.
28
+ * 3. Registers controllers.
29
+ * 4. Initializes the application to start handling incoming events.
30
+ */
31
+ const app = new Moost();
32
+
33
+ // Configure the HTTP adapter and start listening on port 3000
34
+ app.adapter(new MoostHttp()).listen(3000, () => {
35
+ app.getLogger("[{{ projectName }}]").info("Server started on port 3000");
36
+ });
37
+
38
+ //=IF (wf)
39
+ // Configure the Workflow adapter to handle workflow-related events
40
+ app.adapter(new MoostWf());
41
+ //=END IF
42
+
43
+ // Register application controllers
44
+ //=IF (wf)
45
+ app.registerControllers(AppController, WfController).init();
46
+ //=END IF
47
+ //=IF (!wf)
48
+ app.registerControllers(AppController).init();
49
+ //=END IF