coralite-scripts 0.39.0 → 0.40.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/bin/index.js +12 -0
- package/dist/libs/config.d.ts.map +1 -1
- package/libs/assets.js +55 -0
- package/libs/commands/build.js +26 -0
- package/libs/config.js +23 -0
- package/libs/load-config.js +3 -8
- package/package.json +5 -5
package/bin/index.js
CHANGED
|
@@ -7,6 +7,7 @@ import pkg from '../package.json' with { type: 'json' }
|
|
|
7
7
|
import { join } from 'node:path'
|
|
8
8
|
import { mkdir } from 'node:fs/promises'
|
|
9
9
|
import { buildCommand } from '../libs/commands/build.js'
|
|
10
|
+
import { parseAssetMapping, mergeAssets } from '../libs/assets.js'
|
|
10
11
|
|
|
11
12
|
// remove all Node warnings before doing anything else
|
|
12
13
|
process.removeAllListeners('warning')
|
|
@@ -20,6 +21,7 @@ program
|
|
|
20
21
|
.addArgument(new Argument('<mode>', 'Run mode: dev (development server) or build (production compilation)').choices(['dev', 'build']).default('dev'))
|
|
21
22
|
.option('-v, --verbose', 'Enable verbose logging output')
|
|
22
23
|
.option('-c, --clean', 'Clear the output directory before building')
|
|
24
|
+
.option('-a, --assets <mapping...>', 'Static assets to copy during build. Format: pkg:path:dest or src:dest')
|
|
23
25
|
|
|
24
26
|
program.parse(process.argv)
|
|
25
27
|
program.on('error', (err) => {
|
|
@@ -34,6 +36,16 @@ if (!config) {
|
|
|
34
36
|
process.exit(1)
|
|
35
37
|
}
|
|
36
38
|
|
|
39
|
+
if (options.assets) {
|
|
40
|
+
try {
|
|
41
|
+
const cliAssets = options.assets.map(parseAssetMapping)
|
|
42
|
+
config.assets = mergeAssets(config.assets, cliAssets)
|
|
43
|
+
} catch (err) {
|
|
44
|
+
console.error(`\n Error: ${err.message}\n`)
|
|
45
|
+
process.exit(1)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
37
49
|
if (mode === 'dev') {
|
|
38
50
|
config.output = join(process.cwd(), '.coralite')
|
|
39
51
|
await mkdir(config.output, { recursive: true })
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../libs/config.js"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,sCAzBW,oBAAoB,GAClB,oBAAoB,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../libs/config.js"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,sCAzBW,oBAAoB,GAClB,oBAAoB,CA2KhC;0CArLsC,mBAAmB"}
|
package/libs/assets.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @import { CoraliteStaticAsset } from 'coralite'
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Parses an asset mapping string into an asset object.
|
|
7
|
+
*
|
|
8
|
+
* @param {string} mapping - The mapping string (pkg:path:dest or src:dest).
|
|
9
|
+
* @returns {CoraliteStaticAsset} The parsed asset object.
|
|
10
|
+
* @throws {Error} If the mapping format is invalid.
|
|
11
|
+
*/
|
|
12
|
+
export function parseAssetMapping (mapping) {
|
|
13
|
+
const parts = mapping.split(':')
|
|
14
|
+
|
|
15
|
+
if (parts.length === 3) {
|
|
16
|
+
// pkg:path:dest
|
|
17
|
+
return {
|
|
18
|
+
pkg: parts[0],
|
|
19
|
+
path: parts[1],
|
|
20
|
+
dest: parts[2]
|
|
21
|
+
}
|
|
22
|
+
} else if (parts.length === 2) {
|
|
23
|
+
// src:dest
|
|
24
|
+
const src = parts[0]
|
|
25
|
+
if (!src.startsWith('.') && !src.startsWith('/') && !src.startsWith('..')) {
|
|
26
|
+
throw new Error(`Invalid asset mapping "${mapping}". Local paths must start with ".", "..", or "/". NPM package mappings require 3 parts (pkg:path:dest).`)
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
src,
|
|
30
|
+
dest: parts[1]
|
|
31
|
+
}
|
|
32
|
+
} else {
|
|
33
|
+
throw new Error(`Invalid asset mapping "${mapping}". Expected format: pkg:path:dest or src:dest`)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Merges a list of CLI assets into an existing assets array, with CLI assets taking precedence on destination collisions.
|
|
39
|
+
*
|
|
40
|
+
* @param {CoraliteStaticAsset[]} baseAssets - The existing assets array.
|
|
41
|
+
* @param {CoraliteStaticAsset[]} cliAssets - The new assets to merge.
|
|
42
|
+
* @returns {CoraliteStaticAsset[]} The merged assets array.
|
|
43
|
+
*/
|
|
44
|
+
export function mergeAssets (baseAssets = [], cliAssets = []) {
|
|
45
|
+
const merged = [...baseAssets]
|
|
46
|
+
for (const cliAsset of cliAssets) {
|
|
47
|
+
const index = merged.findIndex(a => a.dest === cliAsset.dest)
|
|
48
|
+
if (index !== -1) {
|
|
49
|
+
merged[index] = cliAsset
|
|
50
|
+
} else {
|
|
51
|
+
merged.push(cliAsset)
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return merged
|
|
55
|
+
}
|
package/libs/commands/build.js
CHANGED
|
@@ -148,6 +148,32 @@ export async function buildCommand (config, options, logger = null) {
|
|
|
148
148
|
await Promise.all(assetWrites)
|
|
149
149
|
}
|
|
150
150
|
|
|
151
|
+
// Track assets from config to prevent them from being deleted as stale files
|
|
152
|
+
if (config.assets) {
|
|
153
|
+
for (const asset of config.assets) {
|
|
154
|
+
const fullDestPath = join(config.output, asset.dest)
|
|
155
|
+
if (existsSync(fullDestPath)) {
|
|
156
|
+
const stat = statSync(fullDestPath)
|
|
157
|
+
if (stat.isDirectory()) {
|
|
158
|
+
const trackFiles = (dir) => {
|
|
159
|
+
const files = readdirSync(dir)
|
|
160
|
+
for (const file of files) {
|
|
161
|
+
const fullPath = join(dir, file)
|
|
162
|
+
if (statSync(fullPath).isDirectory()) {
|
|
163
|
+
trackFiles(fullPath)
|
|
164
|
+
} else {
|
|
165
|
+
validFiles.add(fullPath)
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
trackFiles(fullDestPath)
|
|
170
|
+
} else {
|
|
171
|
+
validFiles.add(fullDestPath)
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
151
177
|
if (!options.verbose) {
|
|
152
178
|
if (skippedCount > 0) {
|
|
153
179
|
spinner.succeed(`Pages built (${pageCount} completed, ${skippedCount} skipped)`)
|
package/libs/config.js
CHANGED
|
@@ -154,6 +154,29 @@ export function defineConfig (options) {
|
|
|
154
154
|
if (!Array.isArray(options.assets)) {
|
|
155
155
|
throw new Error('Configuration "assets" must be an array')
|
|
156
156
|
}
|
|
157
|
+
|
|
158
|
+
for (const asset of options.assets) {
|
|
159
|
+
if (typeof asset !== 'object' || asset === null) {
|
|
160
|
+
throw new Error('Configuration "assets" items must be objects')
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (!asset.dest || typeof asset.dest !== 'string') {
|
|
164
|
+
throw new Error('Configuration "assets" items must have a string "dest" property')
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (asset.src) {
|
|
168
|
+
if (typeof asset.src !== 'string') {
|
|
169
|
+
throw new Error('Configuration "assets" items "src" property must be a string')
|
|
170
|
+
}
|
|
171
|
+
} else {
|
|
172
|
+
if (!asset.pkg || typeof asset.pkg !== 'string') {
|
|
173
|
+
throw new Error('Configuration "assets" items must have a string "pkg" property when "src" is not provided')
|
|
174
|
+
}
|
|
175
|
+
if (!asset.path || typeof asset.path !== 'string') {
|
|
176
|
+
throw new Error('Configuration "assets" items must have a string "path" property when "src" is not provided')
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
157
180
|
}
|
|
158
181
|
|
|
159
182
|
return options
|
package/libs/load-config.js
CHANGED
|
@@ -43,15 +43,10 @@ async function loadConfig (cwd = process.cwd()) {
|
|
|
43
43
|
return null
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
return defineConfig(config.default)
|
|
48
|
-
} catch (err) {
|
|
49
|
-
displayError('Invalid configuration', err.message)
|
|
50
|
-
return null
|
|
51
|
-
}
|
|
46
|
+
return defineConfig(config.default)
|
|
52
47
|
} catch (error) {
|
|
53
|
-
displayError('Failed to load configuration file', error)
|
|
54
|
-
|
|
48
|
+
displayError('Failed to load configuration file', error.message || error)
|
|
49
|
+
throw error
|
|
55
50
|
}
|
|
56
51
|
}
|
|
57
52
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "coralite-scripts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.40.0",
|
|
4
4
|
"description": "Configuration and scripts for Create Coralite.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -61,11 +61,11 @@
|
|
|
61
61
|
"portfinder": "^1.0.38",
|
|
62
62
|
"postcss": "^8.5.15",
|
|
63
63
|
"sass": "^1.101.0",
|
|
64
|
-
"coralite": "0.
|
|
64
|
+
"coralite": "0.40.0"
|
|
65
65
|
},
|
|
66
66
|
"scripts": {
|
|
67
|
-
"build": "premove dist && pnpm build
|
|
68
|
-
"build
|
|
69
|
-
"test
|
|
67
|
+
"build": "premove dist && pnpm build:types",
|
|
68
|
+
"build:types": "tsc",
|
|
69
|
+
"test:unit": "node --test tests/**/*.spec.js"
|
|
70
70
|
}
|
|
71
71
|
}
|