@jsonic/multisource
Advanced tools
Comparing version 0.0.8 to 0.1.0
@@ -1,13 +0,44 @@ | ||
import { Plugin, Context } from 'jsonic'; | ||
import { makeMemResolver } from './resolver/mem'; | ||
import { makeFileResolver } from './resolver/file'; | ||
interface Resolution { | ||
path: string; | ||
full: string; | ||
base: string; | ||
import { Jsonic, Context, Rule, Plugin } from 'jsonic'; | ||
interface MultiSourceMeta { | ||
path?: string; | ||
deps?: DependencyMap; | ||
} | ||
declare const NONE = ""; | ||
declare type MultiSourceOptions = { | ||
resolver: Resolver; | ||
path?: string; | ||
markchar?: string; | ||
processor?: { | ||
[kind: string]: Processor; | ||
}; | ||
implictExt?: []; | ||
}; | ||
declare type PathSpec = { | ||
kind: string; | ||
path?: string; | ||
full?: string; | ||
base?: string; | ||
abs: boolean; | ||
}; | ||
declare type Resolution = PathSpec & { | ||
src?: string; | ||
} | ||
declare type Resolver = (path: string, ctx?: Context) => Resolution; | ||
val?: any; | ||
found: boolean; | ||
}; | ||
declare type Resolver = (spec: PathSpec, popts: MultiSourceOptions, rule: Rule, ctx: Context, jsonic: Jsonic) => Resolution; | ||
declare type Processor = (res: Resolution, popts: MultiSourceOptions, rule: Rule, ctx: Context, jsonic: Jsonic) => void; | ||
declare type Dependency = { | ||
tar: string | typeof TOP; | ||
src: string; | ||
wen: number; | ||
}; | ||
declare type DependencyMap = { | ||
[tar_full_path: string]: { | ||
[src_full_path: string]: Dependency; | ||
}; | ||
}; | ||
declare const TOP: unique symbol; | ||
declare let MultiSource: Plugin; | ||
export { MultiSource, Resolver, Resolution, TOP, Context, makeFileResolver, makeMemResolver, }; | ||
declare const MultiSource: Plugin; | ||
declare function resolvePathSpec(popts: MultiSourceOptions, ctx: Context, spec: any, resolvefolder: (path: string) => string): PathSpec; | ||
export type { Resolver, Resolution, Processor, MultiSourceOptions, Dependency, DependencyMap, MultiSourceMeta, PathSpec, }; | ||
export { MultiSource, resolvePathSpec, NONE, TOP, }; |
@@ -0,84 +1,103 @@ | ||
"use strict"; | ||
/* Copyright (c) 2021 Richard Rodger, MIT License */ | ||
/* $lab:coverage:off$ */ | ||
'use strict'; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.makeMemResolver = exports.makeFileResolver = exports.TOP = exports.MultiSource = void 0; | ||
const jsonic_1 = require("jsonic"); | ||
// TODO: get package sub file refs working with ts | ||
const mem_1 = require("./resolver/mem"); | ||
Object.defineProperty(exports, "makeMemResolver", { enumerable: true, get: function () { return mem_1.makeMemResolver; } }); | ||
const file_1 = require("./resolver/file"); | ||
Object.defineProperty(exports, "makeFileResolver", { enumerable: true, get: function () { return file_1.makeFileResolver; } }); | ||
//import { Json } from './json' | ||
//import { Csv } from './csv' | ||
/* $lab:coverage:on$ */ | ||
// TODO: .jsonic suffix optional | ||
// TODO: jsonic-cli should provide basepath | ||
// TODO: auto load index.jsonic, index.<folder-name>.jsonic | ||
let DEFAULTS = { | ||
markchar: '@', | ||
}; | ||
exports.TOP = exports.NONE = exports.resolvePathSpec = exports.MultiSource = void 0; | ||
const directive_1 = require("@jsonic/directive"); | ||
const jsonic_1 = require("./processor/jsonic"); | ||
const js_1 = require("./processor/js"); | ||
// Unknown source reference file extension. | ||
const NONE = ''; | ||
exports.NONE = NONE; | ||
// The top of the dependence tree. | ||
const TOP = Symbol('TOP'); | ||
exports.TOP = TOP; | ||
let MultiSource = function multisource(jsonic) { | ||
let popts = jsonic_1.util.deep({}, DEFAULTS, jsonic.options.plugin.multisource); | ||
let markchar = popts.markchar; | ||
let resolver = popts.resolver; | ||
let tn = '#T<' + markchar + '>'; | ||
const MultiSource = (jsonic, popts) => { | ||
const markchar = popts.markchar; | ||
const resolver = popts.resolver; | ||
const processor = popts.processor; | ||
// Normalize implicit extensions to format `.name`. | ||
const implictExt = (popts.implictExt || []); | ||
for (let extI = 0; extI < implictExt.length; extI++) { | ||
let ext = implictExt[extI]; | ||
implictExt[extI] = ext.startsWith('.') ? ext : '.' + ext; | ||
} | ||
jsonic.options({ | ||
token: { | ||
[tn]: { c: markchar } | ||
}, | ||
error: { | ||
multifile_unsupported_file: 'unsupported file: $path' | ||
multisource_not_found: 'source not found: $path', | ||
}, | ||
hint: { | ||
multifile_unsupported_file: `This file type is not supported and cannot be parsed: $path.`, | ||
multisource_not_found: 'TODO: PATH: $path DETAILS: $details', | ||
}, | ||
}); | ||
// These inherit previous plugins - they are not clean new instances. | ||
//let json = jsonic.make().use(Json, jsonic.options.plugin.json || {}) | ||
//let csv = jsonic.make().use(Csv, jsonic.options.plugin.csv || {}) | ||
let ST = jsonic.token.ST; | ||
let AT = jsonic.token(tn); | ||
jsonic.rule('val', (rs) => { | ||
rs.def.open.push({ s: [AT, ST] }); | ||
let orig_bc = rs.def.bc; | ||
rs.def.bc = function (rule, ctx) { | ||
if (rule.open[0] && AT === rule.open[0].tin) { | ||
// console.log('MS res meta', ctx.meta) | ||
let val = undefined; | ||
let path = rule.open[1].val; | ||
let res = resolver(path, ctx); | ||
if (null != res.src) { | ||
let msmeta = ctx.meta.multisource || {}; | ||
let meta = { | ||
...ctx.meta, | ||
multisource: { | ||
...msmeta, | ||
path: res.full | ||
} | ||
}; | ||
// console.log('MSMETA path', path, res.full) | ||
val = jsonic(res.src, meta); | ||
if (msmeta.deps) { | ||
let depmap = msmeta.deps; | ||
let parent = (msmeta.path || TOP); | ||
if (null != parent) { | ||
(depmap[parent] = depmap[parent] || {})[res.full] = { | ||
tar: parent, | ||
src: res.full, | ||
wen: Date.now() | ||
}; | ||
} | ||
} | ||
} | ||
rule.open[0].val = val; | ||
// Define a directive that can load content from multiple sources. | ||
let dopts = { | ||
name: 'multisource', | ||
open: markchar, | ||
action: (rule, ctx) => { | ||
var _a; | ||
let spec = rule.child.node; | ||
let res = resolver(spec, popts, rule, ctx, jsonic); | ||
if (!res.found) { | ||
return (_a = rule.parent) === null || _a === void 0 ? void 0 : _a.o0.bad('multisource_not_found', { ...res }); | ||
} | ||
return orig_bc(...arguments); | ||
}; | ||
return rs; | ||
}); | ||
res.kind = null == res.kind ? NONE : res.kind; | ||
let proc = processor[res.kind] || processor[NONE]; | ||
proc(res, popts, rule, ctx, jsonic); | ||
rule.node = res.val; | ||
}, | ||
}; | ||
jsonic.use(directive_1.Directive, dopts); | ||
}; | ||
exports.MultiSource = MultiSource; | ||
// Convenience maker for Processors | ||
function makeProcessor(process) { | ||
return (res) => (res.val = process(res.src, res)); | ||
} | ||
// Default is just to insert file contents as a string. | ||
const defaultProcessor = makeProcessor((src) => src); | ||
// TODO: use json plugin to get better error msgs. | ||
const jsonProcessor = makeProcessor((src) => null == src ? undefined : JSON.parse(src)); | ||
const jsonicProcessor = (0, jsonic_1.makeJsonicProcessor)(); | ||
const jsProcessor = (0, js_1.makeJavaScriptProcessor)(); | ||
MultiSource.defaults = { | ||
markchar: '@', | ||
processor: { | ||
[NONE]: defaultProcessor, | ||
jsonic: jsonicProcessor, | ||
jsc: jsonicProcessor, | ||
json: jsonProcessor, | ||
js: jsProcessor, | ||
}, | ||
implictExt: ['jsonic', 'jsc', 'json', 'js'], | ||
}; | ||
function resolvePathSpec(popts, ctx, spec, resolvefolder) { | ||
var _a; | ||
let msmeta = (_a = ctx.meta) === null || _a === void 0 ? void 0 : _a.multisource; | ||
let base = resolvefolder(null == msmeta || null == msmeta.path ? popts.path : msmeta.path); | ||
let path = 'string' === typeof spec | ||
? spec | ||
: null != spec.path | ||
? '' + spec.path | ||
: undefined; | ||
let abs = !!((path === null || path === void 0 ? void 0 : path.startsWith('/')) || (path === null || path === void 0 ? void 0 : path.startsWith('\\'))); | ||
let full = abs | ||
? path | ||
: null != path && '' != path | ||
? null != base && '' != base | ||
? base + '/' + path | ||
: path | ||
: undefined; | ||
let kind = null == full ? NONE : (full.match(/\.([^.]*)$/) || [NONE, NONE])[1]; | ||
let res = { | ||
kind, | ||
path, | ||
full, | ||
base, | ||
abs, | ||
found: false, | ||
}; | ||
// console.log('RES', res) | ||
return res; | ||
} | ||
exports.resolvePathSpec = resolvePathSpec; | ||
//# sourceMappingURL=multisource.js.map |
import { Resolver } from '../multisource'; | ||
declare function makeFileResolver(): Resolver; | ||
export { makeFileResolver }; | ||
export { makeFileResolver, }; |
@@ -9,29 +9,52 @@ "use strict"; | ||
const path_1 = __importDefault(require("path")); | ||
const multisource_1 = require("../multisource"); | ||
const mem_1 = require("./mem"); | ||
function makeFileResolver() { | ||
return function FileResolver(path, ctx) { | ||
let msmeta = ctx && ctx.meta && ctx.meta.multisource || {}; | ||
let popts = ctx && ctx.opts && ctx.opts && | ||
ctx.opts.plugin && ctx.opts.plugin.multisource || {}; | ||
let basefile = null == msmeta.path ? | ||
null == popts.path ? | ||
path : popts.path : msmeta.path; | ||
let fstats = fs_1.default.statSync(basefile); | ||
let basepath = basefile; | ||
if (fstats.isFile()) { | ||
let basedesc = path_1.default.parse(basefile); | ||
basepath = basedesc.dir; | ||
return function FileResolver(spec, popts, _rule, ctx) { | ||
let ps = (0, multisource_1.resolvePathSpec)(popts, ctx, spec, resolvefolder); | ||
let src = undefined; | ||
// console.log(ps) | ||
if (null != ps.full) { | ||
ps.full = path_1.default.resolve(ps.full); | ||
src = load(ps.full); | ||
if (null == src && multisource_1.NONE === ps.kind) { | ||
let potentials = (0, mem_1.buildPotentials)(ps, popts, (...s) => path_1.default.resolve(s.reduce((a, p) => path_1.default.join(a, p)))); | ||
for (let path of potentials) { | ||
if (null != (src = load(path))) { | ||
ps.full = path; | ||
ps.kind = (path.match(/\.([^.]*)$/) || [multisource_1.NONE, multisource_1.NONE])[1]; | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
let isabsolute = path_1.default.isAbsolute(path); | ||
let fullpath = isabsolute ? path : | ||
(null == basepath ? path : path_1.default.resolve(basepath, path)); | ||
let src = fs_1.default.readFileSync(fullpath).toString(); | ||
return { | ||
path: path, | ||
full: fullpath, | ||
base: basepath, | ||
let res = { | ||
...ps, | ||
src, | ||
found: null != src | ||
}; | ||
return res; | ||
}; | ||
} | ||
exports.makeFileResolver = makeFileResolver; | ||
function resolvefolder(path) { | ||
let folder = path; | ||
let pathstats = fs_1.default.statSync(path); | ||
if (pathstats.isFile()) { | ||
let pathdesc = path_1.default.parse(path); | ||
folder = pathdesc.dir; | ||
} | ||
return folder; | ||
} | ||
// TODO: in multisource.ts, generate an error token if cannot resolve | ||
function load(path) { | ||
// console.log('LOAD', path) | ||
try { | ||
return fs_1.default.readFileSync(path).toString(); | ||
} | ||
catch (e) { | ||
// NOTE: don't need this, as in all cases, we consider failed | ||
// reads to indicate non-existence. | ||
} | ||
} | ||
//# sourceMappingURL=file.js.map |
@@ -1,5 +0,6 @@ | ||
import { Resolver } from '../multisource'; | ||
declare function makeMemResolver(map: { | ||
import { MultiSourceOptions, Resolver, PathSpec } from '../multisource'; | ||
declare function makeMemResolver(filemap: { | ||
[fullpath: string]: string; | ||
}): Resolver; | ||
export { makeMemResolver }; | ||
declare function buildPotentials(ps: PathSpec, popts: MultiSourceOptions, pathjoin: (...parts: string[]) => string): string[]; | ||
export { buildPotentials, makeMemResolver, }; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.makeMemResolver = void 0; | ||
function makeMemResolver(map) { | ||
return function MemResolver(path, ctx) { | ||
let msmeta = ctx && ctx.meta && ctx.meta.multisource || {}; | ||
let popts = ctx && ctx.opts && ctx.opts && | ||
ctx.opts.plugin && ctx.opts.plugin.multisource || {}; | ||
let basepath = null == msmeta.path ? popts.path : msmeta.path; | ||
let isabsolute = path.startsWith('/'); | ||
let fullpath = isabsolute ? path : (null == basepath ? '' : basepath) + '/' + path; | ||
//console.log('MEM', path, basepath, isabsolute, fullpath) | ||
let src = map[fullpath]; | ||
return { | ||
path: path, | ||
full: fullpath, | ||
base: basepath, | ||
exports.makeMemResolver = exports.buildPotentials = void 0; | ||
const multisource_1 = require("../multisource"); | ||
function makeMemResolver(filemap) { | ||
return function MemResolver(spec, popts, _rule, ctx) { | ||
let ps = (0, multisource_1.resolvePathSpec)(popts, ctx, spec, makeresolvefolder(filemap)); | ||
let src = undefined; | ||
if (null != ps.full) { | ||
src = filemap[ps.full]; | ||
if (null == src && multisource_1.NONE === ps.kind) { | ||
let potentials = buildPotentials(ps, popts, (...s) => s.reduce((a, p) => a + '/' + p)); | ||
for (let path of potentials) { | ||
if (null != (src = filemap[path])) { | ||
ps.full = path; | ||
ps.kind = (path.match(/\.([^.]*)$/) || [multisource_1.NONE, multisource_1.NONE])[1]; | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
let res = { | ||
...ps, | ||
src, | ||
found: null != src | ||
}; | ||
return res; | ||
}; | ||
} | ||
exports.makeMemResolver = makeMemResolver; | ||
function makeresolvefolder(filemap) { | ||
return function resolvefolder(path) { | ||
let folder = path; | ||
if (filemap[path]) { | ||
folder = (path | ||
.replace(/[\\\/]+$/, '') | ||
.match(/[\\\/]+([^\\\/]+)$/) || ['', ''])[1]; | ||
// console.log('PF', path, folder) | ||
} | ||
// console.log('RF', folder) | ||
return folder; | ||
}; | ||
} | ||
function buildPotentials(ps, popts, pathjoin) { | ||
let full = ps.full; | ||
let potentials = []; | ||
let implictExt = popts.implictExt || []; | ||
// Implicit extensions. | ||
for (let ext of implictExt) { | ||
potentials.push(full + ext); | ||
} | ||
// Folder index file. | ||
for (let ext of implictExt) { | ||
potentials.push(pathjoin(full, 'index' + ext)); | ||
} | ||
// Folder index file (includes folder name). | ||
if (null != ps.path) { | ||
let folder = (ps.path | ||
.replace(/[\\\/]+$/, '') | ||
.match(/[^\\\/]+$/) || [])[0]; | ||
if (null != folder) { | ||
for (let ext of implictExt) { | ||
potentials.push(pathjoin(full, 'index.' + folder + ext)); | ||
} | ||
} | ||
} | ||
// console.log(potentials) | ||
return potentials; | ||
} | ||
exports.buildPotentials = buildPotentials; | ||
//# sourceMappingURL=mem.js.map |
{ | ||
"name": "@jsonic/multisource", | ||
"version": "0.0.8", | ||
"version": "0.1.0", | ||
"description": "", | ||
@@ -8,15 +8,28 @@ "main": "dist/multisource.js", | ||
"types": "dist/multisource.d.ts", | ||
"homepage": "https://github.com/jsonicjs/multisource", | ||
"keywords": [ | ||
"pattern", | ||
"matcher", | ||
"object", | ||
"property", | ||
"json" | ||
], | ||
"author": "Richard Rodger, http://richardrodger.com", | ||
"repository": { | ||
"type": "git", | ||
"url": "git://github.com/jsonicjs/multisource.git" | ||
}, | ||
"scripts": { | ||
"test": "jest --coverage", | ||
"test-some": "jest -t", | ||
"test-watch": "jest --coverage --watchAll", | ||
"watch": "tsc -w -d", | ||
"build": "tsc -d", | ||
"test": "lab -v -P test -t 50 --sourcemaps --transform node_modules/lab-transform-typescript -r console -o stdout -r html -o test/coverage.html", | ||
"test-some": "lab -v -P test --sourcemaps --transform node_modules/lab-transform-typescript -g", | ||
"test-web": "echo no-test-web", | ||
"build": "tsc -d && cp dist/multisource.js dist/multisource.min.js && browserify -o dist/multisource.min.js -e dist/multisource.js -s @JsonicMultiSource -im -i assert -p tinyify", | ||
"prettier": "prettier --write --no-semi --single-quote **/*.ts", | ||
"clean": "rm -rf node_modules yarn.lock package-lock.json", | ||
"reset": "npm run clean && npm i && npm run build && npm test", | ||
"reset": "npm run clean && npm i && npm test", | ||
"repo-tag": "REPO_VERSION=`node -e \"console.log(require('./package').version)\"` && echo TAG: v$REPO_VERSION && git commit -a -m v$REPO_VERSION && git push && git tag v$REPO_VERSION && git push --tags;", | ||
"repo-publish": "npm run clean && npm i && npm run repo-publish-quick", | ||
"repo-publish-quick": "npm run build && npm run test && npm run test-web && npm run repo-tag && npm publish --registry http://registry.npmjs.org --access=public" | ||
"repo-publish-quick": "npm run prettier && npm run build && npm run test && npm run repo-tag && npm publish --access public --registry http://registry.npmjs.org " | ||
}, | ||
"author": "", | ||
"license": "MIT", | ||
@@ -26,14 +39,19 @@ "files": [ | ||
"*.js", | ||
"lib", | ||
"*.map", | ||
"LICENSE", | ||
"resolver", | ||
"src", | ||
"dist" | ||
], | ||
"devDependencies": { | ||
"jsonic": "jsonicjs/jsonic#4edd639987b75ef62a74e3904fb890f59d21379c", | ||
"@hapi/code": "^8.0.3", | ||
"@hapi/lab": "^24.3.0", | ||
"lab-transform-typescript": "^3.0.1", | ||
"typescript": "^4.3.5" | ||
"@types/jest": "^27.0.1", | ||
"jest": "^27.1.1", | ||
"jsonic": "github:jsonicjs/jsonic#nextgen", | ||
"prettier": "^2.4.0", | ||
"tinyify": "^3.0.0", | ||
"ts-jest": "^27.0.5", | ||
"typescript": "^4.4.2" | ||
}, | ||
"dependencies": { | ||
"@jsonic/directive": "^0.3.0" | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
No contributors or author data
MaintenancePackage does not specify a list of contributors or an author in package.json.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
42754
26
783
1
1
7
3
3
+ Added@jsonic/directive@^0.3.0
+ Added@jsonic/directive@0.3.0(transitive)