Comparing version 0.0.7 to 0.0.8
62
bin.js
@@ -8,10 +8,11 @@ #!/usr/bin/env node | ||
.version(version) | ||
.option('--cwd', 'The relative working directory', '.') | ||
.option('--profile', 'The CFW account profile to load') | ||
.option('-C, --cwd', 'The relative working directory', '.') | ||
.option('-P, --profile', 'The CFW account profile to load') | ||
.command('build [src] [output]') | ||
.command('build [dir] [output]') | ||
.describe('Compile the Worker(s) within a directory.') | ||
.option('--dir', 'The directory Worker scripts', 'workers') | ||
.option('--only', 'The list of Worker names to build; overrides `--ignore` list!') | ||
.option('--ignore', 'The list of Worker names to skip') | ||
.option('-d, --dir', 'The directory containing Worker scripts', 'workers') | ||
.option('-o, --only', 'The list of Worker names to build; overrides `--ignore` list!') | ||
.option('-i, --ignore', 'The list of Worker names to skip') | ||
.option('-s, --single', 'The target is a single Worker') | ||
.action(commands.build) | ||
@@ -21,7 +22,50 @@ | ||
.describe('Deploy the built Worker(s) – requires you `build` first.') | ||
.option('--dir', 'The directory Worker scripts', 'workers') | ||
.option('--only', 'The list of Worker names to build; overrides `--ignore` list!') | ||
.option('--ignore', 'The list of Worker names to skip') | ||
.option('-d, --dir', 'The directory containing Worker scripts', 'workers') | ||
.option('-o, --only', 'The list of Worker names to build; overrides `--ignore` list!') | ||
.option('-i, --ignore', 'The list of Worker names to skip') | ||
.option('-s, --single', 'The target is a single Worker') | ||
.action(commands.deploy) | ||
.command('secrets list').alias('secrets ls') | ||
.describe('List the names of secrets attached to Worker(s) within a directory.') | ||
.option('-d, --dir', 'The directory containing Worker scripts', 'workers') | ||
.option('-o, --only', 'The list of Worker names to query; overrides `--ignore` list!') | ||
.option('-i, --ignore', 'The list of Worker names to skip') | ||
.option('-s, --single', 'The target is a single Worker') | ||
.action(commands.secret.list) | ||
.command('secrets create <name> <value>') | ||
.alias('secrets new', 'secrets add', 'secrets put') | ||
.describe('Create a new secret for the Worker(s) within a directory.') | ||
.option('-d, --dir', 'The directory containing Worker scripts', 'workers') | ||
.option('-o, --only', 'The list of Worker names to query; overrides `--ignore` list!') | ||
.option('-i, --ignore', 'The list of Worker names to skip') | ||
.option('-s, --single', 'The target is a single Worker') | ||
.action(commands.secret.create) | ||
.command('secrets destroy <name>') | ||
.alias('secrets delete', 'secrets rm') | ||
.describe('Remove a secret from the Worker(s) within a directory.') | ||
.option('-d, --dir', 'The directory containing Worker scripts', 'workers') | ||
.option('-o, --only', 'The list of Worker names to query; overrides `--ignore` list!') | ||
.option('-q, --quiet', 'Do not throw error if Worker is missing secret') | ||
.option('-i, --ignore', 'The list of Worker names to skip') | ||
.option('-s, --single', 'The target is a single Worker') | ||
.action(commands.secret.destroy) | ||
.command('kv namespaces list') | ||
.describe('List all KV namespaces') | ||
.alias('kv ns list', 'kv ns ls') | ||
.action(commands.ns.list) | ||
.command('kv namespaces create <title>') | ||
.describe('Create a new KV namespace') | ||
.alias('kv ns create', 'kv ns new') | ||
.action(commands.ns.create) | ||
.command('kv namespaces destroy <id>') | ||
.describe('Destroy a KV namespace') | ||
.alias('kv ns delete', 'kv ns rm') | ||
.action(commands.ns.destroy) | ||
.parse(process.argv); |
354
lib/index.js
@@ -1,353 +0,1 @@ | ||
var klona = require('klona'); | ||
var colors = require('kleur'); | ||
var premove = require('premove'); | ||
var fs = require('fs'); | ||
var path = require('path'); | ||
var os = require('os'); | ||
var util = require('util'); | ||
var httpie = require('httpie'); | ||
const SPACER = ' '.repeat(6); | ||
const CFW = colors.bold('[CFW]'); | ||
function print(color, msg) { | ||
console.log(colors[color](CFW), msg.includes('\n') ? msg.replace(/(\r?\n)/g, '$1' + SPACER) : msg); | ||
} | ||
const log = msg => print('white', msg); | ||
const warn = msg => print('yellow', msg); | ||
const success = msg => print('green', msg); | ||
function error(msg, code=1) { | ||
print('red', msg); | ||
process.exit(code); | ||
} | ||
const write = util.promisify(fs.writeFile); | ||
const read = util.promisify(fs.readFile); | ||
function assert(mix, msg, toExist) { | ||
(toExist ? fs.existsSync(mix) : !!mix) || error(msg); | ||
} | ||
function list(str) { | ||
return Array.isArray(str) ? str : str.split(','); | ||
} | ||
function load(str, dir) { | ||
str = path.resolve(dir || '.', str); | ||
return fs.existsSync(str) && require(str); | ||
} | ||
function toConfig(dir, tmp) { | ||
if (tmp = load('cfw.js', dir)) return tmp; | ||
if (tmp = load('cfw.json', dir)) return tmp; | ||
if (tmp = load('package.json', dir)) return tmp.cfw; | ||
} | ||
function toWorker(dir, name, isOne) { | ||
let abs = isOne ? dir : path.join(dir, name); | ||
let out = { abs, name }; | ||
let config = toConfig(abs) || {}; | ||
out.input = path.join(abs, config.entry || 'index.js'); | ||
if (config.name) out.name = config.name; | ||
out.cfw = config; | ||
return out; | ||
} | ||
function toWorkers(dir, opts) { | ||
assert(dir, `Workers directory does not exist: "${dir}"`, true); | ||
let tmp, { cwd, single, only, ignore } = opts; | ||
if (single) { | ||
let name = opts.dirname; | ||
if (name === '.') name = path.parse(cwd).base; | ||
let obj = toWorker(dir, name, true); | ||
// check for root config | ||
if (tmp = toConfig(cwd)) { | ||
if (tmp.name) obj.name = tmp.name; | ||
Object.assign(obj.cfw, tmp); | ||
if (opts.profile) obj.cfw.profile = opts.profile; | ||
} | ||
return [obj]; | ||
} | ||
let arr = fs.readdirSync(dir).map(x => toWorker(dir, x)); | ||
if (only) { | ||
tmp = list(only); | ||
return arr.filter(obj => tmp.includes(obj.name)); | ||
} | ||
if (ignore) { | ||
tmp = list(ignore); | ||
return arr.filter(obj => !tmp.includes(obj.name)); | ||
} | ||
return arr; | ||
} | ||
async function toProfile(profile = 'default') { | ||
let file = path.join(os.homedir(), '.cfw', 'config'); | ||
assert(file, `Missing "${file}" config file`, true); | ||
let data = await read(file, 'utf8'); | ||
let arr = data.split(/\n+/g); | ||
let i=0, name, tmp, map={}; | ||
let rgx = /^\[(.*)\]$/; | ||
for (; i < arr.length; i++) { | ||
if (arr[i].startsWith('#') || !arr[i].trim().length) ; else if (rgx.test(arr[i])) { | ||
name = rgx.exec(arr[i])[1]; | ||
tmp = map[name] = {}; | ||
} else { | ||
let [k, v] = arr[i].split(/\s*=\s*/); | ||
tmp[k] = v; | ||
} | ||
} | ||
let out = map[profile]; | ||
assert(out, `The "${profile}" profile is not defined`); | ||
return out; | ||
} | ||
async function toCredentials(def) { | ||
let { | ||
CLOUDFLARE_ZONEID, CLOUDFLARE_ACCOUNTID, | ||
CLOUDFLARE_AUTH_EMAIL, CLOUDFLARE_AUTH_KEY, CLOUDFLARE_TOKEN | ||
} = process.env; | ||
let email = CLOUDFLARE_AUTH_EMAIL || def.email; | ||
let authkey = CLOUDFLARE_AUTH_KEY || def.authkey; | ||
let accountid = CLOUDFLARE_ACCOUNTID || def.accountid; | ||
let zoneid = CLOUDFLARE_ZONEID || def.zoneid; | ||
let token = CLOUDFLARE_TOKEN || def.token; | ||
let hasAuth = token || (authkey && email); | ||
// return early if all defined already | ||
if (hasAuth && accountid && zoneid) { | ||
return { authkey, accountid, email, token, zoneid }; | ||
} | ||
if (def.profile) { | ||
let extra = await toProfile(def.profile); | ||
for (let k of Object.keys(extra)) { | ||
if (!email && /CLOUDFLARE_AUTH_EMAIL/i.test(k)) email = extra[k]; | ||
if (!accountid && /CLOUDFLARE_ACCOUNTID/i.test(k)) accountid = extra[k]; | ||
if (!authkey && /CLOUDFLARE_AUTH_KEY/i.test(k)) authkey = extra[k]; | ||
if (!zoneid && /CLOUDFLARE_ZONEID/i.test(k)) zoneid = extra[k]; | ||
if (!token && /CLOUDFLARE_TOKEN/i.test(k)) token = extra[k]; | ||
} | ||
} | ||
assert(zoneid, 'Missing Cloudflare "zoneid" value!'); | ||
assert(accountid, 'Missing Cloudflare "accountid" value!'); | ||
if (token || (authkey && email)) ; else if (authkey || email) { | ||
assert(email, 'Missing Cloudflare "email" value!'); | ||
assert(authkey, 'Missing Cloudflare "authkey" value!'); | ||
} else { | ||
error('Missing Cloudflare "token" value or "email" + "authkey" combo!'); | ||
} | ||
return { authkey, accountid, email, token, zoneid }; | ||
} | ||
const options = { | ||
resolve: { | ||
mainFields: ['worker', 'browser', 'module', 'jsnext', 'main'] | ||
} | ||
}; | ||
const config = { | ||
// input: inject | ||
output: { | ||
format: 'esm', | ||
// file: inject | ||
sourcemap: false, | ||
}, | ||
treeshake: { | ||
propertyReadSideEffects: false, | ||
moduleSideEffects: 'no-external', | ||
tryCatchDeoptimization: false | ||
}, | ||
plugins: [ | ||
// injected | ||
] | ||
}; | ||
async function build (src, output, opts) { | ||
let cwd = opts.cwd = path.resolve(opts.cwd); | ||
opts.dirname = src || 'workers'; | ||
opts.dest = output || opts.dest || 'build'; | ||
output = opts.output = path.resolve(cwd, opts.dest); | ||
src = opts.src = path.resolve(cwd, opts.dirname); | ||
let items = toWorkers(src, opts); | ||
if (!items.length) { | ||
let msg = 'No workers to build!'; | ||
if (opts.only || opts.ignore) { | ||
let flag = colors.dim().bold; | ||
msg += `\nPerhaps the ${flag('--only')} or ${flag('--ignore')} flag needs adjusting`; | ||
} | ||
return warn(msg); | ||
} | ||
if (fs.existsSync(output)) { | ||
warn(`Removing existing "${opts.dest}" directory`); | ||
await premove(output); | ||
} | ||
const { rollup } = require('rollup'); | ||
let arrow = colors.cyan(' ~> '); | ||
let sfx = items.length === 1 ? '' : 's'; | ||
let count = colors.bold(items.length); | ||
log(`Building ${count} worker${sfx}:`); | ||
for (let def of items) { | ||
let { name, input, cfw } = def; | ||
let options$1 = klona(options); | ||
let config$1 = { input, ...config }; | ||
let outdir = path.join(output, opts.single ? '' : name); | ||
config$1.output.file = path.join(outdir, 'index.js'); | ||
if (typeof cfw.build === 'function') { | ||
config$1 = klona(config$1); | ||
cfw.build(config$1, options$1); // mutate~! | ||
} | ||
config$1.plugins.push( | ||
require('@rollup/plugin-node-resolve').default(options$1.resolve) | ||
); | ||
let now = Date.now(); | ||
await rollup(config$1).then(b => { | ||
return b.write(config$1.output); | ||
}); | ||
await write( | ||
path.join(outdir, 'cfw.json'), | ||
JSON.stringify({ name, ...cfw }, null, 2) | ||
); | ||
console.log(arrow + name + colors.italic().dim(` (${Date.now() - now}ms)`)); | ||
} | ||
success(`Build complete!\nYour worker${sfx} ${items.length === 1 ? 'is' : 'are'} ready for deployment 🎉`); | ||
} | ||
const API = 'https://api.cloudflare.com/client/v4'; | ||
function toHeaders(creds, obj={}) { | ||
const headers = obj; | ||
if (creds.token) { | ||
headers['Authorization'] = `Bearer ${creds.token}`; | ||
} else { | ||
headers['X-Auth-Key'] = creds.authkey; | ||
headers['X-Auth-Email'] = creds.email; | ||
} | ||
return headers; | ||
} | ||
function send(method, pathname, opts={}) { | ||
return httpie.send(method, API + pathname, opts).then(r => r.data); | ||
} | ||
function route(pattern, script, creds) { | ||
return send('POST', `/zones/${creds.zoneid}/workers/routes`, { | ||
headers: toHeaders(creds, { | ||
'Content-Type': 'application/javascript', | ||
}), | ||
body: { | ||
pattern, | ||
script | ||
} | ||
}).catch(err => { | ||
let { data, message } = err; | ||
if (data && data.errors && data.errors[0].code === 10020) return; // duplicate | ||
error(`Error setting "${pattern}" route pattern!\n${JSON.stringify(data || message, null, 2)}`); | ||
}); | ||
} | ||
function script(filedata, name, creds) { | ||
return send('PUT', `/accounts/${creds.accountid}/workers/scripts/${name}`, { | ||
headers: toHeaders(creds, { | ||
'Content-Type': 'application/javascript', | ||
}), | ||
body: filedata | ||
}).catch(err => { | ||
error(`Error uploading "${name}" script!\n${JSON.stringify(err.data || err.message, null, 2)}`); | ||
}); | ||
} | ||
function upload(file, name, creds) { | ||
return read(file, 'utf8').then(data => { | ||
return script(data, name, creds); | ||
}).catch(err => { | ||
error(`Error reading input file!\nAttempted path: "${file}"\nReason: "${err.message || err.stack}"`); | ||
}); | ||
} | ||
async function deploy (output, opts) { | ||
let cwd = opts.cwd = path.resolve(opts.cwd); | ||
opts.dest = output || 'build'; | ||
output = path.resolve(cwd, opts.dest); | ||
let items = toWorkers(output, opts); | ||
if (!items.length) { | ||
let msg = 'Nothing to deploy!'; | ||
if (opts.only || opts.ignore) { | ||
let flag = colors.dim().bold; | ||
msg += `\nPerhaps the ${flag('--only')} or ${flag('--ignore')} flag needs adjusting`; | ||
} | ||
return warn(msg); | ||
} | ||
let arrow = colors.cyan(' ~> '); | ||
let detached = x => colors.red().dim(` - "${x}"`); | ||
let attached = x => colors.green().dim(` + "${x}"`); | ||
let delta = ms => colors.italic().dim(` (${ms}ms)`); | ||
let sfx = items.length === 1 ? '' : 's'; | ||
let count = colors.bold(items.length); | ||
log(`Deploying ${count} worker${sfx}:`); | ||
for (let def of items) { | ||
let { name, input, cfw } = def; | ||
let creds = await toCredentials(cfw); | ||
let now = Date.now(); | ||
await upload(input, name, creds); | ||
console.log(arrow + name + delta(Date.now() - now)); | ||
if (cfw.routes) { | ||
await Promise.all( | ||
cfw.routes.map(str => { | ||
let iter = Date.now(); | ||
let isNot = str.startsWith('!'); | ||
let pattern = str.substring(+isNot); | ||
return route(pattern, isNot ? null : name, creds).then(() => { | ||
console.log((isNot ? detached : attached)(pattern) + delta(Date.now() - iter)); | ||
}); | ||
}) | ||
); | ||
} | ||
// TODO: resources | ||
} | ||
success(`Deployment complete!\nAll items within "${opts.dest}" uploaded 🎉`); | ||
} | ||
exports.build = build; | ||
exports.deploy = deploy; | ||
var e=require("kleur"),t=require("fs"),n=require("premove"),r=require("klona/lite"),o=require("path"),i=require("os"),a=require("util"),s=require("httpie");const l={resolve:{mainFields:["worker","browser","module","jsnext","main"]}},c={output:{format:"esm",sourcemap:!1},treeshake:{propertyReadSideEffects:!1,moduleSideEffects:"no-external",tryCatchDeoptimization:!1},plugins:[]},u=" ~> ",d=" ".repeat(6),f=e.bold("[CFW]");function p(t,n){console.log(e[t](f),n.includes("\n")?n.replace(/(\r?\n)/g,"$1"+d):n)}const g=e=>p("white",e),m=e=>p("green",e),w=e=>p("yellow",e);function y(e,t=1){p("red",e),process.exit(t)}const h=e.dim().bold;function $(e,t){return(t.only||t.ignore)&&(e+=`\nPerhaps the ${h("--only")} or ${h("--ignore")} flag needs adjusting`),w(e)}function k(t){return e.italic().dim(` (${t}ms)`)}function v(t,n,r){let o="•",i=e.dim,a=null!=n?k(n):"";r?(o="+",i=e.green().dim):null!=r&&(o="-",i=e.red().dim),console.log(i(d+o+` "${t}"`)+a)}const E=a.promisify(t.writeFile),b=a.promisify(t.readFile),_=(e,t)=>!!e||y(t),D=(e,n)=>t.existsSync(e)||y(n);function O(e){return Array.isArray(e)?e:e.split(",")}function C(e,n){return e=o.resolve(n||".",e),t.existsSync(e)&&require(e)}function A(e){let t;return(t=C("cfw.js",e))||(t=C("cfw.json",e))?t:(t=C("package.json",e))?t.cfw:void 0}function L(e,t,n){let r=n?e:o.join(e,t),i=A(r)||{};return{cfw:i,name:i.name||t,input:o.join(r,i.entry||"index.js"),abs:r}}function x(e,n){n.cwd=o.resolve(n.cwd);let r,i,a=o.resolve(n.cwd,e);D(a,`Workers directory does not exist: "${a}"`);let{cwd:s,single:l,only:c,ignore:u}=n;if(l){let e=n.dir;"."===e&&(e=o.parse(s).base);let t=L(a,e,!0);return(i=A(s))&&(Object.assign(t.cfw,i),i.name&&(t.name=i.name),n.profile&&(t.cfw.profile=n.profile)),[t]}let d=t.readdirSync(a).map((e=>L(a,e)));return c?(r=O(c),d.filter((e=>r.includes(e.name)))):u?(r=O(u),d.filter((e=>!r.includes(e.name)))):d}async function N(e,t){let{CLOUDFLARE_ZONEID:n,CLOUDFLARE_ACCOUNTID:r,CLOUDFLARE_AUTH_EMAIL:a,CLOUDFLARE_AUTH_KEY:s,CLOUDFLARE_TOKEN:l}=process.env,c=a||e.email,u=s||e.authkey,d=r||e.accountid,f=n||e.zoneid,p=l||e.token;if((p||u&&c)&&d&&f)return{authkey:u,accountid:d,email:c,token:p,zoneid:f};if(e.profile){let t=await async function(e="default"){let t=o.join(i.homedir(),".cfw","config");D(t,`Missing "${t}" config file`);let n,r,a=(await b(t,"utf8")).split(/\n+/g),s={},l=0,c=/^\[(.*)\]$/;for(;l<a.length;l++)if(a[l].startsWith("#")||!a[l].trim().length);else if(c.test(a[l]))r=c.exec(a[l])[1],n=s[r]={};else{let[e,t]=a[l].split(/\s*=\s*/);n[e]=t}let u=s[e];return _(u,`The "${e}" profile is not defined`),u}(e.profile);Object.keys(t).forEach((e=>{!c&&/CLOUDFLARE_AUTH_EMAIL/i.test(e)&&(c=t[e]),!d&&/CLOUDFLARE_ACCOUNTID/i.test(e)&&(d=t[e]),!u&&/CLOUDFLARE_AUTH_KEY/i.test(e)&&(u=t[e]),!f&&/CLOUDFLARE_ZONEID/i.test(e)&&(f=t[e]),!p&&/CLOUDFLARE_TOKEN/i.test(e)&&(p=t[e])}))}return _(f||t,'Missing Cloudflare "zoneid" value!'),_(d,'Missing Cloudflare "accountid" value!'),p||u&&c||(u||c?(_(c,'Missing Cloudflare "email" value!'),_(u,'Missing Cloudflare "authkey" value!')):y('Missing Cloudflare "token" value or "email" + "authkey" combo!')),{authkey:u,accountid:d,email:c,token:p,zoneid:f}}const T=()=>Math.random().toString(36).slice(2);function j(e,t={}){return e.token?t.Authorization="Bearer "+e.token:(t["X-Auth-Key"]=e.authkey,t["X-Auth-Email"]=e.email),t}function U(e,t,n={}){return s.send(e,"https://api.cloudflare.com/client/v4"+t,n).then((e=>e.data))}function S(e,t,n){return U("POST",`/zones/${e.zoneid}/workers/routes`,{headers:j(e,{"Content-Type":"application/javascript"}),body:{pattern:t,script:n}}).catch((e=>{let{data:n,message:r}=e;n&&n.errors&&10020===n.errors[0].code||y(`Error setting "${t}" route pattern!\n${JSON.stringify(n||r,null,2)}`)}))}async function R(e,t,n,r){const o="----"+T()+T(),i=function(e,t){let n,r,o="",i="\r\n",a="--"+e;for(n in t)r=t[n],o+=a+i,o+=`Content-Disposition: form-data; name="${n}"`,r.filename&&(o+=`; filename="${r.filename}"`),r.type&&(o+="\r\nContent-Type: "+r.type),o+=i+i+r.value+i;return o+a+"--"}(o,{script:{type:"application/javascript",value:n},metadata:{type:"application/json",value:r?JSON.stringify(r):'{"body_part": "script","bindings":[]}'}});return U("PUT",`/accounts/${e.accountid}/workers/scripts/${t}`,{headers:j(e,{"Content-Type":"multipart/form-data; boundary="+o}),body:i}).catch((e=>{y(`Error uploading "${t}" script!\n${JSON.stringify(e.data||e.message,null,2)}`)}))}const F={env:"plain_text",wasm:"wasm_module",secret:"secret_text",kv:"kv_namespace"};function q(e,t){let n=t.indexOf(":"),r=t.substring(0,n),o=t.substring(n+1),i=F[r.toLowerCase()];return i||y(`Unknown binding hint: "${r}"`),"wasm_module"===i?{type:i,name:e,part:"wasm"}:"kv_namespace"===i?{type:i,name:e,namespace_id:o}:{type:i,name:e,text:o}}function K(e){let t,n=[];for(t in e)n.push(q(t,e[t]));if(n.length)return{body_part:"script",bindings:n}}function J(e,t){return U("GET",`/accounts/${e.accountid}/workers/scripts/${t}/secrets`,{headers:j(e)}).catch((e=>{y(`Error fetching "${t}" secrets!\n${JSON.stringify(e.data||e.message,null,2)}`)}))}function M(e,t,n,r){return U("PUT",`/accounts/${e.accountid}/workers/scripts/${t}/secrets`,{headers:j(e),body:{type:"secret_text",text:r,name:n}}).catch((e=>{y(`Error creating new "${t}" secret!\n${JSON.stringify(e.data||e.message,null,2)}`)}))}function z(e,t,n,r){return U("DELETE",`/accounts/${e.accountid}/workers/scripts/${t}/secrets/${n}`,{headers:j(e)}).catch((e=>{let{data:o,message:i}=e;if(r&&o&&o.errors&&10056===o.errors[0].code)return o;y(`Error deleting "${t}/${n}" secret!\n${JSON.stringify(o||i,null,2)}`)}))}var I={__proto__:null,list:async function(t){let n=x(t.dir,t);if(!n.length)return $("No workers found!",t);let r=e.bold(n.length),o=1===n.length?"":"s";g(`Fetching secrets for ${r} worker${o}:`);let i=e.cyan(u);for(let r of n){let{name:n,cfw:o}=r;o.profile=o.profile||t.profile;let a=await N(o),s=await J(a,n);if(console.log(i+`"${n}" secrets:`),s.result.length)for(let e of s.result)v(e.name);else console.log(d+e.italic().dim(" None"))}m(`Retrieved worker${o?"s'":"'s"} secrets`)},create:async function(t,n,r){let o=x(r.dir,r);if(!o.length)return $("No workers found!",r);let i=e.cyan(u),a=e.bold(o.length),s=1===o.length?"":"s",l=[];g(`Adding secret "${t}" value to ${a} worker${s}:`);for(let e of o){let{name:o,cfw:a}=e;a.profile=a.profile||r.profile;let s=await N(a);l.push((()=>{let e=Date.now();return M(s,o,t,n).then((t=>{t.success&&console.log(i+o+k(Date.now()-e))}))}))}await Promise.all(l.map((e=>e()))),m("Added secret to worker"+s)},destroy:async function(t,n){let r=x(n.dir,n);if(!r.length)return $("No workers found!",n);let o=e.bold(r.length),i=1===r.length?"":"s",a=[];g(`Removing "${t}" secret from ${o} worker${i}:`);for(let o of r){let{name:r,cfw:i}=o;i.profile=i.profile||n.profile;let s=await N(i);a.push((()=>{let o=Date.now();return z(s,r,t,!!n.quiet).then((t=>{let n=(t.success?e.cyan:e.red)(u);console.log(n+r+k(Date.now()-o))}))}))}await Promise.all(a.map((e=>e()))),m("Removed secret from worker"+i)}};var P={__proto__:null,list:async function(t){const n=await N(t,!0);g("Retrieving KV namespaces:");const r=await function(e){return U("GET",`/accounts/${e.accountid}/storage/kv/namespaces?per_page=100&order=title`,{headers:j(e)})}(n),o=" ",i=e.dim().bold().italic;m(i("ID")+" ".repeat(30)+o+i("Title"));let a=0,s=r.result,l="";for(;a<s.length;a++)l&&(l+="\n"),l+=(s[a].supports_url_encoding?e.cyan:e.red)(u),l+=s[a].id+o+s[a].title;console.log(l)},create:async function(t,n){const r=await N(n,!0);g("Creating new KV namespace:");const o=await function(e,t){return U("POST",`/accounts/${e.accountid}/storage/kv/namespaces`,{headers:j(e),body:{title:t}}).catch((e=>{y(`Error creating "${t}" namespace!\n${JSON.stringify(e.data||e.message,null,2)}`)}))}(r,t);if(!o)return y("Error creating namespace");console.log(e.cyan(u)+`"${o.result.title}" `+e.italic().dim(`(ID: ${o.result.id})`)),m("KV namespace created!")},destroy:async function(e,t){const n=await N(t,!0);w("Deleting KV namespace");const r=await function(e,t){return U("DELETE",`/accounts/${e.accountid}/storage/kv/namespaces/${t}`,{headers:j(e)}).catch((e=>{y(`Error removing "${t}" namespace!\n${JSON.stringify(e.data||e.message,null,2)}`)}))}(n,e);if(!r||!r.success)return y("Error deleting namespace");m("KV namespace deleted!")}};exports.build=async function(i,a,s){s.dir=i||s.dir;let d=x(s.dir,s);if(!d.length)return $("Nothing to build!",s);let f=a||"build";i=o.resolve(s.cwd,s.dir),a=o.resolve(s.cwd,f),t.existsSync(a)&&(w(`Removing existing "${f}" directory`),await n.premove(a));const{rollup:p}=require("rollup");let y=e.cyan(u),h=e.bold(d.length),v=1===d.length?"":"s";g(`Building ${h} worker${v}:`);for(let e of d){let{name:t,input:n,cfw:i}=e,u=r.klona(l),d={input:n,...c},f=o.join(a,s.single?"":t);d.output.file=o.join(f,"index.js"),"function"==typeof i.build&&(d=r.klona(d),i.build(d,u)),d.plugins.push(require("@rollup/plugin-node-resolve").default(u.resolve));let g=Date.now();await p(d).then((e=>e.write(d.output))),await E(o.join(f,"cfw.json"),JSON.stringify({name:t,...i},null,2)),console.log(y+t+k(Date.now()-g))}m(`Build complete!\nYour worker${v} ${1===d.length?"is":"are"} ready for deployment 🎉`)},exports.deploy=async function(t,n){let r=t||"build",o=x(r,n);if(!o.length)return $("Nothing to deploy!",n);let i=e.cyan(u),a=e.bold(o.length),s=1===o.length?"":"s";g(`Deploying ${a} worker${s}:`);for(let e of o){let{name:t,input:r,cfw:o}=e;o.profile=o.profile||n.profile,D(r,`Worker input does not exist: "${r}"`);let a=await N(o),s=o.globals&&K(o.globals),l=await b(r),c=Date.now();await R(a,t,l,s),console.log(i+t+k(Date.now()-c)),o.routes&&await Promise.all(o.routes.map((e=>{let n=Date.now(),r=e.startsWith("!"),o=e.substring(+r);return S(a,o,r?null:t).then((()=>{v(o,Date.now()-n,!r)}))})))}m(`Deployment complete!\nAll items within "${r}" uploaded 🎉`)},exports.ns=P,exports.secret=I; |
{ | ||
"name": "cfw", | ||
"version": "0.0.7", | ||
"version": "0.0.8", | ||
"repository": "lukeed/cfw", | ||
@@ -9,3 +9,2 @@ "description": "WIP", | ||
"files": [ | ||
"tsconfig.json", | ||
"bin.js", | ||
@@ -20,20 +19,22 @@ "lib" | ||
"engines": { | ||
"node": ">=8" | ||
"node": ">=10" | ||
}, | ||
"scripts": { | ||
"build": "rollup -c", | ||
"test": "eslint bin.js lib" | ||
"test": "tsc --noEmit" | ||
}, | ||
"dependencies": { | ||
"@rollup/plugin-node-resolve": "^8.0.0", | ||
"@rollup/plugin-node-resolve": "^9.0.0", | ||
"httpie": "^1.1.2", | ||
"kleur": "^3.0.3", | ||
"klona": "^1.1.1", | ||
"premove": "^1.0.0", | ||
"rollup": "^2.16.0", | ||
"sade": "^1.6.1" | ||
"kleur": "^4.0.0", | ||
"klona": "^2.0.0", | ||
"premove": "^3.0.1", | ||
"rollup": "^2.20.0", | ||
"sade": "^1.7.4" | ||
}, | ||
"devDependencies": { | ||
"eslint": "6.1.0" | ||
"@types/node": "14.11.2", | ||
"terser": "5.3.3", | ||
"typescript": "4.0.3" | ||
} | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
14736
3
4
97
3
2
+ Added@rollup/plugin-node-resolve@9.0.0(transitive)
+ Addedkleur@4.1.5(transitive)
+ Addedklona@2.0.6(transitive)
+ Addedpremove@3.0.1(transitive)
- Removed@rollup/plugin-node-resolve@8.4.0(transitive)
- Removeddeep-freeze@0.0.1(transitive)
- Removedkleur@3.0.3(transitive)
- Removedklona@1.1.2(transitive)
- Removedpremove@1.0.0(transitive)
Updatedkleur@^4.0.0
Updatedklona@^2.0.0
Updatedpremove@^3.0.1
Updatedrollup@^2.20.0
Updatedsade@^1.7.4