@lexibase/rdx-next 1.0.0-beta.1 → 1.0.0-beta.10

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
@@ -1,6 +1,41 @@
1
- # `@rdx/next`
1
+ # `@lexibase/rdx-next`
2
2
 
3
3
  The official Next.js runtime for RDX documentation projects.
4
4
 
5
+ Requires Node.js 20.9 or newer; use a currently supported Node.js LTS release.
6
+ The MDX renderer keeps JavaScript expression blocking enabled. Markdown, fenced
7
+ code and registered JSX components with literal props remain supported, but
8
+ expressions such as `{value}` or `style={{ ... }}` are not evaluated. Documentation
9
+ must still be trusted project-owned content, not untrusted uploads.
10
+
5
11
  It exposes the `rdx` command used by generated projects to create their
6
12
  internal `.rdx` application and run Next.js.
13
+
14
+ Run `pnpm rdx add versioning` (or `npm exec -- rdx add versioning`) from a
15
+ documentation project to install and activate the official optional plugin.
16
+ The command detects the package manager, preserves config and plugin options,
17
+ validates the result before saving it without creating backups, and prepares
18
+ the runtime. Repeating it does not duplicate or upgrade an installed plugin.
19
+ Use `--package-manager npm|pnpm|yarn` to resolve ambiguous lockfiles. Dynamic
20
+ configurations receive manual instructions and are not automatically edited.
21
+ Installing a package with npm/pnpm/yarn alone never edits `rdx.config.ts`.
22
+
23
+ Generated sites use the same theme and components as the development website,
24
+ through `@lexibase/rdx-ui`: logo, navbar, Base UI version dropdown, mobile/desktop
25
+ sidebar, landing page, MDX styles and theme provider. The adapter owns content
26
+ and route data; it does not implement a parallel UI theme.
27
+
28
+ Use `homepage: { enabled: true }` in `rdx.config.ts` for the centered-logo
29
+ homepage, or import a project-owned React component with `homepage.component`.
30
+ Without the option, `/` redirects to `/docs`. Additional content sources from
31
+ explicitly configured plugins enable the shared navbar dropdown.
32
+
33
+ `.rdx/` is generated. Configure the site or edit a project-owned `home.tsx`
34
+ instead of modifying files inside `.rdx/`.
35
+
36
+ Place images, favicon and downloads in the project-root `public/` directory.
37
+ The CLI links `.rdx/public` to it using a junction on Windows or a directory
38
+ symlink elsewhere. `/images/logo.svg` serves `public/images/logo.svg` in dev and
39
+ production. No asset copies are cached and original files are never removed.
40
+ Restart/redeploy production after adding/removing assets. Documentation versions
41
+ share this directory; snapshots do not copy its contents.
@@ -0,0 +1,229 @@
1
+ import { randomUUID } from 'node:crypto'
2
+ import { createRequire } from 'node:module'
3
+ import { lstat, readFile, writeFile, rename, unlink } from 'node:fs/promises'
4
+ import path from 'node:path'
5
+ import process from 'node:process'
6
+
7
+ import { createRdxProject, resolveConfig } from '@lexibase/rdx-core/config'
8
+ import spawn from 'cross-spawn'
9
+ import { createJiti } from 'jiti'
10
+
11
+ import { activateVersioning, versioningPackage } from './plugin-config.mjs'
12
+
13
+ const managers = new Set(['npm', 'pnpm', 'yarn'])
14
+
15
+ export function parseAddArguments(args) {
16
+ const [plugin, ...rest] = args
17
+ if (plugin !== 'versioning')
18
+ throw new Error(
19
+ 'Usage: rdx add versioning [--package-manager npm|pnpm|yarn]. Only the official versioning plugin is currently supported.'
20
+ )
21
+ if (!rest.length) return {}
22
+ if (
23
+ rest.length === 2 &&
24
+ rest[0] === '--package-manager' &&
25
+ managers.has(rest[1])
26
+ )
27
+ return { packageManager: rest[1] }
28
+ throw new Error(
29
+ 'Usage: rdx add versioning [--package-manager npm|pnpm|yarn].'
30
+ )
31
+ }
32
+
33
+ async function exists(filename) {
34
+ try {
35
+ await lstat(filename)
36
+ return true
37
+ } catch (error) {
38
+ if (error.code === 'ENOENT') return false
39
+ throw error
40
+ }
41
+ }
42
+
43
+ export async function detectPackageManager(
44
+ rootDir,
45
+ pkg,
46
+ env = process.env,
47
+ explicit
48
+ ) {
49
+ if (explicit) {
50
+ if (!managers.has(explicit)) throw new Error('Unsupported package manager.')
51
+ return explicit
52
+ }
53
+ if (
54
+ pkg.packageManager !== undefined &&
55
+ typeof pkg.packageManager !== 'string'
56
+ )
57
+ throw new Error('packageManager in package.json must be a string.')
58
+ const declared = pkg.packageManager?.split('@')[0]
59
+ if (declared && !managers.has(declared))
60
+ throw new Error(
61
+ 'Unsupported packageManager in package.json. Choose --package-manager npm, pnpm or yarn explicitly.'
62
+ )
63
+ const locks = []
64
+ for (const [manager, filenames] of [
65
+ ['npm', ['package-lock.json', 'npm-shrinkwrap.json']],
66
+ ['pnpm', ['pnpm-lock.yaml']],
67
+ ['yarn', ['yarn.lock']],
68
+ ]) {
69
+ if (
70
+ (
71
+ await Promise.all(
72
+ filenames.map((filename) => exists(path.join(rootDir, filename)))
73
+ )
74
+ ).some(Boolean)
75
+ )
76
+ locks.push(manager)
77
+ }
78
+ if (locks.length > 1 || (declared && locks.length && locks[0] !== declared))
79
+ throw new Error(
80
+ 'Conflicting package managers. Keep the intended lockfile or choose --package-manager npm, pnpm or yarn explicitly.'
81
+ )
82
+ const agent = env.npm_config_user_agent?.split('/')[0]
83
+ return declared ?? locks[0] ?? (managers.has(agent) ? agent : 'npm')
84
+ }
85
+
86
+ export function installPackage(manager, rootDir, env = process.env) {
87
+ return new Promise((resolve, reject) => {
88
+ const args = [
89
+ manager === 'npm' ? 'install' : 'add',
90
+ `${versioningPackage}@beta`,
91
+ ]
92
+ const nodeEntry =
93
+ env.npm_config_user_agent?.startsWith(`${manager}/`) &&
94
+ env.npm_execpath &&
95
+ /\.[cm]?js$/i.test(env.npm_execpath)
96
+ const child = spawn(
97
+ nodeEntry ? process.execPath : manager,
98
+ nodeEntry ? [env.npm_execpath, ...args] : args,
99
+ { cwd: rootDir, env, stdio: 'inherit' }
100
+ )
101
+ child.once('error', (error) =>
102
+ reject(
103
+ new Error(
104
+ `Could not run ${manager}: ${error.message}. Install it or choose --package-manager explicitly.`
105
+ )
106
+ )
107
+ )
108
+ child.once('exit', (code, signal) => {
109
+ if (code === 0) resolve()
110
+ else
111
+ reject(
112
+ new Error(
113
+ `${manager} installation failed (${signal ?? code}). rdx.config.ts was not changed. Package/lock files may have changed; inspect them before retrying. If pnpm reports a release-age policy error, approve only the trusted RDX release in your project policy.`
114
+ )
115
+ )
116
+ })
117
+ })
118
+ }
119
+
120
+ async function validateCandidate(filename) {
121
+ const jiti = createJiti(import.meta.url, {
122
+ moduleCache: false,
123
+ fsCache: false,
124
+ jsx: { runtime: 'automatic' },
125
+ })
126
+ const input = await jiti.import(filename, { default: true })
127
+ const config = resolveConfig(input)
128
+ // Validate paths and command registrations without running plugin setup hooks.
129
+ await createRdxProject(
130
+ {
131
+ ...config,
132
+ plugins: config.plugins.map((plugin) => ({
133
+ ...plugin,
134
+ setup: undefined,
135
+ })),
136
+ },
137
+ { rootDir: path.dirname(filename), command: 'prepare' }
138
+ )
139
+ if (
140
+ config.plugins.filter((plugin) => plugin.name === versioningPackage)
141
+ .length !== 1
142
+ )
143
+ throw new Error(
144
+ 'Expected exactly one official versioning plugin in the resulting configuration.'
145
+ )
146
+ }
147
+
148
+ export async function addVersioning(rootDir, options = {}) {
149
+ const {
150
+ install = installPackage,
151
+ log = console.log,
152
+ env = process.env,
153
+ } = options
154
+ const filename = path.join(rootDir, 'rdx.config.ts')
155
+ let info
156
+ try {
157
+ info = await lstat(filename)
158
+ } catch (error) {
159
+ if (error.code === 'ENOENT')
160
+ throw new Error(
161
+ 'Missing rdx.config.ts. Run rdx add from the documentation project root.'
162
+ )
163
+ throw error
164
+ }
165
+ if (!info.isFile() || info.isSymbolicLink())
166
+ throw new Error('rdx.config.ts must be a regular project file, not a link.')
167
+ const original = await readFile(filename, 'utf8')
168
+ // Refuse unsupported configurations before running the package manager.
169
+ const updated = activateVersioning(original)
170
+ const pkg = JSON.parse(
171
+ await readFile(path.join(rootDir, 'package.json'), 'utf8')
172
+ )
173
+ const manager = await detectPackageManager(
174
+ rootDir,
175
+ pkg,
176
+ env,
177
+ options.packageManager
178
+ )
179
+ const declared =
180
+ pkg.dependencies?.[versioningPackage] ??
181
+ pkg.devDependencies?.[versioningPackage]
182
+ let installed = false
183
+ try {
184
+ createRequire(path.join(rootDir, 'package.json')).resolve(versioningPackage)
185
+ installed = true
186
+ } catch (error) {
187
+ // The official package exposes ESM imports only. require.resolve can find
188
+ // its manifest but reject the require condition; validation below uses Jiti.
189
+ if (error.code === 'ERR_PACKAGE_PATH_NOT_EXPORTED') installed = true
190
+ else if (!['MODULE_NOT_FOUND', 'ERR_MODULE_NOT_FOUND'].includes(error.code))
191
+ throw error
192
+ }
193
+ if (!declared || !installed) {
194
+ log(`Installing ${versioningPackage}@beta with ${manager}...`)
195
+ await install(manager, rootDir, env)
196
+ } else
197
+ log(`${versioningPackage} is already installed; preserving its version.`)
198
+
199
+ const temporary = path.join(rootDir, `rdx.config.add-${randomUUID()}.ts`)
200
+ try {
201
+ await writeFile(temporary, updated, { flag: 'wx', mode: info.mode })
202
+ try {
203
+ await validateCandidate(temporary)
204
+ } catch (error) {
205
+ throw new Error(
206
+ `Plugin configuration validation failed: ${error.message}. rdx.config.ts was not changed. Installed dependencies were kept; fix the error and retry.`
207
+ )
208
+ }
209
+ if ((await readFile(filename, 'utf8')) !== original)
210
+ throw new Error(
211
+ 'rdx.config.ts changed during installation. No configuration was overwritten; retry after reviewing your edits.'
212
+ )
213
+ const currentInfo = await lstat(filename)
214
+ if (!currentInfo.isFile() || currentInfo.isSymbolicLink())
215
+ throw new Error(
216
+ 'rdx.config.ts was replaced during installation. No configuration was overwritten.'
217
+ )
218
+ if (updated !== original) {
219
+ await rename(temporary, filename)
220
+ log('Versioning activated in rdx.config.ts.')
221
+ } else
222
+ log('Versioning is already configured; no configuration changes needed.')
223
+ } finally {
224
+ await unlink(temporary).catch((error) => {
225
+ if (error.code !== 'ENOENT') throw error
226
+ })
227
+ }
228
+ return { changed: updated !== original }
229
+ }
@@ -0,0 +1,155 @@
1
+ import ts from 'typescript'
2
+
3
+ export const versioningPackage = '@lexibase/rdx-versioning'
4
+ const manual = `Cannot safely edit rdx.config.ts. Add "import { versioning } from '${versioningPackage}'" and versioning() to plugins manually, then run rdx prepare.`
5
+
6
+ function unwrap(node) {
7
+ while (
8
+ ts.isParenthesizedExpression(node) ||
9
+ ts.isAsExpression(node) ||
10
+ ts.isSatisfiesExpression(node)
11
+ )
12
+ node = node.expression
13
+ return node
14
+ }
15
+
16
+ // Edit only known literal shapes; never print/reconstruct the user's entire file.
17
+ export function activateVersioning(source) {
18
+ const file = ts.createSourceFile(
19
+ 'rdx.config.ts',
20
+ source,
21
+ ts.ScriptTarget.Latest,
22
+ true,
23
+ ts.ScriptKind.TS
24
+ )
25
+ if (file.parseDiagnostics.length) throw new Error(manual)
26
+ const imports = file.statements.filter(ts.isImportDeclaration)
27
+ const definitions = new Set()
28
+ let factory
29
+ for (const entry of imports) {
30
+ const name = entry.moduleSpecifier.text
31
+ const clause = entry.importClause
32
+ if (!clause || clause.isTypeOnly) continue
33
+ const bindings = clause.namedBindings
34
+ if (bindings && ts.isNamedImports(bindings)) {
35
+ for (const specifier of bindings.elements) {
36
+ if (specifier.isTypeOnly) continue
37
+ const imported = (specifier.propertyName ?? specifier.name).text
38
+ if (
39
+ ['@lexibase/rdx-next', '@lexibase/rdx-core/config'].includes(name) &&
40
+ imported === 'defineConfig'
41
+ )
42
+ definitions.add(specifier.name.text)
43
+ if (name === versioningPackage && imported === 'versioning') {
44
+ if (factory) throw new Error(manual)
45
+ factory = specifier.name.text
46
+ }
47
+ }
48
+ } else if (
49
+ bindings &&
50
+ ts.isNamespaceImport(bindings) &&
51
+ name === versioningPackage
52
+ ) {
53
+ if (factory) throw new Error(manual)
54
+ factory = `${bindings.name.text}.versioning`
55
+ }
56
+ }
57
+ const exports = file.statements.filter(ts.isExportAssignment)
58
+ if (exports.length !== 1 || exports[0].isExportEquals) throw new Error(manual)
59
+ let config = unwrap(exports[0].expression)
60
+ if (ts.isCallExpression(config)) {
61
+ if (
62
+ !ts.isIdentifier(config.expression) ||
63
+ !definitions.has(config.expression.text) ||
64
+ config.arguments.length !== 1
65
+ )
66
+ throw new Error(manual)
67
+ config = unwrap(config.arguments[0])
68
+ }
69
+ if (!ts.isObjectLiteralExpression(config)) throw new Error(manual)
70
+ const properties = config.properties
71
+ if (
72
+ properties.some(
73
+ (entry) =>
74
+ !ts.isPropertyAssignment(entry) || ts.isComputedPropertyName(entry.name)
75
+ )
76
+ )
77
+ throw new Error(manual)
78
+ const pluginsProperties = properties.filter(
79
+ (entry) => entry.name.text === 'plugins'
80
+ )
81
+ if (pluginsProperties.length > 1) throw new Error(manual)
82
+ const plugins = pluginsProperties.length
83
+ ? unwrap(pluginsProperties[0].initializer)
84
+ : undefined
85
+ if (
86
+ plugins &&
87
+ (!ts.isArrayLiteralExpression(plugins) ||
88
+ plugins.elements.some(ts.isSpreadElement))
89
+ )
90
+ throw new Error(manual)
91
+ if (plugins && factory) {
92
+ const matches = plugins.elements.filter(
93
+ (entry) =>
94
+ ts.isCallExpression(unwrap(entry)) &&
95
+ unwrap(entry).expression.getText(file) === factory
96
+ )
97
+ if (matches.length > 1)
98
+ throw new Error(
99
+ 'Versioning is configured more than once. Remove the duplicate plugin before retrying.'
100
+ )
101
+ if (matches.length === 1) return source
102
+ }
103
+ const newline = source.includes('\r\n') ? '\r\n' : '\n'
104
+ const edits = []
105
+ if (!factory) {
106
+ const identifiers = new Set()
107
+ function visit(node) {
108
+ if (ts.isIdentifier(node)) identifiers.add(node.text)
109
+ ts.forEachChild(node, visit)
110
+ }
111
+ visit(file)
112
+ factory = 'versioning'
113
+ let suffix = 1
114
+ while (identifiers.has(factory)) factory = `rdxVersioning${suffix++}`
115
+ const specifier =
116
+ factory === 'versioning' ? 'versioning' : `versioning as ${factory}`
117
+ let position = imports.length
118
+ ? imports.at(-1).end
119
+ : file.statements[0].getStart(file)
120
+ if (!imports.length) {
121
+ for (const statement of file.statements) {
122
+ if (
123
+ !ts.isExpressionStatement(statement) ||
124
+ !ts.isStringLiteral(statement.expression)
125
+ )
126
+ break
127
+ position = statement.end
128
+ }
129
+ }
130
+ edits.push({
131
+ position,
132
+ text: `${newline}import { ${specifier} } from '${versioningPackage}'${newline}`,
133
+ })
134
+ }
135
+ if (plugins) {
136
+ const position = plugins.elements.length
137
+ ? plugins.elements.at(-1).end
138
+ : plugins.getStart(file) + 1
139
+ edits.push({
140
+ position,
141
+ text: `${plugins.elements.length ? ',' : ''} ${factory}()`,
142
+ })
143
+ } else {
144
+ if (properties.length && !properties.hasTrailingComma)
145
+ edits.push({ position: properties.at(-1).end, text: ',' })
146
+ edits.push({
147
+ position: config.end - 1,
148
+ text: `${newline} plugins: [${factory}()],${newline}`,
149
+ })
150
+ }
151
+ for (const edit of edits.sort((a, b) => b.position - a.position))
152
+ source =
153
+ source.slice(0, edit.position) + edit.text + source.slice(edit.position)
154
+ return source
155
+ }
@@ -0,0 +1,58 @@
1
+ import { lstat, mkdir, realpath, symlink, unlink } from 'node:fs/promises'
2
+ import path from 'node:path'
3
+ import process from 'node:process'
4
+
5
+ async function inspect(filePath) {
6
+ try {
7
+ return await lstat(filePath)
8
+ } catch (error) {
9
+ if (error.code === 'ENOENT') return null
10
+ throw error
11
+ }
12
+ }
13
+
14
+ /** Link generated Next public/ to project-owned assets; never copy or delete them. */
15
+ export async function preparePublicAssets(projectRoot, runtimeDirectory) {
16
+ const runtime = await inspect(runtimeDirectory)
17
+ if (!runtime?.isDirectory() || runtime.isSymbolicLink())
18
+ throw new Error(
19
+ '.rdx/ must be a real directory, not a symbolic link or junction.'
20
+ )
21
+
22
+ const publicDirectory = path.join(projectRoot, 'public')
23
+ const existing = await inspect(publicDirectory)
24
+ if (existing && (!existing.isDirectory() || existing.isSymbolicLink()))
25
+ throw new Error('public/ must be a real directory in the project root.')
26
+ await mkdir(publicDirectory, { recursive: true })
27
+
28
+ const destination = path.join(runtimeDirectory, 'public')
29
+ const link = await inspect(destination)
30
+ if (link) {
31
+ if (!link.isSymbolicLink())
32
+ throw new Error(
33
+ 'Cannot prepare .rdx/public: a file or directory already exists there. Move any assets to the project public/ directory, then remove the conflicting .rdx/public entry and retry. RDX has not removed it.'
34
+ )
35
+ let target
36
+ try {
37
+ target = await realpath(destination)
38
+ } catch (error) {
39
+ if (error.code !== 'ENOENT') throw error
40
+ }
41
+ if (target === (await realpath(publicDirectory))) return
42
+ // Only unlink the internal pointer, never its old target or the user's files.
43
+ await unlink(destination)
44
+ }
45
+
46
+ const target = process.platform === 'win32' ? publicDirectory : '../public'
47
+ try {
48
+ await symlink(
49
+ target,
50
+ destination,
51
+ process.platform === 'win32' ? 'junction' : 'dir'
52
+ )
53
+ } catch (error) {
54
+ throw new Error(
55
+ `Could not link .rdx/public to public/: ${error.message}. Use a filesystem that supports directory links (junctions on Windows); your public files have not been removed.`
56
+ )
57
+ }
58
+ }
package/bin/rdx.mjs CHANGED
@@ -2,13 +2,18 @@
2
2
 
3
3
  import { spawn } from 'node:child_process'
4
4
  import { createRequire } from 'node:module'
5
- import { cp, mkdir } from 'node:fs/promises'
5
+ import { access, cp, mkdir } from 'node:fs/promises'
6
6
  import path from 'node:path'
7
7
  import { fileURLToPath } from 'node:url'
8
8
  import process from 'node:process'
9
9
 
10
+ import { createRdxProject } from '@lexibase/rdx-core/config'
11
+ import { createJiti } from 'jiti'
12
+
13
+ import { preparePublicAssets } from './public-assets.mjs'
14
+
10
15
  const supportedCommands = new Set(['dev', 'build', 'start'])
11
- const command = process.argv[2]
16
+ let command = process.argv[2]
12
17
  const commandArgs = process.argv.slice(3)
13
18
  const projectRoot = process.cwd()
14
19
  const packageRoot = path.resolve(
@@ -20,31 +25,100 @@ const runtimeDirectory = path.join(projectRoot, '.rdx')
20
25
 
21
26
  async function prepareRuntime() {
22
27
  await mkdir(runtimeDirectory, { recursive: true })
28
+ await preparePublicAssets(projectRoot, runtimeDirectory)
23
29
  await cp(runtimeTemplate, runtimeDirectory, { force: true, recursive: true })
24
30
  }
25
31
 
26
- if (command === 'prepare') {
27
- await prepareRuntime()
28
- console.log('RDX runtime prepared in .rdx/')
29
- process.exit(0)
30
- }
32
+ async function main() {
33
+ if (!command || command === 'help' || command === '--help') {
34
+ console.log('Usage: rdx <dev|build|start|prepare|add|plugin-command>')
35
+ console.log(' rdx add versioning [--package-manager npm|pnpm|yarn]')
36
+ console.log(
37
+ 'Plugin commands are registered through plugins in rdx.config.ts.'
38
+ )
39
+ return
40
+ }
31
41
 
32
- if (!command || !supportedCommands.has(command)) {
33
- console.error('Usage: rdx <dev|build|start|prepare>')
34
- process.exit(1)
35
- }
42
+ if (command === 'add') {
43
+ const { addVersioning, parseAddArguments } =
44
+ await import('./add-plugin.mjs')
45
+ const options = parseAddArguments(commandArgs)
46
+ await addVersioning(projectRoot, options)
47
+ command = 'prepare'
48
+ }
36
49
 
37
- await prepareRuntime()
50
+ const configPath = path.join(projectRoot, 'rdx.config.ts')
51
+ try {
52
+ await access(configPath)
53
+ } catch {
54
+ throw new Error(
55
+ `Missing ${configPath}. Run rdx from the documentation project root.`
56
+ )
57
+ }
38
58
 
39
- const projectRequire = createRequire(path.join(projectRoot, 'package.json'))
40
- const nextCli = projectRequire.resolve('next/dist/bin/next')
41
- const child = spawn(
42
- process.execPath,
43
- [nextCli, command, runtimeDirectory, ...commandArgs],
44
- { cwd: projectRoot, stdio: 'inherit' }
45
- )
59
+ const jiti = createJiti(import.meta.url, {
60
+ moduleCache: false,
61
+ fsCache: false,
62
+ jsx: { runtime: 'automatic' },
63
+ })
64
+ let input
65
+ try {
66
+ input = await jiti.import(configPath, { default: true })
67
+ } catch (error) {
68
+ const hint =
69
+ error.code === 'MODULE_NOT_FOUND' || error.code === 'ERR_MODULE_NOT_FOUND'
70
+ ? ' If a configured plugin cannot be resolved, install its package in this project.'
71
+ : ''
72
+ throw new Error(`Could not load rdx.config.ts: ${error.message}${hint}`)
73
+ }
46
74
 
47
- child.on('exit', (code, signal) => {
48
- if (signal) process.kill(process.pid, signal)
49
- process.exit(code ?? 1)
50
- })
75
+ const project = await createRdxProject(input, {
76
+ rootDir: projectRoot,
77
+ command,
78
+ })
79
+ if (command === 'prepare') {
80
+ await prepareRuntime()
81
+ console.log('RDX runtime prepared in .rdx/')
82
+ return
83
+ }
84
+ if (!supportedCommands.has(command)) {
85
+ const pluginCommand = project.commands.find(
86
+ (entry) => entry.name === command
87
+ )
88
+ if (!pluginCommand)
89
+ throw new Error(
90
+ `Unknown command "${command}". Available: dev, build, start, prepare, add${project.commands.map((entry) => `, ${entry.name}`).join('')}. Install and configure the plugin that provides this command.`
91
+ )
92
+ await pluginCommand.run({
93
+ rootDir: projectRoot,
94
+ config: project.config,
95
+ command,
96
+ args: commandArgs,
97
+ })
98
+ return
99
+ }
100
+
101
+ await prepareRuntime()
102
+ const projectRequire = createRequire(path.join(projectRoot, 'package.json'))
103
+ const nextCli = projectRequire.resolve('next/dist/bin/next')
104
+ const child = spawn(
105
+ process.execPath,
106
+ [nextCli, command, runtimeDirectory, ...commandArgs],
107
+ { cwd: projectRoot, stdio: 'inherit' }
108
+ )
109
+ child.on('error', (error) => {
110
+ console.error(`[RDX] Could not start Next.js: ${error.message}`)
111
+ process.exitCode = 1
112
+ })
113
+ child.on('exit', (code, signal) => {
114
+ if (signal) process.kill(process.pid, signal)
115
+ process.exit(code ?? 1)
116
+ })
117
+ }
118
+
119
+ try {
120
+ await main()
121
+ } catch (error) {
122
+ console.error(`[RDX] ${error.message}`)
123
+ process.exitCode = 1
124
+ }
package/dist/index.d.ts CHANGED
@@ -1 +1,2 @@
1
- export { RdxRuntimeConfig } from '@lexibase/rdx-types';
1
+ export { defineConfig } from '@lexibase/rdx-core/config';
2
+ export { RdxConfig, RdxHomepage, RdxPlugin, RdxPluginContext, RdxRuntimeConfig } from '@lexibase/rdx-types';
package/dist/index.js CHANGED
@@ -0,0 +1,5 @@
1
+ // src/index.ts
2
+ import { defineConfig } from "@lexibase/rdx-core/config";
3
+ export {
4
+ defineConfig
5
+ };
@@ -1,13 +1,24 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
1
+ import * as react from 'react';
2
2
  import { ReactNode } from 'react';
3
- import { RdxRuntimeConfig } from '@lexibase/rdx-types';
3
+ import { RdxProject, RdxRuntimeConfig } from '@lexibase/rdx-types';
4
+ export { createRdxProject, getProjectDocsPaths } from '@lexibase/rdx-core';
4
5
 
5
- declare function RdxLayout({ children, config, }: {
6
+ declare function getSearchSources(project: RdxProject): {
7
+ source: string;
8
+ }[];
9
+ declare function getSearchResponse(project: RdxProject, key: string): Response;
10
+
11
+ declare function RdxLayout({ children, config, bodyClassName, }: {
6
12
  children: ReactNode;
7
13
  config: RdxRuntimeConfig;
8
- }): react_jsx_runtime.JSX.Element;
9
- declare function DocsPage({ slug }: {
14
+ bodyClassName?: string;
15
+ }): react.JSX.Element;
16
+ declare function HomePage({ project }: {
17
+ project: RdxProject;
18
+ }): react.JSX.Element;
19
+ declare function DocsPage({ slug, project, }: {
10
20
  slug?: string[];
11
- }): Promise<react_jsx_runtime.JSX.Element>;
21
+ project: RdxProject;
22
+ }): Promise<react.JSX.Element>;
12
23
 
13
- export { DocsPage, RdxLayout };
24
+ export { DocsPage, HomePage, RdxLayout, getSearchResponse, getSearchSources };