Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/).

## [Unreleased]

## [0.5.8] - 2026-02-02

### Added

- `plugin init` 命令现在会自动从用户会话中获取 `organizationId` 并写入 `.env` 文件
- 插件模板新增 `lang` 属性配置
- 新增 `.env.eta` 模板,包含 `HUB_WS_URL` 默认值

### Changed

- 环境变量重命名:
- `DEBUG_API_KEY` → `HUB_DEBUG_API_KEY`
- `ORGANIZATION_ID` → `HUB_ORGANIZATION_ID`

### Breaking Changes

- 环境变量名称已更改,使用旧版本创建的插件需要手动更新 `.env` 文件中的变量名

## [0.5.7] - 2026-01-21

### Added
Expand Down Expand Up @@ -193,7 +211,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
- Code quality checks with Biome.
- Automated release workflow via GitHub Actions.

[Unreleased]: https://github.com/choice-open/atomemo-plugin-cli/compare/v0.5.7...HEAD
[Unreleased]: https://github.com/choice-open/atomemo-plugin-cli/compare/v0.5.8...HEAD
[0.5.8]: https://github.com/choice-open/atomemo-plugin-cli/compare/v0.5.7...v0.5.8
[0.5.7]: https://github.com/choice-open/atomemo-plugin-cli/compare/v0.5.6...v0.5.7
[0.5.6]: https://github.com/choice-open/atomemo-plugin-cli/compare/v0.5.5...v0.5.6
[0.5.5]: https://github.com/choice-open/atomemo-plugin-cli/compare/v0.5.4...v0.5.5
Expand Down
189 changes: 189 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,52 @@ USAGE
* [`atomemo help [COMMAND]`](#atomemo-help-command)
* [`atomemo version`](#atomemo-version)

## `atomemo auth login`

Uses device authorization flow to login with your Choiceform account by following these steps:

```
USAGE
$ atomemo auth login

DESCRIPTION
Uses device authorization flow to login with your Choiceform account by following these steps:

1. Request a validation code automatically
2. Show the validation code and a verification URL to the user
3. Open the verification URL in the user's browser and paste the verification code
4. Submit the validation code to complete the device authorization flow

EXAMPLES
Login by using device authorization flow

$ atomemo auth login
```

_See code: [src/commands/auth/login.ts](https://github.com/choice-open/atomemo-plugin-cli/blob/v0.5.8/src/commands/auth/login.ts)_

## `atomemo auth status`

Display the current authentication status.

```
USAGE
$ atomemo auth status

DESCRIPTION
Display the current authentication status.

Shows user information and session details if authenticated,
or prompts to login if not yet authenticated.

EXAMPLES
Check current authentication status

$ atomemo auth status
```

_See code: [src/commands/auth/status.ts](https://github.com/choice-open/atomemo-plugin-cli/blob/v0.5.8/src/commands/auth/status.ts)_

## `atomemo autocomplete [SHELL]`

Display autocomplete installation instructions.
Expand Down Expand Up @@ -119,6 +165,149 @@ DESCRIPTION

_See code: [@oclif/plugin-help](https://github.com/oclif/plugin-help/blob/v6.2.36/src/commands/help.ts)_

## `atomemo plugin checksum [FILE]`

describe the command here

```
USAGE
$ atomemo plugin checksum [FILE] [-f] [-n <value>]

ARGUMENTS
[FILE] file to read

FLAGS
-f, --force
-n, --name=<value> name to print

DESCRIPTION
describe the command here

EXAMPLES
$ atomemo plugin checksum
```

_See code: [src/commands/plugin/checksum.ts](https://github.com/choice-open/atomemo-plugin-cli/blob/v0.5.8/src/commands/plugin/checksum.ts)_

## `atomemo plugin init`

Initialize a new plugin with step-by-step interactive instructions.

```
USAGE
$ atomemo plugin init [-i] [-n my-awesome-plugin] [-d Descriptive text...]
[-u <value>] [-l elixir|python|typescript]

FLAGS
-d, --description=Descriptive text... Short description
-i, --[no-]interactive Use interactive mode (by default)
-l, --language=<option> Programming language to use for plugin development
<options: elixir|python|typescript>
-n, --name=my-awesome-plugin Plugin name
-u, --url=<value> Repository URL

DESCRIPTION
Initialize a new plugin with step-by-step interactive instructions.

Providing required flags skips interactive flow and completes initialization in one go.

EXAMPLES
Start with interactive initialization:

$ atomemo plugin init
```

_See code: [src/commands/plugin/init.ts](https://github.com/choice-open/atomemo-plugin-cli/blob/v0.5.8/src/commands/plugin/init.ts)_

## `atomemo plugin pack [FILE]`

describe the command here

```
USAGE
$ atomemo plugin pack [FILE] [-f] [-n <value>]

ARGUMENTS
[FILE] file to read

FLAGS
-f, --force
-n, --name=<value> name to print

DESCRIPTION
describe the command here

EXAMPLES
$ atomemo plugin pack
```

_See code: [src/commands/plugin/pack.ts](https://github.com/choice-open/atomemo-plugin-cli/blob/v0.5.8/src/commands/plugin/pack.ts)_

## `atomemo plugin permission [FILE]`

describe the command here

```
USAGE
$ atomemo plugin permission [FILE] [-f] [-n <value>]

ARGUMENTS
[FILE] file to read

FLAGS
-f, --force
-n, --name=<value> name to print

DESCRIPTION
describe the command here

EXAMPLES
$ atomemo plugin permission
```

_See code: [src/commands/plugin/permission.ts](https://github.com/choice-open/atomemo-plugin-cli/blob/v0.5.8/src/commands/plugin/permission.ts)_

## `atomemo plugin refresh-key`

Refresh or create API Key for plugin debugging in development stage.

```
USAGE
$ atomemo plugin refresh-key

DESCRIPTION
Refresh or create API Key for plugin debugging in development stage.

EXAMPLES
$ atomemo plugin refresh-key
```

_See code: [src/commands/plugin/refresh-key.ts](https://github.com/choice-open/atomemo-plugin-cli/blob/v0.5.8/src/commands/plugin/refresh-key.ts)_

## `atomemo plugin run [FILE]`

describe the command here

```
USAGE
$ atomemo plugin run [FILE] [-f] [-n <value>]

ARGUMENTS
[FILE] file to read

FLAGS
-f, --force
-n, --name=<value> name to print

DESCRIPTION
describe the command here

EXAMPLES
$ atomemo plugin run
```

_See code: [src/commands/plugin/run.ts](https://github.com/choice-open/atomemo-plugin-cli/blob/v0.5.8/src/commands/plugin/run.ts)_

## `atomemo version`

```
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@choiceopen/atomemo-plugin-cli",
"version": "0.5.7",
"version": "0.5.8",
"description": "A command-line utility for building and publishing Choiceform Atomemo Plugin.",
"keywords": [
"oclif"
Expand Down
5 changes: 5 additions & 0 deletions src/commands/plugin/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,12 @@ export default class PluginInit extends Command {
// Fetch user session to get author and email
let author = ""
let email = ""
let organizationId = ""
try {
const session = await this.fetchSession()
author = session.user.name
email = session.user.email
organizationId = session.user.inherentOrganizationId
} catch (error) {
const message = error instanceof Error ? error.message : "Unknown error"
this.log(
Expand All @@ -116,6 +118,7 @@ export default class PluginInit extends Command {
...flags,
author,
email,
organizationId,
createdAt: new Date().toISOString(),
date: new Date().toISOString().slice(0, 10),
year: new Date().getFullYear().toString(),
Expand Down Expand Up @@ -288,6 +291,7 @@ export default class PluginInit extends Command {
user: {
name: string
email: string
inherentOrganizationId: string
}
session: {
updatedAt: string
Expand Down Expand Up @@ -328,6 +332,7 @@ export default class PluginInit extends Command {
user: {
name: string
email: string
inherentOrganizationId: string
}
session: {
updatedAt: string
Expand Down
25 changes: 13 additions & 12 deletions src/commands/plugin/refresh-key.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,13 @@ export default class PluginRefreshKey extends Command {
const apiKey = await this.fetchDebugApiKey(config.auth.access_token)

// Step 5: Manage .env file
assert(config.hub?.endpoint, "Hub endpoint is required")
await this.updateEnvFile(apiKey, session.user.inherentOrganizationId)

// Display success message
this.log(colorize("green", "✓ Debug API Key refreshed successfully"))
this.log(colorize("green", "✓ DEBUG_API_KEY updated in .env file"))
this.log(colorize("green", "✓ ORGANIZATION_ID updated in .env file"))
this.log(colorize("green", "✓ HUB_DEBUG_API_KEY updated in .env file"))
this.log(colorize("green", "✓ HUB_ORGANIZATION_ID updated in .env file"))
this.log("")
this.log("Your debug API Key has been saved to .env file.")
this.log(`Key preview: ${this.maskApiKey(apiKey)}`)
Expand Down Expand Up @@ -145,34 +146,34 @@ export default class PluginRefreshKey extends Command {

try {
envContent = await fs.readFile(envPath, "utf-8")
existingApiKey = envContent.includes("DEBUG_API_KEY=")
existingOrgId = envContent.includes("ORGANIZATION_ID=")
existingApiKey = envContent.includes("HUB_DEBUG_API_KEY=")
existingOrgId = envContent.includes("HUB_ORGANIZATION_ID=")
} catch (_error) {
// File doesn't exist, will create new file
}

let newContent: string = envContent

// Update or add DEBUG_API_KEY
// Update or add HUB_DEBUG_API_KEY
if (existingApiKey) {
newContent = newContent.replace(
/^DEBUG_API_KEY=.*$/m,
`DEBUG_API_KEY=${apiKey}`,
/^HUB_DEBUG_API_KEY=.*$/m,
`HUB_DEBUG_API_KEY=${apiKey}`,
)
} else {
const separator = newContent && !newContent.endsWith("\n") ? "\n" : ""
newContent = `${newContent + separator}DEBUG_API_KEY=${apiKey}\n`
newContent = `${newContent + separator}HUB_DEBUG_API_KEY=${apiKey}\n`
}

// Update or add ORGANIZATION_ID
// Update or add HUB_ORGANIZATION_ID
if (existingOrgId) {
newContent = newContent.replace(
/^ORGANIZATION_ID=.*$/m,
`ORGANIZATION_ID=${organizationId}`,
/^HUB_ORGANIZATION_ID=.*$/m,
`HUB_ORGANIZATION_ID=${organizationId}`,
)
} else {
const separator = newContent && !newContent.endsWith("\n") ? "\n" : ""
newContent = `${newContent + separator}ORGANIZATION_ID=${organizationId}\n`
newContent = `${newContent + separator}HUB_ORGANIZATION_ID=${organizationId}\n`
}

await fs.writeFile(envPath, newContent, "utf-8")
Expand Down
2 changes: 0 additions & 2 deletions src/templates/common/.env

This file was deleted.

3 changes: 3 additions & 0 deletions src/templates/common/.env.eta
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
HUB_ORGANIZATION_ID=<%= props.organizationId %>
HUB_WS_URL=wss://automation-plugin-api.choiceform.io
HUB_DEBUG_API_KEY=
1 change: 1 addition & 0 deletions src/templates/typescript/src/index.ts.eta
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const plugin = await createPlugin({
display_name: t("PLUGIN_DISPLAY_NAME"),
description: t("PLUGIN_DESCRIPTION"),
icon: "🎛️",
lang: "<%= props.language %>",
version: packageJSON.version,
repo: "<%= props.url %>",
locales,
Expand Down
Loading