@xpack/xpm-lib 3.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.
- package/LICENSE +21 -0
- package/README.md +223 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +30 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/chmod-recursive.d.ts +7 -0
- package/dist/lib/chmod-recursive.d.ts.map +1 -0
- package/dist/lib/chmod-recursive.js +81 -0
- package/dist/lib/chmod-recursive.js.map +1 -0
- package/dist/lib/errors.d.ts +11 -0
- package/dist/lib/errors.d.ts.map +1 -0
- package/dist/lib/errors.js +26 -0
- package/dist/lib/errors.js.map +1 -0
- package/dist/lib/functions/chmod-recursive.d.ts +7 -0
- package/dist/lib/functions/chmod-recursive.d.ts.map +1 -0
- package/dist/lib/functions/chmod-recursive.js +81 -0
- package/dist/lib/functions/chmod-recursive.js.map +1 -0
- package/dist/lib/functions/perform-substitutions.d.ts +20 -0
- package/dist/lib/functions/perform-substitutions.d.ts.map +1 -0
- package/dist/lib/functions/perform-substitutions.js +85 -0
- package/dist/lib/functions/perform-substitutions.js.map +1 -0
- package/dist/lib/functions/utils.d.ts +30 -0
- package/dist/lib/functions/utils.d.ts.map +1 -0
- package/dist/lib/functions/utils.js +70 -0
- package/dist/lib/functions/utils.js.map +1 -0
- package/dist/lib/init-template-base.d.ts +46 -0
- package/dist/lib/init-template-base.d.ts.map +1 -0
- package/dist/lib/init-template-base.js +275 -0
- package/dist/lib/init-template-base.js.map +1 -0
- package/dist/lib/liquid-actions.d.ts +32 -0
- package/dist/lib/liquid-actions.d.ts.map +1 -0
- package/dist/lib/liquid-actions.js +113 -0
- package/dist/lib/liquid-actions.js.map +1 -0
- package/dist/lib/liquid-build-configurations.d.ts +49 -0
- package/dist/lib/liquid-build-configurations.d.ts.map +1 -0
- package/dist/lib/liquid-build-configurations.js +267 -0
- package/dist/lib/liquid-build-configurations.js.map +1 -0
- package/dist/lib/liquid-drop.d.ts +13 -0
- package/dist/lib/liquid-drop.d.ts.map +1 -0
- package/dist/lib/liquid-drop.js +56 -0
- package/dist/lib/liquid-drop.js.map +1 -0
- package/dist/lib/liquid-engine.d.ts +5 -0
- package/dist/lib/liquid-engine.d.ts.map +1 -0
- package/dist/lib/liquid-engine.js +85 -0
- package/dist/lib/liquid-engine.js.map +1 -0
- package/dist/lib/liquid-package.d.ts +17 -0
- package/dist/lib/liquid-package.d.ts.map +1 -0
- package/dist/lib/liquid-package.js +70 -0
- package/dist/lib/liquid-package.js.map +1 -0
- package/dist/lib/package.d.ts +66 -0
- package/dist/lib/package.d.ts.map +1 -0
- package/dist/lib/package.js +700 -0
- package/dist/lib/package.js.map +1 -0
- package/dist/lib/perform-substitutions.d.ts +20 -0
- package/dist/lib/perform-substitutions.d.ts.map +1 -0
- package/dist/lib/perform-substitutions.js +85 -0
- package/dist/lib/perform-substitutions.js.map +1 -0
- package/dist/lib/policies.d.ts +13 -0
- package/dist/lib/policies.d.ts.map +1 -0
- package/dist/lib/policies.js +31 -0
- package/dist/lib/policies.js.map +1 -0
- package/dist/lib/substitutions-variables.d.ts +117 -0
- package/dist/lib/substitutions-variables.d.ts.map +1 -0
- package/dist/lib/substitutions-variables.js +51 -0
- package/dist/lib/substitutions-variables.js.map +1 -0
- package/dist/lib/types.d.ts +70 -0
- package/dist/lib/types.d.ts.map +1 -0
- package/dist/lib/types.js +13 -0
- package/dist/lib/types.js.map +1 -0
- package/dist/lib/utils.d.ts +30 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +70 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +102 -0
- package/src/README.md +10 -0
- package/src/index.ts +35 -0
- package/src/lib/errors.ts +29 -0
- package/src/lib/functions/chmod-recursive.ts +103 -0
- package/src/lib/functions/perform-substitutions.ts +116 -0
- package/src/lib/functions/utils.ts +88 -0
- package/src/lib/init-template-base.ts +401 -0
- package/src/lib/liquid-actions.ts +179 -0
- package/src/lib/liquid-build-configurations.ts +410 -0
- package/src/lib/liquid-drop.ts +99 -0
- package/src/lib/liquid-engine.ts +135 -0
- package/src/lib/liquid-package.ts +108 -0
- package/src/lib/package.ts +946 -0
- package/src/lib/policies.ts +49 -0
- package/src/lib/substitutions-variables.ts +177 -0
- package/src/lib/types.ts +109 -0
- package/src/package.json +3 -0
- package/src/tsconfig.json +10 -0
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of the xPack project (http://xpack.github.io).
|
|
3
|
+
* Copyright (c) 2021-2026 Liviu Ionescu. All rights reserved.
|
|
4
|
+
*
|
|
5
|
+
* Permission to use, copy, modify, and/or distribute this software
|
|
6
|
+
* for any purpose is hereby granted, under the terms of the MIT license.
|
|
7
|
+
*
|
|
8
|
+
* If a copy of the license was not distributed with this file, it can
|
|
9
|
+
* be obtained from https://opensource.org/license/mit.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/* eslint max-len: [ "error", 80, { "ignoreUrls": true } ] */
|
|
13
|
+
|
|
14
|
+
// ----------------------------------------------------------------------------
|
|
15
|
+
|
|
16
|
+
import assert from 'node:assert'
|
|
17
|
+
import path from 'node:path'
|
|
18
|
+
|
|
19
|
+
import { Logger } from '@xpack/logger'
|
|
20
|
+
|
|
21
|
+
import { XpmLiquidEngine } from './liquid-engine.js'
|
|
22
|
+
import {
|
|
23
|
+
XpmLiquidSubstitutionsVariables,
|
|
24
|
+
XpmLiquidSubstitutionsStrings,
|
|
25
|
+
} from './substitutions-variables.js'
|
|
26
|
+
import { buildFolderRelativePathPropertyName } from './liquid-package.js'
|
|
27
|
+
import {
|
|
28
|
+
JsonBuildConfiguration,
|
|
29
|
+
JsonBuildConfigurations,
|
|
30
|
+
JsonDependencies,
|
|
31
|
+
} from './types.js'
|
|
32
|
+
import { performSubstitutions } from './functions/perform-substitutions.js'
|
|
33
|
+
import { XpmLiquidActions } from './liquid-actions.js'
|
|
34
|
+
import { isString } from './functions/utils.js'
|
|
35
|
+
import { filterPath } from './functions/utils.js'
|
|
36
|
+
|
|
37
|
+
// ----------------------------------------------------------------------------
|
|
38
|
+
|
|
39
|
+
// A collection of build configurations.
|
|
40
|
+
export class XpmLiquidBuildConfigurations {
|
|
41
|
+
// --------------------------------------------------------------------------
|
|
42
|
+
// Members.
|
|
43
|
+
|
|
44
|
+
readonly log: Logger
|
|
45
|
+
readonly engine: XpmLiquidEngine
|
|
46
|
+
readonly substitutionsVariables: XpmLiquidSubstitutionsVariables
|
|
47
|
+
readonly jsonBuildConfigurations: JsonBuildConfigurations
|
|
48
|
+
|
|
49
|
+
readonly #buildConfigurationsMap: Map<
|
|
50
|
+
string,
|
|
51
|
+
XpmLiquidBuildConfiguration | undefined
|
|
52
|
+
>
|
|
53
|
+
readonly #jsonBuildConfigurationsNamesMap: Map<string, string>
|
|
54
|
+
|
|
55
|
+
#isInitialised = false
|
|
56
|
+
|
|
57
|
+
// --------------------------------------------------------------------------
|
|
58
|
+
// Constructor and async initialiser.
|
|
59
|
+
|
|
60
|
+
constructor({
|
|
61
|
+
log,
|
|
62
|
+
engine,
|
|
63
|
+
substitutionsVariables,
|
|
64
|
+
jsonBuildConfigurations,
|
|
65
|
+
}: {
|
|
66
|
+
log: Logger
|
|
67
|
+
engine: XpmLiquidEngine
|
|
68
|
+
substitutionsVariables: XpmLiquidSubstitutionsVariables
|
|
69
|
+
jsonBuildConfigurations: JsonBuildConfigurations | undefined
|
|
70
|
+
}) {
|
|
71
|
+
log.trace(`${XpmLiquidBuildConfigurations.name}()`)
|
|
72
|
+
|
|
73
|
+
this.log = log
|
|
74
|
+
this.engine = engine
|
|
75
|
+
this.substitutionsVariables = substitutionsVariables
|
|
76
|
+
this.jsonBuildConfigurations = jsonBuildConfigurations ?? {}
|
|
77
|
+
|
|
78
|
+
// Possibly empty if there are no build configurations.
|
|
79
|
+
this.#buildConfigurationsMap = new Map<
|
|
80
|
+
string,
|
|
81
|
+
XpmLiquidBuildConfiguration | undefined
|
|
82
|
+
>()
|
|
83
|
+
this.#jsonBuildConfigurationsNamesMap = new Map<string, string>()
|
|
84
|
+
// log.trace('substitutionsVariables => ', this.substitutionsVariables)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
88
|
+
async initialise(): Promise<void> {
|
|
89
|
+
if (this.#isInitialised) {
|
|
90
|
+
return
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
for (const buildConfigurationName of Object.keys(
|
|
94
|
+
this.jsonBuildConfigurations
|
|
95
|
+
)) {
|
|
96
|
+
if (buildConfigurationName.includes('{{')) {
|
|
97
|
+
// TODO: expand templates and generate multiple build configurations.
|
|
98
|
+
} else {
|
|
99
|
+
this.#buildConfigurationsMap.set(buildConfigurationName, undefined)
|
|
100
|
+
this.#jsonBuildConfigurationsNamesMap.set(
|
|
101
|
+
buildConfigurationName,
|
|
102
|
+
buildConfigurationName
|
|
103
|
+
)
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
this.log.trace(
|
|
108
|
+
`${XpmLiquidBuildConfigurations.name}.initialise() =>`,
|
|
109
|
+
Array.from(this.#buildConfigurationsMap.keys())
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
this.#isInitialised = true
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// --------------------------------------------------------------------------
|
|
116
|
+
// Methods.
|
|
117
|
+
|
|
118
|
+
empty(): boolean {
|
|
119
|
+
return this.#buildConfigurationsMap.size === 0
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
names(): string[] {
|
|
123
|
+
const buildConfigurationsNames = Array.from(
|
|
124
|
+
this.#buildConfigurationsMap.keys()
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
this.log.trace(
|
|
128
|
+
`${XpmLiquidBuildConfigurations.name}.names() =>`,
|
|
129
|
+
buildConfigurationsNames
|
|
130
|
+
)
|
|
131
|
+
return buildConfigurationsNames
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
hasJson(buildConfigurationName: string): boolean {
|
|
135
|
+
return this.#jsonBuildConfigurationsNamesMap.has(buildConfigurationName)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
getJson(buildConfigurationName: string): JsonBuildConfiguration {
|
|
139
|
+
return this.jsonBuildConfigurations[
|
|
140
|
+
this.getJsonName(buildConfigurationName)
|
|
141
|
+
]
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
isHidden(buildConfigurationName: string): boolean {
|
|
145
|
+
return (
|
|
146
|
+
this.jsonBuildConfigurations[this.getJsonName(buildConfigurationName)]
|
|
147
|
+
.hidden ?? false
|
|
148
|
+
)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
has(buildConfigurationName: string): boolean {
|
|
152
|
+
return this.#buildConfigurationsMap.has(buildConfigurationName)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
async get(
|
|
156
|
+
buildConfigurationName: string
|
|
157
|
+
): Promise<XpmLiquidBuildConfiguration> {
|
|
158
|
+
let buildConfiguration = this.#buildConfigurationsMap.get(
|
|
159
|
+
buildConfigurationName
|
|
160
|
+
)
|
|
161
|
+
if (buildConfiguration === undefined) {
|
|
162
|
+
const jsonBuildConfigurationName: string =
|
|
163
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
164
|
+
this.#jsonBuildConfigurationsNamesMap.get(buildConfigurationName)!
|
|
165
|
+
|
|
166
|
+
buildConfiguration = new XpmLiquidBuildConfiguration({
|
|
167
|
+
buildConfigurationName,
|
|
168
|
+
jsonBuildConfigurationName,
|
|
169
|
+
parentBuildConfigurations: this,
|
|
170
|
+
})
|
|
171
|
+
await buildConfiguration.initialise()
|
|
172
|
+
this.#buildConfigurationsMap.set(
|
|
173
|
+
buildConfigurationName,
|
|
174
|
+
buildConfiguration
|
|
175
|
+
)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return buildConfiguration
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
getJsonName(buildConfigurationName: string): string {
|
|
182
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
183
|
+
return this.#jsonBuildConfigurationsNamesMap.get(buildConfigurationName)!
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// ----------------------------------------------------------------------------
|
|
188
|
+
|
|
189
|
+
// An individual build configuration.
|
|
190
|
+
export class XpmLiquidBuildConfiguration {
|
|
191
|
+
// --------------------------------------------------------------------------
|
|
192
|
+
// Members.
|
|
193
|
+
|
|
194
|
+
readonly hidden: boolean
|
|
195
|
+
|
|
196
|
+
// The actual (un-substituted) name from package.json.
|
|
197
|
+
readonly jsonBuildConfigurationName: string
|
|
198
|
+
// Points to the actual buildConfiguration in package.json.
|
|
199
|
+
readonly jsonBuildConfiguration: JsonBuildConfiguration
|
|
200
|
+
|
|
201
|
+
substitutionsVariables: XpmLiquidSubstitutionsVariables
|
|
202
|
+
|
|
203
|
+
properties: XpmLiquidSubstitutionsStrings = {}
|
|
204
|
+
|
|
205
|
+
jsonDependencies: JsonDependencies = {}
|
|
206
|
+
jsonDevDependencies: JsonDependencies = {}
|
|
207
|
+
|
|
208
|
+
// For templates, the actual values.
|
|
209
|
+
matrixParameters?: XpmLiquidSubstitutionsStrings
|
|
210
|
+
|
|
211
|
+
// The name after performing the substitutions.
|
|
212
|
+
readonly #buildConfigurationName: string
|
|
213
|
+
|
|
214
|
+
readonly #parentBuildConfigurations: XpmLiquidBuildConfigurations
|
|
215
|
+
|
|
216
|
+
#actions: XpmLiquidActions | undefined
|
|
217
|
+
|
|
218
|
+
#buildFolderRelativePath?: string
|
|
219
|
+
|
|
220
|
+
#isInitialised = false
|
|
221
|
+
|
|
222
|
+
// --------------------------------------------------------------------------
|
|
223
|
+
// Constructor and async initialiser.
|
|
224
|
+
|
|
225
|
+
constructor({
|
|
226
|
+
buildConfigurationName, // The Liquid-processed name.
|
|
227
|
+
jsonBuildConfigurationName, // The raw name from package.json.
|
|
228
|
+
parentBuildConfigurations,
|
|
229
|
+
}: {
|
|
230
|
+
buildConfigurationName: string
|
|
231
|
+
jsonBuildConfigurationName: string
|
|
232
|
+
parentBuildConfigurations: XpmLiquidBuildConfigurations
|
|
233
|
+
}) {
|
|
234
|
+
parentBuildConfigurations.log.trace(
|
|
235
|
+
`${XpmLiquidBuildConfiguration.name}(${buildConfigurationName})`
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
this.#buildConfigurationName = buildConfigurationName
|
|
239
|
+
this.jsonBuildConfigurationName = jsonBuildConfigurationName
|
|
240
|
+
this.#parentBuildConfigurations = parentBuildConfigurations
|
|
241
|
+
|
|
242
|
+
this.jsonBuildConfiguration =
|
|
243
|
+
parentBuildConfigurations.jsonBuildConfigurations[
|
|
244
|
+
jsonBuildConfigurationName
|
|
245
|
+
] ?? {}
|
|
246
|
+
|
|
247
|
+
this.substitutionsVariables = {
|
|
248
|
+
...this.#parentBuildConfigurations.substitutionsVariables,
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
this.hidden = this.jsonBuildConfiguration.hidden ?? false
|
|
252
|
+
|
|
253
|
+
// The rest of the initialisation is done in the async initialiser.
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
async initialise(): Promise<void> {
|
|
257
|
+
if (this.#isInitialised) {
|
|
258
|
+
return
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
const log = this.#parentBuildConfigurations.log
|
|
262
|
+
const jsonBuildConfiguration = this.jsonBuildConfiguration
|
|
263
|
+
|
|
264
|
+
// TODO: add matrixParameters
|
|
265
|
+
|
|
266
|
+
// Process both the new 'inherits' and the deprecated 'inherit'.
|
|
267
|
+
let inherits: string[] = []
|
|
268
|
+
if (isString(jsonBuildConfiguration.inherits)) {
|
|
269
|
+
inherits = [jsonBuildConfiguration.inherits]
|
|
270
|
+
} else if (Array.isArray(jsonBuildConfiguration.inherits)) {
|
|
271
|
+
inherits = jsonBuildConfiguration.inherit as string[]
|
|
272
|
+
} else if (isString(jsonBuildConfiguration.inherit)) {
|
|
273
|
+
inherits = [jsonBuildConfiguration.inherit]
|
|
274
|
+
} else if (Array.isArray(jsonBuildConfiguration.inherit)) {
|
|
275
|
+
inherits = jsonBuildConfiguration.inherit as string[]
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Add inherited configuration properties.
|
|
279
|
+
// TODO: detect circular references.
|
|
280
|
+
for (const inheritedBuildConfigurationName of inherits) {
|
|
281
|
+
if (
|
|
282
|
+
this.#parentBuildConfigurations.hasJson(inheritedBuildConfigurationName)
|
|
283
|
+
) {
|
|
284
|
+
const inheritedBuildConfiguration =
|
|
285
|
+
await this.#parentBuildConfigurations.get(
|
|
286
|
+
inheritedBuildConfigurationName
|
|
287
|
+
)
|
|
288
|
+
|
|
289
|
+
this.properties = {
|
|
290
|
+
...this.properties,
|
|
291
|
+
...inheritedBuildConfiguration.properties,
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
this.jsonDependencies = {
|
|
295
|
+
...this.jsonDependencies,
|
|
296
|
+
...inheritedBuildConfiguration.jsonDependencies,
|
|
297
|
+
}
|
|
298
|
+
this.jsonDevDependencies = {
|
|
299
|
+
...this.jsonDevDependencies,
|
|
300
|
+
...inheritedBuildConfiguration.jsonDevDependencies,
|
|
301
|
+
}
|
|
302
|
+
} else {
|
|
303
|
+
log.warn(
|
|
304
|
+
'buildConfiguration',
|
|
305
|
+
this.#buildConfigurationName,
|
|
306
|
+
'inherits from missing',
|
|
307
|
+
inheritedBuildConfigurationName,
|
|
308
|
+
'(ignored)'
|
|
309
|
+
)
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
this.properties = {
|
|
314
|
+
...this.properties,
|
|
315
|
+
...jsonBuildConfiguration.properties,
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
this.jsonDependencies = {
|
|
319
|
+
...this.jsonDependencies,
|
|
320
|
+
...jsonBuildConfiguration.dependencies,
|
|
321
|
+
}
|
|
322
|
+
this.jsonDevDependencies = {
|
|
323
|
+
...this.jsonDevDependencies,
|
|
324
|
+
...jsonBuildConfiguration.devDependencies,
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
this.substitutionsVariables = {
|
|
328
|
+
...this.#parentBuildConfigurations.substitutionsVariables,
|
|
329
|
+
properties: {
|
|
330
|
+
...this.substitutionsVariables.properties,
|
|
331
|
+
...this.properties,
|
|
332
|
+
},
|
|
333
|
+
configuration: {
|
|
334
|
+
...jsonBuildConfiguration,
|
|
335
|
+
name: this.#buildConfigurationName,
|
|
336
|
+
},
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// Add the buildFolderRelativePath property.
|
|
340
|
+
// Note: the async initialiser was needed due to this async operation.
|
|
341
|
+
const properties = this.substitutionsVariables.properties
|
|
342
|
+
properties.buildFolderRelativePath = await this.getBuildFolderRelativePath()
|
|
343
|
+
|
|
344
|
+
// Please note that substitutionsVariables is not fully set at this point;
|
|
345
|
+
// it will be in the async initialiser after the constructor returns.
|
|
346
|
+
this.#actions = new XpmLiquidActions({
|
|
347
|
+
log: this.#parentBuildConfigurations.log,
|
|
348
|
+
engine: this.#parentBuildConfigurations.engine,
|
|
349
|
+
substitutionsVariables: this.substitutionsVariables,
|
|
350
|
+
jsonActions: this.jsonBuildConfiguration.actions,
|
|
351
|
+
})
|
|
352
|
+
// Note: this must be done manually by the application.
|
|
353
|
+
// await this.#actions.initialise()
|
|
354
|
+
|
|
355
|
+
log.trace(
|
|
356
|
+
`${XpmLiquidBuildConfiguration.name}.initialise() =>`,
|
|
357
|
+
this.#buildConfigurationName
|
|
358
|
+
)
|
|
359
|
+
log.trace('properties => ', this.properties)
|
|
360
|
+
log.trace('dependencies => ', this.jsonDependencies)
|
|
361
|
+
log.trace('devDependencies => ', this.jsonDevDependencies)
|
|
362
|
+
// log.trace('substitutionsVariables => ', this.substitutionsVariables)
|
|
363
|
+
|
|
364
|
+
this.#isInitialised = true
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// --------------------------------------------------------------------------
|
|
368
|
+
// Methods.
|
|
369
|
+
|
|
370
|
+
get actions(): XpmLiquidActions {
|
|
371
|
+
assert(this.#actions !== undefined)
|
|
372
|
+
return this.#actions
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
async getBuildFolderRelativePath(): Promise<string> {
|
|
376
|
+
this.#buildFolderRelativePath ??= await this.#getBuildFolderRelativePath()
|
|
377
|
+
return this.#buildFolderRelativePath
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
async #getBuildFolderRelativePath(): Promise<string> {
|
|
381
|
+
const log = this.#parentBuildConfigurations.log
|
|
382
|
+
|
|
383
|
+
let folderPath: string
|
|
384
|
+
if (
|
|
385
|
+
buildFolderRelativePathPropertyName in
|
|
386
|
+
this.substitutionsVariables.properties
|
|
387
|
+
) {
|
|
388
|
+
folderPath = this.substitutionsVariables.properties[
|
|
389
|
+
buildFolderRelativePathPropertyName
|
|
390
|
+
] as string
|
|
391
|
+
if (folderPath !== '') {
|
|
392
|
+
try {
|
|
393
|
+
return await performSubstitutions({
|
|
394
|
+
log,
|
|
395
|
+
engine: this.#parentBuildConfigurations.engine,
|
|
396
|
+
input: folderPath,
|
|
397
|
+
substitutionsVariables: this.substitutionsVariables,
|
|
398
|
+
})
|
|
399
|
+
} catch (err) {
|
|
400
|
+
log.trace(err)
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// Provide a default value, based on the name.
|
|
406
|
+
return path.join('build', filterPath(this.#buildConfigurationName))
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
// ----------------------------------------------------------------------------
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of the xPack project (http://xpack.github.io).
|
|
3
|
+
* Copyright (c) 2021-2026 Liviu Ionescu. All rights reserved.
|
|
4
|
+
*
|
|
5
|
+
* Permission to use, copy, modify, and/or distribute this software
|
|
6
|
+
* for any purpose is hereby granted, under the terms of the MIT license.
|
|
7
|
+
*
|
|
8
|
+
* If a copy of the license was not distributed with this file, it can
|
|
9
|
+
* be obtained from https://opensource.org/license/mit.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/* eslint max-len: [ "error", 80, { "ignoreUrls": true } ] */
|
|
13
|
+
|
|
14
|
+
// ----------------------------------------------------------------------------
|
|
15
|
+
|
|
16
|
+
// https://www.npmjs.com/package/liquidjs
|
|
17
|
+
import { Liquid, Context, Drop } from 'liquidjs'
|
|
18
|
+
|
|
19
|
+
// https://www.npmjs.com/package/@xpack/logger
|
|
20
|
+
import { Logger } from '@xpack/logger'
|
|
21
|
+
|
|
22
|
+
import { XpmLiquidSubstitutionsStrings } from './substitutions-variables.js'
|
|
23
|
+
|
|
24
|
+
// ----------------------------------------------------------------------------
|
|
25
|
+
|
|
26
|
+
// https://liquidjs.com/
|
|
27
|
+
|
|
28
|
+
export class XpmLiquidPropertiesDrop extends Drop {
|
|
29
|
+
// --------------------------------------------------------------------------
|
|
30
|
+
// Members.
|
|
31
|
+
|
|
32
|
+
readonly #log: Logger
|
|
33
|
+
readonly #properties: XpmLiquidSubstitutionsStrings
|
|
34
|
+
readonly #engine: Liquid
|
|
35
|
+
|
|
36
|
+
// --------------------------------------------------------------------------
|
|
37
|
+
// Constructor.
|
|
38
|
+
|
|
39
|
+
constructor({
|
|
40
|
+
log,
|
|
41
|
+
engine,
|
|
42
|
+
properties,
|
|
43
|
+
}: {
|
|
44
|
+
log: Logger
|
|
45
|
+
engine: Liquid
|
|
46
|
+
properties: XpmLiquidSubstitutionsStrings
|
|
47
|
+
}) {
|
|
48
|
+
super()
|
|
49
|
+
|
|
50
|
+
log.trace(`${XpmLiquidPropertiesDrop.name}()`)
|
|
51
|
+
|
|
52
|
+
this.#log = log
|
|
53
|
+
this.#engine = engine
|
|
54
|
+
this.#properties = properties
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// --------------------------------------------------------------------------
|
|
58
|
+
// Methods.
|
|
59
|
+
|
|
60
|
+
override async liquidMethodMissing(
|
|
61
|
+
key: string,
|
|
62
|
+
context: Context
|
|
63
|
+
): Promise<string | string[]> {
|
|
64
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
65
|
+
if (this.#properties[key] === undefined) {
|
|
66
|
+
throw new Error(`properties have no ${key} key`)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const log = this.#log
|
|
70
|
+
|
|
71
|
+
const value = this.#properties[key] ?? ''
|
|
72
|
+
log.trace(
|
|
73
|
+
`${XpmLiquidPropertiesDrop.name}.liquidMethodMissing('${key}') value = |`,
|
|
74
|
+
value,
|
|
75
|
+
'|'
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
let result: string | string[]
|
|
79
|
+
|
|
80
|
+
const valueString = Array.isArray(value) ? value.join('') : value
|
|
81
|
+
if (valueString.includes('{{') || valueString.includes('{%')) {
|
|
82
|
+
result = (await this.#engine.parseAndRender(
|
|
83
|
+
valueString,
|
|
84
|
+
context
|
|
85
|
+
)) as string
|
|
86
|
+
} else {
|
|
87
|
+
result = value
|
|
88
|
+
}
|
|
89
|
+
log.trace(
|
|
90
|
+
`${XpmLiquidPropertiesDrop.name}.liquidMethodMissing('${key}') ` +
|
|
91
|
+
`result = |`,
|
|
92
|
+
result,
|
|
93
|
+
'|'
|
|
94
|
+
)
|
|
95
|
+
return result
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// ----------------------------------------------------------------------------
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of the xPack project (http://xpack.github.io).
|
|
3
|
+
* Copyright (c) 2021-2026 Liviu Ionescu. All rights reserved.
|
|
4
|
+
*
|
|
5
|
+
* Permission to use, copy, modify, and/or distribute this software
|
|
6
|
+
* for any purpose is hereby granted, under the terms of the MIT license.
|
|
7
|
+
*
|
|
8
|
+
* If a copy of the license was not distributed with this file, it can
|
|
9
|
+
* be obtained from https://opensource.org/license/mit.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/* eslint max-len: [ "error", 80, { "ignoreUrls": true } ] */
|
|
13
|
+
|
|
14
|
+
// ----------------------------------------------------------------------------
|
|
15
|
+
|
|
16
|
+
import * as os from 'node:os'
|
|
17
|
+
import * as path from 'node:path'
|
|
18
|
+
import * as util from 'node:util'
|
|
19
|
+
|
|
20
|
+
// https://www.npmjs.com/package/liquidjs
|
|
21
|
+
import { Liquid } from 'liquidjs'
|
|
22
|
+
|
|
23
|
+
// ----------------------------------------------------------------------------
|
|
24
|
+
|
|
25
|
+
export class XpmLiquidEngine extends Liquid {
|
|
26
|
+
// --------------------------------------------------------------------------
|
|
27
|
+
// Members.
|
|
28
|
+
|
|
29
|
+
// --------------------------------------------------------------------------
|
|
30
|
+
// Constructor.
|
|
31
|
+
|
|
32
|
+
constructor() {
|
|
33
|
+
super({
|
|
34
|
+
strictFilters: true,
|
|
35
|
+
strictVariables: true,
|
|
36
|
+
trimTagLeft: false,
|
|
37
|
+
trimTagRight: false,
|
|
38
|
+
trimOutputLeft: false,
|
|
39
|
+
trimOutputRight: false,
|
|
40
|
+
greedy: false,
|
|
41
|
+
lenientIf: true,
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
// https://liquidjs.com/api/classes/liquid_.liquid.html#registerFilter
|
|
45
|
+
// https://nodejs.org/dist/latest-v16.x/docs/api/path.html
|
|
46
|
+
|
|
47
|
+
// Add the main path manipulation functions.
|
|
48
|
+
this.registerFilter('path_basename', (p: string, ...arg) =>
|
|
49
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
50
|
+
path.basename(p, ...arg)
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
this.registerFilter('path_dirname', (p: string) => path.dirname(p))
|
|
54
|
+
|
|
55
|
+
this.registerFilter('path_normalize', (p: string) => path.normalize(p))
|
|
56
|
+
|
|
57
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
58
|
+
this.registerFilter('path_join', (p, ...args) => path.join(p, ...args))
|
|
59
|
+
|
|
60
|
+
this.registerFilter('path_relative', (from: string, to: string) =>
|
|
61
|
+
path.relative(from, to)
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
this.registerFilter('path_posix_basename', (p: string, ...arg) =>
|
|
65
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
66
|
+
path.posix.basename(p, ...arg)
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
this.registerFilter('path_posix_dirname', (p: string) =>
|
|
70
|
+
path.posix.dirname(p)
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
this.registerFilter('path_posix_normalize', (p: string) =>
|
|
74
|
+
path.posix.normalize(p)
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
this.registerFilter('path_posix_join', (p, ...args) =>
|
|
78
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
79
|
+
path.posix.join(p, ...args)
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
this.registerFilter('path_posix_relative', (from: string, to: string) =>
|
|
83
|
+
path.posix.relative(from, to)
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
this.registerFilter('path_win32_basename', (p: string, ...arg) =>
|
|
87
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
88
|
+
path.win32.basename(p, ...arg)
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
this.registerFilter('path_win32_dirname', (p: string) =>
|
|
92
|
+
path.win32.dirname(p)
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
this.registerFilter('path_win32_normalize', (p: string) =>
|
|
96
|
+
path.win32.normalize(p)
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
this.registerFilter('path_win32_join', (p, ...args) =>
|
|
100
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
101
|
+
path.win32.join(p, ...args)
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
this.registerFilter('path_win32_relative', (from: string, to: string) =>
|
|
105
|
+
path.win32.relative(from, to)
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
// https://nodejs.org/dist/latest-v16.x/docs/api/util.html
|
|
109
|
+
|
|
110
|
+
this.registerFilter('util_format', (format, ...args) => {
|
|
111
|
+
// console.log([...args])
|
|
112
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
113
|
+
return util.format(format, ...args)
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
// Custom action.
|
|
117
|
+
this.registerFilter(
|
|
118
|
+
'to_filename',
|
|
119
|
+
// Replace non alphanumeric chars with dashes to make the paths
|
|
120
|
+
// comply with filesystem names.
|
|
121
|
+
(input: string): string => {
|
|
122
|
+
/* c8 ignore start */ /* istanbul ignore next */
|
|
123
|
+
const fixed =
|
|
124
|
+
os.platform() === 'win32'
|
|
125
|
+
? input.replace(/[^a-zA-Z0-9\\:]+/g, '-')
|
|
126
|
+
: input.replace(/[^a-zA-Z0-9/]+/g, '-')
|
|
127
|
+
/* c8 ignore stop */
|
|
128
|
+
|
|
129
|
+
return fixed.replace(/--/g, '-')
|
|
130
|
+
}
|
|
131
|
+
)
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// ----------------------------------------------------------------------------
|