@synity/bitrix-skills 1.3.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/CHANGELOG.md +169 -0
- package/LICENSE +21 -0
- package/README.md +83 -0
- package/bin/bitrix-skills.js +3 -0
- package/dist/cli.js +1510 -0
- package/dist/features/bx-task/install.js +111 -0
- package/dist/features/task-sync/index.js +1053 -0
- package/package.json +69 -0
- package/src/features/bx/assets/SKILL.md +34 -0
- package/src/features/bx/feature.json +8 -0
- package/src/features/bx-calendar/assets/SKILL.md +61 -0
- package/src/features/bx-calendar/assets/availability.md +65 -0
- package/src/features/bx-calendar/assets/meeting.md +87 -0
- package/src/features/bx-calendar/assets/reminder.md +71 -0
- package/src/features/bx-calendar/assets/sync.md +70 -0
- package/src/features/bx-calendar/feature.json +10 -0
- package/src/features/bx-crm/assets/SKILL.md +59 -0
- package/src/features/bx-crm/assets/commerce.md +96 -0
- package/src/features/bx-crm/assets/onboard.md +127 -0
- package/src/features/bx-crm/assets/report.md +98 -0
- package/src/features/bx-crm/assets/research.md +71 -0
- package/src/features/bx-crm/feature.json +10 -0
- package/src/features/bx-task/assets/SKILL.md +148 -0
- package/src/features/bx-task/assets/lib/bx-api.sh +39 -0
- package/src/features/bx-task/assets/lib/bx-checklist.sh +127 -0
- package/src/features/bx-task/assets/lib/bx-resolve-task.sh +41 -0
- package/src/features/bx-task/assets/lib/bx-state.sh +131 -0
- package/src/features/bx-task/assets/lib/bx-tasks.sh +109 -0
- package/src/features/bx-task/assets/references/bootstrap.md +184 -0
- package/src/features/bx-task/assets/references/feature.md +97 -0
- package/src/features/bx-task/assets/references/init-templates/cli-tool.md +47 -0
- package/src/features/bx-task/assets/references/init-templates/generic.md +31 -0
- package/src/features/bx-task/assets/references/init-templates/library.md +45 -0
- package/src/features/bx-task/assets/references/init-templates/monorepo.md +38 -0
- package/src/features/bx-task/assets/references/init-templates/npm-package.md +40 -0
- package/src/features/bx-task/assets/references/init-templates/web-app.md +46 -0
- package/src/features/bx-task/assets/references/init.md +107 -0
- package/src/features/bx-task/assets/references/roadmap.md +93 -0
- package/src/features/bx-task/assets/references/summary.md +269 -0
- package/src/features/bx-task/assets/references/sync.md +104 -0
- package/src/features/bx-task/assets/references/time-log.md +214 -0
- package/src/features/bx-task/feature.json +10 -0
- package/src/features/bx-task/install.ts +117 -0
- package/src/features/task-sync/assets/docs/bitrix-task-reference.md +318 -0
- package/src/features/task-sync/assets/docs/bitrix-task-sync.md +254 -0
- package/src/features/task-sync/assets/githooks/commit-msg +44 -0
- package/src/features/task-sync/assets/githooks/install.sh +15 -0
- package/src/features/task-sync/assets/manifest.json +108 -0
- package/src/features/task-sync/assets/rules/00-bitrix-task-sync.md +161 -0
- package/src/features/task-sync/assets/scripts/bitrix-attach-files.sh +55 -0
- package/src/features/task-sync/assets/scripts/bitrix-lib.sh +540 -0
- package/src/features/task-sync/assets/scripts/bitrix-render-digest.sh +116 -0
- package/src/features/task-sync/assets/scripts/bitrix-session-check.sh +51 -0
- package/src/features/task-sync/assets/scripts/bitrix-session-sync.sh +89 -0
- package/src/features/task-sync/assets/scripts/bitrix-skill-end.sh +165 -0
- package/src/features/task-sync/assets/scripts/bitrix-skill-start.sh +58 -0
- package/src/features/task-sync/assets/scripts/lib/bb-formatter.sh +110 -0
- package/src/features/task-sync/assets/scripts/lib/bitrix-lib.sh +540 -0
- package/src/features/task-sync/assets/scripts/lib/time-helpers.sh +57 -0
- package/src/features/task-sync/assets/workflows/bitrix-sync.yml +85 -0
- package/src/features/task-sync/commands/install.ts +296 -0
- package/src/features/task-sync/commands/uninstall.ts +189 -0
- package/src/features/task-sync/commands/update.ts +11 -0
- package/src/features/task-sync/commands/verify.ts +141 -0
- package/src/features/task-sync/feature.json +12 -0
- package/src/features/task-sync/index.ts +121 -0
- package/src/features/task-sync/lib/dest-map.ts +96 -0
- package/src/features/task-sync/lib/drift-check.ts +47 -0
- package/src/features/task-sync/lib/file-ops.ts +36 -0
- package/src/features/task-sync/lib/manifest.ts +66 -0
- package/src/features/task-sync/lib/project-root.ts +38 -0
- package/src/features/task-sync/lib/settings-merge.ts +112 -0
- package/src/features/task-sync/lib/skill-refs.ts +106 -0
- package/src/features/task-sync/lib/task-id-finder.ts +31 -0
- package/src/features/task-sync/lib/token-extractor.ts +52 -0
- package/src/features/task-sync/lib/version.ts +36 -0
- package/src/features/task-sync/types.ts +40 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
// src/features/bx-task/install.ts
|
|
2
|
+
import { homedir } from "os";
|
|
3
|
+
import { resolve, join, dirname } from "path";
|
|
4
|
+
import { fileURLToPath } from "url";
|
|
5
|
+
import { mkdir, copyFile, readdir, stat, rm, access } from "fs/promises";
|
|
6
|
+
|
|
7
|
+
// src/lib/fs-safety.ts
|
|
8
|
+
import { lstat } from "fs/promises";
|
|
9
|
+
import path from "path";
|
|
10
|
+
async function assertNotSymlink(destPath) {
|
|
11
|
+
try {
|
|
12
|
+
const stat2 = await lstat(destPath);
|
|
13
|
+
if (stat2.isSymbolicLink()) {
|
|
14
|
+
throw new Error(
|
|
15
|
+
`Refusing to overwrite symlink: ${destPath}. Remove it manually then re-run install.`
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
} catch (err) {
|
|
19
|
+
if (err.code === "ENOENT") return;
|
|
20
|
+
throw err;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function assertContainedIn(destAbs, allowedRoot, label) {
|
|
24
|
+
const root = allowedRoot.endsWith(path.sep) ? allowedRoot : allowedRoot + path.sep;
|
|
25
|
+
if (!destAbs.startsWith(root)) {
|
|
26
|
+
throw new Error(
|
|
27
|
+
`"${label}" resolves outside allowed root (${root}). Refusing \u2014 possible path traversal.`
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// src/features/bx-task/install.ts
|
|
33
|
+
async function getAssetsDir() {
|
|
34
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
35
|
+
const candidates = [
|
|
36
|
+
// dist/ context (inlined in cli.js): ../src/features/bx-task/assets
|
|
37
|
+
resolve(here, "../src/features/bx-task/assets"),
|
|
38
|
+
// dist/features/bx-task/ context: ../../../src/features/bx-task/assets
|
|
39
|
+
resolve(here, "../../../src/features/bx-task/assets"),
|
|
40
|
+
// src/features/bx-task/ (dev)
|
|
41
|
+
resolve(here, "assets")
|
|
42
|
+
];
|
|
43
|
+
for (const c of candidates) {
|
|
44
|
+
try {
|
|
45
|
+
await access(c);
|
|
46
|
+
return c;
|
|
47
|
+
} catch {
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return candidates[0];
|
|
51
|
+
}
|
|
52
|
+
function getSkillBase() {
|
|
53
|
+
return resolve(homedir(), ".claude", "skills");
|
|
54
|
+
}
|
|
55
|
+
async function install(opts) {
|
|
56
|
+
const skillBase = getSkillBase();
|
|
57
|
+
const dest = opts._destOverride ?? resolve(skillBase, "bx-task");
|
|
58
|
+
const resolvedDest = resolve(dest);
|
|
59
|
+
if (!opts._destOverride && !resolvedDest.startsWith(skillBase)) {
|
|
60
|
+
throw new Error(`Path traversal detected: ${resolvedDest}`);
|
|
61
|
+
}
|
|
62
|
+
const result = {
|
|
63
|
+
installedFiles: [],
|
|
64
|
+
skippedFiles: [],
|
|
65
|
+
warnings: []
|
|
66
|
+
};
|
|
67
|
+
await installDir(await getAssetsDir(), resolvedDest, result, opts);
|
|
68
|
+
result.warnings.push(
|
|
69
|
+
'[bx-task] Requires MCP server "bitrix-synity-mcp" \u2014 verify it is configured in Claude Code settings.'
|
|
70
|
+
);
|
|
71
|
+
return result;
|
|
72
|
+
}
|
|
73
|
+
async function installDir(srcDir, destDir, result, opts) {
|
|
74
|
+
await mkdir(destDir, { recursive: true });
|
|
75
|
+
const entries = await readdir(srcDir, { withFileTypes: true });
|
|
76
|
+
for (const entry of entries) {
|
|
77
|
+
const srcPath = join(srcDir, entry.name);
|
|
78
|
+
const destPath = join(destDir, entry.name);
|
|
79
|
+
if (entry.isDirectory()) {
|
|
80
|
+
await installDir(srcPath, destPath, result, opts);
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
await assertNotSymlink(destPath);
|
|
84
|
+
const exists = await fileExists(destPath);
|
|
85
|
+
if (exists && !opts.force && opts.onConflict === "skip") {
|
|
86
|
+
result.skippedFiles.push(destPath);
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
await copyFile(srcPath, destPath);
|
|
90
|
+
result.installedFiles.push(destPath);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
async function fileExists(filePath) {
|
|
94
|
+
try {
|
|
95
|
+
await stat(filePath);
|
|
96
|
+
return true;
|
|
97
|
+
} catch {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
async function uninstall(opts) {
|
|
102
|
+
const dest = resolve(opts?._destOverride ?? resolve(homedir(), ".claude", "skills", "bx-task"));
|
|
103
|
+
if (!opts?._destOverride) {
|
|
104
|
+
assertContainedIn(dest, getSkillBase(), dest);
|
|
105
|
+
}
|
|
106
|
+
await rm(dest, { recursive: true, force: true });
|
|
107
|
+
}
|
|
108
|
+
export {
|
|
109
|
+
install,
|
|
110
|
+
uninstall
|
|
111
|
+
};
|