nav tabs on admin dashboard
This commit is contained in:
+97
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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]
|
||||
[](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>__`hello ${'world'}`</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
@@ -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
@@ -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
@@ -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
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user