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
3 changes: 3 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,6 @@

# Shared
yarn.lock @zendesk/wattle @zendesk/vikings

# Connectors
/packages/zcli-connectors/ @zendesk/vegemite
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@
"standard": "^17.0.0",
"ts-node": "^10.9.1",
"typescript": "~4.7.4",
"yarn-audit-fix": "^10.1.1"
"yarn-audit-fix": "^10.1.1",
"@types/sinon-chai": "^4.0.0"
},
"engines": {
"node": ">=20.17.0"
Expand Down
8 changes: 8 additions & 0 deletions packages/zcli-connectors/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Change Log

All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.

# [1.0.0-beta.1](https://github.com/zendesk/zcli/compare/v1.0.0-beta.0...v1.0.0-beta.1) (2026-01-12)

**Note:** Initial version for zcli-connectors package
5 changes: 5 additions & 0 deletions packages/zcli-connectors/bin/run
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env node

const oclif = require('@oclif/core')

oclif.run().catch(require('@oclif/core/handle'))
3 changes: 3 additions & 0 deletions packages/zcli-connectors/bin/run.cmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@echo off

node "%~dp0\run" %*
69 changes: 69 additions & 0 deletions packages/zcli-connectors/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
{
"name": "@zendesk/zcli-connectors",
"description": "zcli connectors commands live here",
"version": "1.0.0-beta.1",
"author": "@vegemite",
"npmRegistry": "https://registry.npmjs.org",
"publishConfig": {
"access": "public"
},
"bin": {
"zcli-connectors": "./bin/run"
},
"scripts": {
"build": "tsc",
"prepack": "tsc && ../../scripts/prepack.sh",
"postpack": "rm -f oclif.manifest.json npm-shrinkwrap.json && rm -rf ./dist && git checkout ./package.json",
"type:check": "tsc"
},
"dependencies": {
"adm-zip": "0.5.10",
"archiver": "^5.3.1",
"axios": "^1.7.5",
"chalk": "^4.1.2",
"fs-extra": "^10.0.0",
"rimraf": "^3.0.2",
"tslib": "^2.4.0",
"@rollup/plugin-babel": "^6.0.0",
"@rollup/plugin-commonjs": "^25.0.0",
"@rollup/plugin-node-resolve": "^15.0.0",
"vite": "^7.1.3"
},
"devDependencies": {
"@oclif/test": "=2.1.0",
"@types/adm-zip": "^0.5.5",
"@types/archiver": "^5.3.1",
"@types/chai": "^4",
"@types/mocha": "^9.1.1",
"@types/rimraf": "^3.0.2",
"@types/sinon-chai": "^4.0.0",
"chai": "^4",
"eslint": "^8.18.0",
"eslint-config-oclif": "^4.0.0",
"eslint-config-oclif-typescript": "^1.0.2",
"lerna": "^5.6.2",
"mocha": "^10.8.2",
"sinon": "^14.0.0",
"sinon-chai": "^4.0.1",
"ora": "^5.4.1"
},
"files": [
"/bin",
"/dist",
"/oclif.manifest.json",
"/npm-shrinkwrap.json"
],
"keywords": [
"zcli",
"zendesk",
"cli",
"command"
],
"license": "MIT",
"main": "src/index.js",
"oclif": {
"commands": "./src/commands",
"bin": "zcli-connectors"
},
"types": "lib/index.d.ts"
}
164 changes: 164 additions & 0 deletions packages/zcli-connectors/src/commands/connectors/bundle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
import { Command, Flags } from '@oclif/core'
import { existsSync, mkdirSync } from 'fs'
import { join, resolve } from 'path'
import * as chalk from 'chalk'
import { ViteConfigBuilder, ViteRunner } from '../../lib/vite'
import * as ora from 'ora'

export default class Bundle extends Command {
static examples = [
'<%= config.bin %> <%= command.id %> ./example-connector',
'<%= config.bin %> <%= command.id %> ./example-connector --output ./bundled',
'<%= config.bin %> <%= command.id %> --input ./src --output ./bundle'
]

static flags = {
help: Flags.help({ char: 'h' }),
input: Flags.string({
char: 'i',
description: 'input directory containing connector source files',
default: '.'
}),
output: Flags.string({
char: 'o',
description: 'output directory for bundled files'
}),
verbose: Flags.boolean({
char: 'v',
description: 'verbose output',
default: false
}),
watch: Flags.boolean({
char: 'w',
description: 'watch for changes and rebuild',
default: false
})
}

static args = [
{
name: 'path',
description: 'path to connector directory (will use src/ folder inside)'
}
]

async run (): Promise<void> {
const { args, flags } = await this.parse(Bundle)

let inputPath: string
if (args.path) {
inputPath = resolve(join(args.path, 'src'))
} else {
inputPath = resolve(flags.input)
}

const outputPath = flags.output ? resolve(flags.output) : resolve('dist')
if (!existsSync(outputPath)) {
mkdirSync(outputPath, { recursive: true })
if (flags.verbose) {
this.log(chalk.cyan(`Created output directory: ${outputPath}`))
}
}

if (flags.verbose) {
this.log(chalk.cyan('Verbose mode enabled'))
this.log(chalk.cyan(`Resolved Input path: ${inputPath}`))
this.log(chalk.cyan(`Resolved Output path: ${outputPath}`))
this.log(chalk.cyan(`Watch mode: ${flags.watch ? 'enabled' : 'disabled'}`))
}

const spinner = ora(
`Bundling connector from ${inputPath} to ${outputPath}...`
).start()

try {
await this.generateViteBundle(inputPath, outputPath, flags, spinner)

if (flags.watch) {
spinner.succeed(
chalk.green('Watching for changes... (Press Ctrl+C to stop)')
)
} else {
spinner.succeed(chalk.green('Bundle created successfully!'))
}
} catch (error) {
spinner.fail(chalk.red('Failed to bundle the connector'))

const errorMessage = (error instanceof Error) ? error.message : String(error)
if (flags.verbose) {
this.log('\n' + chalk.red('Error Details:'))
this.log(errorMessage)
}

this.error(errorMessage, { exit: 1 })
}
}

private async generateViteBundle (
inputPath: string,
outputPath: string,
flags: { watch: boolean; verbose: boolean },
spinner: ora.Ora
): Promise<void> {
const { watch, verbose } = flags

if (verbose) {
this.log(chalk.cyan('Creating Vite configuration...'))
}

const viteConfig = ViteConfigBuilder.createConfig(
{
inputPath,
outputPath,
watch
}
)

if (verbose) {
spinner.stop()
this.log(chalk.cyan('Vite configuration created successfully'))
this.log(chalk.cyan('Starting build process...'))
spinner.start()
}

spinner.text = watch
? 'Building connector and watching for changes...'
: 'Building connector...'
const stats = await ViteRunner.run(viteConfig)

if (stats.hasErrors()) {
spinner.fail(chalk.red('Bundle failed with errors!'))

const errors = stats.toJson().errors || []
this.log(chalk.cyan(`Found ${errors.length} error(s)`))
errors.forEach((error: any) => {
this.log(chalk.red(`Error: ${error.message}`))
})

throw new Error('Connector build failed')
}

if (verbose) {
const buildInfo = stats.toJson()
if (buildInfo.assets && buildInfo.assets.length > 0) {
this.log(chalk.cyan(`Generated ${buildInfo.assets.length} asset(s)`))
buildInfo.assets.forEach((asset: any) => {
this.log(chalk.cyan(` - ${asset.name} (${(asset.size / 1024).toFixed(2)} KB)`))
})
}
}

if (stats.hasWarnings()) {
const warnings = stats.toJson().warnings || []
if (verbose) {
this.log(chalk.cyan(`Found ${warnings.length} warning(s)`))
}
this.log(chalk.yellow('\nWarnings:'))
warnings.forEach((warning: any) => {
this.log(chalk.yellow(` - ${warning.message}`))
})
} else if (verbose) {
this.log(chalk.cyan('No warnings found'))
}
}
}
1 change: 1 addition & 0 deletions packages/zcli-connectors/src/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const DEFAULT_CONNECTORS_CONFIG_FILE = 'zcli.connectors.config.json'
1 change: 1 addition & 0 deletions packages/zcli-connectors/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default {}
Loading
Loading