@lexibase/create-rdx 1.2.0 → 1.2.2

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 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.0",
3
+ "version": "1.2.2",
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"
@@ -9,7 +9,7 @@
9
9
  "start": "rdx start"
10
10
  },
11
11
  "dependencies": {
12
- "@lexibase/rdx": "1.2.0",
12
+ "@lexibase/rdx": "1.2.1",
13
13
  "next": "^16.4.2",
14
14
  "react": "19.3.1",
15
15
  "react-dom": "19.3.1"