@citruslime/create-boilerplate 1.6.0 → 2.0.0-beta.1

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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Citrus-Lime UI Library Create Boilerplate Script
2
2
 
3
- A create package script for initialising new Citrus-Lime web apps.
3
+ A create package script for initialising new apps with the Citrus-Lime default configuration.
4
4
 
5
5
  ![version](https://img.shields.io/npm/v/@citruslime/create-boilerplate/latest)
6
6
  ![version next](https://img.shields.io/npm/v/@citruslime/create-boilerplate/next)
@@ -10,7 +10,7 @@ A create package script for initialising new Citrus-Lime web apps.
10
10
  - 📌 [Citrus-Lime Ltd](https://www.citruslime.com)
11
11
 
12
12
 
13
- `npm init @citruslime/boilerplate TargetDirectory`
13
+ `pnpm create @citruslime/boilerplate TargetDirectory`
14
14
 
15
15
  or
16
16
 
@@ -18,7 +18,7 @@ or
18
18
 
19
19
  or
20
20
 
21
- `pnpm create @citruslime/boilerplate TargetDirectory`
21
+ `npm init @citruslime/boilerplate TargetDirectory`
22
22
 
23
23
  - **TargetDirectory**
24
24
  - A relative folder path for the script to create the boilerplate app
@@ -26,4 +26,4 @@ or
26
26
 
27
27
  e.g.
28
28
 
29
- `yarn create @citruslime/boilerplate ./ui/customer`
29
+ `pnpm create @citruslime/boilerplate ./ui/customer`
@@ -1,11 +1,8 @@
1
1
  #!/bin/sh
2
2
  . "$(dirname "$0")/_/husky.sh"
3
- . "$(dirname "$0")/common.sh"
4
3
 
5
- yarn_directory="$APPDATA\npm\node_modules\yarn\bin"
6
-
7
- if ! command -v "$yarn_directory\yarn" -v; then
8
- npm install --global yarn
4
+ if ! command -v pnpm; then
5
+ choco install pnpm -y
9
6
  fi
10
7
 
11
- "$yarn_directory\yarn" install --cwd "[[PACKAGE_DIR]]"
8
+ pnpm install -w -C "[[PACKAGE_DIR]]"
package/hooks/post-merge CHANGED
@@ -1,11 +1,8 @@
1
1
  #!/bin/sh
2
2
  . "$(dirname "$0")/_/husky.sh"
3
- . "$(dirname "$0")/common.sh"
4
3
 
5
- yarn_directory="$APPDATA\npm\node_modules\yarn\bin"
6
-
7
- if ! command -v "$yarn_directory\yarn" -v; then
8
- npm install --global yarn
4
+ if ! command -v pnpm; then
5
+ choco install pnpm -y
9
6
  fi
10
7
 
11
- "$yarn_directory\yarn" install --cwd "[[PACKAGE_DIR]]"
8
+ pnpm install -w -C "[[PACKAGE_DIR]]"
package/hooks/pre-commit CHANGED
@@ -1,11 +1,8 @@
1
1
  #!/bin/sh
2
2
  . "$(dirname "$0")/_/husky.sh"
3
- . "$(dirname "$0")/common.sh"
4
3
 
5
- yarn_directory="$APPDATA\npm\node_modules\yarn\bin"
6
-
7
- if ! command -v "$yarn_directory\yarn" -v; then
8
- npm install --global yarn
4
+ if ! command -v pnpm; then
5
+ choco install pnpm -y
9
6
  fi
10
7
 
11
- "$yarn_directory\yarn" --cwd "[[PACKAGE_DIR]]" pre-commit-lint
8
+ pnpm -C "[[PACKAGE_DIR]]" pre-commit-lint
@@ -1,11 +1,10 @@
1
1
  #!/usr/bin/env node
2
-
3
2
  import { execSync } from 'node:child_process';
4
3
  import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, statSync, writeFileSync } from 'node:fs';
5
4
  import { join, relative } from 'node:path';
6
5
  import { fileURLToPath, URL } from 'node:url';
7
6
 
8
- import { green, lightBlue, lightYellow, red } from 'kolorist';
7
+ import { green, lightBlue, red } from 'kolorist';
9
8
  import parseArgs from 'minimist';
10
9
  import prompts from 'prompts';
11
10
 
@@ -29,12 +28,11 @@ const filesToRename = {
29
28
  _gitattributes: '.gitattributes',
30
29
  _gitignore: '.gitignore',
31
30
  _editorconfig: '.editorconfig',
32
- _eslintignore: '.eslintignore',
33
- '_eslintrc.cjs': '.eslintrc.cjs',
34
- '_lintstagedrc.json': '.lintstagedrc.json',
31
+ '_lintstagedrc.js': '.lintstagedrc.js',
35
32
  _stylelintignore: '.stylelintignore',
36
- '_stylelintrc.cjs': '.stylelintrc.cjs',
37
- 'template.code-workspace': 'citrus-lime.code-workspace'
33
+ '_stylelint.config.js': 'stylelint.config.js',
34
+ 'template.code-workspace': 'citrus-lime.code-workspace',
35
+ _npmrc: '.npmrc'
38
36
  /* eslint-enable @typescript-eslint/naming-convention */
39
37
  };
40
38
 
@@ -42,6 +40,9 @@ const dependenciesToInstall = [
42
40
  {
43
41
  name: '@citruslime/ui'
44
42
  },
43
+ {
44
+ name: '@citruslime/utils'
45
+ },
45
46
  {
46
47
  name: '@vueuse/core'
47
48
  },
@@ -69,7 +70,11 @@ const dependenciesToInstall = [
69
70
  dev: true
70
71
  },
71
72
  {
72
- name: '@tsconfig/node18',
73
+ name: '@tsconfig/node20',
74
+ dev: true
75
+ },
76
+ {
77
+ name: '@types/jsdom',
73
78
  dev: true
74
79
  },
75
80
  {
@@ -153,17 +158,17 @@ async function init () {
153
158
  type: 'text',
154
159
  name: 'packageName',
155
160
  message: 'Enter a name for the project:',
156
- validate: (value) => /^(?:@[a-z0-9-*~][a-z0-9-*._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/.test(value) || 'Invalid package name'
161
+ validate: value => /^(?:@[a-z0-9-*~][a-z0-9-*._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/.test(value) || 'Invalid package name'
157
162
  },
158
163
  {
159
164
  type: packageDir ? null : 'text',
160
165
  name: 'packageDir',
161
166
  message: 'Enter a directory for the project:',
162
167
  initial: '.',
163
- onState: (state) => packageDir = state.value
168
+ onState: state => packageDir = state.value
164
169
  },
165
170
  {
166
- type: () => !existsSync(packageDir) || readdirSync(packageDir).length === 0 ? null : 'confirm',
171
+ type: () => directoryValid(packageDir) ? null : 'confirm',
167
172
  name: 'empty',
168
173
  message: () => `${packageDir === '.' ? 'Current directory' : `Target directory "${packageDir}"`} is not empty. Remove existing files and continue?`
169
174
  },
@@ -184,7 +189,7 @@ async function init () {
184
189
  initial: true
185
190
  },
186
191
  {
187
- type: (prev) => prev ? 'text' : null,
192
+ type: prev => prev ? 'text' : null,
188
193
  name: 'backendPort',
189
194
  message: 'Enter the port that the backend server runs on:',
190
195
  initial: 0
@@ -194,14 +199,14 @@ async function init () {
194
199
  name: 'packageManager',
195
200
  message: 'Select a package manager:',
196
201
  choices: [
197
- {
198
- title: 'yarn',
199
- value: 'yarn'
200
- },
201
202
  {
202
203
  title: 'pnpm',
203
204
  value: 'pnpm'
204
205
  },
206
+ {
207
+ title: 'yarn',
208
+ value: 'yarn'
209
+ },
205
210
  {
206
211
  title: 'npm',
207
212
  value: 'npm'
@@ -217,7 +222,7 @@ async function init () {
217
222
 
218
223
  packageDir = packageDir.toString();
219
224
 
220
- setReplacements(packageName, packageDir, rootDir, backendPort ?? 0);
225
+ setReplacements(packageName, packageDir, rootDir, backendPort ?? 0, packageManager);
221
226
  prepareDir(join(cwd, packageDir), empty);
222
227
  copyTemplate(packageDir);
223
228
 
@@ -230,6 +235,22 @@ async function init () {
230
235
  print(green(`Package ${packageName} has been successfully initialised in ${packageDir}.`), true);
231
236
  }
232
237
 
238
+ /**
239
+ * Checks if a directory is valid for project creation.
240
+ *
241
+ * @param {string} packageDir The directory of the package being created.
242
+ * @returns True, if the directory is valid; false, otherwise.
243
+ */
244
+ function directoryValid (packageDir) {
245
+ const directoryExists = existsSync(packageDir);
246
+ const directorySize = directoryExists ? readdirSync(packageDir).length : 0;
247
+ const directoryOnlyContainsGit = directorySize === 1 && existsSync(`${packageDir}/.git`);
248
+
249
+ return !directoryExists ||
250
+ directorySize === 0 ||
251
+ directoryOnlyContainsGit;
252
+ }
253
+
233
254
  /**
234
255
  * Set the dynamic values for the file renaming and placeholder replacements.
235
256
  *
@@ -237,8 +258,9 @@ async function init () {
237
258
  * @param {string} packageDir The directory of the package being created.
238
259
  * @param {string} rootDir The relative path of the root of the repository.
239
260
  * @param {number} backendPort The port that the backend server runs on.
261
+ * @param packageManager The selected package manager to use.
240
262
  */
241
- function setReplacements (packageName, packageDir, rootDir, backendPort) {
263
+ function setReplacements (packageName, packageDir, rootDir, backendPort, packageManager) {
242
264
  const husky = relative(join(cwd, packageDir, '.vscode'), join(rootDir, '.husky'));
243
265
  const repoRoot = relative(join(cwd, packageDir), rootDir);
244
266
  const projDir = relative(rootDir, join(cwd, packageDir));
@@ -249,6 +271,7 @@ function setReplacements (packageName, packageDir, rootDir, backendPort) {
249
271
  placeholdersToReplace['[[ROOT_DIR]]'] = repoRoot.replaceAll('\\', '/');
250
272
  placeholdersToReplace['[[HUSKY_DIR]]'] = husky.replaceAll('\\', '/');
251
273
  placeholdersToReplace['\'[[FRONTEND_PORT]]\''] = Math.floor(Math.random() * 1001) + 4000;
274
+ placeholdersToReplace['[[PACKAGE_MANAGER]]'] = packageManager;
252
275
 
253
276
  if (backendPort !== 0) {
254
277
  placeholdersToReplace['\'[[PROXY]]\''] = `{
@@ -276,7 +299,7 @@ function prepareDir (path, empty) {
276
299
 
277
300
  print(lightBlue('Emptying directory...'), true);
278
301
 
279
- forEachInDir(path, (item) => rmSync(join(path, item), options));
302
+ forEachInDir(path, item => rmSync(join(path, item), options));
280
303
  }
281
304
  else if (!existsSync(path)) {
282
305
  print(lightBlue('Creating directory...'), true);
@@ -293,7 +316,7 @@ function prepareDir (path, empty) {
293
316
  function copyTemplate (packageDir) {
294
317
  const templateDir = join(codeDir, 'template');
295
318
 
296
- forEachInDir(templateDir, (item) => copy(templateDir, packageDir, item));
319
+ forEachInDir(templateDir, item => copy(templateDir, packageDir, item));
297
320
  }
298
321
 
299
322
  /**
@@ -305,12 +328,7 @@ function copyHooks (rootDir) {
305
328
  const hooksDir = join(codeDir, 'hooks');
306
329
  const huskyDir = join(rootDir, '.husky');
307
330
 
308
- if (existsSync(join(huskyDir, 'common.sh'))) {
309
- print(lightYellow('Git Hooks already installed by another package in this repo. These will need to be edited manually.\n'), true);
310
- }
311
- else {
312
- forEachInDir(hooksDir, (item) => copy(hooksDir, huskyDir, item));
313
- }
331
+ forEachInDir(hooksDir, item => copy(hooksDir, huskyDir, item));
314
332
  }
315
333
 
316
334
  /**
@@ -329,7 +347,7 @@ function copy (source, destination, item) {
329
347
 
330
348
  mkdirSync(destinationDir, { recursive: true });
331
349
 
332
- forEachInDir(sourceItem, (item) => copy(sourceItem, destinationDir, item));
350
+ forEachInDir(sourceItem, item => copy(sourceItem, destinationDir, item));
333
351
  }
334
352
  else {
335
353
  const destinationFile = filesToRename[item] ? join(destination, filesToRename[item]) : join(destination, item);
@@ -369,19 +387,26 @@ function installDependencies (packageManager) {
369
387
  print(lightBlue('Installing dev dependencies...'), true);
370
388
 
371
389
  let devDependencies = '';
390
+
372
391
  for (const dependency of dependenciesToInstall.filter(d => d.dev)) {
373
392
  devDependencies += `${dependency.name}${dependency.next ? '@next' : '@latest'} `;
374
393
  }
375
394
 
395
+ execSync(`${prefix} -D ${devDependencies}`);
396
+
376
397
  print(lightBlue('Installing dependencies...'), true);
377
398
 
378
399
  let dependencies = '';
400
+
379
401
  for (const dependency of dependenciesToInstall.filter(d => !d.dev)) {
380
402
  dependencies += `${dependency.name}${dependency.next ? '@next' : '@latest'} `;
381
403
  }
382
404
 
383
- execSync(`${prefix} -D ${devDependencies}`);
384
405
  execSync(`${prefix} ${dependencies}`);
406
+
407
+ print(lightBlue('Running final install...'), true);
408
+
409
+ execSync(`${packageManager} install`);
385
410
  }
386
411
 
387
412
  /**
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@citruslime/create-boilerplate",
3
3
  "type": "module",
4
- "version": "1.6.0",
4
+ "version": "2.0.0-beta.1",
5
5
  "author": {
6
6
  "name": "Citrus-Lime Ltd",
7
7
  "url": "https://citruslime.com"
@@ -12,19 +12,22 @@
12
12
  "access": "public"
13
13
  },
14
14
  "files": [
15
- "main.mjs",
15
+ "main.js",
16
16
  "template",
17
17
  "hooks"
18
18
  ],
19
19
  "maintainers": [
20
20
  "Citrus-Lime"
21
21
  ],
22
- "main": "main.mjs",
22
+ "main": "main.js",
23
23
  "bin": {
24
- "create-boilerplate": "main.mjs"
24
+ "create-boilerplate": "main.js"
25
25
  },
26
26
  "engines": {
27
- "node": ">=16.0.0"
27
+ "node": ">=18.0.0"
28
+ },
29
+ "scripts": {
30
+ "lint": "eslint . --fix && stylelint **/*.{css,vue} --fix"
28
31
  },
29
32
  "dependencies": {
30
33
  "kolorist": "^1.7.0",
@@ -6,13 +6,14 @@
6
6
  "editor.defaultFormatter": "vscode.json-language-features"
7
7
  },
8
8
  "editor.codeActionsOnSave": {
9
- "source.fixAll": true,
10
- "source.fixAll.eslint": true,
11
- "source.fixAll.stylelint": true,
12
- "source.organizeImports": false
9
+ "source.fixAll": "explicit",
10
+ "source.fixAll.eslint": "explicit",
11
+ "source.fixAll.stylelint": "explicit",
12
+ "source.organizeImports": "never"
13
13
  },
14
14
  "editor.defaultFormatter": "dbaeumer.vscode-eslint",
15
15
  "editor.formatOnSave": true,
16
+ "eslint.experimental.useFlatConfig": true,
16
17
  "eslint.validate": [
17
18
  "html",
18
19
  "javascript",
@@ -17,13 +17,14 @@
17
17
  "editor.defaultFormatter": "vscode.json-language-features"
18
18
  },
19
19
  "editor.codeActionsOnSave": {
20
- "source.fixAll": true,
21
- "source.fixAll.eslint": true,
22
- "source.fixAll.stylelint": true,
23
- "source.organizeImports": false
20
+ "source.fixAll": "explicit",
21
+ "source.fixAll.eslint": "explicit",
22
+ "source.fixAll.stylelint": "explicit",
23
+ "source.organizeImports": "never"
24
24
  },
25
25
  "editor.defaultFormatter": "dbaeumer.vscode-eslint",
26
26
  "editor.formatOnSave": true,
27
+ "eslint.experimental.useFlatConfig": true,
27
28
  "eslint.validate": [
28
29
  "html",
29
30
  "javascript",
@@ -0,0 +1,5 @@
1
+ /* eslint-disable @typescript-eslint/naming-convention */
2
+ export default {
3
+ './**/*.+(js|cjs|mjs|ts|cts|mts|vue)': ['eslint --fix'],
4
+ './**/*.(css|vue)': ['stylelint --fix']
5
+ };
@@ -0,0 +1,3 @@
1
+ public-hoist-pattern[]=*eslint*
2
+ public-hoist-pattern[]=*stylelint*
3
+ public-hoist-pattern[]=*tailwindcss*
@@ -0,0 +1,4 @@
1
+ /** @type {import('stylelint').Config} */
2
+ export default {
3
+ extends: ['@citruslime/config/stylelint']
4
+ };
@@ -0,0 +1,21 @@
1
+ import config from '@citruslime/config/eslint';
2
+ import { FlatCompat } from '@eslint/eslintrc';
3
+
4
+ const compat = new FlatCompat({
5
+ baseDirectory: import.meta.url
6
+ });
7
+
8
+ export default [
9
+ ...config,
10
+ ...compat.extends('./.eslintrc-auto-import.json'),
11
+ {
12
+ ignores: [
13
+ 'dist',
14
+ 'node_modules',
15
+ '**/*.html',
16
+ 'auto-imports.d.ts',
17
+ 'components.d.ts',
18
+ 'typed-router.d.ts'
19
+ ]
20
+ }
21
+ ];
@@ -9,8 +9,8 @@
9
9
  "build-only": "vite build",
10
10
  "type-check": "vue-tsc --noEmit",
11
11
  "serve": "vite preview",
12
- "lint": "eslint . --ext .js,.cjs,.mjs,.ts,.vue --fix && stylelint **/*.{css,vue} --fix",
13
- "pre-commit-lint": "yarn lint-staged",
14
- "prepare": "cd [[ROOT_DIR]] && husky install"
12
+ "lint": "eslint . --fix && stylelint **/*.{css,vue} --fix",
13
+ "pre-commit-lint": "[[PACKAGE_MANAGER]] lint-staged",
14
+ "prepare": "cd [[ROOT_DIR]] && husky"
15
15
  }
16
16
  }
@@ -14,8 +14,8 @@
14
14
  ],
15
15
  "compilerOptions": {
16
16
  "composite": true,
17
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
17
18
  "baseUrl": ".",
18
- "moduleResolution": "node",
19
19
  "lib": [
20
20
  "ESNext",
21
21
  "DOM",
@@ -25,6 +25,9 @@
25
25
  "@/*": [
26
26
  "./src/*"
27
27
  ]
28
- }
28
+ },
29
+ "types": [
30
+ "unplugin-vue-router/client"
31
+ ]
29
32
  }
30
33
  }
@@ -1,5 +1,5 @@
1
1
  {
2
- "extends": "@tsconfig/node18/tsconfig.json",
2
+ "extends": "@tsconfig/node20/tsconfig.json",
3
3
  "include": [
4
4
  "vite.config.*",
5
5
  "vitest.config.*",
@@ -7,8 +7,9 @@
7
7
  ],
8
8
  "compilerOptions": {
9
9
  "composite": true,
10
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
10
11
  "module": "ESNext",
11
- "moduleResolution": "node",
12
+ "moduleResolution": "Bundler",
12
13
  "types": [
13
14
  "node"
14
15
  ]
@@ -6,7 +6,8 @@
6
6
  "lib": [],
7
7
  "types": [
8
8
  "node",
9
- "jsdom"
9
+ "jsdom",
10
+ "unplugin-vue-router/client"
10
11
  ]
11
12
  }
12
13
  }
@@ -69,7 +69,12 @@ export default defineConfig({
69
69
  output: {
70
70
  manualChunks (id) {
71
71
  if (id.includes('node_modules')) {
72
- return id.toString().split('node_modules/')[1].split('/')[0].toString();
72
+ if (id.includes('.pnpm')) {
73
+ return id.toString().split('node_modules/.pnpm')[1].split('/')[1].toString();
74
+ }
75
+ else {
76
+ return id.toString().split('node_modules/')[1].split('/')[0].toString();
77
+ }
73
78
  }
74
79
  }
75
80
  }
@@ -95,7 +100,6 @@ export default defineConfig({
95
100
  },
96
101
  server: {
97
102
  open: true,
98
- https: true,
99
103
  port: '[[FRONTEND_PORT]]',
100
104
  proxy: '[[PROXY]]'
101
105
  }
package/hooks/common.sh DELETED
@@ -1,7 +0,0 @@
1
- command_exists () {
2
- command -v "$1" >/dev/null 2>&1
3
- }
4
-
5
- if command_exists winpty && test -t 1; then
6
- exec < /dev/tty
7
- fi
@@ -1,6 +0,0 @@
1
- dist
2
- node_modules
3
- auto-imports.d.ts
4
- components.d.ts
5
- **/*.html
6
-
@@ -1,6 +0,0 @@
1
- module.exports = {
2
- extends: [
3
- require.resolve('@citruslime/config/eslint'),
4
- './.eslintrc-auto-import.json'
5
- ]
6
- };
@@ -1,8 +0,0 @@
1
- {
2
- "./**/*.+(js|cjs|mjs|ts|vue)": [
3
- "eslint --fix"
4
- ],
5
- "./**/*.(css|vue)": [
6
- "stylelint --fix"
7
- ]
8
- }
@@ -1,3 +0,0 @@
1
- module.exports = {
2
- extends: [require.resolve('@citruslime/config/stylelint')]
3
- };