@aerogel/cli 0.0.0-next.47ed8ee3c048720794026e45140e9b700cb428b9 → 0.0.0-next.926bde19326fe7b6b24b277666936862b64d8295
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/aerogel-cli.cjs.js +1 -1
- package/dist/aerogel-cli.esm.js +1 -1
- package/package.json +1 -1
- package/src/commands/create.ts +9 -8
- package/src/commands/generate-model.ts +9 -1
- package/src/lib/Log.mock.ts +11 -3
- package/src/lib/Log.test.ts +19 -3
- package/src/lib/Log.ts +31 -17
- package/src/testing/setup.ts +2 -0
- package/templates/app/package.json +1 -3
- package/templates/app/tailwind.config.js +1 -1
package/dist/aerogel-cli.cjs.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("commander"),t=require("@babel/runtime/helpers/defineProperty"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("commander"),t=require("@babel/runtime/helpers/defineProperty"),n=require("@noeldemartin/utils"),s=require("fs"),i=require("path");require("core-js/modules/esnext.async-iterator.for-each.js"),require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.for-each.js"),require("core-js/modules/esnext.async-iterator.find.js"),require("core-js/modules/esnext.iterator.find.js"),require("core-js/modules/esnext.async-iterator.map.js"),require("core-js/modules/esnext.iterator.map.js");var r=require("chalk"),o=require("readline");require("core-js/modules/esnext.async-iterator.reduce.js"),require("core-js/modules/esnext.iterator.reduce.js");var a=require("mustache"),c=require("child_process");function l(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var d=l(t);var u=n.facade(new class{contains(e,t){return!!this.read(e)?.includes(t)}exists(e){return s.existsSync(e)}read(e){return this.isFile(e)?s.readFileSync(e).toString():null}getFiles(e){const t=s.readdirSync(e,{withFileTypes:!0}),n=[];for(const s of t){const t=i.resolve(e,s.name);s.isDirectory()?n.push(...this.getFiles(t)):n.push(t)}return n}isDirectory(e){return this.exists(e)&&s.lstatSync(e).isDirectory()}isFile(e){return this.exists(e)&&s.lstatSync(e).isFile()}isEmptyDirectory(e){return!!this.isDirectory(e)&&0===this.getFiles(e).length}makeDirectory(e){s.mkdirSync(e,{recursive:!0})}write(e,t){s.existsSync(i.dirname(e))||s.mkdirSync(i.dirname(e),{recursive:!0}),s.writeFileSync(e,t)}});var m=n.facade(new class{constructor(){d.default(this,"renderInfo",r.hex("#00ffff")),d.default(this,"renderSuccess",r.hex("#00ff00")),d.default(this,"renderError",r.hex("#ff0000"))}async animate(e,t){var n=this;const s=function(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"";const s=n.renderInfo(n.renderMarkdown(e)+".".repeat(i%4))+t;n.stdout(s)};let i=0;s();const r=setInterval((()=>(i++,s())),1e3),o=await t();return clearInterval(r),s("\n"),o}info(e){this.log(this.renderMarkdown(e),this.renderInfo)}error(e){this.log(this.renderMarkdown(e),this.renderError)}fail(e){this.error(e),process.exit(1)}success(e){this.log(this.renderMarkdown(e),this.renderSuccess)}renderMarkdown(e){const t=n.stringMatchAll(e,/\*\*(.*)\*\*/g);for(const n of t)e=e.replace(n[0],r.bold(n[1]));return e}log(e,t){this.formatMessage(e).forEach((e=>{this.logLine(t?t(e):e)}))}formatMessage(e){if("\n"===e[0]){const t=(e=e.slice(1).trimEnd()).split("\n"),n=e.trim()[0]??"",s=t.find((e=>e.trim().length>0))?.indexOf(n)??0;return t.map((e=>e.slice(s)))}return[e]}logLine(e){console.log(e)}stdout(e){o.cursorTo(process.stdout,0),o.clearLine(process.stdout,0),process.stdout.write(e)}});class p{static instantiate(e,t,n){return new p(e).instantiate(t,n)}constructor(e){d.default(this,"path",void 0),this.path=e}instantiate(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const n=this.getFilenameReplacements(t),i=[];e=`${e}/`.replace(/\/\//,"/");for(const r of u.getFiles(this.path)){const o=Object.entries(n).reduce(((e,t)=>{let[n,s]=t;return e.replaceAll(n,s)}),r.substring(this.path.length+1)),c=s.readFileSync(r).toString(),l=e+(o.endsWith(".template")?o.slice(0,-9):o);u.write(l,a.render(c,t,void 0,["<%","%>"])),i.push(l)}return i}getFilenameReplacements(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";return Object.entries(e).reduce(((e,s)=>{let[i,r]=s;return"object"==typeof r?Object.assign(e,this.getFilenameReplacements(r,`${i}.`)):e[`[${t}${i}]`]=n.toString(r),e}),{})}}function h(e){return i.resolve(__dirname,"../",e)}class f{constructor(e){d.default(this,"name",void 0),this.name=e}create(e){!u.exists(e)||u.isDirectory(e)&&u.isEmptyDirectory(e)||m.fail(`Folder at '${e}' already exists!`),p.instantiate(h("templates/app"),e,{app:{name:this.name,slug:n.stringToSlug(this.name)}})}}class g{static define(e){var t=this;e=e.command(this.command).description(this.description);for(const[t,n]of this.parameters)e=e.argument(`<${t}>`,n);for(const[t,n]of Object.entries(this.options)){const s="string"==typeof n?n:n.description,i="string"==typeof n?"string":n.type??"string";e=e.option("boolean"===i?`--${t}`:`--${t} <${i}>`,s)}e=e.action((function(){for(var e=arguments.length,n=new Array(e),s=0;s<e;s++)n[s]=arguments[s];return t.run.call(t,...n)}))}static async run(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];const s=new this(...t);await s.run()}async run(){}assertAerogelOrDirectory(e){const t=u.read("package.json");if(t?.includes("@aerogel/core"))return;if(e&&u.isDirectory(e))return;const n=e?`${e} folder does not exist.`:"package.json does not contain @aerogel/core.";m.fail(`${n} Are you sure this is an Aerogel app?`)}}d.default(g,"command",""),d.default(g,"description",""),d.default(g,"parameters",[]),d.default(g,"options",{});var y=n.facade(new class{constructor(){d.default(this,"cwd",null)}setWorkingDirectory(e){this.cwd=e}async run(e){await new Promise(((t,n)=>{c.exec(e,{cwd:this.cwd??void 0},(e=>{e?n(e):t()}))}))}});class w extends g{constructor(e,t){super(),d.default(this,"path",void 0),d.default(this,"options",void 0),this.path=e,this.options=t}async run(){const e=this.path,t=this.options.name??"Aerogel App";y.setWorkingDirectory(e),await this.createApp(t,e),await this.installDependencies(),await this.initializeGit(),m.success(`\n\n That's it! You can start working on **${t}** doing the following:\n\n cd ${e}\n npm run dev\n\n Have fun!\n `)}async createApp(e,t){m.info(`Creating **${e}**...`),new f(e).create(t)}async installDependencies(){await m.animate("Installing dependencies",(async()=>{await y.run("npm install")}))}async initializeGit(){await m.animate("Initializing git",(async()=>{await y.run("git init"),await y.run("git add ."),await y.run('git commit -m "Start"')}))}}d.default(w,"command","create"),d.default(w,"description","Create AerogelJS app"),d.default(w,"parameters",[["path","Application path"]]),d.default(w,"options",{name:"Application name"});class v extends g{constructor(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};super(),d.default(this,"name",void 0),d.default(this,"options",void 0),this.name=e,this.options=t}async run(){this.assertAerogelOrDirectory("src/components"),this.options.story&&this.assertHistoireInstalled(),u.exists(`src/components/${this.name}.vue`)&&m.fail(`${this.name} component already exists!`);const e=p.instantiate(h("templates/component"),"src/components",{component:{name:this.name}});if(this.options.story){const t=p.instantiate(h("templates/component-story"),"src/components",{component:{name:this.name}});e.push(...t)}const t=e.map((e=>`- ${e}`)).join("\n");m.info(`${this.name} component created successfully! The following files were created:\n\n${t}`)}assertHistoireInstalled(){u.exists("src/main.histoire.ts")||m.fail("Histoire is not installed yet!")}}d.default(v,"command","generate:component"),d.default(v,"description","Generate an AerogelJS component"),d.default(v,"parameters",[["name","Component name"]]),d.default(v,"options",{story:{description:"Create component story using Histoire",type:"boolean"}});class x extends g{constructor(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};super(),d.default(this,"name",void 0),d.default(this,"options",void 0),this.name=e,this.options=t}async run(){this.assertAerogelOrDirectory("src/models"),u.exists(`src/models/${this.name}.ts`)&&m.fail(`${this.name} model already exists!`),this.assertSoukaiInstalled();const e=p.instantiate(h("templates/model"),"src/models",{model:{name:this.name,fieldsDefinition:this.getFieldsDefinition()},soukaiImports:this.options.fields?"FieldType, defineModelSchema":"defineModelSchema"}).map((e=>`- ${e}`)).join("\n");m.info(`${this.name} model created successfully! The following files were created:\n\n${e}`)}getFieldsDefinition(){if(!this.options.fields)return" //";return function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const n=e.split("\n"),s=t.indent??0;let i=0,r="";for(const e of n){const t=e.trim(),n=0===t.length;if(0===r.length){if(n)continue;i=e.indexOf(t[0]??""),r+=`${" ".repeat(s)}${t}\n`;continue}if(n){r+="\n";continue}const o=e.indexOf(t[0]??"");r+=`${" ".repeat(s+o-i)}${t}\n`}return r.trimEnd()}(this.options.fields.split(",").map((e=>{const[t,s]=e.split(":");return{name:t,type:n.stringToStudlyCase(s??"string")}})).reduce(((e,t)=>e+`\n${t.name}: FieldType.${t.type},`),""),{indent:8})}assertSoukaiInstalled(){u.contains("package.json",'"soukai"')||m.fail("\n Soukai is not installed yet! You can install it doing the following:\n\n 1. Run the following command:\n npm install soukai @aerogel/plugin-soukai\"\n\n 2. Add this to your plugins array:\n soukai({ models: import.meta.glob('@/models/*', { eager: true }) })\n ")}}d.default(x,"command","generate:model"),d.default(x,"description","Generate an AerogelJS model"),d.default(x,"parameters",[["name","Model name"]]),d.default(x,"options",{fields:"Create model with the given fields"});var j=n.facade(new class{run(t){const n=new e.Command;n.name("ag").description("AerogelJS CLI").version("0.0.0"),w.define(n),v.define(n),x.define(n),n.parse(t)}});exports.CLI=j;
|
|
2
2
|
//# sourceMappingURL=aerogel-cli.cjs.js.map
|
package/dist/aerogel-cli.esm.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{Command as e}from"commander";import t from"@babel/runtime/helpers/esm/defineProperty";import{facade as s,
|
|
1
|
+
import{Command as e}from"commander";import t from"@babel/runtime/helpers/esm/defineProperty";import{facade as s,stringMatchAll as n,toString as i,stringToSlug as r,stringToStudlyCase as o}from"@noeldemartin/utils";import{existsSync as a,readFileSync as c,readdirSync as l,lstatSync as m,mkdirSync as d,writeFileSync as p}from"fs";import{resolve as h,dirname as u}from"path";import"core-js/modules/esnext.async-iterator.for-each.js";import"core-js/modules/esnext.iterator.constructor.js";import"core-js/modules/esnext.iterator.for-each.js";import"core-js/modules/esnext.async-iterator.find.js";import"core-js/modules/esnext.iterator.find.js";import"core-js/modules/esnext.async-iterator.map.js";import"core-js/modules/esnext.iterator.map.js";import{hex as f,bold as g}from"chalk";import{cursorTo as y,clearLine as w}from"readline";import"core-js/modules/esnext.async-iterator.reduce.js";import"core-js/modules/esnext.iterator.reduce.js";import{render as v}from"mustache";import{exec as $}from"child_process";var j=s(new class{contains(e,t){return!!this.read(e)?.includes(t)}exists(e){return a(e)}read(e){return this.isFile(e)?c(e).toString():null}getFiles(e){const t=l(e,{withFileTypes:!0}),s=[];for(const n of t){const t=h(e,n.name);n.isDirectory()?s.push(...this.getFiles(t)):s.push(t)}return s}isDirectory(e){return this.exists(e)&&m(e).isDirectory()}isFile(e){return this.exists(e)&&m(e).isFile()}isEmptyDirectory(e){return!!this.isDirectory(e)&&0===this.getFiles(e).length}makeDirectory(e){d(e,{recursive:!0})}write(e,t){a(u(e))||d(u(e),{recursive:!0}),p(e,t)}});var x=s(new class{constructor(){t(this,"renderInfo",f("#00ffff")),t(this,"renderSuccess",f("#00ff00")),t(this,"renderError",f("#ff0000"))}async animate(e,t){var s=this;const n=function(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"";const n=s.renderInfo(s.renderMarkdown(e)+".".repeat(i%4))+t;s.stdout(n)};let i=0;n();const r=setInterval((()=>(i++,n())),1e3),o=await t();return clearInterval(r),n("\n"),o}info(e){this.log(this.renderMarkdown(e),this.renderInfo)}error(e){this.log(this.renderMarkdown(e),this.renderError)}fail(e){this.error(e),process.exit(1)}success(e){this.log(this.renderMarkdown(e),this.renderSuccess)}renderMarkdown(e){const t=n(e,/\*\*(.*)\*\*/g);for(const s of t)e=e.replace(s[0],g(s[1]));return e}log(e,t){this.formatMessage(e).forEach((e=>{this.logLine(t?t(e):e)}))}formatMessage(e){if("\n"===e[0]){const t=(e=e.slice(1).trimEnd()).split("\n"),s=e.trim()[0]??"",n=t.find((e=>e.trim().length>0))?.indexOf(s)??0;return t.map((e=>e.slice(n)))}return[e]}logLine(e){console.log(e)}stdout(e){y(process.stdout,0),w(process.stdout,0),process.stdout.write(e)}});class k{static instantiate(e,t,s){return new k(e).instantiate(t,s)}constructor(e){t(this,"path",void 0),this.path=e}instantiate(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const s=this.getFilenameReplacements(t),n=[];e=`${e}/`.replace(/\/\//,"/");for(const i of j.getFiles(this.path)){const r=Object.entries(s).reduce(((e,t)=>{let[s,n]=t;return e.replaceAll(s,n)}),i.substring(this.path.length+1)),o=c(i).toString(),a=e+(r.endsWith(".template")?r.slice(0,-9):r);j.write(a,v(o,t,void 0,["<%","%>"])),n.push(a)}return n}getFilenameReplacements(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";return Object.entries(e).reduce(((e,s)=>{let[n,r]=s;return"object"==typeof r?Object.assign(e,this.getFilenameReplacements(r,`${n}.`)):e[`[${t}${n}]`]=i(r),e}),{})}}function A(e){return h(__dirname,"../",e)}class D{constructor(e){t(this,"name",void 0),this.name=e}create(e){!j.exists(e)||j.isDirectory(e)&&j.isEmptyDirectory(e)||x.fail(`Folder at '${e}' already exists!`),k.instantiate(A("templates/app"),e,{app:{name:this.name,slug:r(this.name)}})}}class F{static define(e){var t=this;e=e.command(this.command).description(this.description);for(const[t,s]of this.parameters)e=e.argument(`<${t}>`,s);for(const[t,s]of Object.entries(this.options)){const n="string"==typeof s?s:s.description,i="string"==typeof s?"string":s.type??"string";e=e.option("boolean"===i?`--${t}`:`--${t} <${i}>`,n)}e=e.action((function(){for(var e=arguments.length,s=new Array(e),n=0;n<e;n++)s[n]=arguments[n];return t.run.call(t,...s)}))}static async run(){for(var e=arguments.length,t=new Array(e),s=0;s<e;s++)t[s]=arguments[s];const n=new this(...t);await n.run()}async run(){}assertAerogelOrDirectory(e){const t=j.read("package.json");if(t?.includes("@aerogel/core"))return;if(e&&j.isDirectory(e))return;const s=e?`${e} folder does not exist.`:"package.json does not contain @aerogel/core.";x.fail(`${s} Are you sure this is an Aerogel app?`)}}t(F,"command",""),t(F,"description",""),t(F,"parameters",[]),t(F,"options",{});var I=s(new class{constructor(){t(this,"cwd",null)}setWorkingDirectory(e){this.cwd=e}async run(e){await new Promise(((t,s)=>{$(e,{cwd:this.cwd??void 0},(e=>{e?s(e):t()}))}))}});class S extends F{constructor(e,s){super(),t(this,"path",void 0),t(this,"options",void 0),this.path=e,this.options=s}async run(){const e=this.path,t=this.options.name??"Aerogel App";I.setWorkingDirectory(e),await this.createApp(t,e),await this.installDependencies(),await this.initializeGit(),x.success(`\n\n That's it! You can start working on **${t}** doing the following:\n\n cd ${e}\n npm run dev\n\n Have fun!\n `)}async createApp(e,t){x.info(`Creating **${e}**...`),new D(e).create(t)}async installDependencies(){await x.animate("Installing dependencies",(async()=>{await I.run("npm install")}))}async initializeGit(){await x.animate("Initializing git",(async()=>{await I.run("git init"),await I.run("git add ."),await I.run('git commit -m "Start"')}))}}t(S,"command","create"),t(S,"description","Create AerogelJS app"),t(S,"parameters",[["path","Application path"]]),t(S,"options",{name:"Application name"});class b extends F{constructor(e){let s=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};super(),t(this,"name",void 0),t(this,"options",void 0),this.name=e,this.options=s}async run(){this.assertAerogelOrDirectory("src/components"),this.options.story&&this.assertHistoireInstalled(),j.exists(`src/components/${this.name}.vue`)&&x.fail(`${this.name} component already exists!`);const e=k.instantiate(A("templates/component"),"src/components",{component:{name:this.name}});if(this.options.story){const t=k.instantiate(A("templates/component-story"),"src/components",{component:{name:this.name}});e.push(...t)}const t=e.map((e=>`- ${e}`)).join("\n");x.info(`${this.name} component created successfully! The following files were created:\n\n${t}`)}assertHistoireInstalled(){j.exists("src/main.histoire.ts")||x.fail("Histoire is not installed yet!")}}t(b,"command","generate:component"),t(b,"description","Generate an AerogelJS component"),t(b,"parameters",[["name","Component name"]]),t(b,"options",{story:{description:"Create component story using Histoire",type:"boolean"}});class M extends F{constructor(e){let s=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};super(),t(this,"name",void 0),t(this,"options",void 0),this.name=e,this.options=s}async run(){this.assertAerogelOrDirectory("src/models"),j.exists(`src/models/${this.name}.ts`)&&x.fail(`${this.name} model already exists!`),this.assertSoukaiInstalled();const e=k.instantiate(A("templates/model"),"src/models",{model:{name:this.name,fieldsDefinition:this.getFieldsDefinition()},soukaiImports:this.options.fields?"FieldType, defineModelSchema":"defineModelSchema"}).map((e=>`- ${e}`)).join("\n");x.info(`${this.name} model created successfully! The following files were created:\n\n${e}`)}getFieldsDefinition(){if(!this.options.fields)return" //";return function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const s=e.split("\n"),n=t.indent??0;let i=0,r="";for(const e of s){const t=e.trim(),s=0===t.length;if(0===r.length){if(s)continue;i=e.indexOf(t[0]??""),r+=`${" ".repeat(n)}${t}\n`;continue}if(s){r+="\n";continue}const o=e.indexOf(t[0]??"");r+=`${" ".repeat(n+o-i)}${t}\n`}return r.trimEnd()}(this.options.fields.split(",").map((e=>{const[t,s]=e.split(":");return{name:t,type:o(s??"string")}})).reduce(((e,t)=>e+`\n${t.name}: FieldType.${t.type},`),""),{indent:8})}assertSoukaiInstalled(){j.contains("package.json",'"soukai"')||x.fail("\n Soukai is not installed yet! You can install it doing the following:\n\n 1. Run the following command:\n npm install soukai @aerogel/plugin-soukai\"\n\n 2. Add this to your plugins array:\n soukai({ models: import.meta.glob('@/models/*', { eager: true }) })\n ")}}t(M,"command","generate:model"),t(M,"description","Generate an AerogelJS model"),t(M,"parameters",[["name","Model name"]]),t(M,"options",{fields:"Create model with the given fields"});var O=s(new class{run(t){const s=new e;s.name("ag").description("AerogelJS CLI").version("0.0.0"),S.define(s),b.define(s),M.define(s),s.parse(t)}});export{O as CLI};
|
|
2
2
|
//# sourceMappingURL=aerogel-cli.esm.js.map
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aerogel/cli",
|
|
3
3
|
"description": "Aerogel CLI",
|
|
4
|
-
"version": "0.0.0-next.
|
|
4
|
+
"version": "0.0.0-next.926bde19326fe7b6b24b277666936862b64d8295",
|
|
5
5
|
"main": "dist/aerogel-cli.cjs.js",
|
|
6
6
|
"module": "dist/aerogel-cli.esm.js",
|
|
7
7
|
"types": "dist/aerogel-cli.d.ts",
|
package/src/commands/create.ts
CHANGED
|
@@ -36,14 +36,15 @@ export class CreateCommand extends Command {
|
|
|
36
36
|
await this.installDependencies();
|
|
37
37
|
await this.initializeGit();
|
|
38
38
|
|
|
39
|
-
Log.success(
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
39
|
+
Log.success(`
|
|
40
|
+
|
|
41
|
+
That's it! You can start working on **${name}** doing the following:
|
|
42
|
+
|
|
43
|
+
cd ${path}
|
|
44
|
+
npm run dev
|
|
45
|
+
|
|
46
|
+
Have fun!
|
|
47
|
+
`);
|
|
47
48
|
}
|
|
48
49
|
|
|
49
50
|
protected async createApp(name: string, path: string): Promise<void> {
|
|
@@ -74,7 +74,15 @@ export class GenerateModelCommand extends Command {
|
|
|
74
74
|
|
|
75
75
|
protected assertSoukaiInstalled(): void {
|
|
76
76
|
if (!File.contains('package.json', '"soukai"')) {
|
|
77
|
-
Log.fail(
|
|
77
|
+
Log.fail(`
|
|
78
|
+
Soukai is not installed yet! You can install it doing the following:
|
|
79
|
+
|
|
80
|
+
1. Run the following command:
|
|
81
|
+
npm install soukai @aerogel/plugin-soukai"
|
|
82
|
+
|
|
83
|
+
2. Add this to your plugins array:
|
|
84
|
+
soukai({ models: import.meta.glob('@/models/*', { eager: true }) })
|
|
85
|
+
`);
|
|
78
86
|
}
|
|
79
87
|
}
|
|
80
88
|
|
package/src/lib/Log.mock.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { expect } from 'vitest';
|
|
2
|
-
import {
|
|
2
|
+
import { facade } from '@noeldemartin/utils';
|
|
3
3
|
|
|
4
4
|
import { LogService } from './Log';
|
|
5
5
|
|
|
@@ -11,14 +11,22 @@ export class LogServiceMock extends LogService {
|
|
|
11
11
|
expect(this.logs, `Expected message "${message}" to have been logged`).toContain(message);
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
this.logs.
|
|
14
|
+
public expectLogLength(count: number): void {
|
|
15
|
+
expect(this.logs, `Expected log to have length ${count}`).toHaveLength(count);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
protected logLine(message: string): void {
|
|
19
|
+
this.logs.push(message);
|
|
16
20
|
}
|
|
17
21
|
|
|
18
22
|
public fail(message: string): void {
|
|
19
23
|
throw new Error(`Fail: ${message}`);
|
|
20
24
|
}
|
|
21
25
|
|
|
26
|
+
public reset(): void {
|
|
27
|
+
this.logs = [];
|
|
28
|
+
}
|
|
29
|
+
|
|
22
30
|
protected stdout(): void {
|
|
23
31
|
//
|
|
24
32
|
}
|
package/src/lib/Log.test.ts
CHANGED
|
@@ -5,12 +5,11 @@ import LogMock from '@/lib/Log.mock';
|
|
|
5
5
|
|
|
6
6
|
import Log from './Log';
|
|
7
7
|
|
|
8
|
+
const info = hex('#00ffff');
|
|
9
|
+
|
|
8
10
|
describe('Log', () => {
|
|
9
11
|
|
|
10
12
|
it('renders markdown bold', () => {
|
|
11
|
-
// Arrange
|
|
12
|
-
const info = hex('#00ffff');
|
|
13
|
-
|
|
14
13
|
// Act
|
|
15
14
|
Log.info('Foo **bar**');
|
|
16
15
|
|
|
@@ -18,4 +17,21 @@ describe('Log', () => {
|
|
|
18
17
|
LogMock.expectLogged(info(`Foo ${bold('bar')}`));
|
|
19
18
|
});
|
|
20
19
|
|
|
20
|
+
it('renders multiline messages', () => {
|
|
21
|
+
// Act
|
|
22
|
+
Log.info(`
|
|
23
|
+
This is multiline,
|
|
24
|
+
but the indentation should be respected.
|
|
25
|
+
|
|
26
|
+
As well as the new lines.
|
|
27
|
+
`);
|
|
28
|
+
|
|
29
|
+
// Assert
|
|
30
|
+
LogMock.expectLogLength(4);
|
|
31
|
+
LogMock.expectLogged(info('This is multiline,'));
|
|
32
|
+
LogMock.expectLogged(info(' but the indentation should be respected.'));
|
|
33
|
+
LogMock.expectLogged(info(''));
|
|
34
|
+
LogMock.expectLogged(info('As well as the new lines.'));
|
|
35
|
+
});
|
|
36
|
+
|
|
21
37
|
});
|
package/src/lib/Log.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { facade, stringMatchAll } from '@noeldemartin/utils';
|
|
2
2
|
import { bold, hex } from 'chalk';
|
|
3
3
|
import { clearLine, cursorTo } from 'readline';
|
|
4
4
|
|
|
@@ -28,28 +28,22 @@ export class LogService {
|
|
|
28
28
|
return result;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
public info(
|
|
32
|
-
|
|
33
|
-
this.log(this.renderInfo(this.renderMarkdown(message)));
|
|
34
|
-
});
|
|
31
|
+
public info(message: string): void {
|
|
32
|
+
this.log(this.renderMarkdown(message), this.renderInfo);
|
|
35
33
|
}
|
|
36
34
|
|
|
37
|
-
public error(
|
|
38
|
-
|
|
39
|
-
this.log(this.renderError(this.renderMarkdown(message)));
|
|
40
|
-
});
|
|
35
|
+
public error(message: string): void {
|
|
36
|
+
this.log(this.renderMarkdown(message), this.renderError);
|
|
41
37
|
}
|
|
42
38
|
|
|
43
|
-
public fail(
|
|
44
|
-
this.error(
|
|
39
|
+
public fail(message: string): void {
|
|
40
|
+
this.error(message);
|
|
45
41
|
|
|
46
42
|
process.exit(1);
|
|
47
43
|
}
|
|
48
44
|
|
|
49
|
-
public success(
|
|
50
|
-
|
|
51
|
-
this.log(this.renderSuccess(this.renderMarkdown(message)));
|
|
52
|
-
});
|
|
45
|
+
public success(message: string): void {
|
|
46
|
+
this.log(this.renderMarkdown(message), this.renderSuccess);
|
|
53
47
|
}
|
|
54
48
|
|
|
55
49
|
protected renderMarkdown(message: string): string {
|
|
@@ -62,9 +56,29 @@ export class LogService {
|
|
|
62
56
|
return message;
|
|
63
57
|
}
|
|
64
58
|
|
|
65
|
-
protected log(
|
|
59
|
+
protected log(message: string, formatMessage?: (message: string) => string): void {
|
|
60
|
+
this.formatMessage(message).forEach((line) => {
|
|
61
|
+
this.logLine(formatMessage ? formatMessage(line) : line);
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
protected formatMessage(message: string): string[] {
|
|
66
|
+
if (message[0] === '\n') {
|
|
67
|
+
message = message.slice(1).trimEnd();
|
|
68
|
+
|
|
69
|
+
const lines = message.split('\n');
|
|
70
|
+
const firstLetter = message.trim()[0] ?? '';
|
|
71
|
+
const indentation = lines.find((line) => line.trim().length > 0)?.indexOf(firstLetter) ?? 0;
|
|
72
|
+
|
|
73
|
+
return lines.map((line) => line.slice(indentation));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return [message];
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
protected logLine(line: string): void {
|
|
66
80
|
// eslint-disable-next-line no-console
|
|
67
|
-
|
|
81
|
+
console.log(line);
|
|
68
82
|
}
|
|
69
83
|
|
|
70
84
|
protected stdout(message: string): void {
|
package/src/testing/setup.ts
CHANGED
|
@@ -20,11 +20,9 @@
|
|
|
20
20
|
"@intlify/unplugin-vue-i18n": "^0.12.2",
|
|
21
21
|
"@tailwindcss/forms": "^0.5.3",
|
|
22
22
|
"@tailwindcss/typography": "^0.5.9",
|
|
23
|
-
"soukai": "^0.5.1",
|
|
24
23
|
"tailwindcss": "^3.3.2",
|
|
25
24
|
"vue": "^3.3.0",
|
|
26
|
-
"vue-i18n": "9.3.0-beta.19"
|
|
27
|
-
"vue-router": "^4.2.1"
|
|
25
|
+
"vue-i18n": "9.3.0-beta.19"
|
|
28
26
|
},
|
|
29
27
|
"devDependencies": {
|
|
30
28
|
"@aerogel/cli": "next",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** @type {import('tailwindcss').Config} */
|
|
2
2
|
module.exports = {
|
|
3
|
-
content: ['./index.html', './src/**/*.{vue,ts}', '
|
|
3
|
+
content: ['./index.html', './src/**/*.{vue,ts}', './node_modules/@aerogel/core/dist/**/*.js'],
|
|
4
4
|
plugins: [require('@tailwindcss/forms'), require('@tailwindcss/typography')],
|
|
5
5
|
};
|