@intra-mart/accel 0.1.0-dev-20260420 → 0.1.0-dev.202604241514
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 +140 -0
- package/assets/assets.tar.gz +0 -0
- package/dist/asset/default-source.js +0 -3
- package/dist/asset/deployer.js +1 -14
- package/dist/asset/walker.d.ts +0 -3
- package/dist/asset/walker.js +5 -19
- package/dist/commands/attach.js +0 -2
- package/dist/commands/detach.js +0 -3
- package/dist/commands/init.js +9 -10
- package/dist/core/constants.js +1 -6
- package/dist/core/module-map.d.ts +0 -4
- package/dist/core/module-map.js +0 -5
- package/dist/core/types.js +0 -2
- package/dist/core/variable-interpolator.d.ts +0 -8
- package/dist/core/variable-interpolator.js +0 -13
- package/dist/core/version-map.js +1 -1
- package/dist/i18n/en.js +0 -7
- package/dist/i18n/ja.js +0 -7
- package/dist/i18n/zh_CN.js +0 -7
- package/dist/interactive/agent-detect.js +1 -11
- package/dist/interactive/prompts.js +5 -69
- package/dist/juggling/parser.js +0 -3
- package/dist/markdown/processor.js +0 -2
- package/dist/markdown/section-replacement.js +0 -5
- package/dist/markdown/text-replacement.js +0 -2
- package/dist/utils/command-exists.d.ts +1 -0
- package/dist/utils/command-exists.js +11 -0
- package/dist/utils/locale-detect.js +9 -4
- package/dist/utils/settings-io.js +0 -2
- package/package.json +60 -60
package/README.md
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# @intra-mart/accel
|
|
2
|
+
|
|
3
|
+
intra-mart Accel Platform (iAP) 開発プロジェクトの作成・管理を行うCLIツール。
|
|
4
|
+
|
|
5
|
+
コーディングエージェント(Claude Code、GitHub Copilot)向けのスキルファイルやインストラクションなどの資材を、資材リポジトリから取得しプロジェクトに配備します。
|
|
6
|
+
|
|
7
|
+
## 必要環境
|
|
8
|
+
|
|
9
|
+
- [Bun](https://bun.sh/) v1.0+
|
|
10
|
+
- Git(`--no-git-init` を指定しない場合)
|
|
11
|
+
|
|
12
|
+
## インストール
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
bun install -g @intra-mart/accel
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
または `bunx` で都度実行:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
bunx @intra-mart/accel init my-project
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## コマンド
|
|
25
|
+
|
|
26
|
+
### `accel init [project-name]`
|
|
27
|
+
|
|
28
|
+
新規プロジェクトを作成し、資材を配備します。
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
accel init my-project
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
`project-name` は省略可能です。省略した場合は対話でプロジェクト名を入力します(デフォルト: `my-accel-project`)。ディレクトリ名は最終的に確定したプロジェクト名と一致します。
|
|
35
|
+
|
|
36
|
+
対話形式でiAPバージョン、使用モジュール、エージェント種別などを選択します。
|
|
37
|
+
|
|
38
|
+
#### 非対話モード
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
accel init my-project \
|
|
42
|
+
--non-interactive \
|
|
43
|
+
--agent claude-code \
|
|
44
|
+
--locale ja
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
#### オプション一覧
|
|
48
|
+
|
|
49
|
+
| オプション | 型 | 説明 | デフォルト |
|
|
50
|
+
|---|---|---|---|
|
|
51
|
+
| `[project-name]` (位置引数) | string | プロジェクト名(ディレクトリ名と一致) | `my-accel-project`(対話で変更可) |
|
|
52
|
+
| `--agent` | string | エージェント種別(`claude-code`, `github-copilot`、カンマ区切り) | 自動検出 |
|
|
53
|
+
| `--locale` | string | ロケール(`ja`, `en`, `zh_CN`) | OS設定から自動検出 |
|
|
54
|
+
| `--group` | string | グループ名(pomの `groupId` に相当) | `my-group` |
|
|
55
|
+
| `--project-version` | string | プロジェクトバージョン | `0.1.0` |
|
|
56
|
+
| `--description` | string | プロジェクトの説明 | `""` |
|
|
57
|
+
| `--database` | string | データベース種別(`postgresql`, `oracle`, `sqlserver`) | `postgresql` |
|
|
58
|
+
| `--javascript` | boolean | JavaScriptを使用 | `false` |
|
|
59
|
+
| `--juggling-project` | string | IM-Jugglingプロジェクトパス | - |
|
|
60
|
+
| `--non-interactive` | boolean | 非対話モード(このモードでは `project-name` が必須) | `false` |
|
|
61
|
+
| `--no-git-init` | boolean | git initをスキップ | `false`(git initする) |
|
|
62
|
+
| `--skip-install` | boolean | 依存インストールをスキップ | `false` |
|
|
63
|
+
|
|
64
|
+
### `accel attach`
|
|
65
|
+
|
|
66
|
+
既存プロジェクト(カレントディレクトリ)にAccel CLIを適用します。
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
cd my-existing-project
|
|
70
|
+
accel attach --non-interactive
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
`init` との違い:
|
|
74
|
+
- ディレクトリを新規作成せず、カレントディレクトリを使用
|
|
75
|
+
- git initは行わない
|
|
76
|
+
- プロジェクト名のデフォルトはカレントディレクトリ名
|
|
77
|
+
- **既存ファイルがある配備先はスキップ**(上書きしない)。スキップされたファイルは `hashsum.txt` および `deployedAssets` に記録されないため、`detach` の対象外となる
|
|
78
|
+
|
|
79
|
+
#### オプション一覧
|
|
80
|
+
|
|
81
|
+
| オプション | 型 | 説明 | デフォルト |
|
|
82
|
+
|---|---|---|---|
|
|
83
|
+
| `--name` | string | プロジェクト名 | カレントディレクトリ名 |
|
|
84
|
+
| `--agent` | string | エージェント種別(`claude-code`, `github-copilot`、カンマ区切り) | 自動検出 |
|
|
85
|
+
| `--locale` | string | ロケール(`ja`, `en`, `zh_CN`) | OS設定から自動検出 |
|
|
86
|
+
| `--group` | string | グループ名(pomの `groupId` に相当) | `my-group` |
|
|
87
|
+
| `--project-version` | string | プロジェクトバージョン | `0.1.0` |
|
|
88
|
+
| `--description` | string | プロジェクトの説明 | `""` |
|
|
89
|
+
| `--database` | string | データベース種別(`postgresql`, `oracle`, `sqlserver`) | `postgresql` |
|
|
90
|
+
| `--javascript` | boolean | JavaScriptを使用 | `false` |
|
|
91
|
+
| `--juggling-project` | string | IM-Jugglingプロジェクトパス | - |
|
|
92
|
+
| `--non-interactive` | boolean | 非対話モード | `false` |
|
|
93
|
+
| `--skip-install` | boolean | 依存インストールをスキップ | `false` |
|
|
94
|
+
|
|
95
|
+
### `accel detach`
|
|
96
|
+
|
|
97
|
+
プロジェクトからAccel CLIの資材を解除します。
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
cd my-project
|
|
101
|
+
accel detach
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
- 配備時からハッシュが変わっていないファイルを削除
|
|
105
|
+
- ユーザーが編集したファイルはスキップ(警告表示)
|
|
106
|
+
- `.accel/` ディレクトリを削除
|
|
107
|
+
|
|
108
|
+
## IM-Juggling連携
|
|
109
|
+
|
|
110
|
+
`--juggling-project` オプションでIM-Jugglingプロジェクトのパスを指定すると、`juggling.im` からiAPバージョンと使用モジュールを自動検出します。
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
accel init my-project --juggling-project /path/to/juggling-project
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## プロジェクト構造
|
|
117
|
+
|
|
118
|
+
`accel init` 実行後に生成されるディレクトリ構造:
|
|
119
|
+
|
|
120
|
+
```
|
|
121
|
+
my-project/
|
|
122
|
+
├── .accel/
|
|
123
|
+
│ ├── settings.json # プロジェクト設定
|
|
124
|
+
│ └── hashsum.txt # 配備資材のSHA-1ハッシュ
|
|
125
|
+
├── .claude/ # agent=claude-code 時
|
|
126
|
+
│ ├── CLAUDE.md
|
|
127
|
+
│ └── skills/
|
|
128
|
+
├── .github/ # agent=github-copilot 時
|
|
129
|
+
│ ├── copilot-instructions.md
|
|
130
|
+
│ └── AGENTS.md
|
|
131
|
+
└── .git/
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
- `.accel/settings.json` — プロジェクト設定。git管理対象、手動編集可
|
|
135
|
+
- `.accel/hashsum.txt` — 配備ファイルのSHA-1。`detach` 時の変更検出に使用
|
|
136
|
+
|
|
137
|
+
## 対応iAPバージョン
|
|
138
|
+
|
|
139
|
+
現段階では、2025-Autumn (8.0.38) のみをサポートしています。
|
|
140
|
+
iAPのバージョン検出処理については、2025-Autumn固定になるように一部処理を変更しています。
|
package/assets/assets.tar.gz
CHANGED
|
Binary file
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import { fileURLToPath } from "node:url";
|
|
2
2
|
import { dirname, join } from "node:path";
|
|
3
|
-
// Layout assumption (both dev and published package):
|
|
4
|
-
// <root>/dist/asset/default-source.js (or <root>/src/asset/default-source.ts in dev)
|
|
5
|
-
// <root>/assets/assets.tar.gz
|
|
6
3
|
export const defaultAssetSourcePath = () => {
|
|
7
4
|
const here = dirname(fileURLToPath(import.meta.url));
|
|
8
5
|
return join(here, "..", "..", "assets", "assets.tar.gz");
|
package/dist/asset/deployer.js
CHANGED
|
@@ -24,9 +24,7 @@ const collectReplacements = (entry) => {
|
|
|
24
24
|
export const deployAssets = async (options) => {
|
|
25
25
|
const { projectDir, settings, provider, noInstall, skipExistingFiles } = options;
|
|
26
26
|
try {
|
|
27
|
-
// 1. Fetch assets
|
|
28
27
|
const repoDir = await provider.fetch();
|
|
29
|
-
// 2. Build eval context
|
|
30
28
|
const semver = labelToSemver(settings.accelplatformVersion);
|
|
31
29
|
const context = {
|
|
32
30
|
version: semver,
|
|
@@ -40,9 +38,7 @@ export const deployAssets = async (options) => {
|
|
|
40
38
|
database: settings.database,
|
|
41
39
|
projectVersion: settings.projectVersion,
|
|
42
40
|
};
|
|
43
|
-
// 3. Walk and filter
|
|
44
41
|
const entries = await walkAssetRepo(repoDir, semver, context);
|
|
45
|
-
// 4. Deploy files
|
|
46
42
|
const deployedFiles = [];
|
|
47
43
|
const hashEntries = [];
|
|
48
44
|
const deployedAssets = {};
|
|
@@ -54,43 +50,35 @@ export const deployAssets = async (options) => {
|
|
|
54
50
|
skippedFiles.push(targetPath);
|
|
55
51
|
continue;
|
|
56
52
|
}
|
|
57
|
-
// Read source file
|
|
58
53
|
let content = await readFile(entry.sourcePath, "utf-8");
|
|
59
|
-
// Apply replacements
|
|
60
54
|
const replacements = collectReplacements(entry);
|
|
61
55
|
if (replacements.length > 0) {
|
|
62
56
|
if (targetPath.endsWith(".md")) {
|
|
63
|
-
// Markdown: process with remark AST
|
|
64
57
|
content = processMarkdown(content, replacements, context);
|
|
65
58
|
}
|
|
66
59
|
else {
|
|
67
|
-
// Non-markdown: apply regex replacements only
|
|
68
60
|
const regexReplacements = replacements.filter((r) => r.type === "regex");
|
|
69
61
|
if (regexReplacements.length > 0) {
|
|
70
62
|
content = applyRegexReplacements(content, regexReplacements, context);
|
|
71
63
|
}
|
|
72
64
|
}
|
|
73
65
|
}
|
|
74
|
-
// Write to project directory
|
|
75
66
|
await mkdir(dirname(destPath), { recursive: true });
|
|
76
67
|
await writeFile(destPath, content, "utf-8");
|
|
77
|
-
// Record hash
|
|
78
68
|
const sha1 = computeSha1(content);
|
|
79
69
|
const version = entry.meta?.version ?? "0.0.0";
|
|
80
70
|
hashEntries.push({ filePath: targetPath, version, sha1 });
|
|
81
71
|
deployedAssets[targetPath] = version;
|
|
82
72
|
deployedFiles.push(targetPath);
|
|
83
73
|
}
|
|
84
|
-
// 5. Write settings and hashsum
|
|
85
74
|
const updatedSettings = {
|
|
86
75
|
...settings,
|
|
87
76
|
deployedAssets,
|
|
88
77
|
};
|
|
89
78
|
await writeSettings(projectDir, updatedSettings);
|
|
90
79
|
await writeHashsum(projectDir, hashEntries);
|
|
91
|
-
// 6. Run install commands at project root
|
|
92
80
|
if (!noInstall) {
|
|
93
|
-
const installCmds = ["bun
|
|
81
|
+
const installCmds = ["bun ci", "bun run build"];
|
|
94
82
|
for (const cmd of installCmds) {
|
|
95
83
|
try {
|
|
96
84
|
execSync(cmd, { cwd: projectDir, stdio: "pipe" });
|
|
@@ -103,7 +91,6 @@ export const deployAssets = async (options) => {
|
|
|
103
91
|
return { deployedFiles, hashEntries, skippedFiles };
|
|
104
92
|
}
|
|
105
93
|
finally {
|
|
106
|
-
// 7. Cleanup (delegated to provider)
|
|
107
94
|
await provider.cleanup().catch(() => { });
|
|
108
95
|
}
|
|
109
96
|
};
|
package/dist/asset/walker.d.ts
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import type { MetaJson, EvalContext } from "../core/types.js";
|
|
2
2
|
export type AssetEntry = {
|
|
3
|
-
/** Absolute path in the extracted repo */
|
|
4
3
|
sourcePath: string;
|
|
5
|
-
/** Relative path for deployment (e.g., ".claude/CLAUDE.md") */
|
|
6
4
|
relativePath: string;
|
|
7
|
-
/** MetaJson from the directory's _meta.json (or parent's) */
|
|
8
5
|
meta: MetaJson | null;
|
|
9
6
|
};
|
|
10
7
|
export declare const walkAssetRepo: (repoDir: string, targetSemver: string, context: EvalContext) => Promise<AssetEntry[]>;
|
package/dist/asset/walker.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { readdir, readFile } from "node:fs/promises";
|
|
2
|
-
import { join, relative, dirname } from "node:path";
|
|
2
|
+
import { join, relative, dirname, sep } from "node:path";
|
|
3
3
|
import { evaluateCondition } from "../core/condition-evaluator.js";
|
|
4
|
+
const toPosixPath = (p) => sep === "/" ? p : p.split(sep).join("/");
|
|
4
5
|
const META_FILE = "_meta.json";
|
|
5
6
|
const readMetaJson = async (dir) => {
|
|
6
7
|
try {
|
|
7
8
|
const content = await readFile(join(dir, META_FILE), "utf-8");
|
|
8
9
|
const parsed = JSON.parse(content);
|
|
9
|
-
// Default type to "directory" for backward compatibility
|
|
10
10
|
if (!parsed.type) {
|
|
11
11
|
parsed.type = "directory";
|
|
12
12
|
}
|
|
@@ -16,10 +16,6 @@ const readMetaJson = async (dir) => {
|
|
|
16
16
|
return null;
|
|
17
17
|
}
|
|
18
18
|
};
|
|
19
|
-
/**
|
|
20
|
-
* Resolve rename rule: evaluate conditions and find the first matching rule.
|
|
21
|
-
* Returns the source file path and target name, or null if no rule matches.
|
|
22
|
-
*/
|
|
23
19
|
const resolveRenameRule = (rules, context, dir) => {
|
|
24
20
|
if (!rules || rules.length === 0)
|
|
25
21
|
return null;
|
|
@@ -42,11 +38,9 @@ const findMatchingVersionDirs = async (repoDir, targetSemver) => {
|
|
|
42
38
|
const dirPath = join(repoDir, entry.name);
|
|
43
39
|
const meta = await readMetaJson(dirPath);
|
|
44
40
|
if (!meta) {
|
|
45
|
-
// No _meta.json — skip version directory without meta
|
|
46
41
|
continue;
|
|
47
42
|
}
|
|
48
43
|
if (meta.conditions) {
|
|
49
|
-
// Evaluate only the version condition at root level
|
|
50
44
|
const context = {
|
|
51
45
|
version: targetSemver,
|
|
52
46
|
modules: [],
|
|
@@ -69,20 +63,16 @@ const findMatchingVersionDirs = async (repoDir, targetSemver) => {
|
|
|
69
63
|
const walkDirectory = async (dir, baseDir, parentMeta, context) => {
|
|
70
64
|
const entries = [];
|
|
71
65
|
const dirEntries = await readdir(dir, { withFileTypes: true });
|
|
72
|
-
// Check if this directory has its own _meta.json
|
|
73
66
|
const ownMeta = await readMetaJson(dir);
|
|
74
67
|
const effectiveMeta = ownMeta ?? parentMeta;
|
|
75
|
-
// If this directory has conditions and they don't match, skip entirely
|
|
76
68
|
if (ownMeta?.conditions) {
|
|
77
69
|
if (!evaluateCondition(ownMeta.conditions, context)) {
|
|
78
70
|
return [];
|
|
79
71
|
}
|
|
80
72
|
}
|
|
81
|
-
// Handle type: "file" — no recursion into subdirectories
|
|
82
73
|
if (ownMeta?.type === "file") {
|
|
83
74
|
const parentRelative = relative(baseDir, dirname(dir));
|
|
84
75
|
if (ownMeta.rename && ownMeta.rename.length > 0) {
|
|
85
|
-
// With rename: select one source file via first-match-wins, deploy with `to` name
|
|
86
76
|
const resolved = resolveRenameRule(ownMeta.rename, context, dir);
|
|
87
77
|
if (!resolved)
|
|
88
78
|
return [];
|
|
@@ -91,12 +81,11 @@ const walkDirectory = async (dir, baseDir, parentMeta, context) => {
|
|
|
91
81
|
: resolved.targetName;
|
|
92
82
|
entries.push({
|
|
93
83
|
sourcePath: resolved.sourcePath,
|
|
94
|
-
relativePath: targetPath,
|
|
84
|
+
relativePath: toPosixPath(targetPath),
|
|
95
85
|
meta: effectiveMeta,
|
|
96
86
|
});
|
|
97
87
|
}
|
|
98
88
|
else {
|
|
99
|
-
// Without rename: deploy all files (except _meta.json) with original names
|
|
100
89
|
for (const entry of dirEntries) {
|
|
101
90
|
if (entry.name === META_FILE)
|
|
102
91
|
continue;
|
|
@@ -108,18 +97,16 @@ const walkDirectory = async (dir, baseDir, parentMeta, context) => {
|
|
|
108
97
|
: entry.name;
|
|
109
98
|
entries.push({
|
|
110
99
|
sourcePath: fullPath,
|
|
111
|
-
relativePath: targetPath,
|
|
100
|
+
relativePath: toPosixPath(targetPath),
|
|
112
101
|
meta: effectiveMeta,
|
|
113
102
|
});
|
|
114
103
|
}
|
|
115
104
|
}
|
|
116
105
|
return entries;
|
|
117
106
|
}
|
|
118
|
-
// type: "directory" — walk recursively (existing behavior)
|
|
119
107
|
for (const entry of dirEntries) {
|
|
120
108
|
const fullPath = join(dir, entry.name);
|
|
121
109
|
if (entry.name === META_FILE) {
|
|
122
|
-
// Skip _meta.json itself
|
|
123
110
|
continue;
|
|
124
111
|
}
|
|
125
112
|
if (entry.isDirectory()) {
|
|
@@ -129,7 +116,7 @@ const walkDirectory = async (dir, baseDir, parentMeta, context) => {
|
|
|
129
116
|
else if (entry.isFile()) {
|
|
130
117
|
entries.push({
|
|
131
118
|
sourcePath: fullPath,
|
|
132
|
-
relativePath: relative(baseDir, fullPath),
|
|
119
|
+
relativePath: toPosixPath(relative(baseDir, fullPath)),
|
|
133
120
|
meta: effectiveMeta,
|
|
134
121
|
});
|
|
135
122
|
}
|
|
@@ -144,7 +131,6 @@ const deduplicateByPath = (entries) => {
|
|
|
144
131
|
byPath.set(entry.relativePath, entry);
|
|
145
132
|
continue;
|
|
146
133
|
}
|
|
147
|
-
// Same relative path collision: prefer entries from a type: "file" directory.
|
|
148
134
|
const existingIsFileType = existing.meta?.type === "file";
|
|
149
135
|
const currentIsFileType = entry.meta?.type === "file";
|
|
150
136
|
if (currentIsFileType && !existingIsFileType) {
|
package/dist/commands/attach.js
CHANGED
|
@@ -82,14 +82,12 @@ export const attachCommand = defineCommand({
|
|
|
82
82
|
run: async ({ args }) => {
|
|
83
83
|
const locale = args.locale ?? detectLocale();
|
|
84
84
|
const projectDir = process.cwd();
|
|
85
|
-
// Check .accel doesn't exist
|
|
86
85
|
try {
|
|
87
86
|
await stat(join(projectDir, ".accel"));
|
|
88
87
|
p.log.error(getMessage("error.accelExists", locale));
|
|
89
88
|
process.exit(1);
|
|
90
89
|
}
|
|
91
90
|
catch {
|
|
92
|
-
// .accel doesn't exist — good
|
|
93
91
|
}
|
|
94
92
|
const moduleArg = args.module;
|
|
95
93
|
const modules = moduleArg
|
package/dist/commands/detach.js
CHANGED
|
@@ -15,7 +15,6 @@ export const detachCommand = defineCommand({
|
|
|
15
15
|
run: async () => {
|
|
16
16
|
const projectDir = process.cwd();
|
|
17
17
|
const locale = detectLocale();
|
|
18
|
-
// Check .accel exists
|
|
19
18
|
try {
|
|
20
19
|
await stat(join(projectDir, ".accel"));
|
|
21
20
|
}
|
|
@@ -57,10 +56,8 @@ export const detachCommand = defineCommand({
|
|
|
57
56
|
}
|
|
58
57
|
}
|
|
59
58
|
catch {
|
|
60
|
-
// File doesn't exist — already removed
|
|
61
59
|
}
|
|
62
60
|
}
|
|
63
|
-
// Delete .accel directory
|
|
64
61
|
await rm(join(projectDir, ".accel"), { recursive: true, force: true });
|
|
65
62
|
if (skipped > 0) {
|
|
66
63
|
p.outro(getMessage("detach.complete", effectiveLocale, {
|
package/dist/commands/init.js
CHANGED
|
@@ -11,6 +11,7 @@ import { createFileAssetProvider } from "../asset/file-provider.js";
|
|
|
11
11
|
import { defaultAssetSourcePath } from "../asset/default-source.js";
|
|
12
12
|
import { getMessage } from "../i18n/index.js";
|
|
13
13
|
import { detectLocale } from "../utils/locale-detect.js";
|
|
14
|
+
import { commandExists } from "../utils/command-exists.js";
|
|
14
15
|
export const initCommand = defineCommand({
|
|
15
16
|
meta: {
|
|
16
17
|
name: "init",
|
|
@@ -89,7 +90,6 @@ export const initCommand = defineCommand({
|
|
|
89
90
|
run: async ({ args }) => {
|
|
90
91
|
const locale = args.locale ?? detectLocale();
|
|
91
92
|
const projectName = args.name;
|
|
92
|
-
// Parse module option (comma-separated or repeated)
|
|
93
93
|
const moduleArg = args.module;
|
|
94
94
|
const modules = moduleArg
|
|
95
95
|
? moduleArg.split(",").map((m) => m.trim())
|
|
@@ -121,7 +121,6 @@ export const initCommand = defineCommand({
|
|
|
121
121
|
p.log.error(err instanceof Error ? err.message : String(err));
|
|
122
122
|
process.exit(1);
|
|
123
123
|
}
|
|
124
|
-
// Resolve final project directory from interactive result and create it
|
|
125
124
|
const projectDir = resolve(process.cwd(), resolved.name);
|
|
126
125
|
try {
|
|
127
126
|
await stat(projectDir);
|
|
@@ -129,10 +128,8 @@ export const initCommand = defineCommand({
|
|
|
129
128
|
process.exit(1);
|
|
130
129
|
}
|
|
131
130
|
catch {
|
|
132
|
-
// Directory doesn't exist — good
|
|
133
131
|
}
|
|
134
132
|
await mkdir(projectDir, { recursive: true });
|
|
135
|
-
// Build settings
|
|
136
133
|
const settings = {
|
|
137
134
|
cliVersion: CLI_VERSION,
|
|
138
135
|
createdAt: new Date().toISOString(),
|
|
@@ -149,7 +146,6 @@ export const initCommand = defineCommand({
|
|
|
149
146
|
jugglingProject: resolved.jugglingProject,
|
|
150
147
|
deployedAssets: {},
|
|
151
148
|
};
|
|
152
|
-
// Deploy assets
|
|
153
149
|
const serverUrl = args["asset-server-url"];
|
|
154
150
|
const assetSource = args["asset-source"] ?? defaultAssetSourcePath();
|
|
155
151
|
const provider = serverUrl
|
|
@@ -162,14 +158,17 @@ export const initCommand = defineCommand({
|
|
|
162
158
|
provider,
|
|
163
159
|
noInstall: args["skip-install"],
|
|
164
160
|
});
|
|
165
|
-
// Git init
|
|
166
161
|
if (resolved.withGit) {
|
|
167
|
-
|
|
168
|
-
execSync("which git", { stdio: "pipe" });
|
|
162
|
+
if (commandExists("git")) {
|
|
169
163
|
p.log.info(getMessage("progress.gitInit", locale));
|
|
170
|
-
|
|
164
|
+
try {
|
|
165
|
+
execSync("git init", { cwd: projectDir, stdio: "pipe" });
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
p.log.warning(getMessage("warning.gitNotFound", locale));
|
|
169
|
+
}
|
|
171
170
|
}
|
|
172
|
-
|
|
171
|
+
else {
|
|
173
172
|
p.log.warning(getMessage("warning.gitNotFound", locale));
|
|
174
173
|
}
|
|
175
174
|
}
|
package/dist/core/constants.js
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
export const CLI_VERSION = "0.1.0";
|
|
2
|
-
// --- Database options ---
|
|
3
2
|
export const DATABASE_OPTIONS = ["postgresql", "oracle", "sqlserver"];
|
|
4
|
-
// --- Agent options ---
|
|
5
3
|
export const AGENT_OPTIONS = ["claude-code", "github-copilot"];
|
|
6
|
-
// --- Module options ---
|
|
7
4
|
export const MODULE_OPTIONS = [
|
|
8
5
|
"workflow",
|
|
9
6
|
"bpm",
|
|
@@ -12,15 +9,13 @@ export const MODULE_OPTIONS = [
|
|
|
12
9
|
"pdfd",
|
|
13
10
|
"kaiden",
|
|
14
11
|
];
|
|
15
|
-
// --- Locale options ---
|
|
16
12
|
export const LOCALE_OPTIONS = ["ja", "en", "zh_CN"];
|
|
17
|
-
// --- Default settings ---
|
|
18
13
|
export const DEFAULT_SETTINGS = {
|
|
19
14
|
name: "my-accel-project",
|
|
20
15
|
group: "my-group",
|
|
21
16
|
projectVersion: "0.1.0",
|
|
22
17
|
description: "",
|
|
23
|
-
accelplatformVersion: "
|
|
18
|
+
accelplatformVersion: "2025-Autumn",
|
|
24
19
|
modules: [],
|
|
25
20
|
database: "postgresql",
|
|
26
21
|
agents: ["claude-code", "github-copilot"],
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Mapping from CLI module names to juggling.im XML module IDs.
|
|
3
|
-
* This map will be extended as more modules are added.
|
|
4
|
-
*/
|
|
5
1
|
export declare const MODULE_ID_MAP: Record<string, string>;
|
|
6
2
|
export declare const xmlIdToModuleName: (xmlId: string) => string | undefined;
|
|
7
3
|
export declare const moduleNameToXmlId: (moduleName: string) => string | undefined;
|
package/dist/core/module-map.js
CHANGED
|
@@ -1,11 +1,6 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Mapping from CLI module names to juggling.im XML module IDs.
|
|
3
|
-
* This map will be extended as more modules are added.
|
|
4
|
-
*/
|
|
5
1
|
export const MODULE_ID_MAP = {
|
|
6
2
|
workflow: "jp.co.intra_mart.im_workflow",
|
|
7
3
|
copilot: "jp.co.intra_mart.im_copilot",
|
|
8
|
-
// TODO: Add mappings for bpm, imbox, pdfd, kaiden
|
|
9
4
|
};
|
|
10
5
|
const reverseMap = new Map(Object.entries(MODULE_ID_MAP).map(([key, value]) => [value, key]));
|
|
11
6
|
export const xmlIdToModuleName = (xmlId) => reverseMap.get(xmlId);
|
package/dist/core/types.js
CHANGED
|
@@ -1,10 +1,2 @@
|
|
|
1
1
|
import type { EvalContext } from "./types.js";
|
|
2
|
-
/**
|
|
3
|
-
* Interpolate {{$variable}} placeholders in a string using EvalContext values.
|
|
4
|
-
*
|
|
5
|
-
* - Known variables are replaced with their EvalContext value (empty string if value is "").
|
|
6
|
-
* - Unknown variables (not in the allowlist) are left unchanged.
|
|
7
|
-
* - Array-type fields (modules, agents) are not available as variables.
|
|
8
|
-
* - No recursive expansion: if a variable's value contains {{$...}}, it is NOT re-expanded.
|
|
9
|
-
*/
|
|
10
2
|
export declare const interpolateVariables: (template: string, context: EvalContext) => string;
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Allowlist of variable names that can be interpolated.
|
|
3
|
-
* Maps {{$varName}} to the corresponding EvalContext field.
|
|
4
|
-
* Array fields (modules, agents) are deliberately excluded.
|
|
5
|
-
*/
|
|
6
1
|
const VARIABLE_MAP = new Map([
|
|
7
2
|
["name", "name"],
|
|
8
3
|
["group", "group"],
|
|
@@ -14,14 +9,6 @@ const VARIABLE_MAP = new Map([
|
|
|
14
9
|
["projectVersion", "projectVersion"],
|
|
15
10
|
]);
|
|
16
11
|
const INTERPOLATION_PATTERN = /\{\{\$(\w+)\}\}/g;
|
|
17
|
-
/**
|
|
18
|
-
* Interpolate {{$variable}} placeholders in a string using EvalContext values.
|
|
19
|
-
*
|
|
20
|
-
* - Known variables are replaced with their EvalContext value (empty string if value is "").
|
|
21
|
-
* - Unknown variables (not in the allowlist) are left unchanged.
|
|
22
|
-
* - Array-type fields (modules, agents) are not available as variables.
|
|
23
|
-
* - No recursive expansion: if a variable's value contains {{$...}}, it is NOT re-expanded.
|
|
24
|
-
*/
|
|
25
12
|
export const interpolateVariables = (template, context) => {
|
|
26
13
|
return template.replace(INTERPOLATION_PATTERN, (match, varName) => {
|
|
27
14
|
const field = VARIABLE_MAP.get(varName);
|
package/dist/core/version-map.js
CHANGED
|
@@ -23,7 +23,7 @@ export const IAP_VERSIONS = [
|
|
|
23
23
|
];
|
|
24
24
|
export const SELECTABLE_VERSIONS = IAP_VERSIONS.filter((v) => {
|
|
25
25
|
const minor = parseInt(v.semver.split(".")[2], 10);
|
|
26
|
-
return minor >= 35;
|
|
26
|
+
return minor >= 35;
|
|
27
27
|
});
|
|
28
28
|
const labelToVersionMap = new Map(IAP_VERSIONS.map((v) => [v.label, v]));
|
|
29
29
|
const semverToVersionMap = new Map(IAP_VERSIONS.map((v) => [v.semver, v]));
|
package/dist/i18n/en.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
export const messages = {
|
|
2
|
-
// init/attach prompts
|
|
3
2
|
"prompt.name": "Enter project name",
|
|
4
3
|
"prompt.jugglingProject": "Enter IM-Juggling project path (optional)",
|
|
5
4
|
"prompt.accelplatformVersion": "Select iAP version",
|
|
@@ -11,25 +10,20 @@ export const messages = {
|
|
|
11
10
|
"prompt.javascript": "Use JavaScript?",
|
|
12
11
|
"prompt.agent": "Select agent",
|
|
13
12
|
"prompt.withGit": "Initialize Git repository?",
|
|
14
|
-
// juggling
|
|
15
13
|
"juggling.detected.version": "Detected version from juggling.im: {version}",
|
|
16
14
|
"juggling.detected.modules": "Detected modules from juggling.im: {modules}",
|
|
17
15
|
"juggling.notFound": "juggling.im not found at specified path: {path}",
|
|
18
|
-
// warnings
|
|
19
16
|
"warning.versionMismatch": "Specified iAP version ({option}) differs from juggling.im ({juggling}). Using specified value.",
|
|
20
17
|
"warning.moduleMismatch": "Specified modules differ from juggling.im. Using specified values.",
|
|
21
18
|
"warning.gitNotFound": "git command not found. Skipping Git initialization.",
|
|
22
19
|
"warning.fileExists": "File already exists, skipping: {path}",
|
|
23
|
-
// attach
|
|
24
20
|
"attach.skipSummary": "{count} file(s) were skipped because they already exist.",
|
|
25
|
-
// detach
|
|
26
21
|
"detach.confirm": "Detach Accel CLI from this project. Are you sure?",
|
|
27
22
|
"detach.deleted": "Deleted: {path}",
|
|
28
23
|
"detach.skipped": "Skipped: {path} (modifications detected)",
|
|
29
24
|
"detach.complete": "Detach complete. {skipped} file(s) were skipped due to user modifications.",
|
|
30
25
|
"detach.completeAll": "Detach complete. All assets removed.",
|
|
31
26
|
"detach.cancelled": "Detach cancelled.",
|
|
32
|
-
// errors
|
|
33
27
|
"error.directoryExists": "Directory already exists: {path}",
|
|
34
28
|
"error.accelExists": ".accel directory already exists",
|
|
35
29
|
"error.accelNotFound": ".accel directory not found",
|
|
@@ -38,7 +32,6 @@ export const messages = {
|
|
|
38
32
|
"error.invalidModule": "Invalid module: {module}",
|
|
39
33
|
"error.invalidDatabase": "Invalid database: {database}",
|
|
40
34
|
"error.invalidAgent": "Invalid agent: {agent}",
|
|
41
|
-
// progress
|
|
42
35
|
"progress.downloading": "Downloading assets...",
|
|
43
36
|
"progress.deploying": "Deploying assets...",
|
|
44
37
|
"progress.installing": "Installing dependencies...",
|
package/dist/i18n/ja.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
export const messages = {
|
|
2
|
-
// init/attach prompts
|
|
3
2
|
"prompt.name": "プロジェクト名を入力してください",
|
|
4
3
|
"prompt.jugglingProject": "IM-Jugglingプロジェクトのパスを入力してください(省略可)",
|
|
5
4
|
"prompt.accelplatformVersion": "iAPバージョンを選択してください",
|
|
@@ -11,25 +10,20 @@ export const messages = {
|
|
|
11
10
|
"prompt.javascript": "JavaScriptを利用しますか?",
|
|
12
11
|
"prompt.agent": "エージェントを選択してください",
|
|
13
12
|
"prompt.withGit": "Gitリポジトリを初期化しますか?",
|
|
14
|
-
// juggling
|
|
15
13
|
"juggling.detected.version": "juggling.imからバージョンを検出: {version}",
|
|
16
14
|
"juggling.detected.modules": "juggling.imからモジュールを検出: {modules}",
|
|
17
15
|
"juggling.notFound": "指定されたパスにjuggling.imが見つかりません: {path}",
|
|
18
|
-
// warnings
|
|
19
16
|
"warning.versionMismatch": "指定されたiAPバージョン ({option}) とjuggling.imのバージョン ({juggling}) が異なります。指定値を優先します。",
|
|
20
17
|
"warning.moduleMismatch": "指定されたモジュールとjuggling.imのモジュールが異なります。指定値を優先します。",
|
|
21
18
|
"warning.gitNotFound": "gitコマンドが見つかりません。Git初期化をスキップします。",
|
|
22
19
|
"warning.fileExists": "既存ファイルのためスキップ: {path}",
|
|
23
|
-
// attach
|
|
24
20
|
"attach.skipSummary": "{count}件のファイルは既に存在したためスキップしました。",
|
|
25
|
-
// detach
|
|
26
21
|
"detach.confirm": "このプロジェクトからAccel CLIを解除します。よろしいですか?",
|
|
27
22
|
"detach.deleted": "削除: {path}",
|
|
28
23
|
"detach.skipped": "スキップ: {path} (変更が検出されました)",
|
|
29
24
|
"detach.complete": "detachが完了しました。{skipped}件のファイルはユーザーによる変更が検出されたためスキップしました。",
|
|
30
25
|
"detach.completeAll": "detachが完了しました。すべての資材を削除しました。",
|
|
31
26
|
"detach.cancelled": "detachをキャンセルしました。",
|
|
32
|
-
// errors
|
|
33
27
|
"error.directoryExists": "ディレクトリが既に存在します: {path}",
|
|
34
28
|
"error.accelExists": ".accelディレクトリが既に存在します",
|
|
35
29
|
"error.accelNotFound": ".accelディレクトリが見つかりません",
|
|
@@ -38,7 +32,6 @@ export const messages = {
|
|
|
38
32
|
"error.invalidModule": "無効なモジュールです: {module}",
|
|
39
33
|
"error.invalidDatabase": "無効なデータベースです: {database}",
|
|
40
34
|
"error.invalidAgent": "無効なエージェントです: {agent}",
|
|
41
|
-
// progress
|
|
42
35
|
"progress.downloading": "資材をダウンロードしています...",
|
|
43
36
|
"progress.deploying": "資材を配備しています...",
|
|
44
37
|
"progress.installing": "依存関係をインストールしています...",
|
package/dist/i18n/zh_CN.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
export const messages = {
|
|
2
|
-
// init/attach prompts
|
|
3
2
|
"prompt.name": "请输入项目名称",
|
|
4
3
|
"prompt.jugglingProject": "请输入IM-Juggling项目路径(可选)",
|
|
5
4
|
"prompt.accelplatformVersion": "请选择iAP版本",
|
|
@@ -11,25 +10,20 @@ export const messages = {
|
|
|
11
10
|
"prompt.javascript": "是否使用JavaScript?",
|
|
12
11
|
"prompt.agent": "请选择代理",
|
|
13
12
|
"prompt.withGit": "是否初始化Git仓库?",
|
|
14
|
-
// juggling
|
|
15
13
|
"juggling.detected.version": "从juggling.im检测到版本: {version}",
|
|
16
14
|
"juggling.detected.modules": "从juggling.im检测到模块: {modules}",
|
|
17
15
|
"juggling.notFound": "在指定路径未找到juggling.im: {path}",
|
|
18
|
-
// warnings
|
|
19
16
|
"warning.versionMismatch": "指定的iAP版本 ({option}) 与juggling.im ({juggling}) 不同。将使用指定值。",
|
|
20
17
|
"warning.moduleMismatch": "指定的模块与juggling.im不同。将使用指定值。",
|
|
21
18
|
"warning.gitNotFound": "未找到git命令。跳过Git初始化。",
|
|
22
19
|
"warning.fileExists": "文件已存在,跳过: {path}",
|
|
23
|
-
// attach
|
|
24
20
|
"attach.skipSummary": "{count}个文件已存在,已跳过。",
|
|
25
|
-
// detach
|
|
26
21
|
"detach.confirm": "从此项目解除Accel CLI。确定吗?",
|
|
27
22
|
"detach.deleted": "已删除: {path}",
|
|
28
23
|
"detach.skipped": "已跳过: {path} (检测到修改)",
|
|
29
24
|
"detach.complete": "解除完成。{skipped}个文件因用户修改而被跳过。",
|
|
30
25
|
"detach.completeAll": "解除完成。所有资源已删除。",
|
|
31
26
|
"detach.cancelled": "解除已取消。",
|
|
32
|
-
// errors
|
|
33
27
|
"error.directoryExists": "目录已存在: {path}",
|
|
34
28
|
"error.accelExists": ".accel目录已存在",
|
|
35
29
|
"error.accelNotFound": "未找到.accel目录",
|
|
@@ -38,7 +32,6 @@ export const messages = {
|
|
|
38
32
|
"error.invalidModule": "无效的模块: {module}",
|
|
39
33
|
"error.invalidDatabase": "无效的数据库: {database}",
|
|
40
34
|
"error.invalidAgent": "无效的代理: {agent}",
|
|
41
|
-
// progress
|
|
42
35
|
"progress.downloading": "正在下载资源...",
|
|
43
36
|
"progress.deploying": "正在部署资源...",
|
|
44
37
|
"progress.installing": "正在安装依赖...",
|
|
@@ -1,18 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { commandExists } from "../utils/command-exists.js";
|
|
2
2
|
const AGENT_COMMANDS = [
|
|
3
3
|
{ name: "claude-code", command: "claude" },
|
|
4
4
|
{ name: "github-copilot", command: "gh" },
|
|
5
5
|
];
|
|
6
|
-
const commandExists = (cmd) => {
|
|
7
|
-
try {
|
|
8
|
-
const whichCmd = process.platform === "win32" ? "where" : "which";
|
|
9
|
-
execSync(`${whichCmd} ${cmd}`, { stdio: "pipe" });
|
|
10
|
-
return true;
|
|
11
|
-
}
|
|
12
|
-
catch {
|
|
13
|
-
return false;
|
|
14
|
-
}
|
|
15
|
-
};
|
|
16
6
|
export const detectAgents = () => {
|
|
17
7
|
return AGENT_COMMANDS.filter((a) => commandExists(a.command));
|
|
18
8
|
};
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import * as p from "@clack/prompts";
|
|
2
|
-
import {
|
|
3
|
-
import { MODULE_OPTIONS, DATABASE_OPTIONS, AGENT_OPTIONS, DEFAULT_SETTINGS, } from "../core/constants.js";
|
|
2
|
+
import { DATABASE_OPTIONS, AGENT_OPTIONS, DEFAULT_SETTINGS, } from "../core/constants.js";
|
|
4
3
|
import { getMessage } from "../i18n/index.js";
|
|
5
4
|
import { detectAgents, detectDefaultAgents } from "./agent-detect.js";
|
|
6
5
|
import { parseJugglingFile } from "../juggling/parser.js";
|
|
@@ -24,17 +23,10 @@ export const validateNonInteractive = (opts) => {
|
|
|
24
23
|
const missing = [];
|
|
25
24
|
if (!opts.name)
|
|
26
25
|
missing.push("--name");
|
|
27
|
-
if (!opts.jugglingProject) {
|
|
28
|
-
if (!opts.accelplatformVersion)
|
|
29
|
-
missing.push("--accelplatform-version");
|
|
30
|
-
if (!opts.module || opts.module.length === 0)
|
|
31
|
-
missing.push("--module");
|
|
32
|
-
}
|
|
33
26
|
return missing;
|
|
34
27
|
};
|
|
35
28
|
export const runPrompts = async (opts) => {
|
|
36
29
|
const locale = opts.locale;
|
|
37
|
-
// Non-interactive mode
|
|
38
30
|
if (opts.noInteraction) {
|
|
39
31
|
const missing = validateNonInteractive(opts);
|
|
40
32
|
if (missing.length > 0) {
|
|
@@ -54,14 +46,8 @@ export const runPrompts = async (opts) => {
|
|
|
54
46
|
group: opts.group ?? DEFAULT_SETTINGS.group,
|
|
55
47
|
projectVersion: opts.projectVersion ?? DEFAULT_SETTINGS.projectVersion,
|
|
56
48
|
description: opts.description ?? DEFAULT_SETTINGS.description,
|
|
57
|
-
accelplatformVersion:
|
|
58
|
-
|
|
59
|
-
DEFAULT_SETTINGS.accelplatformVersion,
|
|
60
|
-
modules: opts.module && opts.module.length > 0
|
|
61
|
-
? opts.module
|
|
62
|
-
: jugglingModules.length > 0
|
|
63
|
-
? jugglingModules
|
|
64
|
-
: [],
|
|
49
|
+
accelplatformVersion: "2025-Autumn",
|
|
50
|
+
modules: ["workflow", "bpm"],
|
|
65
51
|
database: (opts.database ?? DEFAULT_SETTINGS.database),
|
|
66
52
|
agents: opts.agent ?? detectDefaultAgents(),
|
|
67
53
|
javascript: opts.javascript ?? DEFAULT_SETTINGS.javascript,
|
|
@@ -70,9 +56,7 @@ export const runPrompts = async (opts) => {
|
|
|
70
56
|
withGit: opts.withGit ?? true,
|
|
71
57
|
};
|
|
72
58
|
}
|
|
73
|
-
// Interactive mode
|
|
74
59
|
p.intro("Accel CLI");
|
|
75
|
-
// 1. Project name
|
|
76
60
|
const name = (await p.text({
|
|
77
61
|
message: getMessage("prompt.name", locale),
|
|
78
62
|
defaultValue: opts.name ?? DEFAULT_SETTINGS.name,
|
|
@@ -80,7 +64,6 @@ export const runPrompts = async (opts) => {
|
|
|
80
64
|
}));
|
|
81
65
|
if (p.isCancel(name))
|
|
82
66
|
process.exit(0);
|
|
83
|
-
// 2. Juggling project (optional)
|
|
84
67
|
const jugglingInput = (await p.text({
|
|
85
68
|
message: getMessage("prompt.jugglingProject", locale),
|
|
86
69
|
defaultValue: opts.jugglingProject ?? "",
|
|
@@ -104,49 +87,8 @@ export const runPrompts = async (opts) => {
|
|
|
104
87
|
p.log.warning(err instanceof Error ? err.message : String(err));
|
|
105
88
|
}
|
|
106
89
|
}
|
|
107
|
-
|
|
108
|
-
const
|
|
109
|
-
// Warn if option and juggling version differ
|
|
110
|
-
if (opts.accelplatformVersion && jugglingVersion && opts.accelplatformVersion !== jugglingVersion) {
|
|
111
|
-
p.log.warning(getMessage("warning.versionMismatch", locale, {
|
|
112
|
-
option: opts.accelplatformVersion,
|
|
113
|
-
juggling: jugglingVersion,
|
|
114
|
-
}));
|
|
115
|
-
}
|
|
116
|
-
const accelplatformVersion = (await p.select({
|
|
117
|
-
message: getMessage("prompt.accelplatformVersion", locale),
|
|
118
|
-
options: SELECTABLE_VERSIONS.map((v) => ({
|
|
119
|
-
value: v.label,
|
|
120
|
-
label: `${v.label} (${v.codename})`,
|
|
121
|
-
})),
|
|
122
|
-
initialValue: versionDefault,
|
|
123
|
-
}));
|
|
124
|
-
if (p.isCancel(accelplatformVersion))
|
|
125
|
-
process.exit(0);
|
|
126
|
-
// 4. Modules
|
|
127
|
-
const moduleDefault = opts.module && opts.module.length > 0
|
|
128
|
-
? opts.module
|
|
129
|
-
: jugglingModules.length > 0
|
|
130
|
-
? jugglingModules
|
|
131
|
-
: [];
|
|
132
|
-
if (opts.module && opts.module.length > 0 && jugglingModules.length > 0) {
|
|
133
|
-
const diff = opts.module.some((m) => !jugglingModules.includes(m)) ||
|
|
134
|
-
jugglingModules.some((m) => !opts.module.includes(m));
|
|
135
|
-
if (diff) {
|
|
136
|
-
p.log.warning(getMessage("warning.moduleMismatch", locale));
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
const modules = (await p.multiselect({
|
|
140
|
-
message: getMessage("prompt.modules", locale),
|
|
141
|
-
options: MODULE_OPTIONS.map((m) => ({
|
|
142
|
-
value: m,
|
|
143
|
-
label: m,
|
|
144
|
-
})),
|
|
145
|
-
initialValues: moduleDefault,
|
|
146
|
-
}));
|
|
147
|
-
if (p.isCancel(modules))
|
|
148
|
-
process.exit(0);
|
|
149
|
-
// 5. Group
|
|
90
|
+
const accelplatformVersion = "2025-Autumn";
|
|
91
|
+
const modules = ["workflow", "bpm"];
|
|
150
92
|
const group = (await p.text({
|
|
151
93
|
message: getMessage("prompt.group", locale),
|
|
152
94
|
defaultValue: opts.group ?? DEFAULT_SETTINGS.group,
|
|
@@ -154,7 +96,6 @@ export const runPrompts = async (opts) => {
|
|
|
154
96
|
}));
|
|
155
97
|
if (p.isCancel(group))
|
|
156
98
|
process.exit(0);
|
|
157
|
-
// 6. Project version
|
|
158
99
|
const projectVersion = (await p.text({
|
|
159
100
|
message: getMessage("prompt.projectVersion", locale),
|
|
160
101
|
defaultValue: opts.projectVersion ?? DEFAULT_SETTINGS.projectVersion,
|
|
@@ -162,7 +103,6 @@ export const runPrompts = async (opts) => {
|
|
|
162
103
|
}));
|
|
163
104
|
if (p.isCancel(projectVersion))
|
|
164
105
|
process.exit(0);
|
|
165
|
-
// 7. Description
|
|
166
106
|
const description = (await p.text({
|
|
167
107
|
message: getMessage("prompt.description", locale),
|
|
168
108
|
defaultValue: opts.description ?? DEFAULT_SETTINGS.description,
|
|
@@ -170,7 +110,6 @@ export const runPrompts = async (opts) => {
|
|
|
170
110
|
}));
|
|
171
111
|
if (p.isCancel(description))
|
|
172
112
|
process.exit(0);
|
|
173
|
-
// 8. Database
|
|
174
113
|
const database = (await p.select({
|
|
175
114
|
message: getMessage("prompt.database", locale),
|
|
176
115
|
options: DATABASE_OPTIONS.map((d) => ({ value: d, label: d })),
|
|
@@ -178,14 +117,12 @@ export const runPrompts = async (opts) => {
|
|
|
178
117
|
}));
|
|
179
118
|
if (p.isCancel(database))
|
|
180
119
|
process.exit(0);
|
|
181
|
-
// 9. JavaScript
|
|
182
120
|
const javascript = (await p.confirm({
|
|
183
121
|
message: getMessage("prompt.javascript", locale),
|
|
184
122
|
initialValue: opts.javascript ?? DEFAULT_SETTINGS.javascript,
|
|
185
123
|
}));
|
|
186
124
|
if (p.isCancel(javascript))
|
|
187
125
|
process.exit(0);
|
|
188
|
-
// 10. Agent (multi-select)
|
|
189
126
|
const detected = detectAgents();
|
|
190
127
|
const agentOptions = AGENT_OPTIONS.map((a) => ({ value: a, label: a }));
|
|
191
128
|
const defaultAgents = opts.agent ??
|
|
@@ -199,7 +136,6 @@ export const runPrompts = async (opts) => {
|
|
|
199
136
|
}));
|
|
200
137
|
if (p.isCancel(agents))
|
|
201
138
|
process.exit(0);
|
|
202
|
-
// 11. Git init (init only)
|
|
203
139
|
let withGit = opts.withGit ?? true;
|
|
204
140
|
if (opts.isInit) {
|
|
205
141
|
withGit = (await p.confirm({
|
package/dist/juggling/parser.js
CHANGED
|
@@ -45,7 +45,6 @@ export const parseJugglingXml = (xmlContent) => {
|
|
|
45
45
|
if (!Array.isArray(structures) || structures.length === 0) {
|
|
46
46
|
return { modules: [], baseVersion: "" };
|
|
47
47
|
}
|
|
48
|
-
// Search from the end for the first structure with valid="true"
|
|
49
48
|
let validStructure;
|
|
50
49
|
for (let i = structures.length - 1; i >= 0; i--) {
|
|
51
50
|
if (structures[i]["@_valid"] === "true") {
|
|
@@ -56,10 +55,8 @@ export const parseJugglingXml = (xmlContent) => {
|
|
|
56
55
|
if (!validStructure) {
|
|
57
56
|
return { modules: [], baseVersion: "" };
|
|
58
57
|
}
|
|
59
|
-
// Extract baseVersion from ns2:base version attribute
|
|
60
58
|
const base = validStructure["ns2:base"];
|
|
61
59
|
const baseVersion = String(base?.["@_version"] ?? "");
|
|
62
|
-
// Extract modules
|
|
63
60
|
const modulesObj = validStructure["ns2:modules"];
|
|
64
61
|
const modules = modulesObj ? parseXmlModules(modulesObj) : [];
|
|
65
62
|
return { modules, baseVersion };
|
|
@@ -3,12 +3,10 @@ import { applySectionReplacements } from "./section-replacement.js";
|
|
|
3
3
|
export const processMarkdown = (content, replacements, context, placeholderMatcher) => {
|
|
4
4
|
const textReplacements = replacements.filter((r) => r.type === "text");
|
|
5
5
|
const sectionReplacements = replacements.filter((r) => r.type === "section");
|
|
6
|
-
// Apply text replacements first (plain string, before remark touches content)
|
|
7
6
|
let result = content;
|
|
8
7
|
if (textReplacements.length > 0) {
|
|
9
8
|
result = applyTextReplacements(result, textReplacements, context, placeholderMatcher);
|
|
10
9
|
}
|
|
11
|
-
// Then apply section replacements (remark AST parse + stringify)
|
|
12
10
|
if (sectionReplacements.length > 0) {
|
|
13
11
|
result = applySectionReplacements(result, sectionReplacements, context);
|
|
14
12
|
}
|
|
@@ -8,7 +8,6 @@ const findSectionRange = (tree, heading) => {
|
|
|
8
8
|
for (let i = 0; i < tree.children.length; i++) {
|
|
9
9
|
const node = tree.children[i];
|
|
10
10
|
if (startIdx === -1) {
|
|
11
|
-
// Looking for the target heading
|
|
12
11
|
if (node.type === "heading") {
|
|
13
12
|
const text = extractHeadingText(node);
|
|
14
13
|
if (text === heading) {
|
|
@@ -18,14 +17,12 @@ const findSectionRange = (tree, heading) => {
|
|
|
18
17
|
}
|
|
19
18
|
}
|
|
20
19
|
else {
|
|
21
|
-
// Looking for the end of the section (same or higher level heading)
|
|
22
20
|
if (node.type === "heading" && node.depth <= headingDepth) {
|
|
23
21
|
return { start: startIdx, end: i };
|
|
24
22
|
}
|
|
25
23
|
}
|
|
26
24
|
}
|
|
27
25
|
if (startIdx !== -1) {
|
|
28
|
-
// Section extends to end of document
|
|
29
26
|
return { start: startIdx, end: tree.children.length };
|
|
30
27
|
}
|
|
31
28
|
return null;
|
|
@@ -49,7 +46,6 @@ const extractHeadingText = (node) => {
|
|
|
49
46
|
export const applySectionReplacements = (content, replacements, context) => {
|
|
50
47
|
const processor = unified().use(remarkParse).use(remarkStringify);
|
|
51
48
|
const tree = processor.parse(content);
|
|
52
|
-
// Process replacements in reverse order to maintain correct indices
|
|
53
49
|
const removals = [];
|
|
54
50
|
for (const replacement of replacements) {
|
|
55
51
|
if (!evaluateCondition(replacement.condition, context)) {
|
|
@@ -59,7 +55,6 @@ export const applySectionReplacements = (content, replacements, context) => {
|
|
|
59
55
|
}
|
|
60
56
|
}
|
|
61
57
|
}
|
|
62
|
-
// Sort removals in reverse order and apply
|
|
63
58
|
removals.sort((a, b) => b.start - a.start);
|
|
64
59
|
for (const { start, end } of removals) {
|
|
65
60
|
tree.children.splice(start, end - start);
|
|
@@ -10,7 +10,6 @@ export const defaultPlaceholderMatcher = (text, target) => {
|
|
|
10
10
|
return matches;
|
|
11
11
|
};
|
|
12
12
|
export const resolveTextValue = (replacement, context) => {
|
|
13
|
-
// first-match-wins
|
|
14
13
|
for (const entry of replacement.values) {
|
|
15
14
|
if (evaluateCondition(entry.condition, context)) {
|
|
16
15
|
return entry.value;
|
|
@@ -23,7 +22,6 @@ export const applyTextReplacements = (content, replacements, context, matcher =
|
|
|
23
22
|
for (const replacement of replacements) {
|
|
24
23
|
const rawValue = resolveTextValue(replacement, context);
|
|
25
24
|
const value = interpolateVariables(rawValue, context);
|
|
26
|
-
// Simple string replacement — replace all occurrences
|
|
27
25
|
while (matcher(result, replacement.target).length > 0) {
|
|
28
26
|
result = result.replace(replacement.target, value);
|
|
29
27
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const commandExists: (cmd: string) => boolean;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { execSync } from "node:child_process";
|
|
2
|
+
export const commandExists = (cmd) => {
|
|
3
|
+
try {
|
|
4
|
+
const whichCmd = process.platform === "win32" ? "where" : "which";
|
|
5
|
+
execSync(`${whichCmd} ${cmd}`, { stdio: "pipe" });
|
|
6
|
+
return true;
|
|
7
|
+
}
|
|
8
|
+
catch {
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
};
|
|
@@ -15,20 +15,25 @@ export const detectLocale = () => {
|
|
|
15
15
|
process.env["LANG"] ||
|
|
16
16
|
process.env["LANGUAGE"] ||
|
|
17
17
|
"";
|
|
18
|
-
|
|
18
|
+
if (envLocale)
|
|
19
|
+
return normalizeLocale(envLocale);
|
|
20
|
+
try {
|
|
21
|
+
const intlLocale = Intl.DateTimeFormat().resolvedOptions().locale;
|
|
22
|
+
return normalizeLocale(intlLocale.replace(/-/g, "_"));
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return normalizeLocale("");
|
|
26
|
+
}
|
|
19
27
|
};
|
|
20
28
|
export const normalizeLocale = (raw) => {
|
|
21
|
-
// Strip encoding (e.g., ".UTF-8")
|
|
22
29
|
const stripped = raw.split(".")[0].toLowerCase();
|
|
23
30
|
const matched = LOCALE_NORMALIZE_MAP[stripped];
|
|
24
31
|
if (matched)
|
|
25
32
|
return matched;
|
|
26
|
-
// Try language part only (e.g., "ja_JP" -> "ja")
|
|
27
33
|
const langPart = stripped.split("_")[0];
|
|
28
34
|
const langMatched = LOCALE_NORMALIZE_MAP[langPart];
|
|
29
35
|
if (langMatched)
|
|
30
36
|
return langMatched;
|
|
31
|
-
// Check if it's directly a supported locale
|
|
32
37
|
if (LOCALE_OPTIONS.includes(raw))
|
|
33
38
|
return raw;
|
|
34
39
|
return DEFAULT_LOCALE;
|
|
@@ -8,7 +8,6 @@ const ensureAccelDir = async (projectDir) => {
|
|
|
8
8
|
await mkdir(accelDir, { recursive: true });
|
|
9
9
|
return accelDir;
|
|
10
10
|
};
|
|
11
|
-
// --- settings.json ---
|
|
12
11
|
export const writeSettings = async (projectDir, settings) => {
|
|
13
12
|
const accelDir = await ensureAccelDir(projectDir);
|
|
14
13
|
const filePath = join(accelDir, SETTINGS_FILE);
|
|
@@ -19,7 +18,6 @@ export const readSettings = async (projectDir) => {
|
|
|
19
18
|
const content = await readFile(filePath, "utf-8");
|
|
20
19
|
return JSON.parse(content);
|
|
21
20
|
};
|
|
22
|
-
// --- hashsum.txt ---
|
|
23
21
|
export const serializeHashsum = (entries) => {
|
|
24
22
|
const sorted = [...entries].sort((a, b) => a.filePath.localeCompare(b.filePath));
|
|
25
23
|
return sorted
|
package/package.json
CHANGED
|
@@ -1,60 +1,60 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@intra-mart/accel",
|
|
3
|
-
"version": "0.1.0-dev
|
|
4
|
-
"type": "module",
|
|
5
|
-
"description": "CLI tool for intra-mart Accel Platform development",
|
|
6
|
-
"author": "NTT DATA INTRAMART",
|
|
7
|
-
"license": "UNLICENSED",
|
|
8
|
-
"keywords": [
|
|
9
|
-
"intra-mart",
|
|
10
|
-
"AccelPlatform",
|
|
11
|
-
"iAP"
|
|
12
|
-
],
|
|
13
|
-
"repository": {
|
|
14
|
-
"type": "git",
|
|
15
|
-
"url": "git+https://github.com/accelplatform/accel-cli.git"
|
|
16
|
-
},
|
|
17
|
-
"homepage": "http://oss.intra-mart.org",
|
|
18
|
-
"bin": {
|
|
19
|
-
"accel": "./dist/index.js"
|
|
20
|
-
},
|
|
21
|
-
"files": [
|
|
22
|
-
"dist",
|
|
23
|
-
"assets/assets.tar.gz"
|
|
24
|
-
],
|
|
25
|
-
"engines": {
|
|
26
|
-
"node": ">=20.0.0"
|
|
27
|
-
},
|
|
28
|
-
"publishConfig": {
|
|
29
|
-
"access": "public"
|
|
30
|
-
},
|
|
31
|
-
"scripts": {
|
|
32
|
-
"build": "tsc",
|
|
33
|
-
"dev": "tsc --watch",
|
|
34
|
-
"test": "vitest run",
|
|
35
|
-
"test:unit": "vitest run tests/unit",
|
|
36
|
-
"test:e2e": "vitest run tests/e2e",
|
|
37
|
-
"test:watch": "vitest",
|
|
38
|
-
"typecheck": "tsc --noEmit",
|
|
39
|
-
"prepublishOnly": "tsc"
|
|
40
|
-
},
|
|
41
|
-
"dependencies": {
|
|
42
|
-
"@clack/prompts": "^0.10.0",
|
|
43
|
-
"citty": "^0.1.6",
|
|
44
|
-
"fast-xml-parser": "^5.2.0",
|
|
45
|
-
"remark": "^15.0.1",
|
|
46
|
-
"remark-parse": "^11.0.0",
|
|
47
|
-
"remark-stringify": "^11.0.0",
|
|
48
|
-
"semver": "^7.7.1",
|
|
49
|
-
"tar": "^7.4.3",
|
|
50
|
-
"unified": "^11.0.5",
|
|
51
|
-
"unist-util-visit": "^5.0.0"
|
|
52
|
-
},
|
|
53
|
-
"devDependencies": {
|
|
54
|
-
"@types/node": "^22.15.2",
|
|
55
|
-
"@types/semver": "^7.7.0",
|
|
56
|
-
"execa": "^9.5.2",
|
|
57
|
-
"typescript": "^5.8.3",
|
|
58
|
-
"vitest": "^3.1.2"
|
|
59
|
-
}
|
|
60
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@intra-mart/accel",
|
|
3
|
+
"version": "0.1.0-dev.202604241514",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "CLI tool for intra-mart Accel Platform development",
|
|
6
|
+
"author": "NTT DATA INTRAMART",
|
|
7
|
+
"license": "UNLICENSED",
|
|
8
|
+
"keywords": [
|
|
9
|
+
"intra-mart",
|
|
10
|
+
"AccelPlatform",
|
|
11
|
+
"iAP"
|
|
12
|
+
],
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "git+https://github.com/accelplatform/accel-cli.git"
|
|
16
|
+
},
|
|
17
|
+
"homepage": "http://oss.intra-mart.org",
|
|
18
|
+
"bin": {
|
|
19
|
+
"accel": "./dist/index.js"
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist",
|
|
23
|
+
"assets/assets.tar.gz"
|
|
24
|
+
],
|
|
25
|
+
"engines": {
|
|
26
|
+
"node": ">=20.0.0"
|
|
27
|
+
},
|
|
28
|
+
"publishConfig": {
|
|
29
|
+
"access": "public"
|
|
30
|
+
},
|
|
31
|
+
"scripts": {
|
|
32
|
+
"build": "tsc",
|
|
33
|
+
"dev": "tsc --watch",
|
|
34
|
+
"test": "vitest run",
|
|
35
|
+
"test:unit": "vitest run tests/unit",
|
|
36
|
+
"test:e2e": "vitest run tests/e2e",
|
|
37
|
+
"test:watch": "vitest",
|
|
38
|
+
"typecheck": "tsc --noEmit",
|
|
39
|
+
"prepublishOnly": "tsc"
|
|
40
|
+
},
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"@clack/prompts": "^0.10.0",
|
|
43
|
+
"citty": "^0.1.6",
|
|
44
|
+
"fast-xml-parser": "^5.2.0",
|
|
45
|
+
"remark": "^15.0.1",
|
|
46
|
+
"remark-parse": "^11.0.0",
|
|
47
|
+
"remark-stringify": "^11.0.0",
|
|
48
|
+
"semver": "^7.7.1",
|
|
49
|
+
"tar": "^7.4.3",
|
|
50
|
+
"unified": "^11.0.5",
|
|
51
|
+
"unist-util-visit": "^5.0.0"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@types/node": "^22.15.2",
|
|
55
|
+
"@types/semver": "^7.7.0",
|
|
56
|
+
"execa": "^9.5.2",
|
|
57
|
+
"typescript": "^5.8.3",
|
|
58
|
+
"vitest": "^3.1.2"
|
|
59
|
+
}
|
|
60
|
+
}
|