nav tabs on admin dashboard

This commit is contained in:
2019-03-07 00:20:34 -06:00
parent f73d6ae228
commit e4f473f376
11661 changed files with 216240 additions and 1544253 deletions
+97
View File
@@ -2,6 +2,103 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
<a name="11.3.2"></a>
## [11.3.2](https://github.com/zkat/cacache/compare/v11.3.1...v11.3.2) (2018-12-21)
### Bug Fixes
* **get:** make sure to handle errors in the .then ([b10bcd0](https://github.com/zkat/cacache/commit/b10bcd0))
<a name="11.3.1"></a>
## [11.3.1](https://github.com/zkat/cacache/compare/v11.3.0...v11.3.1) (2018-11-05)
### Bug Fixes
* **get:** export hasContent.sync properly ([d76c920](https://github.com/zkat/cacache/commit/d76c920))
<a name="11.3.0"></a>
# [11.3.0](https://github.com/zkat/cacache/compare/v11.2.0...v11.3.0) (2018-11-05)
### Features
* **get:** add sync API for reading ([db1e094](https://github.com/zkat/cacache/commit/db1e094))
<a name="11.2.0"></a>
# [11.2.0](https://github.com/zkat/cacache/compare/v11.1.0...v11.2.0) (2018-08-08)
### Features
* **read:** add sync support to other internal read.js fns ([fe638b6](https://github.com/zkat/cacache/commit/fe638b6))
<a name="11.1.0"></a>
# [11.1.0](https://github.com/zkat/cacache/compare/v11.0.3...v11.1.0) (2018-08-01)
### Features
* **read:** add sync support for low-level content read ([b43af83](https://github.com/zkat/cacache/commit/b43af83))
<a name="11.0.3"></a>
## [11.0.3](https://github.com/zkat/cacache/compare/v11.0.2...v11.0.3) (2018-08-01)
### Bug Fixes
* **config:** add ssri config options ([#136](https://github.com/zkat/cacache/issues/136)) ([10d5d9a](https://github.com/zkat/cacache/commit/10d5d9a))
* **perf:** refactor content.read to avoid lstats ([c5ac10e](https://github.com/zkat/cacache/commit/c5ac10e))
* **test:** oops when removing safe-buffer ([1950490](https://github.com/zkat/cacache/commit/1950490))
<a name="11.0.2"></a>
## [11.0.2](https://github.com/zkat/cacache/compare/v11.0.1...v11.0.2) (2018-05-07)
### Bug Fixes
* **verify:** size param no longer lost in a verify ([#131](https://github.com/zkat/cacache/issues/131)) ([c614a19](https://github.com/zkat/cacache/commit/c614a19)), closes [#130](https://github.com/zkat/cacache/issues/130)
<a name="11.0.1"></a>
## [11.0.1](https://github.com/zkat/cacache/compare/v11.0.0...v11.0.1) (2018-04-10)
<a name="11.0.0"></a>
# [11.0.0](https://github.com/zkat/cacache/compare/v10.0.4...v11.0.0) (2018-04-09)
### Features
* **opts:** use figgy-pudding for opts ([#128](https://github.com/zkat/cacache/issues/128)) ([33d4eed](https://github.com/zkat/cacache/commit/33d4eed))
### meta
* drop support for node@4 ([529f347](https://github.com/zkat/cacache/commit/529f347))
### BREAKING CHANGES
* node@4 is no longer supported
<a name="10.0.4"></a>
## [10.0.4](https://github.com/zkat/cacache/compare/v10.0.3...v10.0.4) (2018-02-16)
+72 -15
View File
@@ -2,6 +2,7 @@
const BB = require('bluebird')
const figgyPudding = require('figgy-pudding')
const fs = require('fs')
const index = require('./lib/entry-index')
const memo = require('./lib/memoization')
@@ -10,6 +11,12 @@ const pipeline = require('mississippi').pipeline
const read = require('./lib/content/read')
const through = require('mississippi').through
const GetOpts = figgyPudding({
integrity: {},
memoize: {},
size: {}
})
module.exports = function get (cache, key, opts) {
return getData(false, cache, key, opts)
}
@@ -17,11 +24,11 @@ module.exports.byDigest = function getByDigest (cache, digest, opts) {
return getData(true, cache, digest, opts)
}
function getData (byDigest, cache, key, opts) {
opts = opts || {}
opts = GetOpts(opts)
const memoized = (
byDigest
? memo.get.byDigest(cache, key, opts)
: memo.get(cache, key, opts)
? memo.get.byDigest(cache, key, opts)
: memo.get(cache, key, opts)
)
if (memoized && opts.memoize !== false) {
return BB.resolve(byDigest ? memoized : {
@@ -56,9 +63,58 @@ function getData (byDigest, cache, key, opts) {
})
}
module.exports.sync = function get (cache, key, opts) {
return getDataSync(false, cache, key, opts)
}
module.exports.sync.byDigest = function getByDigest (cache, digest, opts) {
return getDataSync(true, cache, digest, opts)
}
function getDataSync (byDigest, cache, key, opts) {
opts = GetOpts(opts)
const memoized = (
byDigest
? memo.get.byDigest(cache, key, opts)
: memo.get(cache, key, opts)
)
if (memoized && opts.memoize !== false) {
return byDigest ? memoized : {
metadata: memoized.entry.metadata,
data: memoized.data,
integrity: memoized.entry.integrity,
size: memoized.entry.size
}
}
const entry = !byDigest && index.find.sync(cache, key, opts)
if (!entry && !byDigest) {
throw new index.NotFoundError(cache, key)
}
const data = read.sync(
cache,
byDigest ? key : entry.integrity,
{
integrity: opts.integrity,
size: opts.size
}
)
const res = byDigest
? data
: {
metadata: entry.metadata,
data: data,
size: entry.size,
integrity: entry.integrity
}
if (opts.memoize && byDigest) {
memo.put.byDigest(cache, key, res, opts)
} else if (opts.memoize) {
memo.put(cache, entry, res.data, opts)
}
return res
}
module.exports.stream = getStream
function getStream (cache, key, opts) {
opts = opts || {}
opts = GetOpts(opts)
let stream = through()
const memoized = memo.get(cache, key, opts)
if (memoized && opts.memoize !== false) {
@@ -91,7 +147,6 @@ function getStream (cache, key, opts) {
} else {
memoStream = through()
}
opts.size = opts.size == null ? entry.size : opts.size
stream.emit('metadata', entry.metadata)
stream.emit('integrity', entry.integrity)
stream.emit('size', entry.size)
@@ -101,17 +156,19 @@ function getStream (cache, key, opts) {
ev === 'size' && cb(entry.size)
})
pipe(
read.readStream(cache, entry.integrity, opts),
read.readStream(cache, entry.integrity, opts.concat({
size: opts.size == null ? entry.size : opts.size
})),
memoStream,
stream
)
}, err => stream.emit('error', err))
}).catch(err => stream.emit('error', err))
return stream
}
module.exports.stream.byDigest = getStreamDigest
function getStreamDigest (cache, integrity, opts) {
opts = opts || {}
opts = GetOpts(opts)
const memoized = memo.get.byDigest(cache, integrity, opts)
if (memoized && opts.memoize !== false) {
const stream = through()
@@ -143,7 +200,7 @@ function getStreamDigest (cache, integrity, opts) {
module.exports.info = info
function info (cache, key, opts) {
opts = opts || {}
opts = GetOpts(opts)
const memoized = memo.get(cache, key, opts)
if (memoized && opts.memoize !== false) {
return BB.resolve(memoized.entry)
@@ -161,7 +218,7 @@ module.exports.copy.byDigest = function cpDigest (cache, digest, dest, opts) {
return copy(true, cache, digest, dest, opts)
}
function copy (byDigest, cache, key, dest, opts) {
opts = opts || {}
opts = GetOpts(opts)
if (read.copy) {
return (
byDigest ? BB.resolve(null) : index.find(cache, key, opts)
@@ -180,11 +237,11 @@ function copy (byDigest, cache, key, dest, opts) {
} else {
return getData(byDigest, cache, key, opts).then(res => {
return fs.writeFileAsync(dest, byDigest ? res : res.data)
.then(() => byDigest ? key : {
metadata: res.metadata,
size: res.size,
integrity: res.integrity
})
.then(() => byDigest ? key : {
metadata: res.metadata,
size: res.size,
integrity: res.integrity
})
})
}
}
+112 -42
View File
@@ -3,21 +3,25 @@
const BB = require('bluebird')
const contentPath = require('./path')
const figgyPudding = require('figgy-pudding')
const fs = require('graceful-fs')
const PassThrough = require('stream').PassThrough
const pipe = BB.promisify(require('mississippi').pipe)
const ssri = require('ssri')
const Y = require('../util/y.js')
BB.promisifyAll(fs)
const lstatAsync = BB.promisify(fs.lstat)
const readFileAsync = BB.promisify(fs.readFile)
const ReadOpts = figgyPudding({
size: {}
})
module.exports = read
function read (cache, integrity, opts) {
opts = opts || {}
return pickContentSri(cache, integrity).then(content => {
const sri = content.sri
const cpath = contentPath(cache, sri)
return fs.readFileAsync(cpath, null).then(data => {
opts = ReadOpts(opts)
return withContentSri(cache, integrity, (cpath, sri) => {
return readFileAsync(cpath, null).then(data => {
if (typeof opts.size === 'number' && opts.size !== data.length) {
throw sizeError(opts.size, data.length)
} else if (ssri.checkData(data, sri)) {
@@ -29,17 +33,31 @@ function read (cache, integrity, opts) {
})
}
module.exports.sync = readSync
function readSync (cache, integrity, opts) {
opts = ReadOpts(opts)
return withContentSriSync(cache, integrity, (cpath, sri) => {
const data = fs.readFileSync(cpath)
if (typeof opts.size === 'number' && opts.size !== data.length) {
throw sizeError(opts.size, data.length)
} else if (ssri.checkData(data, sri)) {
return data
} else {
throw integrityError(sri, cpath)
}
})
}
module.exports.stream = readStream
module.exports.readStream = readStream
function readStream (cache, integrity, opts) {
opts = opts || {}
opts = ReadOpts(opts)
const stream = new PassThrough()
pickContentSri(
cache, integrity
).then(content => {
const sri = content.sri
withContentSri(cache, integrity, (cpath, sri) => {
return lstatAsync(cpath).then(stat => ({cpath, sri, stat}))
}).then(({cpath, sri, stat}) => {
return pipe(
fs.createReadStream(contentPath(cache, sri)),
fs.createReadStream(cpath),
ssri.integrityStream({
integrity: sri,
size: opts.size
@@ -52,37 +70,93 @@ function readStream (cache, integrity, opts) {
return stream
}
let copyFileAsync
if (fs.copyFile) {
module.exports.copy = copy
module.exports.copy.sync = copySync
copyFileAsync = BB.promisify(fs.copyFile)
}
function copy (cache, integrity, dest, opts) {
opts = opts || {}
return pickContentSri(cache, integrity).then(content => {
const sri = content.sri
const cpath = contentPath(cache, sri)
return fs.copyFileAsync(cpath, dest).then(() => content.size)
opts = ReadOpts(opts)
return withContentSri(cache, integrity, (cpath, sri) => {
return copyFileAsync(cpath, dest)
})
}
function copySync (cache, integrity, dest, opts) {
opts = ReadOpts(opts)
return withContentSriSync(cache, integrity, (cpath, sri) => {
return fs.copyFileSync(cpath, dest)
})
}
module.exports.hasContent = hasContent
function hasContent (cache, integrity) {
if (!integrity) { return BB.resolve(false) }
return pickContentSri(cache, integrity)
.catch({code: 'ENOENT'}, () => false)
.catch({code: 'EPERM'}, err => {
if (process.platform !== 'win32') {
throw err
} else {
return false
return withContentSri(cache, integrity, (cpath, sri) => {
return lstatAsync(cpath).then(stat => ({size: stat.size, sri, stat}))
}).catch(err => {
if (err.code === 'ENOENT') { return false }
if (err.code === 'EPERM') {
if (process.platform !== 'win32') {
throw err
} else {
return false
}
}
}).then(content => {
if (!content.sri) return false
return ({ sri: content.sri, size: content.stat.size })
})
}
module.exports._pickContentSri = pickContentSri
function pickContentSri (cache, integrity) {
module.exports.hasContent.sync = hasContentSync
function hasContentSync (cache, integrity) {
if (!integrity) { return false }
return withContentSriSync(cache, integrity, (cpath, sri) => {
try {
const stat = fs.lstatSync(cpath)
return {size: stat.size, sri, stat}
} catch (err) {
if (err.code === 'ENOENT') { return false }
if (err.code === 'EPERM') {
if (process.platform !== 'win32') {
throw err
} else {
return false
}
}
}
})
}
function withContentSri (cache, integrity, fn) {
return BB.try(() => {
const sri = ssri.parse(integrity)
// If `integrity` has multiple entries, pick the first digest
// with available local data.
const algo = sri.pickAlgorithm()
const digests = sri[algo]
if (digests.length <= 1) {
const cpath = contentPath(cache, digests[0])
return fn(cpath, digests[0])
} else {
return BB.any(sri[sri.pickAlgorithm()].map(meta => {
return withContentSri(cache, meta, fn)
}, {concurrency: 1}))
.catch(err => {
if ([].some.call(err, e => e.code === 'ENOENT')) {
throw Object.assign(
new Error('No matching content found for ' + sri.toString()),
{code: 'ENOENT'}
)
} else {
throw err[0]
}
})
}
})
}
function withContentSriSync (cache, integrity, fn) {
const sri = ssri.parse(integrity)
// If `integrity` has multiple entries, pick the first digest
// with available local data.
@@ -90,21 +164,17 @@ function pickContentSri (cache, integrity) {
const digests = sri[algo]
if (digests.length <= 1) {
const cpath = contentPath(cache, digests[0])
return fs.lstatAsync(cpath).then(stat => ({ sri: digests[0], stat }))
return fn(cpath, digests[0])
} else {
return BB.any(sri[sri.pickAlgorithm()].map(meta => {
return pickContentSri(cache, meta)
}))
.catch(err => {
if ([].some.call(err, e => e.code === 'ENOENT')) {
throw Object.assign(
new Error('No matching content found for ' + sri.toString()),
{code: 'ENOENT'}
)
} else {
throw err[0]
let lastErr = null
for (const meta of sri[sri.pickAlgorithm()]) {
try {
return withContentSriSync(cache, meta, fn)
} catch (err) {
lastErr = err
}
})
}
if (lastErr) { throw lastErr }
}
}
+3 -1
View File
@@ -28,7 +28,9 @@ function write (cache, data, opts) {
if (typeof opts.size === 'number' && data.length !== opts.size) {
return BB.reject(sizeError(opts.size, data.length))
}
const sri = ssri.fromData(data, opts)
const sri = ssri.fromData(data, {
algorithms: opts.algorithms
})
if (opts.integrity && !ssri.checkData(data, opts.integrity, opts)) {
return BB.reject(checksumError(opts.integrity, sri))
}
+96 -31
View File
@@ -4,6 +4,7 @@ const BB = require('bluebird')
const contentPath = require('./content/path')
const crypto = require('crypto')
const figgyPudding = require('figgy-pudding')
const fixOwner = require('./util/fix-owner')
const fs = require('graceful-fs')
const hashToSegments = require('./util/hash-to-segments')
@@ -29,9 +30,16 @@ module.exports.NotFoundError = class NotFoundError extends Error {
}
}
const IndexOpts = figgyPudding({
metadata: {},
size: {},
uid: {},
gid: {}
})
module.exports.insert = insert
function insert (cache, key, integrity, opts) {
opts = opts || {}
opts = IndexOpts(opts)
const bucket = bucketPath(cache, key)
const entry = {
key,
@@ -67,10 +75,36 @@ function insert (cache, key, integrity, opts) {
})
}
module.exports.insert.sync = insertSync
function insertSync (cache, key, integrity, opts) {
opts = IndexOpts(opts)
const bucket = bucketPath(cache, key)
const entry = {
key,
integrity: integrity && ssri.stringify(integrity),
time: Date.now(),
size: opts.size,
metadata: opts.metadata
}
fixOwner.mkdirfix.sync(path.dirname(bucket), opts.uid, opts.gid)
const stringified = JSON.stringify(entry)
fs.appendFileSync(
bucket, `\n${hashEntry(stringified)}\t${stringified}`
)
try {
fixOwner.chownr.sync(bucket, opts.uid, opts.gid)
} catch (err) {
if (err.code !== 'ENOENT') {
throw err
}
}
return formatEntry(cache, entry)
}
module.exports.find = find
function find (cache, key) {
const bucket = bucketPath(cache, key)
return bucketEntries(cache, bucket).then(entries => {
return bucketEntries(bucket).then(entries => {
return entries.reduce((latest, next) => {
if (next && next.key === key) {
return formatEntry(cache, next)
@@ -87,11 +121,36 @@ function find (cache, key) {
})
}
module.exports.find.sync = findSync
function findSync (cache, key) {
const bucket = bucketPath(cache, key)
try {
return bucketEntriesSync(bucket).reduce((latest, next) => {
if (next && next.key === key) {
return formatEntry(cache, next)
} else {
return latest
}
}, null)
} catch (err) {
if (err.code === 'ENOENT') {
return null
} else {
throw err
}
}
}
module.exports.delete = del
function del (cache, key, opts) {
return insert(cache, key, null, opts)
}
module.exports.delete.sync = delSync
function delSync (cache, key, opts) {
return insertSync(cache, key, null, opts)
}
module.exports.lsStream = lsStream
function lsStream (cache) {
const indexDir = bucketDir(cache)
@@ -108,7 +167,6 @@ function lsStream (cache) {
// "/cachename/<bucket 0xFF>/<bucket 0xFF>/*"
return readdirOrEmpty(subbucketPath).map(entry => {
const getKeyToEntry = bucketEntries(
cache,
path.join(subbucketPath, entry)
).reduce((acc, entry) => {
acc.set(entry.key, entry)
@@ -144,32 +202,39 @@ function ls (cache) {
})
}
function bucketEntries (cache, bucket, filter) {
function bucketEntries (bucket, filter) {
return readFileAsync(
bucket, 'utf8'
).then(data => {
let entries = []
data.split('\n').forEach(entry => {
if (!entry) { return }
const pieces = entry.split('\t')
if (!pieces[1] || hashEntry(pieces[1]) !== pieces[0]) {
// Hash is no good! Corruption or malice? Doesn't matter!
// EJECT EJECT
return
}
let obj
try {
obj = JSON.parse(pieces[1])
} catch (e) {
// Entry is corrupted!
return
}
if (obj) {
entries.push(obj)
}
})
return entries
).then(data => _bucketEntries(data, filter))
}
function bucketEntriesSync (bucket, filter) {
const data = fs.readFileSync(bucket, 'utf8')
return _bucketEntries(data, filter)
}
function _bucketEntries (data, filter) {
let entries = []
data.split('\n').forEach(entry => {
if (!entry) { return }
const pieces = entry.split('\t')
if (!pieces[1] || hashEntry(pieces[1]) !== pieces[0]) {
// Hash is no good! Corruption or malice? Doesn't matter!
// EJECT EJECT
return
}
let obj
try {
obj = JSON.parse(pieces[1])
} catch (e) {
// Entry is corrupted!
return
}
if (obj) {
entries.push(obj)
}
})
return entries
}
module.exports._bucketDir = bucketDir
@@ -197,9 +262,9 @@ function hashEntry (str) {
function hash (str, digest) {
return crypto
.createHash(digest)
.update(str)
.digest('hex')
.createHash(digest)
.update(str)
.digest('hex')
}
function formatEntry (cache, entry) {
@@ -217,8 +282,8 @@ function formatEntry (cache, entry) {
function readdirOrEmpty (dir) {
return readdirAsync(dir)
.catch({code: 'ENOENT'}, () => [])
.catch({code: 'ENOTDIR'}, () => [])
.catch({code: 'ENOENT'}, () => [])
.catch({code: 'ENOTDIR'}, () => [])
}
function nop () {
+46
View File
@@ -31,6 +31,34 @@ function fixOwner (filepath, uid, gid) {
)
}
module.exports.chownr.sync = fixOwnerSync
function fixOwnerSync (filepath, uid, gid) {
if (!process.getuid) {
// This platform doesn't need ownership fixing
return
}
if (typeof uid !== 'number' && typeof gid !== 'number') {
// There's no permissions override. Nothing to do here.
return
}
if ((typeof uid === 'number' && process.getuid() === uid) &&
(typeof gid === 'number' && process.getgid() === gid)) {
// No need to override if it's already what we used.
return
}
try {
chownr.sync(
filepath,
typeof uid === 'number' ? uid : process.getuid(),
typeof gid === 'number' ? gid : process.getgid()
)
} catch (err) {
if (err.code === 'ENOENT') {
return null
}
}
}
module.exports.mkdirfix = mkdirfix
function mkdirfix (p, uid, gid, cb) {
return mkdirp(p).then(made => {
@@ -42,3 +70,21 @@ function mkdirfix (p, uid, gid, cb) {
return fixOwner(p, uid, gid).then(() => null)
})
}
module.exports.mkdirfix.sync = mkdirfixSync
function mkdirfixSync (p, uid, gid) {
try {
const made = mkdirp.sync(p)
if (made) {
fixOwnerSync(made, uid, gid)
return made
}
} catch (err) {
if (err.code === 'EEXIST') {
fixOwnerSync(p, uid, gid)
return null
} else {
throw err
}
}
}
+10 -2
View File
@@ -2,14 +2,21 @@
const BB = require('bluebird')
const figgyPudding = require('figgy-pudding')
const fixOwner = require('./fix-owner')
const path = require('path')
const rimraf = BB.promisify(require('rimraf'))
const uniqueFilename = require('unique-filename')
const TmpOpts = figgyPudding({
tmpPrefix: {},
uid: {},
gid: {}
})
module.exports.mkdir = mktmpdir
function mktmpdir (cache, opts) {
opts = opts || {}
opts = TmpOpts(opts)
const tmpTarget = uniqueFilename(path.join(cache, 'tmp'), opts.tmpPrefix)
return fixOwner.mkdirfix(tmpTarget, opts.uid, opts.gid).then(() => {
return tmpTarget
@@ -22,11 +29,12 @@ function withTmp (cache, opts, cb) {
cb = opts
opts = null
}
opts = opts || {}
opts = TmpOpts(opts)
return BB.using(mktmpdir(cache, opts).disposer(rimraf), cb)
}
module.exports.fix = fixtmpdir
function fixtmpdir (cache, opts) {
opts = TmpOpts(opts)
return fixOwner(path.join(cache, 'tmp'), opts.uid, opts.gid)
}
+27 -13
View File
@@ -3,6 +3,7 @@
const BB = require('bluebird')
const contentPath = require('./content/path')
const figgyPudding = require('figgy-pudding')
const finished = BB.promisify(require('mississippi').finished)
const fixOwner = require('./util/fix-owner')
const fs = require('graceful-fs')
@@ -14,10 +15,22 @@ const ssri = require('ssri')
BB.promisifyAll(fs)
const VerifyOpts = figgyPudding({
concurrency: {
default: 20
},
filter: {},
log: {
default: { silly () {} }
},
uid: {},
gid: {}
})
module.exports = verify
function verify (cache, opts) {
opts = opts || {}
opts.log && opts.log.silly('verify', 'verifying cache at', cache)
opts = VerifyOpts(opts)
opts.log.silly('verify', 'verifying cache at', cache)
return BB.reduce([
markStartTime,
fixPerms,
@@ -40,7 +53,7 @@ function verify (cache, opts) {
})
}, {}).tap(stats => {
stats.runTime.total = stats.endTime - stats.startTime
opts.log && opts.log.silly('verify', 'verification finished for', cache, 'in', `${stats.runTime.total}ms`)
opts.log.silly('verify', 'verification finished for', cache, 'in', `${stats.runTime.total}ms`)
})
}
@@ -53,7 +66,7 @@ function markEndTime (cache, opts) {
}
function fixPerms (cache, opts) {
opts.log && opts.log.silly('verify', 'fixing cache permissions')
opts.log.silly('verify', 'fixing cache permissions')
return fixOwner.mkdirfix(cache, opts.uid, opts.gid).then(() => {
// TODO - fix file permissions too
return fixOwner.chownr(cache, opts.uid, opts.gid)
@@ -70,11 +83,11 @@ function fixPerms (cache, opts) {
// 5. If content is not marked as live, rimraf it.
//
function garbageCollect (cache, opts) {
opts.log && opts.log.silly('verify', 'garbage collecting content')
opts.log.silly('verify', 'garbage collecting content')
const indexStream = index.lsStream(cache)
const liveContent = new Set()
indexStream.on('data', entry => {
if (opts && opts.filter && !opts.filter(entry)) { return }
if (opts.filter && !opts.filter(entry)) { return }
liveContent.add(entry.integrity.toString())
})
return finished(indexStream).then(() => {
@@ -117,7 +130,7 @@ function garbageCollect (cache, opts) {
})
})
}
}, {concurrency: opts.concurrency || 20}))
}, {concurrency: opts.concurrency}))
})
})
}
@@ -141,7 +154,7 @@ function verifyContent (filepath, sri) {
}
function rebuildIndex (cache, opts) {
opts.log && opts.log.silly('verify', 'rebuilding index')
opts.log.silly('verify', 'rebuilding index')
return index.ls(cache).then(entries => {
const stats = {
missingContent: 0,
@@ -153,7 +166,7 @@ function rebuildIndex (cache, opts) {
if (entries.hasOwnProperty(k)) {
const hashed = index._hashKey(k)
const entry = entries[k]
const excluded = opts && opts.filter && !opts.filter(entry)
const excluded = opts.filter && !opts.filter(entry)
excluded && stats.rejectedEntries++
if (buckets[hashed] && !excluded) {
buckets[hashed].push(entry)
@@ -170,7 +183,7 @@ function rebuildIndex (cache, opts) {
}
return BB.map(Object.keys(buckets), key => {
return rebuildBucket(cache, buckets[key], stats, opts)
}, {concurrency: opts.concurrency || 20}).then(() => stats)
}, {concurrency: opts.concurrency}).then(() => stats)
})
}
@@ -184,7 +197,8 @@ function rebuildBucket (cache, bucket, stats, opts) {
return index.insert(cache, entry.key, entry.integrity, {
uid: opts.uid,
gid: opts.gid,
metadata: entry.metadata
metadata: entry.metadata,
size: entry.size
}).then(() => { stats.totalEntries++ })
}).catch({code: 'ENOENT'}, () => {
stats.rejectedEntries++
@@ -195,13 +209,13 @@ function rebuildBucket (cache, bucket, stats, opts) {
}
function cleanTmp (cache, opts) {
opts.log && opts.log.silly('verify', 'cleaning tmp directory')
opts.log.silly('verify', 'cleaning tmp directory')
return rimraf(path.join(cache, 'tmp'))
}
function writeVerifile (cache, opts) {
const verifile = path.join(cache, '_lastverified')
opts.log && opts.log.silly('verify', 'writing verifile to ' + verifile)
opts.log.silly('verify', 'writing verifile to ' + verifile)
return fs.writeFileAsync(verifile, '' + (+(new Date())))
}
+3
View File
@@ -18,12 +18,15 @@ x.ls.stream = cache => ls.stream(cache)
x.get = (cache, key, opts) => get(cache, key, opts)
x.get.byDigest = (cache, hash, opts) => get.byDigest(cache, hash, opts)
x.get.sync = (cache, key, opts) => get.sync(cache, key, opts)
x.get.sync.byDigest = (cache, key, opts) => get.sync.byDigest(cache, key, opts)
x.get.stream = (cache, key, opts) => get.stream(cache, key, opts)
x.get.stream.byDigest = (cache, hash, opts) => get.stream.byDigest(cache, hash, opts)
x.get.copy = (cache, key, dest, opts) => get.copy(cache, key, dest, opts)
x.get.copy.byDigest = (cache, hash, dest, opts) => get.copy.byDigest(cache, hash, dest, opts)
x.get.info = (cache, key) => get.info(cache, key)
x.get.hasContent = (cache, hash) => get.hasContent(cache, hash)
x.get.hasContent.sync = (cache, hash) => get.hasContent.sync(cache, hash)
x.put = (cache, key, data, opts) => put(cache, key, data, opts)
x.put.stream = (cache, key, opts) => put.stream(cache, key, opts)
+3
View File
@@ -18,12 +18,15 @@ x.ls.flujo = cache => ls.stream(cache)
x.saca = (cache, clave, ops) => get(cache, clave, ops)
x.saca.porHacheo = (cache, hacheo, ops) => get.byDigest(cache, hacheo, ops)
x.saca.sinc = (cache, clave, ops) => get.sync(cache, clave, ops)
x.saca.sinc.porHacheo = (cache, hacheo, ops) => get.sync.byDigest(cache, hacheo, ops)
x.saca.flujo = (cache, clave, ops) => get.stream(cache, clave, ops)
x.saca.flujo.porHacheo = (cache, hacheo, ops) => get.stream.byDigest(cache, hacheo, ops)
x.sava.copia = (cache, clave, destino, opts) => get.copy(cache, clave, destino, opts)
x.sava.copia.porHacheo = (cache, hacheo, destino, opts) => get.copy.byDigest(cache, hacheo, destino, opts)
x.saca.info = (cache, clave) => get.info(cache, clave)
x.saca.tieneDatos = (cache, hacheo) => get.hasContent(cache, hacheo)
x.saca.tieneDatos.sinc = (cache, hacheo) => get.hasContent.sync(cache, hacheo)
x.mete = (cache, clave, datos, ops) => put(cache, clave, datos, ops)
x.mete.flujo = (cache, clave, ops) => put.stream(cache, clave, ops)
-21
View File
@@ -1,21 +0,0 @@
# Change Log
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
<a name="4.0.0"></a>
# [4.0.0](https://github.com/yargs/y18n/compare/v3.2.1...v4.0.0) (2017-10-10)
### Bug Fixes
* allow support for falsy values like 0 in tagged literal ([#45](https://github.com/yargs/y18n/issues/45)) ([c926123](https://github.com/yargs/y18n/commit/c926123))
### Features
* **__:** added tagged template literal support ([#44](https://github.com/yargs/y18n/issues/44)) ([0598daf](https://github.com/yargs/y18n/commit/0598daf))
### BREAKING CHANGES
* **__:** dropping Node 0.10/Node 0.12 support
-13
View File
@@ -1,13 +0,0 @@
Copyright (c) 2015, Contributors
Permission to use, copy, modify, and/or distribute this software for any purpose
with or without fee is hereby granted, provided that the above copyright notice
and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.
-109
View File
@@ -1,109 +0,0 @@
# y18n
[![Build Status][travis-image]][travis-url]
[![Coverage Status][coveralls-image]][coveralls-url]
[![NPM version][npm-image]][npm-url]
[![js-standard-style][standard-image]][standard-url]
[![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg)](https://conventionalcommits.org)
The bare-bones internationalization library used by yargs.
Inspired by [i18n](https://www.npmjs.com/package/i18n).
## Examples
_simple string translation:_
```js
var __ = require('y18n').__
console.log(__('my awesome string %s', 'foo'))
```
output:
`my awesome string foo`
_using tagged template literals_
```js
var __ = require('y18n').__
var str = 'foo'
console.log(__`my awesome string ${str}`)
```
output:
`my awesome string foo`
_pluralization support:_
```js
var __n = require('y18n').__n
console.log(__n('one fish %s', '%d fishes %s', 2, 'foo'))
```
output:
`2 fishes foo`
## JSON Language Files
The JSON language files should be stored in a `./locales` folder.
File names correspond to locales, e.g., `en.json`, `pirate.json`.
When strings are observed for the first time they will be
added to the JSON file corresponding to the current locale.
## Methods
### require('y18n')(config)
Create an instance of y18n with the config provided, options include:
* `directory`: the locale directory, default `./locales`.
* `updateFiles`: should newly observed strings be updated in file, default `true`.
* `locale`: what locale should be used.
* `fallbackToLanguage`: should fallback to a language-only file (e.g. `en.json`)
be allowed if a file matching the locale does not exist (e.g. `en_US.json`),
default `true`.
### y18n.\_\_(str, arg, arg, arg)
Print a localized string, `%s` will be replaced with `arg`s.
This function can also be used as a tag for a template literal. You can use it
like this: <code>__&#96;hello ${'world'}&#96;</code>. This will be equivalent to
`__('hello %s', 'world')`.
### y18n.\_\_n(singularString, pluralString, count, arg, arg, arg)
Print a localized string with appropriate pluralization. If `%d` is provided
in the string, the `count` will replace this placeholder.
### y18n.setLocale(str)
Set the current locale being used.
### y18n.getLocale()
What locale is currently being used?
### y18n.updateLocale(obj)
Update the current locale with the key value pairs in `obj`.
## License
ISC
[travis-url]: https://travis-ci.org/yargs/y18n
[travis-image]: https://img.shields.io/travis/yargs/y18n.svg
[coveralls-url]: https://coveralls.io/github/yargs/y18n
[coveralls-image]: https://img.shields.io/coveralls/yargs/y18n.svg
[npm-url]: https://npmjs.org/package/y18n
[npm-image]: https://img.shields.io/npm/v/y18n.svg
[standard-image]: https://img.shields.io/badge/code%20style-standard-brightgreen.svg
[standard-url]: https://github.com/feross/standard
-188
View File
@@ -1,188 +0,0 @@
var fs = require('fs')
var path = require('path')
var util = require('util')
function Y18N (opts) {
// configurable options.
opts = opts || {}
this.directory = opts.directory || './locales'
this.updateFiles = typeof opts.updateFiles === 'boolean' ? opts.updateFiles : true
this.locale = opts.locale || 'en'
this.fallbackToLanguage = typeof opts.fallbackToLanguage === 'boolean' ? opts.fallbackToLanguage : true
// internal stuff.
this.cache = {}
this.writeQueue = []
}
Y18N.prototype.__ = function () {
if (typeof arguments[0] !== 'string') {
return this._taggedLiteral.apply(this, arguments)
}
var args = Array.prototype.slice.call(arguments)
var str = args.shift()
var cb = function () {} // start with noop.
if (typeof args[args.length - 1] === 'function') cb = args.pop()
cb = cb || function () {} // noop.
if (!this.cache[this.locale]) this._readLocaleFile()
// we've observed a new string, update the language file.
if (!this.cache[this.locale][str] && this.updateFiles) {
this.cache[this.locale][str] = str
// include the current directory and locale,
// since these values could change before the
// write is performed.
this._enqueueWrite([this.directory, this.locale, cb])
} else {
cb()
}
return util.format.apply(util, [this.cache[this.locale][str] || str].concat(args))
}
Y18N.prototype._taggedLiteral = function (parts) {
var args = arguments
var str = ''
parts.forEach(function (part, i) {
var arg = args[i + 1]
str += part
if (typeof arg !== 'undefined') {
str += '%s'
}
})
return this.__.apply(null, [str].concat([].slice.call(arguments, 1)))
}
Y18N.prototype._enqueueWrite = function (work) {
this.writeQueue.push(work)
if (this.writeQueue.length === 1) this._processWriteQueue()
}
Y18N.prototype._processWriteQueue = function () {
var _this = this
var work = this.writeQueue[0]
// destructure the enqueued work.
var directory = work[0]
var locale = work[1]
var cb = work[2]
var languageFile = this._resolveLocaleFile(directory, locale)
var serializedLocale = JSON.stringify(this.cache[locale], null, 2)
fs.writeFile(languageFile, serializedLocale, 'utf-8', function (err) {
_this.writeQueue.shift()
if (_this.writeQueue.length > 0) _this._processWriteQueue()
cb(err)
})
}
Y18N.prototype._readLocaleFile = function () {
var localeLookup = {}
var languageFile = this._resolveLocaleFile(this.directory, this.locale)
try {
localeLookup = JSON.parse(fs.readFileSync(languageFile, 'utf-8'))
} catch (err) {
if (err instanceof SyntaxError) {
err.message = 'syntax error in ' + languageFile
}
if (err.code === 'ENOENT') localeLookup = {}
else throw err
}
this.cache[this.locale] = localeLookup
}
Y18N.prototype._resolveLocaleFile = function (directory, locale) {
var file = path.resolve(directory, './', locale + '.json')
if (this.fallbackToLanguage && !this._fileExistsSync(file) && ~locale.lastIndexOf('_')) {
// attempt fallback to language only
var languageFile = path.resolve(directory, './', locale.split('_')[0] + '.json')
if (this._fileExistsSync(languageFile)) file = languageFile
}
return file
}
// this only exists because fs.existsSync() "will be deprecated"
// see https://nodejs.org/api/fs.html#fs_fs_existssync_path
Y18N.prototype._fileExistsSync = function (file) {
try {
return fs.statSync(file).isFile()
} catch (err) {
return false
}
}
Y18N.prototype.__n = function () {
var args = Array.prototype.slice.call(arguments)
var singular = args.shift()
var plural = args.shift()
var quantity = args.shift()
var cb = function () {} // start with noop.
if (typeof args[args.length - 1] === 'function') cb = args.pop()
if (!this.cache[this.locale]) this._readLocaleFile()
var str = quantity === 1 ? singular : plural
if (this.cache[this.locale][singular]) {
str = this.cache[this.locale][singular][quantity === 1 ? 'one' : 'other']
}
// we've observed a new string, update the language file.
if (!this.cache[this.locale][singular] && this.updateFiles) {
this.cache[this.locale][singular] = {
one: singular,
other: plural
}
// include the current directory and locale,
// since these values could change before the
// write is performed.
this._enqueueWrite([this.directory, this.locale, cb])
} else {
cb()
}
// if a %d placeholder is provided, add quantity
// to the arguments expanded by util.format.
var values = [str]
if (~str.indexOf('%d')) values.push(quantity)
return util.format.apply(util, values.concat(args))
}
Y18N.prototype.setLocale = function (locale) {
this.locale = locale
}
Y18N.prototype.getLocale = function () {
return this.locale
}
Y18N.prototype.updateLocale = function (obj) {
if (!this.cache[this.locale]) this._readLocaleFile()
for (var key in obj) {
this.cache[this.locale][key] = obj[key]
}
}
module.exports = function (opts) {
var y18n = new Y18N(opts)
// bind all functions to y18n, so that
// they can be used in isolation.
for (var key in y18n) {
if (typeof y18n[key] === 'function') {
y18n[key] = y18n[key].bind(y18n)
}
}
return y18n
}
-67
View File
@@ -1,67 +0,0 @@
{
"_from": "y18n@^4.0.0",
"_id": "y18n@4.0.0",
"_inBundle": false,
"_integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
"_location": "/cacache/y18n",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "y18n@^4.0.0",
"name": "y18n",
"escapedName": "y18n",
"rawSpec": "^4.0.0",
"saveSpec": null,
"fetchSpec": "^4.0.0"
},
"_requiredBy": [
"/cacache"
],
"_resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
"_shasum": "95ef94f85ecc81d007c264e190a120f0a3c8566b",
"_spec": "y18n@^4.0.0",
"_where": "C:\\xampp\\htdocs\\w4rpservices\\node_modules\\cacache",
"author": {
"name": "Ben Coe",
"email": "ben@npmjs.com"
},
"bugs": {
"url": "https://github.com/yargs/y18n/issues"
},
"bundleDependencies": false,
"deprecated": false,
"description": "the bare-bones internationalization library used by yargs",
"devDependencies": {
"chai": "^4.0.1",
"coveralls": "^3.0.0",
"mocha": "^4.0.1",
"nyc": "^11.0.1",
"rimraf": "^2.5.0",
"standard": "^10.0.0-beta.0",
"standard-version": "^4.2.0"
},
"files": [
"index.js"
],
"homepage": "https://github.com/yargs/y18n",
"keywords": [
"i18n",
"internationalization",
"yargs"
],
"license": "ISC",
"main": "index.js",
"name": "y18n",
"repository": {
"type": "git",
"url": "git+ssh://git@github.com/yargs/y18n.git"
},
"scripts": {
"coverage": "nyc report --reporter=text-lcov | coveralls",
"pretest": "standard",
"release": "standard-version",
"test": "nyc mocha"
},
"version": "4.0.0"
}
+28 -29
View File
@@ -1,27 +1,27 @@
{
"_from": "cacache@^10.0.4",
"_id": "cacache@10.0.4",
"_from": "cacache@^11.0.2",
"_id": "cacache@11.3.2",
"_inBundle": false,
"_integrity": "sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==",
"_integrity": "sha512-E0zP4EPGDOaT2chM08Als91eYnf8Z+eH1awwwVsngUmgppfM5jjJ8l3z5vO5p5w/I3LsiXawb1sW0VY65pQABg==",
"_location": "/cacache",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "cacache@^10.0.4",
"raw": "cacache@^11.0.2",
"name": "cacache",
"escapedName": "cacache",
"rawSpec": "^10.0.4",
"rawSpec": "^11.0.2",
"saveSpec": null,
"fetchSpec": "^10.0.4"
"fetchSpec": "^11.0.2"
},
"_requiredBy": [
"/uglifyjs-webpack-plugin"
"/terser-webpack-plugin"
],
"_resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz",
"_shasum": "6452367999eff9d4188aefd9a14e9d7c6a263460",
"_spec": "cacache@^10.0.4",
"_where": "C:\\xampp\\htdocs\\w4rpservices\\node_modules\\uglifyjs-webpack-plugin",
"_resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.2.tgz",
"_shasum": "2d81e308e3d258ca38125b676b98b2ac9ce69bfa",
"_spec": "cacache@^11.0.2",
"_where": "C:\\xampp\\htdocs\\w4rpservices\\node_modules\\terser-webpack-plugin",
"author": {
"name": "Kat Marchán",
"email": "kzm@sykosomatic.org"
@@ -53,33 +53,32 @@
}
],
"dependencies": {
"bluebird": "^3.5.1",
"chownr": "^1.0.1",
"glob": "^7.1.2",
"graceful-fs": "^4.1.11",
"lru-cache": "^4.1.1",
"mississippi": "^2.0.0",
"bluebird": "^3.5.3",
"chownr": "^1.1.1",
"figgy-pudding": "^3.5.1",
"glob": "^7.1.3",
"graceful-fs": "^4.1.15",
"lru-cache": "^5.1.1",
"mississippi": "^3.0.0",
"mkdirp": "^0.5.1",
"move-concurrently": "^1.0.1",
"promise-inflight": "^1.0.1",
"rimraf": "^2.6.2",
"ssri": "^5.2.4",
"unique-filename": "^1.1.0",
"ssri": "^6.0.1",
"unique-filename": "^1.1.1",
"y18n": "^4.0.0"
},
"deprecated": false,
"description": "Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.",
"devDependencies": {
"benchmark": "^2.1.4",
"chalk": "^2.3.1",
"cross-env": "^5.1.3",
"nyc": "^11.4.1",
"chalk": "^2.3.2",
"cross-env": "^5.1.4",
"require-inject": "^1.4.2",
"safe-buffer": "^5.1.1",
"standard": "^10.0.3",
"standard-version": "^4.3.0",
"tacks": "^1.2.2",
"tap": "^11.1.0",
"standard": "^11.0.1",
"standard-version": "^4.4.0",
"tacks": "^1.2.7",
"tap": "^12.1.1",
"weallbehave": "^1.2.0",
"weallcontribute": "^1.0.8"
},
@@ -117,10 +116,10 @@
"prerelease": "npm t",
"pretest": "standard",
"release": "standard-version -s",
"test": "cross-env CACACHE_UPDATE_LOCALE_FILES=true nyc --all -- tap -J test/*.js",
"test": "cross-env CACACHE_UPDATE_LOCALE_FILES=true tap --coverage --nyc-arg=--all -J test/*.js",
"test-docker": "docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test",
"update-coc": "weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'",
"update-contrib": "weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"
},
"version": "10.0.4"
"version": "11.3.2"
}
+24 -8
View File
@@ -1,17 +1,35 @@
'use strict'
const figgyPudding = require('figgy-pudding')
const index = require('./lib/entry-index')
const memo = require('./lib/memoization')
const write = require('./lib/content/write')
const to = require('mississippi').to
const PutOpts = figgyPudding({
algorithms: {
default: ['sha512']
},
integrity: {},
memoize: {},
metadata: {},
pickAlgorithm: {},
size: {},
tmpPrefix: {},
uid: {},
gid: {},
single: {},
sep: {},
strict: {}
})
module.exports = putData
function putData (cache, key, data, opts) {
opts = opts || {}
opts = PutOpts(opts)
return write(cache, data, opts).then(res => {
// TODO - stop modifying opts
opts.size = res.size
return index.insert(cache, key, res.integrity, opts).then(entry => {
return index.insert(
cache, key, res.integrity, opts.concat({size: res.size})
).then(entry => {
if (opts.memoize) {
memo.put(cache, entry, data, opts)
}
@@ -22,7 +40,7 @@ function putData (cache, key, data, opts) {
module.exports.stream = putStream
function putStream (cache, key, opts) {
opts = opts || {}
opts = PutOpts(opts)
let integrity
let size
const contentStream = write.stream(
@@ -45,9 +63,7 @@ function putStream (cache, key, opts) {
})
}, cb => {
contentStream.end(() => {
// TODO - stop modifying `opts`
opts.size = size
index.insert(cache, key, integrity, opts).then(entry => {
index.insert(cache, key, integrity, opts.concat({size})).then(entry => {
if (opts.memoize) {
memo.put(cache, entry, Buffer.concat(memoData, memoTotal), opts)
}