@lexibase/create-rdx 1.2.0 → 1.2.1
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/README.md +6 -0
- package/bin/index.js +5 -0
- package/bin/pnpm-policy.mjs +115 -0
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -41,6 +41,12 @@ the runtime. Follow the commands printed by the generator.
|
|
|
41
41
|
|
|
42
42
|
## Recovery
|
|
43
43
|
|
|
44
|
+
In a pnpm workspace, installation uses the workspace's existing dependencies and
|
|
45
|
+
policy. Before installation and runtime preparation, the creator consolidates
|
|
46
|
+
duplicate exact-version approvals for RDX in `minimumReleaseAgeExclude`. Only
|
|
47
|
+
versions already listed are combined; the age threshold, strict mode, unrelated
|
|
48
|
+
package rules, comments and other workspace settings are preserved.
|
|
49
|
+
|
|
44
50
|
If installation or preparation fails, the command exits with an error and keeps
|
|
45
51
|
the generated files. Fix the reported issue, enter the created folder and retry
|
|
46
52
|
installation/development using the same package manager. Do not rerun creation
|
package/bin/index.js
CHANGED
|
@@ -8,6 +8,7 @@ import fs from 'fs-extra'
|
|
|
8
8
|
import prompts from 'prompts'
|
|
9
9
|
|
|
10
10
|
import { parseArguments, validateProjectName } from './options.mjs'
|
|
11
|
+
import { normalizePnpmRdxApprovals } from './pnpm-policy.mjs'
|
|
11
12
|
|
|
12
13
|
function getPackageManager() {
|
|
13
14
|
const userAgent = process.env.npm_config_user_agent || ''
|
|
@@ -149,7 +150,11 @@ async function main() {
|
|
|
149
150
|
if (!skipInstall) {
|
|
150
151
|
try {
|
|
151
152
|
console.log(`\nInstalling dependencies with ${packageManager}...\n`)
|
|
153
|
+
if (packageManager === 'pnpm')
|
|
154
|
+
await normalizePnpmRdxApprovals(targetDir)
|
|
152
155
|
await run(packageManager, ['install'], targetDir)
|
|
156
|
+
if (packageManager === 'pnpm')
|
|
157
|
+
await normalizePnpmRdxApprovals(targetDir)
|
|
153
158
|
const prepareArgs =
|
|
154
159
|
packageManager === 'npm'
|
|
155
160
|
? ['exec', '--', 'rdx', 'prepare']
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto'
|
|
2
|
+
import { lstat, readFile, rename, rm, writeFile } from 'node:fs/promises'
|
|
3
|
+
import path from 'node:path'
|
|
4
|
+
|
|
5
|
+
import { isScalar, isSeq, parseDocument } from 'yaml'
|
|
6
|
+
|
|
7
|
+
const rdxPackages = new Set([
|
|
8
|
+
'@lexibase/rdx',
|
|
9
|
+
'@lexibase/rdx-core',
|
|
10
|
+
'@lexibase/rdx-next',
|
|
11
|
+
'@lexibase/rdx-types',
|
|
12
|
+
'@lexibase/rdx-ui',
|
|
13
|
+
'@lexibase/rdx-versioning',
|
|
14
|
+
'@lexibase/create-rdx',
|
|
15
|
+
])
|
|
16
|
+
const version =
|
|
17
|
+
/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-[\da-z.-]+)?(?:\+[\da-z.-]+)?$/i
|
|
18
|
+
|
|
19
|
+
async function workspaceFile(directory) {
|
|
20
|
+
let current = path.resolve(directory)
|
|
21
|
+
while (true) {
|
|
22
|
+
const filename = path.join(current, 'pnpm-workspace.yaml')
|
|
23
|
+
try {
|
|
24
|
+
const info = await lstat(filename)
|
|
25
|
+
if (!info.isFile() || info.isSymbolicLink()) return undefined
|
|
26
|
+
return filename
|
|
27
|
+
} catch (error) {
|
|
28
|
+
if (error.code !== 'ENOENT') throw error
|
|
29
|
+
}
|
|
30
|
+
const parent = path.dirname(current)
|
|
31
|
+
if (parent === current) return undefined
|
|
32
|
+
current = parent
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function exactRule(value) {
|
|
37
|
+
if (typeof value !== 'string') return undefined
|
|
38
|
+
const at = value.indexOf('@', 1)
|
|
39
|
+
if (at < 0 || !rdxPackages.has(value.slice(0, at))) return undefined
|
|
40
|
+
const versions = value
|
|
41
|
+
.slice(at + 1)
|
|
42
|
+
.split('||')
|
|
43
|
+
.map((item) => item.trim())
|
|
44
|
+
if (!versions.length || !versions.every((item) => version.test(item)))
|
|
45
|
+
return undefined
|
|
46
|
+
return { name: value.slice(0, at), versions }
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Merge only exact RDX approvals already recorded by the user or pnpm. */
|
|
50
|
+
export async function normalizePnpmRdxApprovals(directory) {
|
|
51
|
+
const filename = await workspaceFile(directory)
|
|
52
|
+
if (!filename) return false
|
|
53
|
+
const original = await readFile(filename, 'utf8')
|
|
54
|
+
const document = parseDocument(original)
|
|
55
|
+
if (document.errors.length)
|
|
56
|
+
throw new Error(`Cannot read ${filename}: ${document.errors[0].message}`)
|
|
57
|
+
const approvals = document.get('minimumReleaseAgeExclude', true)
|
|
58
|
+
if (approvals === undefined) return false
|
|
59
|
+
// Leave aliases and non-literal policy definitions to pnpm itself.
|
|
60
|
+
if (
|
|
61
|
+
!isSeq(approvals) ||
|
|
62
|
+
approvals.items.some(
|
|
63
|
+
(item) => !isScalar(item) || typeof item.value !== 'string'
|
|
64
|
+
)
|
|
65
|
+
)
|
|
66
|
+
return false
|
|
67
|
+
|
|
68
|
+
const groups = new Map()
|
|
69
|
+
const removed = new Set()
|
|
70
|
+
for (const node of approvals.items) {
|
|
71
|
+
const rule = exactRule(node.value)
|
|
72
|
+
if (!rule) continue
|
|
73
|
+
const first = groups.get(rule.name)
|
|
74
|
+
if (!first) {
|
|
75
|
+
groups.set(rule.name, { node, versions: new Set(rule.versions) })
|
|
76
|
+
continue
|
|
77
|
+
}
|
|
78
|
+
for (const value of rule.versions) first.versions.add(value)
|
|
79
|
+
first.node.value = `${rule.name}@${[...first.versions].join(' || ')}`
|
|
80
|
+
// Retain comments attached to approvals that are folded into the first rule.
|
|
81
|
+
if (node.commentBefore)
|
|
82
|
+
first.node.commentBefore = [first.node.commentBefore, node.commentBefore]
|
|
83
|
+
.filter(Boolean)
|
|
84
|
+
.join('\n')
|
|
85
|
+
if (node.comment)
|
|
86
|
+
first.node.comment = [first.node.comment, node.comment]
|
|
87
|
+
.filter(Boolean)
|
|
88
|
+
.join('\n')
|
|
89
|
+
removed.add(node)
|
|
90
|
+
}
|
|
91
|
+
if (!removed.size) return false
|
|
92
|
+
approvals.items = approvals.items.filter((node) => !removed.has(node))
|
|
93
|
+
let updated = document.toString({ lineWidth: 0 })
|
|
94
|
+
if (original.includes('\r\n')) updated = updated.replaceAll('\n', '\r\n')
|
|
95
|
+
const temporary = path.join(
|
|
96
|
+
path.dirname(filename),
|
|
97
|
+
`.rdx-policy-${randomUUID()}.tmp`
|
|
98
|
+
)
|
|
99
|
+
try {
|
|
100
|
+
const info = await lstat(filename)
|
|
101
|
+
await writeFile(temporary, updated, { flag: 'wx', mode: info.mode })
|
|
102
|
+
if (
|
|
103
|
+
info.isSymbolicLink() ||
|
|
104
|
+
(await readFile(filename, 'utf8')) !== original
|
|
105
|
+
)
|
|
106
|
+
throw new Error(
|
|
107
|
+
`The pnpm policy changed during project creation: ${filename}. Retry without concurrent installs.`
|
|
108
|
+
)
|
|
109
|
+
await rename(temporary, filename)
|
|
110
|
+
} finally {
|
|
111
|
+
await rm(temporary, { force: true })
|
|
112
|
+
}
|
|
113
|
+
console.log(`Consolidated existing RDX version approvals in ${filename}.`)
|
|
114
|
+
return true
|
|
115
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lexibase/create-rdx",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "Create a new RDX documentation project.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"bin": {
|
|
@@ -30,7 +30,8 @@
|
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"cross-spawn": "^7.0.6",
|
|
32
32
|
"fs-extra": "^11.1.1",
|
|
33
|
-
"prompts": "^2.4.2"
|
|
33
|
+
"prompts": "^2.4.2",
|
|
34
|
+
"yaml": "^2.9.1"
|
|
34
35
|
},
|
|
35
36
|
"scripts": {
|
|
36
37
|
"test": "node --test tests/*.test.mjs"
|