@jsonic/multisource 0.0.7 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/multisource.d.ts +42 -11
- package/dist/multisource.js +89 -70
- package/dist/multisource.js.map +1 -1
- package/dist/multisource.min.js +1 -0
- package/dist/processor/js.d.ts +5 -0
- package/dist/processor/js.js +27 -0
- package/dist/processor/js.js.map +1 -0
- package/dist/processor/jsonic.d.ts +3 -0
- package/dist/processor/jsonic.js +39 -0
- package/dist/processor/jsonic.js.map +1 -0
- package/dist/resolver/file.d.ts +1 -1
- package/dist/resolver/file.js +43 -20
- package/dist/resolver/file.js.map +1 -1
- package/dist/resolver/mem.d.ts +4 -3
- package/dist/resolver/mem.js +63 -15
- package/dist/resolver/mem.js.map +1 -1
- package/jest.config.js +9 -0
- package/package.json +36 -15
- package/src/multisource.ts +217 -0
- package/src/processor/js.ts +42 -0
- package/src/processor/jsonic.ts +63 -0
- package/src/resolver/file.ts +91 -0
- package/src/resolver/mem.ts +110 -0
- package/dist/test/multisource.test.d.ts +0 -1
- package/dist/test/multisource.test.js +0 -85
- package/dist/test/multisource.test.js.map +0 -1
- package/multisource.ts +0 -152
- package/resolver/file.ts +0 -49
- package/resolver/mem.ts +0 -36
package/package.json
CHANGED
|
@@ -1,37 +1,58 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jsonic/multisource",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/multisource.js",
|
|
6
6
|
"type": "commonjs",
|
|
7
7
|
"types": "dist/multisource.d.ts",
|
|
8
|
+
"homepage": "https://github.com/jsonicjs/multisource",
|
|
9
|
+
"keywords": [
|
|
10
|
+
"pattern",
|
|
11
|
+
"matcher",
|
|
12
|
+
"object",
|
|
13
|
+
"property",
|
|
14
|
+
"json"
|
|
15
|
+
],
|
|
16
|
+
"author": "Richard Rodger, http://richardrodger.com",
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git://github.com/jsonicjs/multisource.git"
|
|
20
|
+
},
|
|
8
21
|
"scripts": {
|
|
22
|
+
"test": "jest --coverage",
|
|
23
|
+
"test-some": "jest -t",
|
|
24
|
+
"test-watch": "jest --coverage --watchAll",
|
|
9
25
|
"watch": "tsc -w -d",
|
|
10
|
-
"build": "tsc -d",
|
|
11
|
-
"
|
|
12
|
-
"test-some": "lab -v -P test --sourcemaps --transform node_modules/lab-transform-typescript -g",
|
|
13
|
-
"test-web": "echo no-test-web",
|
|
26
|
+
"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",
|
|
27
|
+
"prettier": "prettier --write --no-semi --single-quote **/*.ts",
|
|
14
28
|
"clean": "rm -rf node_modules yarn.lock package-lock.json",
|
|
15
|
-
"reset": "npm run clean && npm i && npm
|
|
29
|
+
"reset": "npm run clean && npm i && npm test",
|
|
16
30
|
"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;",
|
|
17
31
|
"repo-publish": "npm run clean && npm i && npm run repo-publish-quick",
|
|
18
|
-
"repo-publish-quick": "npm run
|
|
32
|
+
"repo-publish-quick": "npm run prettier && npm run build && npm run test && npm run repo-tag && npm publish --access public --registry https://registry.npmjs.org "
|
|
19
33
|
},
|
|
20
|
-
"author": "",
|
|
21
34
|
"license": "MIT",
|
|
22
35
|
"files": [
|
|
23
36
|
"*.ts",
|
|
24
37
|
"*.js",
|
|
25
|
-
"
|
|
38
|
+
"*.map",
|
|
26
39
|
"LICENSE",
|
|
27
|
-
"
|
|
40
|
+
"src",
|
|
28
41
|
"dist"
|
|
29
42
|
],
|
|
30
43
|
"devDependencies": {
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
44
|
+
"@types/jest": "^27.4.1",
|
|
45
|
+
"browserify": "^17.0.0",
|
|
46
|
+
"esbuild": "^0.14.28",
|
|
47
|
+
"esbuild-jest": "^0.5.0",
|
|
48
|
+
"jest": "^27.5.1",
|
|
49
|
+
"jsonic": "github:jsonicjs/jsonic#nextgen",
|
|
50
|
+
"prettier": "^2.6.1",
|
|
51
|
+
"tinyify": "^3.0.0",
|
|
52
|
+
"ts-jest": "^27.1.4",
|
|
53
|
+
"typescript": "^4.6.3"
|
|
54
|
+
},
|
|
55
|
+
"dependencies": {
|
|
56
|
+
"@jsonic/directive": "^0.4.1"
|
|
36
57
|
}
|
|
37
58
|
}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
/* Copyright (c) 2021 Richard Rodger, MIT License */
|
|
2
|
+
|
|
3
|
+
import { Jsonic, Context, Rule, Plugin } from 'jsonic'
|
|
4
|
+
import { Directive, DirectiveOptions } from '@jsonic/directive'
|
|
5
|
+
|
|
6
|
+
import { makeJsonicProcessor } from './processor/jsonic'
|
|
7
|
+
import { makeJavaScriptProcessor } from './processor/js'
|
|
8
|
+
|
|
9
|
+
// TODO: jsonic-cli should provide basepath
|
|
10
|
+
|
|
11
|
+
// Jsonic parsing meta data. In this case, storing the dependency tree.
|
|
12
|
+
interface MultiSourceMeta {
|
|
13
|
+
path?: string // Base path for this parse run.
|
|
14
|
+
deps?: DependencyMap // Provide an empty object to be filled.
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Unknown source reference file extension.
|
|
18
|
+
const NONE = ''
|
|
19
|
+
|
|
20
|
+
// Options for this plugin.
|
|
21
|
+
type MultiSourceOptions = {
|
|
22
|
+
resolver: Resolver // Resolve multisource spec to source
|
|
23
|
+
path?: string // Base path, prefixed to paths
|
|
24
|
+
markchar?: string // Character to mark start of multisource directive
|
|
25
|
+
processor?: { [kind: string]: Processor }
|
|
26
|
+
implictExt?: []
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// The path to the source, including base prefix (if any).
|
|
30
|
+
type PathSpec = {
|
|
31
|
+
kind: string // Source kind, usually normalized file extension
|
|
32
|
+
path?: string // Original path (possibly relative)
|
|
33
|
+
full?: string // Normalized full path
|
|
34
|
+
base?: string // Current base path
|
|
35
|
+
abs: boolean // Path was absolute
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// The source and where it was found.
|
|
39
|
+
type Resolution = PathSpec & {
|
|
40
|
+
src?: string // Undefined if no resolution
|
|
41
|
+
val?: any // Undefined if no resolution
|
|
42
|
+
found: boolean // True if source file was found
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Resolve the source.
|
|
46
|
+
type Resolver = (
|
|
47
|
+
spec: PathSpec,
|
|
48
|
+
popts: MultiSourceOptions,
|
|
49
|
+
rule: Rule,
|
|
50
|
+
ctx: Context,
|
|
51
|
+
jsonic: Jsonic
|
|
52
|
+
) => Resolution
|
|
53
|
+
|
|
54
|
+
// Process the source into a value.
|
|
55
|
+
type Processor = (
|
|
56
|
+
res: Resolution,
|
|
57
|
+
popts: MultiSourceOptions,
|
|
58
|
+
rule: Rule,
|
|
59
|
+
ctx: Context,
|
|
60
|
+
jsonic: Jsonic
|
|
61
|
+
) => void
|
|
62
|
+
|
|
63
|
+
type Dependency = {
|
|
64
|
+
tar: string | typeof TOP // Target that depends on source (src).
|
|
65
|
+
src: string // Source that target (tar) depends on.
|
|
66
|
+
wen: number // Time of resolution.
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// A flattened dependency tree (assumes each element is a unique full path).
|
|
70
|
+
type DependencyMap = {
|
|
71
|
+
[tar_full_path: string]: {
|
|
72
|
+
[src_full_path: string]: Dependency
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// The top of the dependence tree.
|
|
77
|
+
const TOP = Symbol('TOP')
|
|
78
|
+
|
|
79
|
+
const MultiSource: Plugin = (jsonic: Jsonic, popts: MultiSourceOptions) => {
|
|
80
|
+
const markchar = popts.markchar as string
|
|
81
|
+
const resolver = popts.resolver as Resolver
|
|
82
|
+
const processor = popts.processor as { [kind: string]: Processor }
|
|
83
|
+
|
|
84
|
+
// Normalize implicit extensions to format `.name`.
|
|
85
|
+
const implictExt = (popts.implictExt || []) as string[]
|
|
86
|
+
for (let extI = 0; extI < implictExt.length; extI++) {
|
|
87
|
+
let ext = implictExt[extI]
|
|
88
|
+
implictExt[extI] = ext.startsWith('.') ? ext : '.' + ext
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
jsonic.options({
|
|
92
|
+
error: {
|
|
93
|
+
multisource_not_found: 'source not found: $path',
|
|
94
|
+
},
|
|
95
|
+
hint: {
|
|
96
|
+
multisource_not_found: 'TODO: PATH: $path DETAILS: $details',
|
|
97
|
+
},
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
// Define a directive that can load content from multiple sources.
|
|
101
|
+
let dopts: DirectiveOptions = {
|
|
102
|
+
name: 'multisource',
|
|
103
|
+
open: markchar,
|
|
104
|
+
action: (rule: Rule, ctx: Context) => {
|
|
105
|
+
let spec = rule.child.node
|
|
106
|
+
|
|
107
|
+
let res = resolver(spec, popts, rule, ctx, jsonic)
|
|
108
|
+
if (!res.found) {
|
|
109
|
+
return rule.parent?.o0.bad('multisource_not_found', { ...res })
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
res.kind = null == res.kind ? NONE : res.kind
|
|
113
|
+
|
|
114
|
+
let proc = processor[res.kind] || processor[NONE]
|
|
115
|
+
proc(res, popts, rule, ctx, jsonic)
|
|
116
|
+
|
|
117
|
+
rule.node = res.val
|
|
118
|
+
},
|
|
119
|
+
}
|
|
120
|
+
jsonic.use(Directive, dopts)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Convenience maker for Processors
|
|
124
|
+
function makeProcessor(process: (src: string, res: Resolution) => any) {
|
|
125
|
+
return (res: Resolution) => (res.val = process(res.src as string, res))
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Default is just to insert file contents as a string.
|
|
129
|
+
const defaultProcessor = makeProcessor((src: string) => src)
|
|
130
|
+
|
|
131
|
+
// TODO: use json plugin to get better error msgs.
|
|
132
|
+
const jsonProcessor = makeProcessor((src: string) =>
|
|
133
|
+
null == src ? undefined : JSON.parse(src)
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
const jsonicProcessor = makeJsonicProcessor()
|
|
137
|
+
const jsProcessor = makeJavaScriptProcessor()
|
|
138
|
+
|
|
139
|
+
MultiSource.defaults = {
|
|
140
|
+
markchar: '@',
|
|
141
|
+
processor: {
|
|
142
|
+
[NONE]: defaultProcessor,
|
|
143
|
+
jsonic: jsonicProcessor,
|
|
144
|
+
jsc: jsonicProcessor,
|
|
145
|
+
json: jsonProcessor,
|
|
146
|
+
js: jsProcessor,
|
|
147
|
+
},
|
|
148
|
+
implictExt: ['jsonic', 'jsc', 'json', 'js'],
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function resolvePathSpec(
|
|
152
|
+
popts: MultiSourceOptions,
|
|
153
|
+
ctx: Context,
|
|
154
|
+
spec: any,
|
|
155
|
+
resolvefolder: (path: string) => string
|
|
156
|
+
): PathSpec {
|
|
157
|
+
let msmeta = ctx.meta?.multisource
|
|
158
|
+
let base = resolvefolder(
|
|
159
|
+
null == msmeta || null == msmeta.path ? popts.path : msmeta.path
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
let path =
|
|
163
|
+
'string' === typeof spec
|
|
164
|
+
? spec
|
|
165
|
+
: null != spec.path
|
|
166
|
+
? '' + spec.path
|
|
167
|
+
: undefined
|
|
168
|
+
|
|
169
|
+
let abs = !!(path?.startsWith('/') || path?.startsWith('\\'))
|
|
170
|
+
let full = abs
|
|
171
|
+
? path
|
|
172
|
+
: null != path && '' != path
|
|
173
|
+
? null != base && '' != base
|
|
174
|
+
? base + '/' + path
|
|
175
|
+
: path
|
|
176
|
+
: undefined
|
|
177
|
+
|
|
178
|
+
let kind = null == full ? NONE : (full.match(/\.([^.]*)$/) || [NONE, NONE])[1]
|
|
179
|
+
|
|
180
|
+
let res: Resolution = {
|
|
181
|
+
kind,
|
|
182
|
+
path,
|
|
183
|
+
full,
|
|
184
|
+
base,
|
|
185
|
+
abs,
|
|
186
|
+
found: false,
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// console.log('RES', res)
|
|
190
|
+
|
|
191
|
+
return res
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export type {
|
|
195
|
+
Resolver,
|
|
196
|
+
Resolution,
|
|
197
|
+
Processor,
|
|
198
|
+
MultiSourceOptions,
|
|
199
|
+
Dependency,
|
|
200
|
+
DependencyMap,
|
|
201
|
+
MultiSourceMeta,
|
|
202
|
+
PathSpec,
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export {
|
|
206
|
+
MultiSource,
|
|
207
|
+
resolvePathSpec,
|
|
208
|
+
NONE,
|
|
209
|
+
TOP,
|
|
210
|
+
|
|
211
|
+
// // Re-exported from jsonic for convenience
|
|
212
|
+
// Context,
|
|
213
|
+
|
|
214
|
+
// // TODO: remove for better tree shaking
|
|
215
|
+
// makeFileResolver,
|
|
216
|
+
// makeMemResolver,
|
|
217
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/* Copyright (c) 2021 Richard Rodger, MIT License */
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
Processor,
|
|
6
|
+
Resolution,
|
|
7
|
+
} from '../multisource'
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
function makeJavaScriptProcessor(opts?: {
|
|
11
|
+
evalOnly?: boolean
|
|
12
|
+
}): Processor {
|
|
13
|
+
|
|
14
|
+
const JavaScriptProcessor = (
|
|
15
|
+
res: Resolution,
|
|
16
|
+
) => {
|
|
17
|
+
res.val = evaluate(res, opts)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
JavaScriptProcessor.opts = opts
|
|
21
|
+
|
|
22
|
+
return JavaScriptProcessor
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// TODO: too simplistic - handle more module cases
|
|
26
|
+
function evaluate(res: Resolution, opts?: any) {
|
|
27
|
+
let out = undefined
|
|
28
|
+
if (true !== opts?.evalOnly && undefined !== typeof (require)) {
|
|
29
|
+
out = require((res.full as string))
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
let exports = null
|
|
33
|
+
let module = { exports }
|
|
34
|
+
eval((res.src as string))
|
|
35
|
+
out = module.exports
|
|
36
|
+
}
|
|
37
|
+
return out
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export {
|
|
41
|
+
makeJavaScriptProcessor
|
|
42
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/* Copyright (c) 2021 Richard Rodger, MIT License */
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
import { Jsonic, Rule, Context } from 'jsonic'
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
MultiSourceOptions,
|
|
8
|
+
Processor,
|
|
9
|
+
Resolution,
|
|
10
|
+
TOP,
|
|
11
|
+
DependencyMap,
|
|
12
|
+
Dependency,
|
|
13
|
+
MultiSourceMeta,
|
|
14
|
+
} from '../multisource'
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
function makeJsonicProcessor(): Processor {
|
|
18
|
+
|
|
19
|
+
return function JsonicProcessor(
|
|
20
|
+
res: Resolution,
|
|
21
|
+
_popts: MultiSourceOptions,
|
|
22
|
+
_rule: Rule,
|
|
23
|
+
ctx: Context,
|
|
24
|
+
jsonic: Jsonic
|
|
25
|
+
) {
|
|
26
|
+
if (null != res.src && null != res.full) {
|
|
27
|
+
|
|
28
|
+
// Pass down any meta info.
|
|
29
|
+
let msmeta: MultiSourceMeta = ctx.meta?.multisource || {}
|
|
30
|
+
let meta = {
|
|
31
|
+
...(ctx.meta || {}),
|
|
32
|
+
multisource: {
|
|
33
|
+
...msmeta,
|
|
34
|
+
path: res.full
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// console.log('PM', meta, res)
|
|
39
|
+
res.val = jsonic(res.src, meta)
|
|
40
|
+
|
|
41
|
+
// Build dependency tree branch.
|
|
42
|
+
if (msmeta.deps) {
|
|
43
|
+
let depmap = (msmeta.deps as DependencyMap)
|
|
44
|
+
let parent = (msmeta.path || TOP) as string
|
|
45
|
+
if (null != parent) {
|
|
46
|
+
let dep: Dependency = {
|
|
47
|
+
tar: parent,
|
|
48
|
+
src: res.full,
|
|
49
|
+
wen: Date.now()
|
|
50
|
+
}
|
|
51
|
+
depmap[parent] = depmap[parent] || {}
|
|
52
|
+
depmap[parent][res.full] = dep
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
export {
|
|
62
|
+
makeJsonicProcessor
|
|
63
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import Fs from 'fs'
|
|
2
|
+
import Path from 'path'
|
|
3
|
+
|
|
4
|
+
import { Rule, Context } from 'jsonic'
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
MultiSourceOptions,
|
|
8
|
+
Resolver,
|
|
9
|
+
Resolution,
|
|
10
|
+
resolvePathSpec,
|
|
11
|
+
NONE,
|
|
12
|
+
} from '../multisource'
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
import {
|
|
16
|
+
buildPotentials
|
|
17
|
+
} from './mem'
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
function makeFileResolver(): Resolver {
|
|
21
|
+
|
|
22
|
+
return function FileResolver(
|
|
23
|
+
spec: any,
|
|
24
|
+
popts: MultiSourceOptions,
|
|
25
|
+
_rule: Rule,
|
|
26
|
+
ctx: Context,
|
|
27
|
+
): Resolution {
|
|
28
|
+
let ps = resolvePathSpec(popts, ctx, spec, resolvefolder)
|
|
29
|
+
let src = undefined
|
|
30
|
+
|
|
31
|
+
// console.log(ps)
|
|
32
|
+
|
|
33
|
+
if (null != ps.full) {
|
|
34
|
+
ps.full = Path.resolve(ps.full)
|
|
35
|
+
|
|
36
|
+
src = load(ps.full)
|
|
37
|
+
|
|
38
|
+
if (null == src && NONE === ps.kind) {
|
|
39
|
+
let potentials =
|
|
40
|
+
buildPotentials(ps, popts, (...s) =>
|
|
41
|
+
Path.resolve(s.reduce((a, p) => Path.join(a, p))))
|
|
42
|
+
|
|
43
|
+
for (let path of potentials) {
|
|
44
|
+
if (null != (src = load(path))) {
|
|
45
|
+
ps.full = path
|
|
46
|
+
ps.kind = (path.match(/\.([^.]*)$/) || [NONE, NONE])[1]
|
|
47
|
+
break
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
let res: Resolution = {
|
|
54
|
+
...ps,
|
|
55
|
+
src,
|
|
56
|
+
found: null != src
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return res
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function resolvefolder(path: string) {
|
|
64
|
+
let folder = path
|
|
65
|
+
let pathstats = Fs.statSync(path)
|
|
66
|
+
|
|
67
|
+
if (pathstats.isFile()) {
|
|
68
|
+
let pathdesc = Path.parse(path)
|
|
69
|
+
folder = pathdesc.dir
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return folder
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
// TODO: in multisource.ts, generate an error token if cannot resolve
|
|
77
|
+
function load(path: string) {
|
|
78
|
+
// console.log('LOAD', path)
|
|
79
|
+
try {
|
|
80
|
+
return Fs.readFileSync(path).toString()
|
|
81
|
+
}
|
|
82
|
+
catch (e) {
|
|
83
|
+
// NOTE: don't need this, as in all cases, we consider failed
|
|
84
|
+
// reads to indicate non-existence.
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
export {
|
|
90
|
+
makeFileResolver,
|
|
91
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
import { Rule, Context } from 'jsonic'
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
MultiSourceOptions,
|
|
7
|
+
Resolver,
|
|
8
|
+
Resolution,
|
|
9
|
+
resolvePathSpec,
|
|
10
|
+
NONE,
|
|
11
|
+
PathSpec,
|
|
12
|
+
} from '../multisource'
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
function makeMemResolver(filemap: { [fullpath: string]: string }): Resolver {
|
|
16
|
+
|
|
17
|
+
return function MemResolver(
|
|
18
|
+
spec: any,
|
|
19
|
+
popts: MultiSourceOptions,
|
|
20
|
+
_rule: Rule,
|
|
21
|
+
ctx: Context,
|
|
22
|
+
): Resolution {
|
|
23
|
+
let ps = resolvePathSpec(popts, ctx, spec, makeresolvefolder(filemap))
|
|
24
|
+
let src = undefined
|
|
25
|
+
|
|
26
|
+
if (null != ps.full) {
|
|
27
|
+
src = filemap[ps.full]
|
|
28
|
+
|
|
29
|
+
if (null == src && NONE === ps.kind) {
|
|
30
|
+
let potentials =
|
|
31
|
+
buildPotentials(ps, popts, (...s) =>
|
|
32
|
+
s.reduce((a, p) => a + '/' + p))
|
|
33
|
+
|
|
34
|
+
for (let path of potentials) {
|
|
35
|
+
if (null != (src = filemap[path])) {
|
|
36
|
+
ps.full = path
|
|
37
|
+
ps.kind = (path.match(/\.([^.]*)$/) || [NONE, NONE])[1]
|
|
38
|
+
break
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
let res: Resolution = {
|
|
45
|
+
...ps,
|
|
46
|
+
src,
|
|
47
|
+
found: null != src
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return res
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
function makeresolvefolder(filemap: { [fullpath: string]: string }) {
|
|
56
|
+
return function resolvefolder(path: string) {
|
|
57
|
+
let folder = path
|
|
58
|
+
if (filemap[path]) {
|
|
59
|
+
folder = (path
|
|
60
|
+
.replace(/[\\\/]+$/, '')
|
|
61
|
+
.match(/[\\\/]+([^\\\/]+)$/) || ['', ''])[1]
|
|
62
|
+
// console.log('PF', path, folder)
|
|
63
|
+
}
|
|
64
|
+
// console.log('RF', folder)
|
|
65
|
+
return folder
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
function buildPotentials(
|
|
71
|
+
ps: PathSpec,
|
|
72
|
+
popts: MultiSourceOptions,
|
|
73
|
+
pathjoin: (...parts: string[]) => string): string[] {
|
|
74
|
+
let full = (ps.full as string)
|
|
75
|
+
let potentials: string[] = []
|
|
76
|
+
let implictExt: string[] = popts.implictExt || []
|
|
77
|
+
|
|
78
|
+
// Implicit extensions.
|
|
79
|
+
for (let ext of implictExt) {
|
|
80
|
+
potentials.push(full + ext)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Folder index file.
|
|
84
|
+
for (let ext of implictExt) {
|
|
85
|
+
potentials.push(pathjoin(full, 'index' + ext))
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Folder index file (includes folder name).
|
|
89
|
+
if (null != ps.path) {
|
|
90
|
+
let folder = (ps.path
|
|
91
|
+
.replace(/[\\\/]+$/, '')
|
|
92
|
+
.match(/[^\\\/]+$/) || [])[0]
|
|
93
|
+
if (null != folder) {
|
|
94
|
+
for (let ext of implictExt) {
|
|
95
|
+
potentials.push(pathjoin(full, 'index.' + folder + ext))
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// console.log(potentials)
|
|
101
|
+
|
|
102
|
+
return potentials
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
export {
|
|
108
|
+
buildPotentials,
|
|
109
|
+
makeMemResolver,
|
|
110
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/* Copyright (c) 2021 Richard Rodger and other contributors, MIT License */
|
|
3
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
-
};
|
|
6
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
const lab_1 = __importDefault(require("@hapi/lab"));
|
|
8
|
-
const code_1 = __importDefault(require("@hapi/code"));
|
|
9
|
-
const lab = (exports.lab = lab_1.default.script());
|
|
10
|
-
const describe = lab.describe;
|
|
11
|
-
const it = lab.it;
|
|
12
|
-
const expect = code_1.default.expect;
|
|
13
|
-
const jsonic_1 = require("jsonic");
|
|
14
|
-
const multisource_1 = require("../multisource");
|
|
15
|
-
const file_1 = require("../resolver/file");
|
|
16
|
-
const mem_1 = require("../resolver/mem");
|
|
17
|
-
describe('multisource', function () {
|
|
18
|
-
it('happy', () => {
|
|
19
|
-
let j0 = jsonic_1.Jsonic.make().use(multisource_1.MultiSource, {
|
|
20
|
-
resolver: mem_1.makeMemResolver({
|
|
21
|
-
'/a': 'b:1',
|
|
22
|
-
}),
|
|
23
|
-
});
|
|
24
|
-
expect(j0('c:1')).equals({ c: 1 });
|
|
25
|
-
expect(j0('c:@"/a"')).equals({ c: { b: 1 } });
|
|
26
|
-
expect(j0('x:y:1, x:z:2')).equals({ x: { y: 1, z: 2 } });
|
|
27
|
-
});
|
|
28
|
-
it('file', () => {
|
|
29
|
-
let r0 = file_1.makeFileResolver();
|
|
30
|
-
let j0 = jsonic_1.Jsonic.make().use(multisource_1.MultiSource, {
|
|
31
|
-
resolver: r0,
|
|
32
|
-
});
|
|
33
|
-
let deps = {};
|
|
34
|
-
expect(j0('a:1,b:@"./t01.jsonic"', { multisource: { path: __dirname, deps } }))
|
|
35
|
-
.equals({ a: 1, b: { c: 2 } });
|
|
36
|
-
//console.dir(deps, { depth: null })
|
|
37
|
-
deps = {};
|
|
38
|
-
expect(j0('a:1,b:@"./t02.jsonic",c:3', { multisource: { path: __dirname, deps } }))
|
|
39
|
-
.equals({ a: 1, b: { d: 2, e: { f: 4 } }, c: 3 });
|
|
40
|
-
//console.dir(deps, { depth: null })
|
|
41
|
-
});
|
|
42
|
-
it('mem', () => {
|
|
43
|
-
let r0 = mem_1.makeMemResolver({
|
|
44
|
-
'/a': 'a:1',
|
|
45
|
-
'/b': 'b:@"c",',
|
|
46
|
-
'/b/c': 'c:@"/a"',
|
|
47
|
-
'/d': 'd:4',
|
|
48
|
-
});
|
|
49
|
-
let j0 = jsonic_1.Jsonic.make().use(multisource_1.MultiSource, {
|
|
50
|
-
resolver: r0,
|
|
51
|
-
});
|
|
52
|
-
let deps = {};
|
|
53
|
-
expect(j0('q:11,x:@"a",k:@"d",y:@"b",z:@"/b/c",w:22', { multisource: { deps } }))
|
|
54
|
-
.equals({
|
|
55
|
-
q: 11,
|
|
56
|
-
x: { a: 1 },
|
|
57
|
-
k: { d: 4 },
|
|
58
|
-
y: { b: { c: { a: 1 } } },
|
|
59
|
-
z: { c: { a: 1 } },
|
|
60
|
-
w: 22,
|
|
61
|
-
});
|
|
62
|
-
//console.dir(deps, { depth: null })
|
|
63
|
-
expect(remove(deps, 'wen')).equal({
|
|
64
|
-
'/b/c': { '/a': { tar: '/b/c', src: '/a' } },
|
|
65
|
-
'/b': { '/b/c': { tar: '/b', src: '/b/c' } },
|
|
66
|
-
[multisource_1.TOP]: {
|
|
67
|
-
'/a': { tar: multisource_1.TOP, src: '/a' },
|
|
68
|
-
'/d': { tar: multisource_1.TOP, src: '/d' },
|
|
69
|
-
'/b': { tar: multisource_1.TOP, src: '/b' },
|
|
70
|
-
'/b/c': { tar: multisource_1.TOP, src: '/b/c' }
|
|
71
|
-
}
|
|
72
|
-
});
|
|
73
|
-
});
|
|
74
|
-
});
|
|
75
|
-
function remove(o, k) {
|
|
76
|
-
if (null != o && 'object' === typeof (o)) {
|
|
77
|
-
delete o[k];
|
|
78
|
-
remove(o[multisource_1.TOP], k);
|
|
79
|
-
for (let p in o) {
|
|
80
|
-
remove(o[p], k);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
return o;
|
|
84
|
-
}
|
|
85
|
-
//# sourceMappingURL=multisource.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"multisource.test.js","sourceRoot":"","sources":["../../test/multisource.test.ts"],"names":[],"mappings":"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"}
|