diff --git a/.eslintrc.js b/.eslintrc.cjs similarity index 100% rename from .eslintrc.js rename to .eslintrc.cjs diff --git a/.github/workflows/npm.yml b/.github/workflows/npm.yml index 613d101..905f1a2 100644 --- a/.github/workflows/npm.yml +++ b/.github/workflows/npm.yml @@ -7,8 +7,10 @@ jobs: name: Build strategy: matrix: - os: [ubuntu-latest] - node: [12] + os: + - ubuntu-latest + node-version: + - 16 runs-on: ${{ matrix.os }} steps: @@ -17,6 +19,8 @@ jobs: uses: actions/setup-node@v1 with: node-version: ${{ matrix.node-version }} + cache: npm + cache-dependency-path: package.json - name: Install Dependencies run: npm install @@ -34,9 +38,11 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - uses: actions/setup-node@v1 + - uses: actions/setup-node@v2 with: - node-version: 12 + node-version: 16 + cache: npm + cache-dependency-path: package.json - name: Install Dependencies run: npm install @@ -56,10 +62,12 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - uses: actions/setup-node@v1 + - uses: actions/setup-node@v2 with: - node-version: 12 + node-version: 16 registry-url: https://registry.npmjs.org/ + cache: npm + cache-dependency-path: package.json - name: Install Dependencies run: npm install diff --git a/README.md b/README.md index 3b11a7d..00a2885 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ [![NPM Version](https://img.shields.io/npm/v/wechaty-qnamaker?color=brightgreen)](https://www.npmjs.com/package/wechaty-qnamaker) [![NPM](https://github.com/wechaty/wechaty-qnamaker/workflows/NPM/badge.svg)](https://github.com/wechaty/wechaty-qnamaker/actions?query=workflow%3ANPM) +[![ES Modules](https://img.shields.io/badge/ES-Modules-brightgreen)](https://github.com/Chatie/tsconfig/issues/16) [QnA Maker](https://qnamaker.ai) is a cloud-based Natural Language Processing (NLP) service that easily creates a natural conversational layer over your data. @@ -136,7 +137,9 @@ Our Friday BOT are using `wechaty-qnamaker` to connect our WeChat conversations ## HISTORY -### master +### master v0.7 (Oct 2022) + +1. Enable ESM module ### v0.6 (Aut 5, 2020) diff --git a/package.json b/package.json index 8fec220..53a0dd7 100644 --- a/package.json +++ b/package.json @@ -1,49 +1,52 @@ { "name": "wechaty-qnamaker", - "version": "0.6.2", + "version": "0.7.1", "description": "QnAMaker.ai Plugin for Wechaty", - "directories": { - "doc": "docs", - "example": "examples", - "test": "tests" + "type": "module", + "exports": { + ".": { + "import": "./dist/esm/src/mod.js", + "require": "./dist/cjs/src/mod.js" + } + }, + "typings": "./dist/esm/src/mod.d.ts", + "engines": { + "node": ">=16", + "npm": ">=7" }, "dependencies": { - "@azure/cognitiveservices-qnamaker-runtime": "^1.0.0", - "@azure/ms-rest-js": "^2.0.7", + "@azure/cognitiveservices-qnamaker-runtime": "^1.0.1", + "@azure/ms-rest-js": "^2.6.0", "language-monitor": "^1.0.3", - "wechaty-plugin-contrib": "^0.14.2" - }, - "peerDependencies": { - "wechaty-vorpal": "*" + "wechaty-plugin-contrib": "^0.19.4" }, "devDependencies": { - "@chatie/eslint-config": "^0.12.1", + "@chatie/eslint-config": "^0.16.2", "@chatie/git-scripts": "^0.6.2", "@chatie/semver": "^0.4.7", - "@chatie/tsconfig": "^0.10.1", - "@types/body-parser": "^1.19.0", - "@types/express": "^4.17.6", - "pkg-jq": "^0.2.4", - "shx": "^0.3.2", - "tstest": "^0.4.10", - "wechaty": "^0.60.9", - "wechaty-vorpal": "^0.6.11", - "wechaty-puppet-mock": "^0.28.2" + "@chatie/tsconfig": "^0.20.6", + "@types/body-parser": "^1.19.1", + "@types/express": "^4.17.13", + "pkg-jq": "^0.2.11", + "shx": "^0.3.3", + "tstest": "^0.7.3", + "wechaty": "^0.77.2", + "wechaty-puppet-mock": "^0.35.8", + "wechaty-vorpal": "^0.9.2" }, - "main": "dist/src/mod.js", - "typings": "dist/src/mod.d.ts", "scripts": { + "build": "tsc && tsc -p tsconfig.cjs.json", "clean": "shx rm -fr dist/*", - "dist": "npm run clean && tsc", - "pack": "npm pack", - "lint": "npm run lint:es && npm run lint:ts && npm run lint:md", + "dist": "npm-run-all clean build dist:commonjs", + "dist:commonjs": "jq -n \"{ type: \\\"commonjs\\\" }\" > dist/cjs/package.json", + "lint": "npm-run-all lint:es lint:ts lint:md", "lint:md": "markdownlint README.md", - "lint:ts": "tsc --noEmit", - "example": "ts-node examples/ding-dong-bot.ts", + "lint:ts": "tsc --isolatedModules --noEmit", + "example": "cross-env NODE_OPTIONS=\"--no-warnings --loader=ts-node/esm\" node examples/ding-dong-bot.ts", "start": "npm run example", - "test": "npm run lint && npm run test:unit", + "test": "npm-run-all lint test:unit", "test:pack": "bash -x scripts/npm-pack-testing.sh", - "test:unit": "blue-tape -r ts-node/register \"src/**/*.spec.ts\" \"src/*.spec.ts\" \"tests/*.spec.ts\" \"tests/**/*.spec.ts\"", + "test:unit": "cross-env NODE_OPTIONS=\"--no-warnings --loader=ts-node/esm\" tap \"src/**/*.spec.ts\" \"tests/**/*.spec.ts\"", "lint:es": "eslint --ignore-pattern tests/fixtures/ '{bin,examples,scripts,src,tests}/**/*.ts'" }, "repository": { @@ -67,6 +70,11 @@ "pre-push": "npx git-scripts-pre-push" } }, + "files": [ + "bin/", + "dist/", + "src/" + ], "publishConfig": { "tag": "next" }, diff --git a/scripts/npm-pack-testing.sh b/scripts/npm-pack-testing.sh index 86a8912..960466e 100755 --- a/scripts/npm-pack-testing.sh +++ b/scripts/npm-pack-testing.sh @@ -3,14 +3,14 @@ set -e VERSION=$(npx pkg-jq -r .version) -if npx --package @chatie/semver semver-is-prod $VERSION; then +if npx --package @chatie/semver semver-is-prod "$VERSION"; then NPM_TAG=latest else NPM_TAG=next fi npm run dist -npm run pack +npm pack TMPDIR="/tmp/npm-pack-testing.$$" mkdir "$TMPDIR" @@ -18,12 +18,44 @@ mv ./*-*.*.*.tgz "$TMPDIR" cp tests/fixtures/smoke-testing.ts "$TMPDIR" cd $TMPDIR + npm init -y -npm install *-*.*.*.tgz \ - @chatie/tsconfig \ +npm install --production *-*.*.*.tgz \ + @types/node \ + @chatie/tsconfig@$NPM_TAG \ + pkg-jq \ "wechaty@$NPM_TAG" \ +# +# CommonJS +# +./node_modules/.bin/tsc \ + --target es6 \ + --module CommonJS \ + \ + --moduleResolution node \ + --esModuleInterop \ + --lib esnext \ + --noEmitOnError \ + --noImplicitAny \ + --skipLibCheck \ + smoke-testing.ts + +echo +echo "CommonJS: pack testing..." +node smoke-testing.js + +# +# ES Modules +# +npx pkg-jq -i '.type="module"' + + ./node_modules/.bin/tsc \ + --target es2020 \ + --module es2020 \ + \ + --moduleResolution node \ --esModuleInterop \ --lib esnext \ --noEmitOnError \ @@ -31,4 +63,6 @@ npm install *-*.*.*.tgz \ --skipLibCheck \ smoke-testing.ts +echo +echo "ES Module: pack testing..." node smoke-testing.js diff --git a/src/asker.spec.ts b/src/asker.spec.ts index 5fbec65..fabbca9 100755 --- a/src/asker.spec.ts +++ b/src/asker.spec.ts @@ -1,9 +1,9 @@ -#!/usr/bin/env ts-node +#!/usr/bin/env -S node --no-warnings --loader ts-node/esm -import test from 'tstest' +import { test } from 'tstest' -import { asker } from './asker' -import { normalizeConfig } from './normalize-config' +import { asker } from './asker.js' +import { normalizeConfig } from './normalize-config.js' test('asker()', async t => { // use our normalizeConfig() helper function to get the config: @@ -16,7 +16,7 @@ test('asker()', async t => { const ask = asker(config) let answers = await ask('wechaty') - t.true(answers[0].answer, 'should get answer back: ' + answers[0].answer) + t.ok(answers[0]!.answer, 'should get answer back: ' + answers[0]!.answer) answers = await ask('中文') t.equal(answers.length, 0, 'should get no answer for 中文') diff --git a/src/asker.ts b/src/asker.ts index 8cdfa4a..5ff6fed 100644 --- a/src/asker.ts +++ b/src/asker.ts @@ -10,8 +10,9 @@ import * as runtime from '@azure/cognitiveservices-qnamaker-runtime' import { log } from 'wechaty' -import { QnAMakerOptions } from './qnamaker' -import { QueryDTO } from '@azure/cognitiveservices-qnamaker-runtime/esm/models' +import type { QnAMakerOptions } from './qnamaker.js' +// eslint-disable-next-line import/extensions +import type { QueryDTO } from '@azure/cognitiveservices-qnamaker-runtime/esm/models' function asker (options: QnAMakerOptions) { log.verbose('WechatyQnAMaker', 'asker(%s)', JSON.stringify(options)) @@ -41,7 +42,7 @@ function asker (options: QnAMakerOptions) { const requestQuery = await runtimeClient.runtime.generateAnswer( options.knowledgeBaseId, normalizedQueryDto, - { customHeaders } + { customHeaders }, ) // console.info(JSON.stringify(requestQuery)) diff --git a/src/mod.ts b/src/mod.ts index 998bf6c..0032777 100644 --- a/src/mod.ts +++ b/src/mod.ts @@ -1,8 +1,10 @@ -export { VERSION } from './version' +export { VERSION } from './version.js' +export type { + WechatyQnAMakerConfig, +} from './plugin.js' export { WechatyQnAMaker, - WechatyQnAMakerConfig, -} from './plugin' +} from './plugin.js' export { Faq, -} from './vorpal' +} from './vorpal.js' diff --git a/src/normalize-config.ts b/src/normalize-config.ts index 4762ff5..4be0f29 100644 --- a/src/normalize-config.ts +++ b/src/normalize-config.ts @@ -1,8 +1,8 @@ -import { WechatyQnAMakerConfig } from './plugin' +import type { WechatyQnAMakerConfig } from './plugin.js' import { QnAMakerOptions, DEFAULT_SCORE_THRESHOLD, -} from './qnamaker' +} from './qnamaker.js' function normalizeConfig (config: WechatyQnAMakerConfig): QnAMakerOptions { const WECHATY_PLUGIN_QNAMAKER_ENDPOINT_KEY = 'WECHATY_PLUGIN_QNAMAKER_ENDPOINT_KEY' diff --git a/src/plugin.ts b/src/plugin.ts index 5823824..baad101 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -8,11 +8,11 @@ import { matchers, } from 'wechaty-plugin-contrib' -import { asker } from './asker' -import { normalizeConfig } from './normalize-config' -import { mentionMatcher } from './mention-matcher' +import { asker } from './asker.js' +import { normalizeConfig } from './normalize-config.js' +import { mentionMatcher } from './mention-matcher.js' -import { QnAMakerOptions } from './qnamaker' +import type { QnAMakerOptions } from './qnamaker.js' interface WechatyQnAMakerConfigMatcher { contact? : matchers.ContactMatcherOptions, @@ -111,7 +111,7 @@ function WechatyQnAMaker (config: WechatyQnAMakerConfig): WechatyPlugin { if (!text) { return } const answers = await ask(text) - if (answers.length <= 0) { return } + if (answers.length <= 0 || !answers[0]) { return } const answer = answers[0].answer if (!answer) { diff --git a/src/qnamaker.ts b/src/qnamaker.ts index 5cc6416..39cd4ae 100644 --- a/src/qnamaker.ts +++ b/src/qnamaker.ts @@ -1,4 +1,4 @@ -import { matchers } from 'wechaty-plugin-contrib' +import type { matchers } from 'wechaty-plugin-contrib' export interface QnAMakerOptions { endpointKey : string diff --git a/src/version.spec.ts b/src/version.spec.ts index 40a5d4b..5ee3552 100755 --- a/src/version.spec.ts +++ b/src/version.spec.ts @@ -1,8 +1,8 @@ -#!/usr/bin/env ts-node +#!/usr/bin/env -S node --no-warnings --loader ts-node/esm -import test from 'tstest' +import { test } from 'tstest' -import { VERSION } from './version' +import { VERSION } from './version.js' test('Make sure the VERSION is fresh in source code', async t => { t.equal(VERSION, '0.0.0', 'version should be 0.0.0 in source code, only updated before publish to NPM') diff --git a/src/vorpal.ts b/src/vorpal.ts index ebe4144..296b1df 100644 --- a/src/vorpal.ts +++ b/src/vorpal.ts @@ -1,5 +1,5 @@ import { log } from 'wechaty' -import { +import type { Args, CommandContext, Vorpal, @@ -8,12 +8,13 @@ import { matchers, } from 'wechaty-plugin-contrib' -import { QnAMakerOptions } from './qnamaker' -import { normalizeConfig } from './normalize-config' -import { asker } from './asker' -import { +import type { QnAMakerOptions } from './qnamaker.js' +import { normalizeConfig } from './normalize-config.js' +import { asker } from './asker.js' +import type { QnASearchResult, QueryDTO, + // eslint-disable-next-line } from '@azure/cognitiveservices-qnamaker-runtime/esm/models' function Faq (config: Partial | Partial[]) { @@ -25,7 +26,7 @@ function Faq (config: Partial | Partial[]) { normalizedConfigList.push(normalizeConfig(config)) } else { normalizedConfigList.push( - ...config.map(c => normalizeConfig(c)) + ...config.map(c => normalizeConfig(c)), ) } @@ -62,7 +63,7 @@ const faqAction = (configList : QnAMakerOptions[]) => { const resultList = await Promise.all( askerDictList .filter(dict => dict.matchLanguage(question)) - .map(dict => dict.ask(question, dto)) + .map(dict => dict.ask(question, dto)), ) return resultList @@ -73,17 +74,17 @@ const faqAction = (configList : QnAMakerOptions[]) => { return async function faqActionExector ( this: CommandContext, - args: Args + args: Args, ): Promise { log.verbose('WechatyQnAMaker', 'Faq() faqAction() faqActionExecutor("%s")', JSON.stringify(args)) const options: FaqOptions = args.options let question: string - if (Array.isArray(args.question)) { - question = args.question.join(' ') + if (Array.isArray(args['question'])) { + question = args['question'].join(' ') } else { - question = args.question + question = args['question']! } const queryDto: QueryDTO = { @@ -105,7 +106,7 @@ const faqAction = (configList : QnAMakerOptions[]) => { if (idx > (options.number ?? 0)) { return } this.log( - toReply(result, idx + 1, options.verbose) + toReply(result, idx + 1, options.verbose), ) }) } diff --git a/tests/fixtures/smoke-testing.ts b/tests/fixtures/smoke-testing.ts index 35c1073..a6787a1 100644 --- a/tests/fixtures/smoke-testing.ts +++ b/tests/fixtures/smoke-testing.ts @@ -1,4 +1,4 @@ -#!/usr/bin/env ts-node +#!/usr/bin/env -S node --no-warnings --loader ts-node/esm import { VERSION, } from 'wechaty-qnamaker' diff --git a/tests/integration.spec.ts b/tests/integration.spec.ts index 713b334..0381b38 100755 --- a/tests/integration.spec.ts +++ b/tests/integration.spec.ts @@ -1,10 +1,10 @@ -#!/usr/bin/env ts-node +#!/usr/bin/env -S node --no-warnings --loader ts-node/esm import { test, } from 'tstest' -import * as plugins from '../src/mod' +import * as plugins from '../src/mod.js' // import { // Wechaty, @@ -25,7 +25,7 @@ test('integration testing', async (t) => { // room: 'id', // webhookProxyUrl: 'https://smee.io/fdasfadsfasdfs', // })) - t.skip('should get a bot') + await t.skip('should get a bot') }) test('plugin name', async t => { @@ -38,7 +38,7 @@ test('plugin name', async t => { continue // our helper functions } - t.skip('to be fixed') + await t.skip('to be fixed') // t.doesNotThrow(() => validatePlugin(plugin), 'plugin ' + plugin.name + ' should be valid') } }) diff --git a/tsconfig.cjs.json b/tsconfig.cjs.json new file mode 100644 index 0000000..8693cd0 --- /dev/null +++ b/tsconfig.cjs.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "module": "CommonJS", + "outDir": "dist/cjs", + }, +} diff --git a/tsconfig.json b/tsconfig.json index 728a055..bbf1a08 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,7 @@ { "extends": "@chatie/tsconfig", "compilerOptions": { - "outDir": "dist", + "outDir": "dist/esm", }, "exclude": [ "node_modules/",