@overlayed/cli 0.6.2 → 0.6.3

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.
Files changed (2) hide show
  1. package/dist/cli.js +1 -1
  2. package/package.json +14 -14
package/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import{Builtins as e,Cli as t,Command as n,UsageError as r}from"clipanion";import{scope as i,type as a}from"arktype";import o,{createWriteStream as ee,existsSync as te,mkdirSync as ne,readdirSync as re,unlinkSync as ie,writeFileSync as s}from"fs";import{ensureDirSync as c,ensureFileSync as l}from"fs-extra";import u,{join as ae}from"path";import d from"node:path";import f from"chalk";import oe,{createReadStream as se,existsSync as p,lstatSync as ce,readFileSync as le}from"node:fs";import{glob as m}from"glob";import ue,{fileURLToPath as de}from"node:url";import{createJiti as fe}from"jiti";import{readdir as h}from"node:fs/promises";import g from"jszip";import _,{isXiorError as v}from"xior";import{checkbox as y,password as b}from"@inquirer/prompts";import{Listr as x}from"listr2";import{ListrInquirerPromptAdapter as S}from"@listr2/prompt-adapter-inquirer";import{exec as C}from"child_process";import{promisify as w}from"util";import T from"update-notifier";const E={deployment:`deployment`};function D(e){throw e}function O(e){return Object.prototype.toString.call(e)===`[object Object]`}function k(e){return e?Array.isArray(e)?e:[e]:[]}function A(e){return{all:e||=new Map,on:function(t,n){var r=e.get(t);r?r.push(n):e.set(t,[n])},off:function(t,n){var r=e.get(t);r&&(n?r.splice(r.indexOf(n)>>>0,1):e.set(t,[]))},emit:function(t,n){var r=e.get(t);r&&r.slice().map(function(e){e(n)}),(r=e.get(`*`))&&r.slice().map(function(e){e(t,n)})}}}var j=class{emitter;constructor(){this.emitter=A()}on(e,t){k(e).forEach(e=>{this.emitter.on(e,t)})}off(e,t){k(e).forEach(e=>{this.emitter.off(e,t)})}emit(e,t){k(e).forEach(e=>{this.emitter.emit(e,t)})}removeAllListeners(){this.emitter.all.clear()}};function M(e,...t){return class extends e{static _instance;static getInstance(){return this._instance||=new e(...t),this._instance}static clearInstance(){this._instance=void 0}}}const N=M(class extends j{destroy(){this.removeAllListeners()}fatal(e,t,n){this.emit(`fatal`,{code:t,message:e,data:n,timestamp:Date.now()})}error(e,t,n){this.emit(`error`,{code:t,message:e,data:n,timestamp:Date.now()})}warn(e,t,n){this.emit(`warning`,{code:t,message:e,data:n,timestamp:Date.now()})}});var P=class{data;_schema;_defaultValue;_path;constructor(e){let{schema:t,default:n,path:r}=e;this._schema=t,this._defaultValue=n,this._path=r}set(e){let t=this._schema[`~standard`].validate(e);if(t instanceof Promise)throw Error(`StructuredConfigFile does not support async validation`);if(t.issues){this.reportInvalidConfigFile(t.issues);return}this.data=this.onBeforeSave(e),this.save(e)}get(){return this.data?this.data:this.load()}getKey(e){return this.get()[e]}save(e){let t=this.onBeforeSave(e);try{l(this.getFilePath()),o.writeFileSync(this.getFilePath(),JSON.stringify(t,void 0,2))}catch{return}return this.data=t}load(){if(!this.fileExists(this.getFilePath())||!this.canReadWriteFile(this.getFilePath())){this.save(this._defaultValue);let e=this.onAfterLoad(this._defaultValue);return this.data=e,e}try{let e=o.readFileSync(this.getFilePath(),`utf8`),t=this.onAfterLoad(this.parseStoredData(e));return this.data=t,t}catch{return this.data=this._defaultValue}}onBeforeSave(e){return e}onAfterLoad(e){return e}getFilePath(){return this._path}parseStoredData(e){try{let t=a(`string.json.parse`).to(`object`)(e);if(t instanceof a.errors)return this._defaultValue;let n=this._schema[`~standard`].validate(t);if(n instanceof Promise)throw Error(`StructuredConfigFile does not support async validation`);return n.issues?this.migrate(t,this._defaultValue):this.migrate(n.value,this._defaultValue)}catch{return this._defaultValue}}canReadWriteFile(e){try{return o.accessSync(e,o.constants.R_OK|o.constants.W_OK),!0}catch{return!1}}fileExists(e){try{return o.accessSync(e,o.constants.F_OK),!0}catch{return!1}}migrate(e,t){let n={...e};for(let r in t){if(!Object.prototype.hasOwnProperty.call(t,r))continue;r in e?e[r]!==null&&t[r]!==null&&typeof e[r]==`object`&&typeof t[r]==`object`&&!Array.isArray(e[r])&&!Array.isArray(t[r])?n[r]=this.migrate(e[r],t[r]):Array.isArray(t[r])&&(n[r]=e[r]):n[r]=t[r]}return n}reportInvalidConfigFile(e){N.getInstance().error(`Invalid config file`,`INVALID_CONFIG_FILE`,{issues:e.map(e=>e.message),filePath:this._path,data:this.data})}};const F=`**/overlayed.config.{js,ts,mts}`;async function I(){let e=R(),t=fe(import.meta.url);return(await Promise.all(e.map(async e=>e.endsWith(`.ts`)?[await t.import(e,{default:!0}),e]:[(await import(ue.pathToFileURL(e).toString())).default,e]))).filter(([e])=>L(e)).map(([e,t])=>[e,t])}function L(e){return O(e)&&`app`in e}function R(){return m.globSync(F,{absolute:!0,cwd:process.cwd()})}var z=class{pattern;options;constructor(e,t){this.pattern=e,this.options=t}},B=class{defaultIgnore=[`overlayed.config.ts`];patterns=[];constructor(e){this.config=e}addGlobPattern(e,t){let n=this.resolveOptions(t),r=k(e);this.patterns.push(new z(r,n))}async bundle(){let e=new g;for(let t of this.patterns){let n={...t.options},r;r=n.cwd?typeof n.cwd==`string`?n.cwd:de(n.cwd):process.cwd(),d.isAbsolute(r)||(r=d.resolve(r)),n.absolute=!0,n.cwd=r;let i=await m(t.pattern,n),a=await this.getFilesPathsFromPaths(i);await Promise.all(a.map(async t=>{await this.zipFile(r,e,t)}))}return e}async validateFilePath(e){return Promise.resolve(!0)}async zipFile(e,t,n){let r=d.relative(e,n);if(r=r.replace(/^(\.\.\\|\.\.\/)+/,``),!p(n)){t.file(r,``,{compression:`DEFLATE`});return}if(!await this.validateFilePath(n))return;let i=se(n,`binary`);t.file(r,i,{compression:`DEFLATE`})}resolveOptions(e){return{...e,ignore:[...k(e?.ignore),...this.defaultIgnore]}}async getFilesPathsFromPaths(e){return Promise.all(e.map(async e=>await this.getFilePathsFromPathRecursive(e))).then(e=>e.flat())}async getFilePathsFromPathRecursive(e){if(!p(e)||!ce(e).isDirectory())return[e];let t=await h(e,{withFileTypes:!0});return(await Promise.all(t.map(async t=>{let n=d.join(e,t.name);return t.isDirectory()?await this.getFilePathsFromPathRecursive(n):[n]}))).flat()}},V=class extends B{defaultIgnore=[`overlayed.config.ts`,`**/installer/**`];mainFile;constructor(e){super(e),this.addGlobPattern(`package.json`)}async bundle(){let e=await super.bundle();return await this.validateZip(e),e}async validateFilePath(e){return e.endsWith(`package.json`)&&!e.includes(`node_modules`)&&await this.validatePackageJson(e),!0}async validateZip(e){await Promise.all([this.validateNoInstallFolder(e),this.validateMainFile(e)])}async validatePackageJson(e){if(!e)throw new H;let t=oe.readFileSync(e,`utf-8`),n=a(`string.json.parse`).to({main:`string`,devDependencies:{"@overlayed/electron":`string`}})(t);if(n instanceof a.errors)throw new pe(n.summary);this.mainFile=n.main}async validateMainFile(e){if(!this.mainFile)throw new H;if(!e.file(u.normalize(this.mainFile)))throw new U(this.mainFile)}async validateNoInstallFolder(e){let t=e.folder(`install`);if(t&&t.length>0)throw new W}},H=class extends Error{constructor(){super(`package.json not found in bundle`),this.name=`PackageJsonNotFoundError`}},pe=class extends Error{constructor(e){super(`package.json is invalid: ${e}`),this.name=`PackageJsonInvalidError`}},U=class extends Error{constructor(e){super(`referenced package.json main file ${e} not found in bundle`),this.name=`MainFileNotFoundError`}},W=class extends Error{constructor(){super("folder `install` found in bundle is not allowed and is reserved for the installer"),this.name=`InstallFolderFoundError`}};_.create({baseURL:`https://updater.stats.cc`,headers:{Accept:`application/json`,"Accept-Encoding":`gzip, deflate, br`}}).interceptors.request.use(e=>e);const G=_.create({baseURL:`https://api.overlayed.gg`,headers:{Accept:`application/json`,"Accept-Encoding":`gzip, deflate, br`}});let K;function q(e){K=e}G.interceptors.request.use(e=>{let t=K?.();return e.headers??={},t&&(e.headers[`X-Api-Key`]=t),e});function me(e){return e}function he(e){return e?t=>(e(t),t):me}function ge(e,t){return G.post(`/v1/applications/${e}/bundles/tasks/upload`,t)}function _e(e,t){return G.post(`/v1/applications/${e}/bundles/tasks/queue`,{name:t})}function ve(e,t){return G.get(`/v1/applications/${e}/bundles/tasks/${t}`)}function ye(e,t){return G.put(e.url,t,{headers:{...e.headers,"Content-Length":t.length}})}const be=he();function J(){return G.get(`/v1/auth/me`)}const xe=u.normalize(`${process.env.APPDATA||process.env.HOME||`.`}/.overlayed/config.json`),Se=i({Account:a({email:`string`,apiKey:`string`})}).type({currentAccount:`Account | undefined`,accounts:`Account[]`}).or(`undefined`),Y=new P({path:xe,default:void 0,schema:Se});async function X(){if(!Y.get()?.currentAccount)throw new r(`Not authenticated. Run 'overlayed login' to authenticate.`);try{return(await J()).data.email}catch(e){if(!v(e))throw e;switch(e.response?.status){case 401:case 403:throw new r(`Authentication failed. Your API key may be invalid or expired. Run 'overlayed login' to re-authenticate.`);default:throw Error(`API error occurred. Please try again later.`)}}}async function Ce(e){let t=await I();if(t.length===0)throw new r(`No config file found matching `+F);return t.length>1&&e.stdout.write(f.yellow(`
2
+ import{Builtins as e,Cli as t,Command as n,UsageError as r}from"clipanion";import{scope as i,type as a}from"arktype";import o,{createWriteStream as ee,existsSync as te,mkdirSync as ne,readdirSync as re,unlinkSync as ie,writeFileSync as s}from"fs";import{ensureDirSync as c,ensureFileSync as l}from"fs-extra";import u,{join as ae}from"path";import d from"node:path";import f from"chalk";import oe,{createReadStream as se,existsSync as p,lstatSync as ce,readFileSync as le}from"node:fs";import{glob as m}from"glob";import ue,{fileURLToPath as de}from"node:url";import{createJiti as fe}from"jiti";import{readdir as h}from"node:fs/promises";import g from"jszip";import _,{isXiorError as v}from"xior";import{checkbox as y,password as b}from"@inquirer/prompts";import{Listr as x}from"listr2";import{ListrInquirerPromptAdapter as S}from"@listr2/prompt-adapter-inquirer";import{exec as C}from"child_process";import{promisify as w}from"util";import T from"update-notifier";const E={deployment:`deployment`};function D(e){throw e}function O(e){return Object.prototype.toString.call(e)===`[object Object]`}function k(e){return e?Array.isArray(e)?e:[e]:[]}function A(e){return{all:e||=new Map,on:function(t,n){var r=e.get(t);r?r.push(n):e.set(t,[n])},off:function(t,n){var r=e.get(t);r&&(n?r.splice(r.indexOf(n)>>>0,1):e.set(t,[]))},emit:function(t,n){var r=e.get(t);r&&r.slice().map(function(e){e(n)}),(r=e.get(`*`))&&r.slice().map(function(e){e(t,n)})}}}var j=class{emitter;constructor(){this.emitter=A()}on(e,t){k(e).forEach(e=>{this.emitter.on(e,t)})}off(e,t){k(e).forEach(e=>{this.emitter.off(e,t)})}emit(e,t){k(e).forEach(e=>{this.emitter.emit(e,t)})}removeAllListeners(){this.emitter.all.clear()}};function M(e,...t){return class extends e{static _instance;static getInstance(){return this._instance||=new e(...t),this._instance}static clearInstance(){this._instance=void 0}}}const N=M(class extends j{destroy(){this.removeAllListeners()}fatal(e,t,n){this.emit(`fatal`,{code:t,message:e,data:n,timestamp:Date.now()})}error(e,t,n){this.emit(`error`,{code:t,message:e,data:n,timestamp:Date.now()})}warn(e,t,n){this.emit(`warning`,{code:t,message:e,data:n,timestamp:Date.now()})}});var P=class{data;_schema;_defaultValue;_path;constructor(e){let{schema:t,default:n,path:r}=e;this._schema=t,this._defaultValue=n,this._path=r}set(e){let t=this._schema[`~standard`].validate(e);if(t instanceof Promise)throw Error(`StructuredConfigFile does not support async validation`);if(t.issues){this.reportInvalidConfigFile(t.issues);return}this.data=this.onBeforeSave(e),this.save(e)}get(){return this.data?this.data:this.load()}getKey(e){return this.get()[e]}save(e){let t=this.onBeforeSave(e);try{l(this.getFilePath()),o.writeFileSync(this.getFilePath(),JSON.stringify(t,void 0,2))}catch{return}return this.data=t}load(){if(!this.fileExists(this.getFilePath())||!this.canReadWriteFile(this.getFilePath())){this.save(this._defaultValue);let e=this.onAfterLoad(this._defaultValue);return this.data=e,e}try{let e=o.readFileSync(this.getFilePath(),`utf8`),t=this.onAfterLoad(this.parseStoredData(e));return this.data=t,t}catch{return this.data=this._defaultValue}}onBeforeSave(e){return e}onAfterLoad(e){return e}getFilePath(){return this._path}parseStoredData(e){try{let t=a(`string.json.parse`).to(`object`)(e);if(t instanceof a.errors)return this._defaultValue;let n=this._schema[`~standard`].validate(t);if(n instanceof Promise)throw Error(`StructuredConfigFile does not support async validation`);return n.issues?this.migrate(t,this._defaultValue):this.migrate(n.value,this._defaultValue)}catch{return this._defaultValue}}canReadWriteFile(e){try{return o.accessSync(e,o.constants.R_OK|o.constants.W_OK),!0}catch{return!1}}fileExists(e){try{return o.accessSync(e,o.constants.F_OK),!0}catch{return!1}}migrate(e,t){let n={...e};for(let r in t)Object.prototype.hasOwnProperty.call(t,r)&&(r in e?e[r]!==null&&t[r]!==null&&typeof e[r]==`object`&&typeof t[r]==`object`&&!Array.isArray(e[r])&&!Array.isArray(t[r])?n[r]=this.migrate(e[r],t[r]):Array.isArray(t[r])&&(n[r]=e[r]):n[r]=t[r]);return n}reportInvalidConfigFile(e){N.getInstance().error(`Invalid config file`,`INVALID_CONFIG_FILE`,{issues:e.map(e=>e.message),filePath:this._path,data:this.data})}};const F=`**/overlayed.config.{js,ts,mts}`;async function I(){let e=R(),t=fe(import.meta.url);return(await Promise.all(e.map(async e=>e.endsWith(`.ts`)?[await t.import(e,{default:!0}),e]:[(await import(ue.pathToFileURL(e).toString())).default,e]))).filter(([e])=>L(e)).map(([e,t])=>[e,t])}function L(e){return O(e)&&`app`in e}function R(){return m.globSync(F,{absolute:!0,cwd:process.cwd()})}var z=class{pattern;options;constructor(e,t){this.pattern=e,this.options=t}},B=class{defaultIgnore=[`overlayed.config.ts`];patterns=[];constructor(e){this.config=e}addGlobPattern(e,t){let n=this.resolveOptions(t),r=k(e);this.patterns.push(new z(r,n))}async bundle(){let e=new g;for(let t of this.patterns){let n={...t.options},r;r=n.cwd?typeof n.cwd==`string`?n.cwd:de(n.cwd):process.cwd(),d.isAbsolute(r)||(r=d.resolve(r)),n.absolute=!0,n.cwd=r;let i=await m(t.pattern,n),a=await this.getFilesPathsFromPaths(i);await Promise.all(a.map(async t=>{await this.zipFile(r,e,t)}))}return e}async validateFilePath(e){return Promise.resolve(!0)}async zipFile(e,t,n){let r=d.relative(e,n);if(r=r.replace(/^(\.\.\\|\.\.\/)+/,``),!p(n)){t.file(r,``,{compression:`DEFLATE`});return}if(!await this.validateFilePath(n))return;let i=se(n,`binary`);t.file(r,i,{compression:`DEFLATE`})}resolveOptions(e){return{...e,ignore:[...k(e?.ignore),...this.defaultIgnore]}}async getFilesPathsFromPaths(e){return Promise.all(e.map(async e=>await this.getFilePathsFromPathRecursive(e))).then(e=>e.flat())}async getFilePathsFromPathRecursive(e){if(!p(e)||!ce(e).isDirectory())return[e];let t=await h(e,{withFileTypes:!0});return(await Promise.all(t.map(async t=>{let n=d.join(e,t.name);return t.isDirectory()?await this.getFilePathsFromPathRecursive(n):[n]}))).flat()}},V=class extends B{defaultIgnore=[`overlayed.config.ts`,`**/installer/**`];mainFile;constructor(e){super(e),this.addGlobPattern(`package.json`)}async bundle(){let e=await super.bundle();return await this.validateZip(e),e}async validateFilePath(e){return e.endsWith(`package.json`)&&!e.includes(`node_modules`)&&await this.validatePackageJson(e),!0}async validateZip(e){await Promise.all([this.validateNoInstallFolder(e),this.validateMainFile(e)])}async validatePackageJson(e){if(!e)throw new H;let t=oe.readFileSync(e,`utf-8`),n=a(`string.json.parse`).to({main:`string`,devDependencies:{"@overlayed/electron":`string`}})(t);if(n instanceof a.errors)throw new pe(n.summary);this.mainFile=n.main}async validateMainFile(e){if(!this.mainFile)throw new H;if(!e.file(u.normalize(this.mainFile)))throw new U(this.mainFile)}async validateNoInstallFolder(e){let t=e.folder(`install`);if(t&&t.length>0)throw new W}},H=class extends Error{constructor(){super(`package.json not found in bundle`),this.name=`PackageJsonNotFoundError`}},pe=class extends Error{constructor(e){super(`package.json is invalid: ${e}`),this.name=`PackageJsonInvalidError`}},U=class extends Error{constructor(e){super(`referenced package.json main file ${e} not found in bundle`),this.name=`MainFileNotFoundError`}},W=class extends Error{constructor(){super("folder `install` found in bundle is not allowed and is reserved for the installer"),this.name=`InstallFolderFoundError`}};_.create({baseURL:`https://updater.stats.cc`,headers:{Accept:`application/json`,"Accept-Encoding":`gzip, deflate, br`}}).interceptors.request.use(e=>e);const G=_.create({baseURL:import.meta.env.VITE_API_BASE_URL,headers:{Accept:`application/json`,"Accept-Encoding":`gzip, deflate, br`}});let K;function q(e){K=e}G.interceptors.request.use(e=>{let t=K?.();return e.headers??={},t&&(e.headers[`X-Api-Key`]=t),e});function me(e){return e}function he(e){return e?t=>(e(t),t):me}function ge(e,t){return G.post(`/v1/applications/${e}/bundles/tasks/upload`,t)}function _e(e,t){return G.post(`/v1/applications/${e}/bundles/tasks/queue`,{name:t})}function ve(e,t){return G.get(`/v1/applications/${e}/bundles/tasks/${t}`)}function ye(e,t){return G.put(e.url,t,{headers:{...e.headers,"Content-Length":t.length}})}const be=he();function J(){return G.get(`/v1/auth/me`)}const xe=u.normalize(`${process.env.APPDATA||process.env.HOME||`.`}/.overlayed/config.json`),Se=i({Account:a({email:`string`,apiKey:`string`})}).type({currentAccount:`Account | undefined`,accounts:`Account[]`}).or(`undefined`),Y=new P({path:xe,default:void 0,schema:Se});async function X(){if(!Y.get()?.currentAccount)throw new r(`Not authenticated. Run 'overlayed login' to authenticate.`);try{return(await J()).data.email}catch(e){if(!v(e))throw e;switch(e.response?.status){case 401:case 403:throw new r(`Authentication failed. Your API key may be invalid or expired. Run 'overlayed login' to re-authenticate.`);default:throw Error(`API error occurred. Please try again later.`)}}}async function Ce(e){let t=await I();if(t.length===0)throw new r(`No config file found matching `+F);return t.length>1&&e.stdout.write(f.yellow(`
3
3
  Multiple config files found matching ${F}, using the first one.
4
4
  `)),t.at(0)}var we=class extends B{defaultIgnore=[`overlayed.config.ts`];constructor(e){super(e)}async bundle(){let e=await super.bundle();if(!Object.keys(e.files).some(e=>e.endsWith(`.html`)))throw new Te;return e}},Te=class extends Error{constructor(){super(`Site bundle must contain at least one HTML file`)}},Ee=class extends n{static paths=[[`bundle`]];static usage=n.Usage({category:E.deployment,description:`Bundle the app and site for deployment.`,details:`
5
5
  Bundle the app and site for deployment.
package/package.json CHANGED
@@ -10,7 +10,7 @@
10
10
  "keywords": [
11
11
  "typescript"
12
12
  ],
13
- "version": "0.6.2",
13
+ "version": "0.6.3",
14
14
  "description": "Overlayed CLI",
15
15
  "type": "module",
16
16
  "bin": {
@@ -23,27 +23,27 @@
23
23
  "access": "public"
24
24
  },
25
25
  "devDependencies": {
26
- "@ark/attest": "^0.48.2",
26
+ "@ark/attest": "^0.49.0",
27
27
  "@types/fs-extra": "^11.0.4",
28
28
  "@types/update-notifier": "^6.0.8",
29
- "tsdown": "^0.14.2",
30
- "typescript": "^5.9.2",
29
+ "tsdown": "^0.15.6",
30
+ "typescript": "^5.9.3",
31
31
  "vitest": "^3.2.4",
32
- "@overlayed/api": "0.0.3",
33
- "@overlayed/utils": "0.0.3",
34
- "@overlayed/utils-node": "0.0.3"
32
+ "@overlayed/api": "0.0.4",
33
+ "@overlayed/utils": "0.0.4",
34
+ "@overlayed/utils-node": "0.0.4"
35
35
  },
36
36
  "dependencies": {
37
- "@inquirer/prompts": "^7.8.4",
38
- "@listr2/prompt-adapter-inquirer": "^3.0.1",
39
- "arktype": "^2.1.20",
40
- "chalk": "^5.6.0",
37
+ "@inquirer/prompts": "^7.8.6",
38
+ "@listr2/prompt-adapter-inquirer": "^3.0.4",
39
+ "arktype": "^2.1.22",
40
+ "chalk": "^5.6.2",
41
41
  "clipanion": "4.0.0-rc.4",
42
- "fs-extra": "^11.3.1",
42
+ "fs-extra": "^11.3.2",
43
43
  "glob": "^11.0.3",
44
- "jiti": "^2.5.1",
44
+ "jiti": "^2.6.1",
45
45
  "jszip": "^3.10.1",
46
- "listr2": "^9.0.1",
46
+ "listr2": "^9.0.4",
47
47
  "update-notifier": "^7.3.1",
48
48
  "xior": "^0.7.8"
49
49
  },