@unchainedshop/platform 4.8.9 → 4.8.11
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/unchained.js +161 -0
- package/package.json +4 -1
package/bin/unchained.js
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { execFileSync } from 'node:child_process';
|
|
4
|
+
import {
|
|
5
|
+
cpSync,
|
|
6
|
+
existsSync,
|
|
7
|
+
mkdtempSync,
|
|
8
|
+
readFileSync,
|
|
9
|
+
readdirSync,
|
|
10
|
+
rmSync,
|
|
11
|
+
writeFileSync,
|
|
12
|
+
} from 'node:fs';
|
|
13
|
+
import { join, relative } from 'node:path';
|
|
14
|
+
import { tmpdir } from 'node:os';
|
|
15
|
+
import { createRequire } from 'node:module';
|
|
16
|
+
|
|
17
|
+
const GITHUB_REPO = 'https://github.com/unchainedshop/unchained.git';
|
|
18
|
+
const DOCS_SUBPATH = 'docs/docs';
|
|
19
|
+
const DOCS_DIR = join(process.cwd(), '.unchained-docs');
|
|
20
|
+
const INDEX_START = '<!-- UNCHAINED_DOCS_INDEX:BEGIN -->';
|
|
21
|
+
const INDEX_END = '<!-- UNCHAINED_DOCS_INDEX:END -->';
|
|
22
|
+
|
|
23
|
+
const command = process.argv[2];
|
|
24
|
+
|
|
25
|
+
if (command !== 'download-llm-docs') {
|
|
26
|
+
console.log(`Usage: unchained <command>
|
|
27
|
+
|
|
28
|
+
Commands:
|
|
29
|
+
download-llm-docs Download Unchained Engine docs for LLM coding assistants
|
|
30
|
+
(Claude Code, Cursor, etc.) and inject a file index into
|
|
31
|
+
CLAUDE.md and/or agents.md`);
|
|
32
|
+
process.exit(command ? 1 : 0);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Resolve version from own package.json
|
|
36
|
+
const require = createRequire(import.meta.url);
|
|
37
|
+
const pkg = require('../package.json');
|
|
38
|
+
const version = pkg.version;
|
|
39
|
+
|
|
40
|
+
// Determine git ref: try tag first, fallback to master
|
|
41
|
+
function tagExists(tag) {
|
|
42
|
+
try {
|
|
43
|
+
execFileSync('git', ['ls-remote', '--tags', '--exit-code', GITHUB_REPO, `refs/tags/${tag}`], {
|
|
44
|
+
stdio: 'pipe',
|
|
45
|
+
});
|
|
46
|
+
return true;
|
|
47
|
+
} catch {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const tag = `v${version}`;
|
|
53
|
+
const ref = tagExists(tag) ? tag : 'master';
|
|
54
|
+
if (ref === 'master') {
|
|
55
|
+
console.log(`Tag ${tag} not found on remote, falling back to master branch.`);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Clone docs using sparse-checkout into a temp directory
|
|
59
|
+
const tempDir = mkdtempSync(join(tmpdir(), 'unchained-docs-'));
|
|
60
|
+
console.log(`Cloning docs from ${ref} using sparse-checkout ...`);
|
|
61
|
+
try {
|
|
62
|
+
execFileSync(
|
|
63
|
+
'git',
|
|
64
|
+
[
|
|
65
|
+
'clone',
|
|
66
|
+
'--filter=blob:none',
|
|
67
|
+
'--no-checkout',
|
|
68
|
+
'--depth',
|
|
69
|
+
'1',
|
|
70
|
+
'--branch',
|
|
71
|
+
ref,
|
|
72
|
+
GITHUB_REPO,
|
|
73
|
+
tempDir,
|
|
74
|
+
],
|
|
75
|
+
{ stdio: 'inherit' },
|
|
76
|
+
);
|
|
77
|
+
execFileSync('git', ['-C', tempDir, 'sparse-checkout', 'set', DOCS_SUBPATH], {
|
|
78
|
+
stdio: 'inherit',
|
|
79
|
+
});
|
|
80
|
+
execFileSync('git', ['-C', tempDir, 'checkout'], { stdio: 'inherit' });
|
|
81
|
+
} catch {
|
|
82
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
83
|
+
console.error('Failed to clone docs repository.');
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Copy docs/docs/ contents to .unchained-docs/
|
|
88
|
+
const sourceDir = join(tempDir, DOCS_SUBPATH);
|
|
89
|
+
if (!existsSync(sourceDir)) {
|
|
90
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
91
|
+
console.error(`Docs directory not found at ${DOCS_SUBPATH} in the repository.`);
|
|
92
|
+
process.exit(1);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
rmSync(DOCS_DIR, { recursive: true, force: true });
|
|
96
|
+
cpSync(sourceDir, DOCS_DIR, { recursive: true });
|
|
97
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
98
|
+
|
|
99
|
+
// Scan for markdown files
|
|
100
|
+
const markdownsByDir = Map.groupBy(
|
|
101
|
+
readdirSync(DOCS_DIR, { withFileTypes: true, recursive: true }).filter(
|
|
102
|
+
(e) => e.isFile() && (e.name.endsWith('.md') || e.name.endsWith('.mdx')),
|
|
103
|
+
),
|
|
104
|
+
(e) => relative(DOCS_DIR, e.parentPath) || '.',
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
const fileCount = [...markdownsByDir.values()].flat().length;
|
|
108
|
+
console.log(`Found ${fileCount} markdown files in .unchained-docs/`);
|
|
109
|
+
|
|
110
|
+
// Build compact pipe-delimited index
|
|
111
|
+
const indexSnippet = [
|
|
112
|
+
INDEX_START,
|
|
113
|
+
[
|
|
114
|
+
`[Unchained Engine v${version} Docs Index]`,
|
|
115
|
+
'root: ./.unchained-docs',
|
|
116
|
+
'Search these docs before answering Unchained questions.',
|
|
117
|
+
'If docs missing, run: npx unchained download-llm-docs',
|
|
118
|
+
...[...markdownsByDir]
|
|
119
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
120
|
+
.map(
|
|
121
|
+
([dir, entries]) =>
|
|
122
|
+
`${dir}:{${entries
|
|
123
|
+
.map((e) => e.name)
|
|
124
|
+
.sort()
|
|
125
|
+
.join(',')}}`,
|
|
126
|
+
),
|
|
127
|
+
].join('|'),
|
|
128
|
+
INDEX_END,
|
|
129
|
+
].join('');
|
|
130
|
+
|
|
131
|
+
// Upsert index into target files
|
|
132
|
+
function upsertIndex(filePath) {
|
|
133
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
134
|
+
const [before, ...afterParts] = content.split(INDEX_START);
|
|
135
|
+
const after =
|
|
136
|
+
afterParts.length > 0
|
|
137
|
+
? afterParts.join(INDEX_START).split(INDEX_END).slice(1).join(INDEX_END)
|
|
138
|
+
: undefined;
|
|
139
|
+
|
|
140
|
+
writeFileSync(
|
|
141
|
+
filePath,
|
|
142
|
+
after !== undefined ? before + indexSnippet + after : `${content.trimEnd()}\n${indexSnippet}\n`,
|
|
143
|
+
);
|
|
144
|
+
console.log(`Updated ${relative(process.cwd(), filePath)} with docs index.`);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const claudeMdPath = join(process.cwd(), 'CLAUDE.md');
|
|
148
|
+
const agentsMdPath = join(process.cwd(), 'agents.md');
|
|
149
|
+
const claudeExists = existsSync(claudeMdPath);
|
|
150
|
+
const agentsExists = existsSync(agentsMdPath);
|
|
151
|
+
|
|
152
|
+
if (claudeExists) upsertIndex(claudeMdPath);
|
|
153
|
+
if (agentsExists) upsertIndex(agentsMdPath);
|
|
154
|
+
|
|
155
|
+
if (!claudeExists && !agentsExists) {
|
|
156
|
+
writeFileSync(claudeMdPath, `${indexSnippet}\n`);
|
|
157
|
+
console.log('Created CLAUDE.md with docs index.');
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Remind about .gitignore
|
|
161
|
+
console.log('\nDone! Remember to add .unchained-docs to your .gitignore.');
|
package/package.json
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unchainedshop/platform",
|
|
3
3
|
"description": "Complete e-commerce platform bundle for the Unchained Engine",
|
|
4
|
-
"version": "4.8.
|
|
4
|
+
"version": "4.8.11",
|
|
5
5
|
"main": "lib/platform-index.js",
|
|
6
6
|
"types": "lib/platform-index.d.ts",
|
|
7
7
|
"type": "module",
|
|
8
|
+
"bin": {
|
|
9
|
+
"unchained": "./bin/unchained.js"
|
|
10
|
+
},
|
|
8
11
|
"scripts": {
|
|
9
12
|
"clean": "tsc -b --clean",
|
|
10
13
|
"build": "tsc -b",
|