vue-ninja 0.6.0 → 2.0.0-beta.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/vue-ninja.js +1 -1
- package/package.json +22 -23
- package/rolldown.config.ts +13 -0
package/dist/vue-ninja.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import
|
|
2
|
+
import{parseArgs as m}from"node:util";import{rimrafSync as b}from"rimraf";import v from"node:fs";import S from"node:fs/promises";import E from"crypto";import k from"child_process";import x from"util";import f from"prompt";import{glob as T}from"glob";import a from"chalk";import g from"axios";const L=x.promisify(k.exec),u=r=>S.readFile(r,"utf8"),l=r=>L(r,{maxBuffer:1024*1e3}),O=r=>new Promise((e,s)=>{f.start(),f.get(r,(o,c)=>{o?s():e(c)})}),A=r=>T(r,{nodir:!0,posix:!0}),F=r=>{process.exit(r)},j=r=>{const e=v.readFileSync(r),s=E.createHash("sha256");return s.update(e),s.digest("hex")},t={log:console.log,error:r=>console.log(a.red(r)),warn:r=>console.log(a.yellow(r)),success:r=>console.log(a.green(r)),debug:(r,e,s)=>{r.verbose&&(s?console.log(a.gray(e),a.gray(s)):console.log(a.gray(e)))}},C="results/vitest-results.json";function N(r){if(r.failed===void 0)return 0;const e=100-r.failed*5;return e>=0?e:0}function R(r){const e=N(r);t.warn("Unit tests score: "+e+"%"),t.warn("Looks like you have "+(r.failed?r.failed:"a few")+" unit test(s) failing."),t.warn("Launch `npm run test:unit` and try to fix them.")}function J(){t.error("Error while running unit tests."),t.error("Maybe your code doesn't compile?"),t.error("Launch `npm run test:unit` to see more.")}function P(r){const e=JSON.parse(r);if(!e)throw t.error("An error occurred during the unit tests."),t.error("Run `npm run test:unit` to see the problem."),new Error("Invalid test results");const o={failed:e.numFailedTests?e.numFailedTests:e.numFailedTestSuites,success:e.numPassedTests};return o.failed!==0?R(o):t.success("Unit tests score: 100%"),o}async function I(r){t.log("Starting unit tests...");try{await l("npm run test:unit:ci")}catch(e){t.debug(r,"Vitest test failed",e)}try{const e=await u(C);return P(e)}catch(e){throw t.debug(r,"An error occurred while reading vitest results: ",e),J(),e}}function U(r,e){return r.find(s=>s.name.includes(e))}function q(){return A("./{e2e,src}/**/*.ts")}function H(r){return r.map(e=>({name:e,hash:j(e)}))}function M(){return q().then(r=>H(r))}async function V(r){t.log("Checking submission...");let e;try{e=JSON.parse(await u("./exercise.json"))}catch(n){throw t.error("Looks like you have no exercise.json file."),t.debug(r,"An error occurred while reading exercise.json: ",n),new Error("No exercise.json file")}if(t.success(`Pack V${e.pack} - Exercise ${e.id} - ${e.title}`),r["skip-check"])return e;let s=[];try{s=await M()}catch(n){throw t.debug(r,"Error while computing the hash of the spec files. ",n),n}t.debug(r,"Exercise :",JSON.stringify(e)),t.debug(r,"Hashes :",JSON.stringify(s));const o=[],c=[];if(e.specs.forEach(n=>{const h=U(s,n.name);h?h.hash!==n.hash&&o.push(n.name):c.push(n.name)}),o.length!==0||c.length!==0)throw o.length!==0&&(t.error("It looks like you forgot to update these spec files"),t.error("or that you modified them manually:"),o.forEach(n=>t.error(` - ${n}`))),c.length!==0&&(t.error("It looks like you forgot to add these spec files:"),c.forEach(n=>t.error(` - ${n}`))),t.error("Copy the new specs and try again."),new Error("Specs are not up to date");return e}const _="coverage/coverage-summary.json";function B(r){const e=100+r.covered-r.total;return e<0?0:e}function W(r){const e=r.replace(/\\/g,"/"),s=JSON.parse(e),o={covered:s.total.lines.covered,total:s.total.lines.total},c=B(o);return c!==100?(t.warn("Code coverage score: "+c+"%"),t.warn("Looks like you don't have a perfect code coverage."),t.warn("Maybe you skipped/deleted some unit tests?"),t.warn("Or maybe you added some code to try something, and this is not covered by a unit test?"),t.warn("To have more info open `coverage/index.html`"),t.warn("You should see which file has a problem.")):t.success("Code coverage score: 100%"),o}async function $(r){t.log("Starting code coverage...");try{const e=await u(_);return W(e)}catch(e){throw t.error("Error while reading the code coverage results. Try to run `npm run test:unit`."),t.debug(r,"Error while reading the code coverage results was: ",e),e}}const p="results/lint-results.json";async function z(r){t.log("Starting code analysis...");try{await l(`npm run lint -- --no-fix --format=json --output-file=${p}`)}catch{}try{const e=await u(p),s=JSON.parse(e),o={errors:0};if(o.errors=s.map(c=>c.errorCount+c.warningCount).reduce((c,n)=>c+n,0),o.errors!==0){const c=Math.max(0,100-o.errors);t.warn("Code quality score: "+c+"%"),t.warn("Looks like you have some issues in your code."),t.warn("Try to run `npm run lint` to see what you can fix.")}else t.success("Code quality score: 100%");return o}catch(e){throw t.error("Error while running `npm run lint`."),t.error("Try to run `npm run lint`."),t.debug(r,"Error was: ",e),e}}const Y="results/playwright-results.json";function D(){t.error("Error while running end-to-end tests."),t.error("Check if your app is running with no error in the browser console,"),t.error("and try to launch the tests using `npm run test:e2e`.")}function G(r){const e=JSON.parse(r),s=e.stats.unexpected,o=e.stats.expected,c={success:o,failed:s};return s?(t.warn("Looks like you have "+s+" e2e tests failing."),t.warn("Try to launch the tests using `npm run test:e2e`."),t.warn(`E2e tests score: ${Math.round(o*100/(o+s))}%`)):t.success("E2e tests score: 100%"),c}async function K(r){t.log("Starting end to end tests...");try{await l("npm run test:e2e:ci")}catch(e){t.debug(r,"Error while running e2e tests: ",e)}try{const e=await u(Y);return G(e)}catch(e){throw t.debug(r,"Error while reading e2e results: ",e),D(),e}}const w="https://vue-exercises.ninja-squad.com",y="http://localhost:8080";function Q(r,e){return t.success("Authentication success"),r.token=e,r}async function d(r,e,s){if(e=e+1,e>3)return t.error("Aborting authentication after 3 failures"),Promise.reject();const o={properties:{email:{required:!0},password:{hidden:!0,required:!0}}};try{const c=await O(o),n=await g.post(`${r["local-server"]?y:w}/api/authentications`,c);return n.status!==201?(t.error("Authentication failed, try again."),t.debug(r,`Authentication request returned with status: ${n.status}`),d(r,e,s)):(t.debug(r,"Authentication succeeded and we can store credentials"),Q(s,n.data.token))}catch(c){return t.error("Authentication failed, try again."),t.debug(r,"An error occurred during authentication: ",c),d(r,e,s)}}function X(r,e){let s=100-r.vitest.failed*5-r.lint.errors-(r.coverage.total-r.coverage.covered)-r.e2e.failed;return s<10&&(s=10),e.local?(s!==100&&(t.error("Score is not perfect! "+s+"%"),F(1)),t.success("Exercise score: "+s+"%")):s!==100?t.warn("Score is not perfect yet: "+s+"%"):t.success("Perfect score, congrats! "+s+"%"),s}async function Z(r,e){const s={Authorization:`Bearer: ${e.token}`},o=r["local-server"]?y:w,c={score:e.score};try{const n=await g.post(`${o}/api/packs/${e.pack}/exercises/${e.id}/scores`,c,{headers:s});return n.status!==201?(t.error("Error while sending the results."),t.debug(r,`${n.status}`,JSON.stringify(n.data)),Promise.reject()):(t.log("Score submitted."),e)}catch(n){throw t.error("Error while sending the results."),t.error("Maybe check your connection?"),t.debug(r,"Error while sending the result was: ",n),n}}async function ee(r,e){let s;try{s=JSON.parse(await u("./exercise.json"))}catch(n){throw t.error("Looks like you have no exercise.json file."),t.debug(e,"An error occurred while reading exercise.json: ",n),n}if(s.score=X(r,e),e.local)return s;const c=await d(e,0,s);return Z(e,c)}const re=process.argv.slice(2),te={local:{type:"boolean"},"local-server":{type:"boolean"},verbose:{type:"boolean"},"skip-check":{type:"boolean"}},{values:i}=m({args:re,parseArgsOptions:te,strict:!1});b("results");try{const r=await V(i);t.debug(i,"Exercise: ",r.title);const e=await I(i);t.debug(i,"Vitest results: ",JSON.stringify(e));const s=await $(i);t.debug(i,"Coverage results: ",JSON.stringify(s));const o=await z(i);t.debug(i,"Linter results: ",JSON.stringify(o));const c=await K(i);t.debug(i,"E2e results: ",JSON.stringify(c)),await ee({exercise:r,vitest:e,coverage:s,lint:o,e2e:c},i)}catch(r){t.error("Try to fix it and retry!"),i.verbose&&t.error(r),i.local&&(t.error("Running locally, we exit"),process.exit(1))}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vue-ninja",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "2.0.0-beta.0",
|
|
4
4
|
"description": "CLI for the exercises of \"Become a ninja with Vue\"",
|
|
5
5
|
"main": "dist/vue-ninja.js",
|
|
6
6
|
"exports": null,
|
|
@@ -8,31 +8,30 @@
|
|
|
8
8
|
"author": "",
|
|
9
9
|
"license": "ISC",
|
|
10
10
|
"dependencies": {
|
|
11
|
-
"axios": "1.
|
|
12
|
-
"chalk": "5.
|
|
13
|
-
"
|
|
14
|
-
"glob": "10.3.10",
|
|
11
|
+
"axios": "1.8.4",
|
|
12
|
+
"chalk": "5.4.1",
|
|
13
|
+
"glob": "11.0.1",
|
|
15
14
|
"prompt": "1.3.0",
|
|
16
|
-
"rimraf": "
|
|
15
|
+
"rimraf": "6.0.1"
|
|
17
16
|
},
|
|
18
17
|
"devDependencies": {
|
|
19
|
-
"@
|
|
20
|
-
"@
|
|
21
|
-
"@types/
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"@typescript-eslint/eslint-plugin": "6.16.0",
|
|
25
|
-
"@typescript-eslint/parser": "6.16.0",
|
|
26
|
-
"create-vue": "3.9.1",
|
|
27
|
-
"eslint": "8.56.0",
|
|
18
|
+
"@eslint/js": "9.24.0",
|
|
19
|
+
"@types/node": "22.14.1",
|
|
20
|
+
"@types/prompt": "1.1.9",
|
|
21
|
+
"create-vue": "3.16.4",
|
|
22
|
+
"eslint": "9.24.0",
|
|
28
23
|
"eslint-config-prettier": "9.1.0",
|
|
29
|
-
"eslint-plugin-
|
|
30
|
-
"prettier": "
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
24
|
+
"eslint-plugin-import": "2.31.0",
|
|
25
|
+
"eslint-plugin-prettier": "5.2.6",
|
|
26
|
+
"jiti": "2.4.2",
|
|
27
|
+
"prettier": "3.5.3",
|
|
28
|
+
"rolldown": "1.0.0-beta.7",
|
|
29
|
+
"rollup-plugin-esbuild": "6.2.1",
|
|
30
|
+
"tslib": "2.8.1",
|
|
31
|
+
"typescript": "5.8.3",
|
|
32
|
+
"typescript-eslint": "8.29.1",
|
|
33
|
+
"vite": "6.2.6",
|
|
34
|
+
"vitest": "3.1.1"
|
|
36
35
|
},
|
|
37
36
|
"bin": {
|
|
38
37
|
"vue-ninja": "dist/vue-ninja.js"
|
|
@@ -44,7 +43,7 @@
|
|
|
44
43
|
"trailingComma": "none"
|
|
45
44
|
},
|
|
46
45
|
"scripts": {
|
|
47
|
-
"build": "
|
|
46
|
+
"build": "rolldown --config rolldown.config.ts",
|
|
48
47
|
"test": "vitest",
|
|
49
48
|
"lint": "eslint {src,tests}/**/* --ext .ts",
|
|
50
49
|
"type-check": "tsc --noEmit"
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { defineConfig, RolldownPluginOption } from 'rolldown'
|
|
2
|
+
import { minify } from 'rollup-plugin-esbuild'
|
|
3
|
+
|
|
4
|
+
export default defineConfig({
|
|
5
|
+
platform: 'node',
|
|
6
|
+
input: 'src/vue-ninja.ts',
|
|
7
|
+
output: {
|
|
8
|
+
file: 'dist/vue-ninja.js',
|
|
9
|
+
format: 'esm'
|
|
10
|
+
},
|
|
11
|
+
plugins: [minify() as RolldownPluginOption],
|
|
12
|
+
external: ['node:util', 'rimraf', 'axios', 'chalk', 'prompt', 'glob', 'fs', 'crypto', 'child_process', 'util']
|
|
13
|
+
});
|