@nxtedition/lib 26.8.8 → 27.0.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.
@@ -1,226 +0,0 @@
1
- import * as rxjs from 'rxjs'
2
- import fp from 'lodash/fp.js'
3
- import getNxtpressionsCompiler from './nextpressions.js'
4
- import getJavascriptCompiler from './javascript.js'
5
- import JSON5 from 'json5'
6
- import firstValueFrom from '../../rxjs/firstValueFrom.js'
7
-
8
- export function makeTemplateCompiler({ ds, proxify, logger, platform }) {
9
- const compiler = {
10
- current: null,
11
- resolveTemplate,
12
- onResolveTemplate,
13
- compileTemplate,
14
- isTemplate,
15
- }
16
-
17
- const compilers = {
18
- nxt: getNxtpressionsCompiler({ ds, logger, platform }),
19
- js: getJavascriptCompiler({ ds, proxify, compiler, logger, platform }),
20
- }
21
-
22
- function inner(str) {
23
- const templateStart = str.lastIndexOf('{{')
24
- if (templateStart === -1) {
25
- return null
26
- }
27
- let bodyStart = templateStart + 2
28
-
29
- let templateEnd = str.indexOf('}}', templateStart + 2)
30
- if (templateEnd === -1) {
31
- return null
32
- }
33
- const bodyEnd = templateEnd
34
- templateEnd += 2
35
-
36
- let type = 'nxt'
37
- if (str[bodyStart] === '#') {
38
- type = str.slice(bodyStart + 1).match(/^([a-z]*)/)[1]
39
- bodyStart += type.length + 1
40
- }
41
-
42
- return {
43
- input: str,
44
- pre: str.slice(0, templateStart),
45
- type,
46
- body: str.slice(bodyStart, bodyEnd),
47
- post: str.slice(templateEnd),
48
- }
49
- }
50
-
51
- function compileArrayTemplate(template) {
52
- let resolvers
53
- let indices
54
-
55
- for (let i = 0; i < template.length; i++) {
56
- const resolver = _compileTemplate(template[i])
57
- if (resolver) {
58
- resolvers ??= []
59
- resolvers.push(resolver)
60
- indices ??= []
61
- indices.push(i)
62
- }
63
- }
64
-
65
- return resolvers
66
- ? (arr, args$) => {
67
- const len = resolvers.length
68
- const values = new Array(len)
69
- for (let n = 0; n < len; n++) {
70
- values[n] = resolvers[n](arr[indices[n]], args$)
71
- }
72
-
73
- return rxjs.combineLatest(values).pipe(
74
- rxjs.map((values) => {
75
- const ret = [...arr]
76
- for (let n = 0; n < values.length; n++) {
77
- ret[indices[n]] = values[n]
78
- }
79
- return ret
80
- }),
81
- )
82
- }
83
- : null
84
- }
85
-
86
- function compileObjectTemplate(template) {
87
- let resolvers
88
- let indices
89
-
90
- const keys = Object.keys(template)
91
-
92
- for (let i = 0; i < keys.length; i++) {
93
- const resolver = _compileTemplate(template[keys[i]])
94
- if (resolver) {
95
- resolvers ??= []
96
- resolvers.push(resolver)
97
- indices ??= []
98
- indices.push(keys[i])
99
- }
100
- }
101
-
102
- return resolvers
103
- ? (obj, args$) => {
104
- const len = resolvers.length
105
- const values = new Array(len)
106
- for (let n = 0; n < len; n++) {
107
- values[n] = resolvers[n](obj[indices[n]], args$)
108
- }
109
-
110
- return rxjs.combineLatest(values).pipe(
111
- rxjs.map((values) => {
112
- const ret = { ...obj }
113
- for (let n = 0; n < values.length; n++) {
114
- ret[indices[n]] = values[n]
115
- }
116
- return ret
117
- }),
118
- )
119
- }
120
- : null
121
- }
122
-
123
- function compileStringTemplate(template) {
124
- const match = inner(template)
125
- if (!match) {
126
- return null
127
- }
128
-
129
- const { pre, type, body, post } = match
130
-
131
- if (type === 'js') {
132
- const expr = compilers.js(body)
133
-
134
- if (!pre && !post) {
135
- return (str, args$) => expr(args$)
136
- }
137
-
138
- return (str, args$) =>
139
- rxjs
140
- .combineLatest([
141
- compileStringTemplate(pre)?.(str, args$) ?? rxjs.of(pre),
142
- expr(args$),
143
- compileStringTemplate(post)?.(str, args$) ?? rxjs.of(post),
144
- ])
145
- .pipe(
146
- rxjs.map(([pre, body, post]) =>
147
- pre || post ? `${pre}${stringify(body)}${post}` : body,
148
- ),
149
- )
150
- } else if (type === 'nxt') {
151
- const expr = compilers.nxt(body)
152
-
153
- if (!pre && !post) {
154
- return (str, args$) => expr(args$)
155
- }
156
-
157
- return (str, args$) =>
158
- expr(args$).pipe(
159
- rxjs.switchMap((body) =>
160
- onResolveTemplate(`${pre}${stringify(body, true)}${post}`, args$),
161
- ),
162
- )
163
- } else {
164
- throw new Error('unknown expression type: ' + type)
165
- }
166
- }
167
-
168
- function stringify(value, escape) {
169
- if (value == null) {
170
- return ''
171
- } else if (fp.isArray(value) || fp.isPlainObject(value)) {
172
- return JSON5.stringify(value)
173
- } else if (fp.isString(value) && escape) {
174
- return value.replace(/"/g, '\\"')
175
- }
176
- return value
177
- }
178
-
179
- function isTemplate(val) {
180
- return typeof val === 'string' && val.indexOf('{{') !== -1
181
- }
182
-
183
- const objCache = new WeakMap()
184
-
185
- const _compileTemplate = (template) => {
186
- if (fp.isPlainObject(template)) {
187
- let resolver = objCache.get(template)
188
- if (resolver == null) {
189
- resolver = compileObjectTemplate(template)
190
- objCache.set(template, resolver)
191
- }
192
- return resolver
193
- } else if (Array.isArray(template)) {
194
- let resolver = objCache.get(template)
195
- if (resolver == null) {
196
- resolver = compileArrayTemplate(template)
197
- objCache.set(template, resolver)
198
- }
199
- return resolver
200
- } else if (isTemplate(template)) {
201
- return compileStringTemplate(template)
202
- } else {
203
- return null
204
- }
205
- }
206
-
207
- function compileTemplate(template) {
208
- const resolver = _compileTemplate(template)
209
- return resolver ? (args$) => resolver(template, args$) : null
210
- }
211
-
212
- async function resolveTemplate(template, args$, options) {
213
- const expr = _compileTemplate(template)
214
- return expr ? firstValueFrom(expr(template, args$), options) : template
215
- }
216
-
217
- function onResolveTemplate(template, args$) {
218
- try {
219
- return _compileTemplate(template)?.(template, args$) ?? rxjs.of(template)
220
- } catch (err) {
221
- return rxjs.throwError(() => err)
222
- }
223
- }
224
-
225
- return compiler
226
- }
@@ -1 +0,0 @@
1
- export * from './index-common.js'
@@ -1,28 +0,0 @@
1
- import { makeTemplateCompiler as commonMakeTemplateCompiler } from './index-common.js'
2
-
3
- export function makeTemplateCompiler({ ds, proxify, logger = console }) {
4
- return commonMakeTemplateCompiler({
5
- ds,
6
- proxify,
7
- logger,
8
- platform: {
9
- hasha: (data) => {
10
- throw new Error('hasha is not supported')
11
- },
12
- fetch: async (resource, options) => {
13
- // eslint-disable-next-line no-undef
14
- const res = await window.fetch(resource, options)
15
- return {
16
- statusCode: res.status,
17
- headers: Object.fromEntries(res.headers.entries()),
18
- body: {
19
- text: async () => {
20
- return await res.text()
21
- },
22
- },
23
- }
24
- },
25
- schedule: (fn) => setTimeout(fn, 0),
26
- },
27
- })
28
- }
@@ -1 +0,0 @@
1
- export * from './index-common.js'
@@ -1,26 +0,0 @@
1
- import { makeTemplateCompiler as commonMakeTemplateCompiler } from './index-common.js'
2
- import { hashSync } from 'hasha'
3
- import { request } from '@nxtedition/nxt-undici'
4
- import { doYield } from '../../yield.js'
5
-
6
- export * from './index-common.js'
7
-
8
- export function makeTemplateCompiler({
9
- logger = globalThis.__nxt_lib_app?.logger,
10
- dispatcher,
11
- platform,
12
- ...args
13
- }) {
14
- const defaultOptions = { dispatcher }
15
- return commonMakeTemplateCompiler({
16
- ...args,
17
- logger,
18
- platform: {
19
- hasha: hashSync,
20
- fetch: (resource, options) =>
21
- request(resource, options && dispatcher ? { dispatcher, ...options } : defaultOptions),
22
- ...platform,
23
- schedule: (fn) => doYield(fn),
24
- },
25
- })
26
- }
@@ -1,94 +0,0 @@
1
- import { test } from 'node:test'
2
- import assert from 'node:assert'
3
- import { makeTemplateCompiler } from './index.js'
4
-
5
- test('javascript', async () => {
6
- const compiler = makeTemplateCompiler({
7
- ds: {},
8
- logger: console,
9
- })
10
-
11
- assert.strictEqual(
12
- await compiler.resolveTemplate('{{#js _($.foo, foo => foo.toUpperCase()) }}', { foo: 'bar' }),
13
- 'BAR',
14
- )
15
- })
16
-
17
- test('nexpression', async () => {
18
- const compiler = makeTemplateCompiler({
19
- ds: {},
20
- logger: console,
21
- })
22
-
23
- assert.strictEqual(await compiler.resolveTemplate('{{ foo }}', { foo: 'bar' }), 'bar')
24
- })
25
-
26
- test('pipe short-circuit', async () => {
27
- const compiler = makeTemplateCompiler({
28
- ds: {},
29
- logger: console,
30
- })
31
-
32
- assert.strictEqual(
33
- await compiler.resolveTemplate('{{#js _($.id, x => x + "ASD") }}', { foo: 'bar' }),
34
- undefined,
35
- )
36
- })
37
-
38
- test('return function', async () => {
39
- const compiler = makeTemplateCompiler({
40
- ds: {},
41
- logger: console,
42
- })
43
-
44
- assert.strictEqual(
45
- (
46
- await compiler.resolveTemplate(`{{#js (input) => fp.toUpper($.foo + input) }}`, {
47
- foo: 'bar',
48
- })
49
- )('baz'),
50
- 'BARBAZ',
51
- )
52
- })
53
-
54
- test('noop', async (t) => {
55
- const { resolveTemplate } = makeTemplateCompiler({})
56
- const x = { foo: 1, bar: {} }
57
- const y = await resolveTemplate(x)
58
- assert.strictEqual(x, y)
59
- })
60
-
61
- test('simple', async (t) => {
62
- const { resolveTemplate } = makeTemplateCompiler({})
63
- const x = { bar: '{{#js $.test }}' }
64
- const y = await resolveTemplate(x, { test: 1 })
65
- assert.deepStrictEqual(y, { bar: 1 })
66
- })
67
-
68
- // test('cache', async (t) => {
69
- // const x = '{{#js $.test }}'
70
- // t.equal(compileTemplate(x), compileTemplate(x))
71
- // t.end()
72
- // })
73
-
74
- test('string concat', async (t) => {
75
- const { resolveTemplate } = makeTemplateCompiler({})
76
- const x = '{{#js $.pre }} {{#js $.body}} {{#js $.post}}'
77
- assert.strictEqual(
78
- await resolveTemplate(x, { pre: 'pre', body: 'body', post: 'post' }),
79
- 'pre body post',
80
- )
81
- })
82
-
83
- test('syntax error', async (t) => {
84
- const { resolveTemplate } = makeTemplateCompiler({})
85
- const x = '{{#js $.test + }}'
86
- await assert.rejects(
87
- async () => {
88
- await resolveTemplate(x, { test: 1 })
89
- },
90
- {
91
- name: 'Error',
92
- },
93
- )
94
- })