@intra-mart/accel 0.2.0 → 0.3.0-dev.202606150745
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 +148 -4
- package/dist/asset/deployer.js +8 -17
- package/dist/asset/foreach-replacement.d.ts +2 -0
- package/dist/asset/foreach-replacement.js +20 -0
- package/dist/asset/github-provider.d.ts +2 -0
- package/dist/asset/github-provider.js +37 -0
- package/dist/asset/local-provider.js +1 -22
- package/dist/asset/walker.js +4 -15
- package/dist/commands/attach.d.ts +13 -1
- package/dist/commands/attach.js +33 -12
- package/dist/commands/deploy.d.ts +62 -0
- package/dist/commands/deploy.js +293 -0
- package/dist/commands/init.d.ts +13 -1
- package/dist/commands/init.js +33 -12
- package/dist/commands/login.d.ts +31 -0
- package/dist/commands/login.js +75 -0
- package/dist/core/catalog.d.ts +11 -0
- package/dist/core/catalog.js +40 -0
- package/dist/core/condition-evaluator.js +6 -3
- package/dist/core/constants.d.ts +2 -2
- package/dist/core/constants.js +4 -9
- package/dist/core/eval-context.d.ts +3 -0
- package/dist/core/eval-context.js +45 -0
- package/dist/core/types.d.ts +76 -10
- package/dist/core/types.js +2 -1
- package/dist/core/validators.d.ts +7 -2
- package/dist/core/validators.js +25 -12
- package/dist/core/variable-interpolator.d.ts +1 -1
- package/dist/core/variable-interpolator.js +19 -19
- package/dist/deploy/api-client.d.ts +16 -0
- package/dist/deploy/api-client.js +105 -0
- package/dist/deploy/target-scanner.d.ts +5 -0
- package/dist/deploy/target-scanner.js +20 -0
- package/dist/deploy/target-selector.d.ts +11 -0
- package/dist/deploy/target-selector.js +16 -0
- package/dist/i18n/en.js +53 -1
- package/dist/i18n/ja.js +53 -1
- package/dist/i18n/zh_CN.js +53 -1
- package/dist/index.js +4 -0
- package/dist/interactive/credential-auth.d.ts +15 -0
- package/dist/interactive/credential-auth.js +61 -0
- package/dist/interactive/credentials-prompts.d.ts +4 -0
- package/dist/interactive/credentials-prompts.js +85 -0
- package/dist/interactive/prompts.d.ts +3 -0
- package/dist/interactive/prompts.js +125 -26
- package/dist/interactive/summary.js +12 -0
- package/dist/juggling/extractor.d.ts +3 -2
- package/dist/juggling/extractor.js +9 -9
- package/dist/utils/args.d.ts +1 -0
- package/dist/utils/args.js +4 -0
- package/dist/utils/credentials.d.ts +12 -0
- package/dist/utils/credentials.js +46 -0
- package/dist/utils/date-formatter.d.ts +1 -0
- package/dist/utils/date-formatter.js +23 -0
- package/dist/utils/gitignore.d.ts +1 -0
- package/dist/utils/gitignore.js +23 -0
- package/dist/utils/https.d.ts +2 -0
- package/dist/utils/https.js +44 -0
- package/dist/utils/settings-io.d.ts +1 -0
- package/dist/utils/settings-io.js +8 -0
- package/package.json +5 -5
- package/assets/assets.tar.gz +0 -0
- package/dist/asset/default-source.d.ts +0 -1
- package/dist/asset/default-source.js +0 -6
- package/dist/core/module-map.d.ts +0 -3
- package/dist/core/module-map.js +0 -7
- package/dist/core/version-map.d.ts +0 -7
- package/dist/core/version-map.js +0 -45
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ intra-mart Accel Platform (iAP) 開発プロジェクトの作成・管理を行
|
|
|
7
7
|
## 必要環境
|
|
8
8
|
|
|
9
9
|
- 以下のいずれかのパッケージマネージャ(`--package-manager` で選択、デフォルト: Bun)
|
|
10
|
-
- [Bun](https://bun.sh/)
|
|
10
|
+
- [Bun](https://bun.sh/)
|
|
11
11
|
- [npm](https://www.npmjs.com/)
|
|
12
12
|
- [Yarn](https://classic.yarnpkg.com/) (classic v1)
|
|
13
13
|
- [pnpm](https://pnpm.io/)
|
|
@@ -44,6 +44,9 @@ accel init my-project
|
|
|
44
44
|
```bash
|
|
45
45
|
accel init my-project \
|
|
46
46
|
--non-interactive \
|
|
47
|
+
--accelplatform-version 2026-spring \
|
|
48
|
+
--module im_workflow \
|
|
49
|
+
--feature jssp,e2e \
|
|
47
50
|
--agent claude-code \
|
|
48
51
|
--locale ja
|
|
49
52
|
```
|
|
@@ -53,6 +56,9 @@ accel init my-project \
|
|
|
53
56
|
| オプション | 型 | 説明 | デフォルト |
|
|
54
57
|
|---|---|---|---|
|
|
55
58
|
| `[project-name]` (位置引数) | string | プロジェクト名(ディレクトリ名と一致) | `my-accel-project`(対話で変更可) |
|
|
59
|
+
| `--accelplatform-version` | string | iAPバージョン。カタログのリリースID形式(例: `2026-spring`) | 対話で選択 |
|
|
60
|
+
| `--module` | string | 使用モジュール。カタログの `artifactId`(カンマ区切り。例: `im_workflow,im_activiti`) | 対話で選択 |
|
|
61
|
+
| `--feature` | string | 使用機能。カタログの機能ID(カンマ区切り。例: `jssp,e2e`) | 未選択 |
|
|
56
62
|
| `--agent` | string | エージェント種別(`claude-code`, `github-copilot`、カンマ区切り) | 自動検出 |
|
|
57
63
|
| `--locale` | string | ロケール(`ja`, `en`, `zh_CN`) | OS設定から自動検出 |
|
|
58
64
|
| `--artifact-id` | string | アーティファクトID(pomの `artifactId` に相当) | プロジェクト名と同値 |
|
|
@@ -66,6 +72,10 @@ accel init my-project \
|
|
|
66
72
|
| `--non-interactive` | boolean | 非対話モード(このモードでは `project-name` が必須) | `false` |
|
|
67
73
|
| `--no-git-init` | boolean | git initをスキップ | `false`(git initする) |
|
|
68
74
|
| `--skip-install` | boolean | 依存インストールをスキップ | `false` |
|
|
75
|
+
| `--asset-server-url` | string | 資材を取得するGitHubリポジトリのURL(デフォルトProviderの取得先を上書き) | `https://github.com/accelplatform/skills` |
|
|
76
|
+
| `--asset-ref` | string | GitHubから取得するブランチ/タグ/コミット | `experiment` |
|
|
77
|
+
| `--asset-source` | string | (デバッグ用)ローカル資材のパス(tarアーカイブまたは展開済みディレクトリ)。明示時はGitHubより優先 | - |
|
|
78
|
+
| `--debug-server-url` | string | (デバッグ用)ローカル資材サーバーのURL(`GET /archive`)。明示時はGitHubより優先 | - |
|
|
69
79
|
|
|
70
80
|
### `accel attach`
|
|
71
81
|
|
|
@@ -73,7 +83,7 @@ accel init my-project \
|
|
|
73
83
|
|
|
74
84
|
```bash
|
|
75
85
|
cd my-existing-project
|
|
76
|
-
accel attach --non-interactive
|
|
86
|
+
accel attach --non-interactive --accelplatform-version 2026-spring --module im_workflow
|
|
77
87
|
```
|
|
78
88
|
|
|
79
89
|
`init` との違い:
|
|
@@ -89,6 +99,9 @@ accel attach --non-interactive
|
|
|
89
99
|
| オプション | 型 | 説明 | デフォルト |
|
|
90
100
|
|---|---|---|---|
|
|
91
101
|
| `--name` | string | プロジェクト名 | カレントディレクトリ名 |
|
|
102
|
+
| `--accelplatform-version` | string | iAPバージョン。カタログのリリースID形式(例: `2026-spring`) | 対話で選択 |
|
|
103
|
+
| `--module` | string | 使用モジュール。カタログの `artifactId`(カンマ区切り。例: `im_workflow,im_activiti`) | 対話で選択 |
|
|
104
|
+
| `--feature` | string | 使用機能。カタログの機能ID(カンマ区切り。例: `jssp,e2e`) | 未選択 |
|
|
92
105
|
| `--agent` | string | エージェント種別(`claude-code`, `github-copilot`、カンマ区切り) | 自動検出 |
|
|
93
106
|
| `--locale` | string | ロケール(`ja`, `en`, `zh_CN`) | OS設定から自動検出 |
|
|
94
107
|
| `--artifact-id` | string | アーティファクトID(pomの `artifactId` に相当) | プロジェクト名と同値 |
|
|
@@ -102,6 +115,10 @@ accel attach --non-interactive
|
|
|
102
115
|
| `--overwrite` | boolean | 既存ファイルの上書き確認を行わず、全て上書きする | `false`(対話で確認 / 非対話ではスキップ) |
|
|
103
116
|
| `--non-interactive` | boolean | 非対話モード | `false` |
|
|
104
117
|
| `--skip-install` | boolean | 依存インストールをスキップ | `false` |
|
|
118
|
+
| `--asset-server-url` | string | 資材を取得するGitHubリポジトリのURL(デフォルトProviderの取得先を上書き) | `https://github.com/accelplatform/skills` |
|
|
119
|
+
| `--asset-ref` | string | GitHubから取得するブランチ/タグ/コミット | `experiment` |
|
|
120
|
+
| `--asset-source` | string | (デバッグ用)ローカル資材のパス(tarアーカイブまたは展開済みディレクトリ)。明示時はGitHubより優先 | - |
|
|
121
|
+
| `--debug-server-url` | string | (デバッグ用)ローカル資材サーバーのURL(`GET /archive`)。明示時はGitHubより優先 | - |
|
|
105
122
|
|
|
106
123
|
### `accel detach`
|
|
107
124
|
|
|
@@ -116,6 +133,110 @@ accel detach
|
|
|
116
133
|
- ユーザーが編集したファイルはスキップ(警告表示)
|
|
117
134
|
- `.accel/` ディレクトリを削除
|
|
118
135
|
|
|
136
|
+
### `accel login`
|
|
137
|
+
|
|
138
|
+
iAP の接続情報(エンドポイントURL・APIキー)を入力し、`.accel/credentials.json` に保存します。`accel deploy` を実行する前に、コマンドラインから直接接続情報を設定しておけます。
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
cd my-project
|
|
142
|
+
accel login
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
- `endpoint`(テキスト入力)と `apiKey`(マスク入力)を対話で入力します。
|
|
146
|
+
- 入力したトークンの有効性は、トークン検証API(`{endpoint}/oauth/token/verify`)を呼び出して確認します。検証に失敗(401 など)した場合や接続エラーの場合は、その場で再入力を促します。
|
|
147
|
+
- 検証に成功した時点で `.accel/credentials.json` に保存します。**APIキーはシークレットのため、ファイルは自動的に `.gitignore` に追加されます**(コミット対象外)。
|
|
148
|
+
|
|
149
|
+
#### 非対話モード
|
|
150
|
+
|
|
151
|
+
CIでの利用を想定し、プロンプトを出さずに接続情報を検証・保存するモードです。
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
ACCEL_API_KEY=*** accel login \
|
|
155
|
+
--non-interactive \
|
|
156
|
+
--endpoint https://example.com/imart
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
- `endpoint` / `apiKey` は **フラグ > 環境変数 > `.accel/credentials.json`** の優先順位で解決します。
|
|
160
|
+
- `endpoint`: `--endpoint` / `ACCEL_ENDPOINT`
|
|
161
|
+
- `apiKey`: `--api-key` / `ACCEL_API_KEY`
|
|
162
|
+
- **APIキーはシークレット情報のため、CI では `ACCEL_API_KEY` 環境変数での指定を推奨します**(`--api-key` はプロセス一覧やCIログに漏れ得ます)。
|
|
163
|
+
- トークン検証は1回だけ実行します。**失敗時は再入力せず、エラーメッセージを表示して非0終了します**。
|
|
164
|
+
- 検証成功時に `.accel/credentials.json` へ保存します(対話モードと同様、`.gitignore` に自動追記)。
|
|
165
|
+
- `endpoint` / `apiKey` のいずれかが解決できない場合はエラー終了します。
|
|
166
|
+
|
|
167
|
+
#### オプション一覧
|
|
168
|
+
|
|
169
|
+
| オプション | 型 | 説明 | デフォルト |
|
|
170
|
+
|---|---|---|---|
|
|
171
|
+
| `--endpoint` | string | iAPのベースURL(環境変数 `ACCEL_ENDPOINT` でも指定可) | 対話で入力 / 保存値 |
|
|
172
|
+
| `--api-key` | string | OAuth Bearerトークン(**環境変数 `ACCEL_API_KEY` 推奨**) | 対話で入力 / 保存値 |
|
|
173
|
+
| `--non-interactive` | boolean | 非対話モード(プロンプトを出さず、検証失敗時は非0終了) | `false` |
|
|
174
|
+
|
|
175
|
+
### `accel deploy`
|
|
176
|
+
|
|
177
|
+
ビルド成果物(`./target/` 配下の zip)を iAP のステージング環境へデプロイします。対話モードに加え、CIでの利用を想定した非対話モード(`--non-interactive`)に対応します。
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
cd my-project
|
|
181
|
+
accel deploy
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
- プロジェクトのルートで実行します。ビルド成果物は `./target/` 配下に出力されている前提です(`mvn package` で生成される `<artifactId>-<version>.zip`)。
|
|
185
|
+
- 初回実行時に iAP の接続情報(エンドポイントURL・APIキー)の入力を求めます。入力値は `.accel/credentials.json` に保存され、保存値で接続できる限り次回以降は再入力不要です。事前に `accel login`(前述)で設定しておくこともできます。
|
|
186
|
+
- **APIキーはシークレット情報のため、`.accel/credentials.json` は自動的に `.gitignore` に追加されます**(コミット対象外)。
|
|
187
|
+
- デプロイ実行前に、トークン検証API(`/oauth/token/verify`)で接続情報の有効性を確認します。保存済みのエンドポイント/APIキーが誤っていて**接続エラーや認証エラー(401 など)になった場合は、その場で再入力を促し、接続できるまでリトライします**。中断したい場合は ESC / Ctrl+C で抜けられます。
|
|
188
|
+
- 既存のステージング環境を一覧から選択します(ステージングは iAP 側で事前に作成しておく必要があります)。
|
|
189
|
+
- デプロイ対象の zip は、`.accel/settings.json` の `artifactId` と `projectVersion` から `<artifactId>-<projectVersion>.zip` を `./target/` 配下で完全一致で特定し、見つかれば自動選択します。
|
|
190
|
+
- 該当ファイルが見つからない場合、または `.accel/settings.json` が無い場合は、従来通り `./target/` 配下の zip を一覧から選択します(単一なら自動選択)。
|
|
191
|
+
- この選択式の一覧では、`<artifactId>-main-storage.zip` / `<artifactId>-main-public.zip` / `<artifactId>-sample-jssp-internal.zip` のような**バージョンを含まない途中成果物**(`<artifactId>-` の直後が数字で始まらない zip)を除外します。
|
|
192
|
+
- ただし、除外した結果 0 件になった場合(`.accel/settings.json` の `artifactId` と実ファイル名の artifactId が乖離しているケースなど)は、除外せず `./target/` 配下の全 zip を選択候補とします。
|
|
193
|
+
- いずれの場合もデプロイ実行前に最終確認を行います。
|
|
194
|
+
- 送信時、zip は imm 形式としてアップロードされます(送信時のファイル名のみ `.imm` に変更され、ディスク上のファイルはそのままです)。
|
|
195
|
+
|
|
196
|
+
#### 非対話モード
|
|
197
|
+
|
|
198
|
+
CIでの利用を想定し、プロンプトを一切出さずにデプロイを実行するモードです。
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
ACCEL_API_KEY=*** accel deploy \
|
|
202
|
+
--non-interactive \
|
|
203
|
+
--endpoint https://example.com/imart \
|
|
204
|
+
--staging-id my-staging \
|
|
205
|
+
--file ./target/my-app-1.0.0.zip \
|
|
206
|
+
--description "CI deploy"
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
- **接続情報**は login と同じく **フラグ > 環境変数(`ACCEL_ENDPOINT` / `ACCEL_API_KEY`)> `.accel/credentials.json`** の優先順位で解決します(APIキーは `ACCEL_API_KEY` 環境変数での指定を推奨)。
|
|
210
|
+
- デプロイ前にトークン検証を1回だけ実行します。**失敗時は再入力せず、エラーメッセージを表示して非0終了します**。
|
|
211
|
+
- `--staging-id` は**必須**です(一覧選択は行いません。未指定はエラー終了。存在しないステージングはデプロイ時の 404 として表面化します)。
|
|
212
|
+
- デプロイ対象 zip:
|
|
213
|
+
- `--file` を指定した場合はそのパス(`./target/` 配下に限定しません)を使います。ファイルが存在しなければエラー終了します。
|
|
214
|
+
- `--file` 未指定の場合は対話モードと同じ自動特定(`<artifactId>-<projectVersion>.zip` 完全一致)を試みます。**自動特定できない場合**(settings 無し/完全一致無し/複数候補)は `--file` 指定が必要な旨を表示してエラー終了します。`./target/` に zip が 1 件も無い場合は、ビルド未実行の旨(`mvn package` 等の実行を促す)を表示してエラー終了します。
|
|
215
|
+
- `--description` は任意です。最終確認プロンプトは出さず、即デプロイします。
|
|
216
|
+
- フラグ/環境変数で渡した接続情報は **`.accel/credentials.json` に保存しません**(CIランナーにシークレット情報を残さないため)。
|
|
217
|
+
|
|
218
|
+
#### オプション一覧
|
|
219
|
+
|
|
220
|
+
| オプション | 型 | 説明 | デフォルト |
|
|
221
|
+
|---|---|---|---|
|
|
222
|
+
| `--endpoint` | string | iAPのベースURL(環境変数 `ACCEL_ENDPOINT` でも指定可) | 保存値 / 対話で入力 |
|
|
223
|
+
| `--api-key` | string | OAuth Bearerトークン(**環境変数 `ACCEL_API_KEY` 推奨**) | 保存値 / 対話で入力 |
|
|
224
|
+
| `--staging-id` | string | デプロイ先ステージングID(**非対話モードでは必須**) | 対話で一覧選択 |
|
|
225
|
+
| `--file` | string | デプロイする zip のパス(`./target/` 配下に限定しない) | 自動特定 / 対話で選択 |
|
|
226
|
+
| `--description` | string | デプロイメントの説明 | `""` |
|
|
227
|
+
| `--non-interactive` | boolean | 非対話モード(プロンプトを出さず、失敗時は非0終了) | `false` |
|
|
228
|
+
|
|
229
|
+
#### 接続情報ファイル `.accel/credentials.json`
|
|
230
|
+
|
|
231
|
+
```json
|
|
232
|
+
{
|
|
233
|
+
"endpoint": "https://example.com/imart",
|
|
234
|
+
"apiKey": "<OAuth Bearer トークン>"
|
|
235
|
+
}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
`endpoint` には iAP のベースURL を指定します。API パス(`/api/bearer/development/...`)は CLI が組み立てます。
|
|
239
|
+
|
|
119
240
|
## IM-Juggling連携
|
|
120
241
|
|
|
121
242
|
`--juggling-project` オプションでIM-Jugglingプロジェクトのパスを指定すると、`juggling.im` からiAPバージョンと使用モジュールを自動検出します。
|
|
@@ -124,6 +245,12 @@ accel detach
|
|
|
124
245
|
accel init my-project --juggling-project /path/to/juggling-project
|
|
125
246
|
```
|
|
126
247
|
|
|
248
|
+
- iAPバージョンは `juggling.im` のベースバージョンを `@intra-mart/catalog` のリリースと突合して解決します
|
|
249
|
+
- モジュールは選択済みモジュールのIDをカタログのモジュールID(`jp.co.intra_mart.im_workflow` 等)と突合し、一致したものを `artifactId`(`im_workflow` 等)として採用します
|
|
250
|
+
- モジュール自体のバージョンは突合しません(パッチ適用により `8.0.39-PATCH_001` のようにずれることがあるため)
|
|
251
|
+
- カタログに存在しないモジュールは無視されます
|
|
252
|
+
- 機能(`--feature`)は `juggling.im` から検出できないため自動設定されません
|
|
253
|
+
|
|
127
254
|
## プロジェクト構造
|
|
128
255
|
|
|
129
256
|
`accel init` 実行後に生成されるディレクトリ構造:
|
|
@@ -144,8 +271,25 @@ my-project/
|
|
|
144
271
|
|
|
145
272
|
- `.accel/settings.json` — プロジェクト設定。git管理対象、手動編集可
|
|
146
273
|
- `.accel/hashsum.txt` — 配備ファイルのSHA-1。`detach` 時の変更検出に使用
|
|
274
|
+
- `.accel/credentials.json` — iAP接続情報(endpoint / APIキー)。`accel deploy` 初回実行時に生成。APIキーを含むため `.gitignore` 対象(git管理対象外)
|
|
147
275
|
|
|
148
276
|
## 対応iAPバージョン
|
|
149
277
|
|
|
150
|
-
|
|
151
|
-
|
|
278
|
+
選択可能なiAPバージョン・モジュール・機能は、同梱のマスタデータパッケージ `@intra-mart/catalog` のカタログに基づきます(2025 Spring / 8.0.37 以降)。バージョンは `2026-spring` のようなリリースID形式で指定します。新しいリリースへの対応はカタログの更新によって行われます。
|
|
279
|
+
|
|
280
|
+
## 入力値のバリデーション
|
|
281
|
+
|
|
282
|
+
CLIに渡された値および対話で入力された値は、以下のルールでバリデーションされます。違反する値は対話モードでは再入力を促し、非対話モードではエラーメッセージを表示して終了します。
|
|
283
|
+
|
|
284
|
+
| オプション | ルール |
|
|
285
|
+
|-----------|------|
|
|
286
|
+
| `[project-name]` / `--name` | 空文字不可。ディレクトリ名として不正な文字を含まない(`/ \ : * ? " < > \|`、制御文字、先頭末尾の空白/ドット) |
|
|
287
|
+
| `--artifact-id` | Maven artifactId 規約: `^[A-Za-z0-9][A-Za-z0-9._-]*$` |
|
|
288
|
+
| `--group` | Maven groupId 規約: ドット区切りの識別子 `^[A-Za-z_$][\w$]*(\.[A-Za-z_$][\w$]*)*$` |
|
|
289
|
+
| `--project-version` | Maven version 規約: `^[A-Za-z0-9][A-Za-z0-9._-]*$` |
|
|
290
|
+
| `--accelplatform-version` | カタログのリリースID(`2025-spring` 以降)に含まれる値 |
|
|
291
|
+
| `--module` | 選択したiAPリリースのカタログに含まれるモジュールの `artifactId`(例: `im_workflow`, `im_activiti`)のいずれか(各要素) |
|
|
292
|
+
| `--feature` | 選択したiAPリリースのカタログに含まれる機能ID(例: `jssp`, `imds`, `i18n`, `e2e`)のいずれか(各要素) |
|
|
293
|
+
| `--database` | `postgresql`, `oracle`, `sqlserver` のいずれか |
|
|
294
|
+
| `--agent` | `claude-code`, `github-copilot` のいずれか(各要素) |
|
|
295
|
+
| `--package-manager` | `bun`, `npm`, `yarn`, `pnpm` のいずれか |
|
package/dist/asset/deployer.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { readFile, writeFile, mkdir, stat } from "node:fs/promises";
|
|
2
2
|
import { join, dirname, resolve, sep } from "node:path";
|
|
3
|
-
import {
|
|
3
|
+
import { buildEvalContext } from "../core/eval-context.js";
|
|
4
4
|
import { walkAssetRepo } from "./walker.js";
|
|
5
5
|
import { processMarkdown } from "../markdown/processor.js";
|
|
6
6
|
import { applyRegexReplacements } from "./regex-replacement.js";
|
|
7
|
+
import { applyForeachReplacements } from "./foreach-replacement.js";
|
|
7
8
|
import { computeSha1 } from "../utils/hash.js";
|
|
8
9
|
import { writeSettings, writeHashsum } from "../utils/settings-io.js";
|
|
9
10
|
import { execSync } from "node:child_process";
|
|
@@ -57,22 +58,8 @@ export const deployAssets = async (options) => {
|
|
|
57
58
|
try {
|
|
58
59
|
progress?.onFetchStart?.();
|
|
59
60
|
const repoDir = await provider.fetch();
|
|
60
|
-
const semver =
|
|
61
|
-
const context =
|
|
62
|
-
version: semver,
|
|
63
|
-
modules: settings.modules,
|
|
64
|
-
locale: settings.locale,
|
|
65
|
-
agents: settings.agents,
|
|
66
|
-
name: settings.name,
|
|
67
|
-
artifactId: settings.artifactId,
|
|
68
|
-
group: settings.group,
|
|
69
|
-
description: settings.description,
|
|
70
|
-
accelplatformVersion: settings.accelplatformVersion,
|
|
71
|
-
database: settings.database,
|
|
72
|
-
projectVersion: settings.projectVersion,
|
|
73
|
-
packageManager: settings.packageManager,
|
|
74
|
-
javascript: settings.javascript,
|
|
75
|
-
};
|
|
61
|
+
const semver = settings.accelplatformVersion.semver;
|
|
62
|
+
const context = buildEvalContext(settings);
|
|
76
63
|
const entries = await walkAssetRepo(repoDir, semver, context);
|
|
77
64
|
const deployedFiles = [];
|
|
78
65
|
const hashEntries = [];
|
|
@@ -119,6 +106,10 @@ export const deployAssets = async (options) => {
|
|
|
119
106
|
let content = await readFile(entry.sourcePath, "utf-8");
|
|
120
107
|
const replacements = collectReplacements(entry);
|
|
121
108
|
if (replacements.length > 0) {
|
|
109
|
+
const foreachReplacements = replacements.filter((r) => r.type === "foreach");
|
|
110
|
+
if (foreachReplacements.length > 0) {
|
|
111
|
+
content = applyForeachReplacements(content, foreachReplacements, context);
|
|
112
|
+
}
|
|
122
113
|
if (targetPath.endsWith(".md")) {
|
|
123
114
|
content = processMarkdown(content, replacements, context);
|
|
124
115
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { evaluateCondition } from "../core/condition-evaluator.js";
|
|
2
|
+
import { interpolateVariables } from "../core/variable-interpolator.js";
|
|
3
|
+
const DEFAULT_SEPARATOR = "\n";
|
|
4
|
+
const itemVariables = (item) => new Map(Object.entries(item).map(([key, value]) => [`item.${key}`, value]));
|
|
5
|
+
export const applyForeachReplacements = (content, replacements, context) => {
|
|
6
|
+
let result = content;
|
|
7
|
+
for (const replacement of replacements) {
|
|
8
|
+
if (!evaluateCondition(replacement.condition, context)) {
|
|
9
|
+
continue;
|
|
10
|
+
}
|
|
11
|
+
const items = replacement.items === "modules"
|
|
12
|
+
? context.moduleItems
|
|
13
|
+
: context.featureItems;
|
|
14
|
+
const expanded = items
|
|
15
|
+
.map((item) => interpolateVariables(replacement.template, context, itemVariables(item)))
|
|
16
|
+
.join(replacement.separator ?? DEFAULT_SEPARATOR);
|
|
17
|
+
result = result.split(replacement.target).join(expanded);
|
|
18
|
+
}
|
|
19
|
+
return result;
|
|
20
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { mkdir, rm, readdir } from "node:fs/promises";
|
|
3
|
+
import { extractTarGz, createTempDir } from "../utils/archive.js";
|
|
4
|
+
import { downloadFile } from "../utils/https.js";
|
|
5
|
+
export const createGitHubAssetProvider = (repoUrl, ref) => {
|
|
6
|
+
let tmpDir = null;
|
|
7
|
+
return {
|
|
8
|
+
fetch: async () => {
|
|
9
|
+
tmpDir = await createTempDir("accel-assets-");
|
|
10
|
+
const archivePath = join(tmpDir, "assets.tar.gz");
|
|
11
|
+
const extractDir = join(tmpDir, "repo");
|
|
12
|
+
await mkdir(extractDir, { recursive: true });
|
|
13
|
+
const base = repoUrl.replace(/\/+$/, "");
|
|
14
|
+
const archiveUrl = `${base}/archive/${ref}.tar.gz`;
|
|
15
|
+
try {
|
|
16
|
+
await downloadFile(archiveUrl, archivePath);
|
|
17
|
+
}
|
|
18
|
+
catch (err) {
|
|
19
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
20
|
+
throw new Error(`Failed to fetch the asset repository from ${archiveUrl}. Check the URL and ref: ${reason}`);
|
|
21
|
+
}
|
|
22
|
+
await extractTarGz(archivePath, extractDir);
|
|
23
|
+
const entries = await readdir(extractDir, { withFileTypes: true });
|
|
24
|
+
const dirs = entries.filter((e) => e.isDirectory());
|
|
25
|
+
if (dirs.length !== 1) {
|
|
26
|
+
throw new Error(`Unexpected tarball structure (top-level directory count: ${dirs.length}).`);
|
|
27
|
+
}
|
|
28
|
+
return join(extractDir, dirs[0].name);
|
|
29
|
+
},
|
|
30
|
+
cleanup: async () => {
|
|
31
|
+
if (tmpDir) {
|
|
32
|
+
await rm(tmpDir, { recursive: true, force: true }).catch(() => { });
|
|
33
|
+
tmpDir = null;
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
};
|
|
@@ -1,28 +1,7 @@
|
|
|
1
|
-
import { get } from "node:http";
|
|
2
|
-
import { createWriteStream } from "node:fs";
|
|
3
1
|
import { join } from "node:path";
|
|
4
2
|
import { mkdir, rm } from "node:fs/promises";
|
|
5
3
|
import { extractTarGz, createTempDir } from "../utils/archive.js";
|
|
6
|
-
|
|
7
|
-
return new Promise((resolve, reject) => {
|
|
8
|
-
const file = createWriteStream(destPath);
|
|
9
|
-
get(url, (response) => {
|
|
10
|
-
if (response.statusCode !== 200) {
|
|
11
|
-
file.close();
|
|
12
|
-
reject(new Error(`HTTP ${response.statusCode} when downloading from ${url}`));
|
|
13
|
-
return;
|
|
14
|
-
}
|
|
15
|
-
response.pipe(file);
|
|
16
|
-
file.on("finish", () => {
|
|
17
|
-
file.close();
|
|
18
|
-
resolve();
|
|
19
|
-
});
|
|
20
|
-
}).on("error", (err) => {
|
|
21
|
-
file.close();
|
|
22
|
-
reject(err);
|
|
23
|
-
});
|
|
24
|
-
});
|
|
25
|
-
};
|
|
4
|
+
import { downloadFile } from "../utils/https.js";
|
|
26
5
|
export const createLocalAssetProvider = (serverUrl) => {
|
|
27
6
|
let tmpDir = null;
|
|
28
7
|
return {
|
package/dist/asset/walker.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { readdir, readFile } from "node:fs/promises";
|
|
2
2
|
import { join, relative, dirname, sep } from "node:path";
|
|
3
3
|
import { evaluateCondition } from "../core/condition-evaluator.js";
|
|
4
|
+
import { emptyEvalContext } from "../core/eval-context.js";
|
|
4
5
|
const toPosixPath = (p) => sep === "/" ? p : p.split(sep).join("/");
|
|
5
6
|
const META_FILE = "_meta.json";
|
|
6
7
|
const readMetaJson = async (dir) => {
|
|
@@ -41,21 +42,9 @@ const findMatchingVersionDirs = async (repoDir, targetSemver) => {
|
|
|
41
42
|
continue;
|
|
42
43
|
}
|
|
43
44
|
if (meta.conditions) {
|
|
44
|
-
const context = {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
locale: "",
|
|
48
|
-
agents: [],
|
|
49
|
-
name: "",
|
|
50
|
-
artifactId: "",
|
|
51
|
-
group: "",
|
|
52
|
-
description: "",
|
|
53
|
-
accelplatformVersion: "",
|
|
54
|
-
database: "",
|
|
55
|
-
projectVersion: "",
|
|
56
|
-
packageManager: "",
|
|
57
|
-
javascript: false,
|
|
58
|
-
};
|
|
45
|
+
const context = emptyEvalContext({
|
|
46
|
+
accelplatformVersion: { label: "", semver: targetSemver },
|
|
47
|
+
});
|
|
59
48
|
if (evaluateCondition(meta.conditions, context)) {
|
|
60
49
|
matched.push(dirPath);
|
|
61
50
|
}
|
|
@@ -11,6 +11,10 @@ export declare const attachCommand: import("citty").CommandDef<{
|
|
|
11
11
|
type: "string";
|
|
12
12
|
description: string;
|
|
13
13
|
};
|
|
14
|
+
feature: {
|
|
15
|
+
type: "string";
|
|
16
|
+
description: string;
|
|
17
|
+
};
|
|
14
18
|
name: {
|
|
15
19
|
type: "string";
|
|
16
20
|
description: string;
|
|
@@ -66,11 +70,19 @@ export declare const attachCommand: import("citty").CommandDef<{
|
|
|
66
70
|
description: string;
|
|
67
71
|
default: false;
|
|
68
72
|
};
|
|
73
|
+
"asset-server-url": {
|
|
74
|
+
type: "string";
|
|
75
|
+
description: string;
|
|
76
|
+
};
|
|
77
|
+
"asset-ref": {
|
|
78
|
+
type: "string";
|
|
79
|
+
description: string;
|
|
80
|
+
};
|
|
69
81
|
"asset-source": {
|
|
70
82
|
type: "string";
|
|
71
83
|
description: string;
|
|
72
84
|
};
|
|
73
|
-
"
|
|
85
|
+
"debug-server-url": {
|
|
74
86
|
type: "string";
|
|
75
87
|
description: string;
|
|
76
88
|
};
|
package/dist/commands/attach.js
CHANGED
|
@@ -2,12 +2,12 @@ import { defineCommand } from "citty";
|
|
|
2
2
|
import * as p from "@clack/prompts";
|
|
3
3
|
import { stat } from "node:fs/promises";
|
|
4
4
|
import { basename, join } from "node:path";
|
|
5
|
-
import { CLI_VERSION } from "../core/constants.js";
|
|
5
|
+
import { CLI_VERSION, DEFAULT_ASSET_REPO_URL, DEFAULT_ASSET_REF, } from "../core/constants.js";
|
|
6
6
|
import { runPrompts } from "../interactive/prompts.js";
|
|
7
7
|
import { deployAssets, } from "../asset/deployer.js";
|
|
8
8
|
import { createLocalAssetProvider } from "../asset/local-provider.js";
|
|
9
9
|
import { createFileAssetProvider } from "../asset/file-provider.js";
|
|
10
|
-
import {
|
|
10
|
+
import { createGitHubAssetProvider } from "../asset/github-provider.js";
|
|
11
11
|
import { getMessage } from "../i18n/index.js";
|
|
12
12
|
import { detectLocale } from "../utils/locale-detect.js";
|
|
13
13
|
import { printSummary } from "../interactive/summary.js";
|
|
@@ -25,11 +25,15 @@ export const attachCommand = defineCommand({
|
|
|
25
25
|
},
|
|
26
26
|
"accelplatform-version": {
|
|
27
27
|
type: "string",
|
|
28
|
-
description: "iAP version (e.g., 2026-
|
|
28
|
+
description: "iAP version (e.g., 2026-spring)",
|
|
29
29
|
},
|
|
30
30
|
module: {
|
|
31
31
|
type: "string",
|
|
32
|
-
description: "Modules to use (comma-separated)",
|
|
32
|
+
description: "Modules to use (comma-separated artifactIds, e.g., im_workflow)",
|
|
33
|
+
},
|
|
34
|
+
feature: {
|
|
35
|
+
type: "string",
|
|
36
|
+
description: "Features to use (comma-separated function ids, e.g., jssp)",
|
|
33
37
|
},
|
|
34
38
|
name: {
|
|
35
39
|
type: "string",
|
|
@@ -86,13 +90,21 @@ export const attachCommand = defineCommand({
|
|
|
86
90
|
description: "Non-interactive mode",
|
|
87
91
|
default: false,
|
|
88
92
|
},
|
|
93
|
+
"asset-server-url": {
|
|
94
|
+
type: "string",
|
|
95
|
+
description: "GitHub repository URL to fetch assets from (overrides the default repository)",
|
|
96
|
+
},
|
|
97
|
+
"asset-ref": {
|
|
98
|
+
type: "string",
|
|
99
|
+
description: "Git ref (branch/tag/commit) to fetch from the GitHub asset repository. Default: master",
|
|
100
|
+
},
|
|
89
101
|
"asset-source": {
|
|
90
102
|
type: "string",
|
|
91
|
-
description: "Local asset source path (tar archive or extracted directory)
|
|
103
|
+
description: "(debug) Local asset source path (tar archive or extracted directory)",
|
|
92
104
|
},
|
|
93
|
-
"
|
|
105
|
+
"debug-server-url": {
|
|
94
106
|
type: "string",
|
|
95
|
-
description: "
|
|
107
|
+
description: "(debug) Local asset server URL serving GET /archive",
|
|
96
108
|
},
|
|
97
109
|
},
|
|
98
110
|
run: async ({ args }) => {
|
|
@@ -109,6 +121,10 @@ export const attachCommand = defineCommand({
|
|
|
109
121
|
const modules = moduleArg
|
|
110
122
|
? moduleArg.split(",").map((m) => m.trim())
|
|
111
123
|
: undefined;
|
|
124
|
+
const featureArg = args.feature;
|
|
125
|
+
const features = featureArg
|
|
126
|
+
? featureArg.split(",").map((f) => f.trim())
|
|
127
|
+
: undefined;
|
|
112
128
|
const agentArg = args.agent;
|
|
113
129
|
const promptOpts = {
|
|
114
130
|
name: args.name ?? basename(projectDir),
|
|
@@ -116,6 +132,7 @@ export const attachCommand = defineCommand({
|
|
|
116
132
|
jugglingProject: args["juggling-project"],
|
|
117
133
|
accelplatformVersion: args["accelplatform-version"],
|
|
118
134
|
module: modules,
|
|
135
|
+
feature: features,
|
|
119
136
|
group: args.group,
|
|
120
137
|
projectVersion: args["project-version"],
|
|
121
138
|
description: args.description,
|
|
@@ -147,6 +164,7 @@ export const attachCommand = defineCommand({
|
|
|
147
164
|
description: resolved.description,
|
|
148
165
|
accelplatformVersion: resolved.accelplatformVersion,
|
|
149
166
|
modules: resolved.modules,
|
|
167
|
+
features: resolved.features,
|
|
150
168
|
database: resolved.database,
|
|
151
169
|
agents: resolved.agents,
|
|
152
170
|
javascript: resolved.javascript,
|
|
@@ -155,11 +173,14 @@ export const attachCommand = defineCommand({
|
|
|
155
173
|
jugglingProject: resolved.jugglingProject,
|
|
156
174
|
deployedAssets: {},
|
|
157
175
|
};
|
|
158
|
-
const
|
|
159
|
-
const
|
|
160
|
-
const provider =
|
|
161
|
-
?
|
|
162
|
-
:
|
|
176
|
+
const assetSource = args["asset-source"];
|
|
177
|
+
const debugServerUrl = args["debug-server-url"];
|
|
178
|
+
const provider = assetSource
|
|
179
|
+
? createFileAssetProvider(assetSource)
|
|
180
|
+
: debugServerUrl
|
|
181
|
+
? createLocalAssetProvider(debugServerUrl)
|
|
182
|
+
: createGitHubAssetProvider(args["asset-server-url"] ??
|
|
183
|
+
DEFAULT_ASSET_REPO_URL, args["asset-ref"] ?? DEFAULT_ASSET_REF);
|
|
163
184
|
const isInteractive = !args["non-interactive"];
|
|
164
185
|
const overwriteFlag = args.overwrite;
|
|
165
186
|
if (isInteractive) {
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { AccelCredentials, StagingResponse } from "../core/types.js";
|
|
2
|
+
import { type ApiClient } from "../deploy/api-client.js";
|
|
3
|
+
export declare const toImmFileName: (zipPath: string) => string;
|
|
4
|
+
type ConfirmInfo = {
|
|
5
|
+
endpoint: string;
|
|
6
|
+
stagingId: string;
|
|
7
|
+
sourceFile: string;
|
|
8
|
+
sentAs: string;
|
|
9
|
+
};
|
|
10
|
+
export type DeployPrompts = {
|
|
11
|
+
selectStaging: (stagings: StagingResponse[], locale: string) => Promise<string>;
|
|
12
|
+
selectZip: (zips: string[], locale: string) => Promise<string>;
|
|
13
|
+
description: (locale: string) => Promise<string>;
|
|
14
|
+
confirm: (info: ConfirmInfo, locale: string) => Promise<boolean>;
|
|
15
|
+
};
|
|
16
|
+
export type RunDeployDeps = {
|
|
17
|
+
projectDir: string;
|
|
18
|
+
locale?: string;
|
|
19
|
+
nonInteractive?: boolean;
|
|
20
|
+
endpoint?: string;
|
|
21
|
+
apiKey?: string;
|
|
22
|
+
stagingId?: string;
|
|
23
|
+
file?: string;
|
|
24
|
+
description?: string;
|
|
25
|
+
env?: Record<string, string | undefined>;
|
|
26
|
+
ensureCredentials?: (projectDir: string, locale: string, seed?: Partial<AccelCredentials>) => Promise<AccelCredentials>;
|
|
27
|
+
repromptCredentials?: (current: AccelCredentials, locale: string) => Promise<AccelCredentials>;
|
|
28
|
+
resolveCredentialsOrThrow?: (projectDir: string, locale: string, seed: Partial<AccelCredentials>) => Promise<AccelCredentials>;
|
|
29
|
+
persistCredentials?: (projectDir: string, creds: AccelCredentials) => Promise<void>;
|
|
30
|
+
scanTargets?: (projectDir: string) => Promise<string[]>;
|
|
31
|
+
apiClientFactory?: (endpoint: string, apiKey: string) => ApiClient;
|
|
32
|
+
prompts?: DeployPrompts;
|
|
33
|
+
};
|
|
34
|
+
export declare const runDeploy: (deps: RunDeployDeps) => Promise<void>;
|
|
35
|
+
export declare const deployCommand: import("citty").CommandDef<{
|
|
36
|
+
endpoint: {
|
|
37
|
+
type: "string";
|
|
38
|
+
description: string;
|
|
39
|
+
};
|
|
40
|
+
"api-key": {
|
|
41
|
+
type: "string";
|
|
42
|
+
description: string;
|
|
43
|
+
};
|
|
44
|
+
"staging-id": {
|
|
45
|
+
type: "string";
|
|
46
|
+
description: string;
|
|
47
|
+
};
|
|
48
|
+
file: {
|
|
49
|
+
type: "string";
|
|
50
|
+
description: string;
|
|
51
|
+
};
|
|
52
|
+
description: {
|
|
53
|
+
type: "string";
|
|
54
|
+
description: string;
|
|
55
|
+
};
|
|
56
|
+
"non-interactive": {
|
|
57
|
+
type: "boolean";
|
|
58
|
+
description: string;
|
|
59
|
+
default: false;
|
|
60
|
+
};
|
|
61
|
+
}>;
|
|
62
|
+
export {};
|