Skip to content

Commit

Permalink
✨ feat: Update build
Browse files Browse the repository at this point in the history
  • Loading branch information
canisminor1990 committed Dec 15, 2024
1 parent 64debd6 commit 8d534ed
Show file tree
Hide file tree
Showing 18 changed files with 141 additions and 104 deletions.
8 changes: 7 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
name: Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4

- name: Install bun
uses: oven-sh/setup-bun@v1
Expand Down Expand Up @@ -52,3 +52,9 @@ jobs:
git push
env:
GH_TOKEN: ${{ secrets.GH_TOKEN }}

- name: Release
run: bun run release
env:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
8 changes: 4 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ test-output
# misc
# add other ignore file below
public
.prettierrc.js
.eslintrc.js
.remarkrc.js
.prettierrc.*js
.eslintrc.*js
.remarkrc.*js
.env
bun.lockb
bun.lockb
1 change: 1 addition & 0 deletions .prettierrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('@lobehub/lint').prettier;
1 change: 1 addition & 0 deletions .releaserc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('@lobehub/lint').semanticRelease;
1 change: 1 addition & 0 deletions .remarkrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('@lobehub/lint').remarklint;
14 changes: 12 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
{
"name": "@lobehub/lobe-chat-plugins",
"name": "@lobehub/plugins-index",
"version": "0.0.0",
"private": true,
"description": "LobeChat Plugins Index",
"homepage": "https://github.com/lobehub/lobe-chat-plugins",
"repository": {
Expand All @@ -11,13 +10,18 @@
"license": "MIT",
"author": "LobeHub <i@lobehub.com>",
"type": "module",
"main": "public/index.json",
"files": [
"public"
],
"scripts": {
"awesome": "bun scripts/build.ts && bun scripts/updateAwesome.ts",
"build": "bun scripts/build.ts",
"format": "bun scripts/format.ts",
"lint": "eslint \"scripts/**/*.ts\" --fix",
"lint:md": "remark . --quiet --output",
"prettier": "prettier -c --write \"**/*.{json,ts,md}\"",
"release": "semantic-release",
"sync": "bun scripts/sync.ts",
"test": "bun scripts/test.ts"
},
Expand All @@ -30,6 +34,7 @@
"@types/node": "^20.14.14",
"consola": "^3.2.3",
"dayjs": "^1.11.12",
"dirty-json": "^0.9.2",
"dotenv": "^16.4.5",
"eslint": "^8.57.0",
"fs-extra": "^11.2.0",
Expand All @@ -40,8 +45,13 @@
"remark": "^14.0.3",
"remark-cli": "^11.0.0",
"remark-pangu": "^2.2.0",
"semantic-release": "^21.1.2",
"typescript": "^5.5.4",
"zod": "^3.23.8",
"zod-to-json-schema": "^3.23.2"
},
"publishConfig": {
"access": "public",
"registry": "https://registry.npmjs.org"
}
}
22 changes: 14 additions & 8 deletions scripts/build.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { consola } from 'consola';
import { readJSONSync, writeJSONSync } from 'fs-extra';
import { cloneDeep, merge } from 'lodash-es';
import { resolve } from 'node:path';

import { formatAndCheckSchema } from './check';
import { config, localesDir, meta, plugins, pluginsDir, publicDir } from './const';
import { checkDir, findDuplicates, readJSON, writeJSON } from './utils';
import { checkDir, findDuplicates } from './utils';

const build = async () => {
checkDir(publicDir);
Expand All @@ -18,37 +19,42 @@ const build = async () => {

for (const file of plugins) {
if (file.isFile()) {
const data = readJSON(resolve(pluginsDir, file.name));
const data = readJSONSync(resolve(pluginsDir, file.name));
const plugin = formatAndCheckSchema(data);
if (!list[config.entryLocale]) list[config.entryLocale] = [];
list[config.entryLocale].push(plugin);
for (const locale of config.outputLocales) {
if (!list[locale]) list[locale] = [];
const localeFilePath = resolve(localesDir, file.name.replace('.json', `.${locale}.json`));
const localeData = readJSON(localeFilePath);
const localeData = readJSONSync(localeFilePath);
list[locale].push(merge(cloneDeep(plugin), localeData));
}
}
}

for (const locale of [config.entryLocale, ...config.outputLocales]) {
// @ts-ignore
pluginsIndex.plugins = list[locale].sort(
// @ts-ignore
(a, b) => new Date(b.createdAt) - new Date(a.createdAt),
);

let tags: string[] = [];

pluginsIndex.plugins.forEach((plugin) => {
for (const plugin of pluginsIndex.plugins) {
tags = [...tags, ...plugin.meta.tags];
});
}

tags = findDuplicates(tags);

pluginsIndex.tags = tags;

const name = locale === config.entryLocale ? `index.json` : `index.${locale}.json`;
writeJSON(resolve(publicDir, name), pluginsIndex, false);
const name = `index.${locale}.json`;

if (locale === config.entryLocale) {
writeJSONSync(resolve(publicDir, `index.json`), pluginsIndex);
}
writeJSONSync(resolve(publicDir, name), pluginsIndex);

consola.success(`build ${name}`);
}
};
Expand Down
9 changes: 2 additions & 7 deletions scripts/category.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
import { consola } from 'consola';
import 'dotenv/config';
import { ChatOpenAI } from 'langchain/chat_models/openai';
import { HumanMessage, SystemMessage } from 'langchain/schema';

import { category, config } from './const';

const model = new ChatOpenAI(
{ modelName: config.modelName, temperature: 0 },
{ baseURL: process.env.OPENAI_PROXY_URL },
);
import { category } from './const';
import { model } from './model';

export const addCategory = async (json) => {
consola.info(`category generating...`);
Expand Down
8 changes: 4 additions & 4 deletions scripts/check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ export const checkUniqueIdentifier = (arr) => {
let duplicates = [];
let set = new Set();

for (let i = 0; i < arr.length; i++) {
if (set.has(arr[i])) {
duplicates.push(arr[i]);
for (const element of arr) {
if (set.has(element)) {
duplicates.push(element);
} else {
set.add(arr[i]);
set.add(element);
}
}

Expand Down
50 changes: 25 additions & 25 deletions scripts/const.ts
Original file line number Diff line number Diff line change
@@ -1,41 +1,41 @@
import { readdirSync } from 'node:fs';
import { resolve } from 'node:path';
import { readdirSync } from "node:fs";
import { resolve } from "node:path";

import { readJSON } from './utils';
import { readJSONSync } from "fs-extra";

export const root = resolve(__dirname, '..');
export const root = resolve(__dirname, "..");

export const pluginsDir = resolve(root, './src');
export const localesDir = resolve(root, './locales');
export const publicDir = resolve(root, 'public');
export const pluginsDir = resolve(root, "./src");
export const localesDir = resolve(root, "./locales");
export const publicDir = resolve(root, "public");

export const plugins = readdirSync(pluginsDir, { withFileTypes: true });
export const pluginLocales = readdirSync(localesDir, { withFileTypes: true });

export const templatePath = resolve(root, 'plugin-template.json');
export const templatePath = resolve(root, "plugin-template.json");

export const indexPath = resolve(publicDir, 'index.json');
export const indexCnPath = resolve(publicDir, 'index.zh-CN.json');
export const indexPath = resolve(publicDir, "index.json");
export const indexCnPath = resolve(publicDir, "index.zh-CN.json");

export const readmePath = resolve(root, 'README.md');
export const readmeCnPath = resolve(root, 'README.zh-CN.md');
export const readmePath = resolve(root, "README.md");
export const readmeCnPath = resolve(root, "README.zh-CN.md");

export const metaPath = resolve(root, 'meta.json');
export const meta = readJSON(metaPath);
export const metaPath = resolve(root, "meta.json");
export const meta = readJSONSync(metaPath);

export const readmeSplit = '<!-- AWESOME PLUGINS -->';
export const readmeSplit = "<!-- AWESOME PLUGINS -->";

export const SYNC_URL = 'https://openai-collections.chat-plugin.lobehub.com';
export const SYNC_URL = "https://openai-collections.chat-plugin.lobehub.com";

export const category = [
'gaming-entertainment',
'lifestyle',
'media-generate',
'science-education',
'social',
'stocks-finance',
'tools',
'web-search',
"gaming-entertainment",
"lifestyle",
"media-generate",
"science-education",
"social",
"stocks-finance",
"tools",
"web-search",
];

export const config = require('../.i18nrc.js');
export const config = require("../.i18nrc.js");
20 changes: 11 additions & 9 deletions scripts/format.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { consola } from 'consola';
import { readJSONSync, writeJSONSync } from 'fs-extra';
import { get, kebabCase, merge, set } from 'lodash-es';
import { existsSync } from 'node:fs';
import { resolve } from 'node:path';
Expand All @@ -9,23 +10,23 @@ import { formatAndCheckSchema } from './check';
import { config, localesDir, metaPath, plugins, pluginsDir, templatePath } from './const';
import { formatFilenames } from './formatFilename';
import { translateJSON } from './i18n';
import { checkJSON, readJSON, split, writeJSON } from './utils';
import { checkJSON, split } from './utils';

class Formatter {
formatJSON = async (fileName: string, checkType?: boolean) => {
consola.start(fileName);

const filePath = resolve(pluginsDir, fileName);

let plugin = readJSON(filePath);
let plugin = readJSONSync(filePath);

if (checkType) {
plugin = formatAndCheckSchema(plugin);

if (!plugin.meta.category) {
plugin = await addCategory(plugin);
consola.info(plugin.meta.category);
writeJSON(resolve(pluginsDir, fileName), plugin);
writeJSONSync(resolve(pluginsDir, fileName), plugin);
}

if (plugin?.meta?.tags?.length > 0) {
Expand All @@ -43,29 +44,30 @@ class Formatter {
if (rawData) {
if (plugin.locale && plugin.locale !== config.entryLocale) {
if (config.outputLocales.includes(plugin.locale)) {
writeJSON(
writeJSONSync(
resolve(localesDir, fileName.replace('.json', `.${plugin.locale}.json`)),
rawData,
);
}
rawData = await translateJSON(rawData, config.entryLocale, plugin.locale);
rawData = await translateJSON(fileName, rawData, config.entryLocale, plugin.locale);
plugin = merge(plugin, rawData);
delete plugin.locale;
}

for (const locale of config.outputLocales) {
const localeFilePath = resolve(localesDir, fileName.replace('.json', `.${locale}.json`));
const localeFilename = fileName.replace('.json', `.${locale}.json`);
const localeFilePath = resolve(localesDir, localeFilename);
if (existsSync(localeFilePath)) continue;
const translateResult = await translateJSON(rawData, locale);
const translateResult = await translateJSON(localeFilename, rawData, locale);
if (translateResult) {
writeJSON(localeFilePath, translateResult);
writeJSONSync(localeFilePath, translateResult);
consola.success(`${locale} generated`);
}
}
}
}

writeJSON(filePath, plugin);
writeJSONSync(filePath, plugin);
consola.success(`format success`);
};
run = async () => {
Expand Down
5 changes: 3 additions & 2 deletions scripts/formatFilename.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { consola } from 'consola';
import { readJSONSync } from 'fs-extra';
import { renameSync } from 'node:fs';
import { resolve } from 'node:path';

import { localesDir, pluginLocales, plugins, pluginsDir } from './const';
import { checkJSON, readJSON } from './utils';
import { checkJSON } from './utils';

const formatFilenameById = (fileName) => {
const filePath = resolve(pluginsDir, fileName);
const plugin = readJSON(filePath);
const plugin = readJSONSync(filePath);
const newFilename = plugin.identifier + '.json';
if (fileName !== newFilename) {
const newFilepath = resolve(pluginsDir, newFilename);
Expand Down
33 changes: 24 additions & 9 deletions scripts/i18n.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
import { consola } from 'consola';
import { colors } from 'consola/utils';
import dJSON from 'dirty-json';
import 'dotenv/config';
import { ChatOpenAI } from 'langchain/chat_models/openai';
import { HumanMessage, SystemMessage } from 'langchain/schema';

import { config } from './const';
import { model } from './model';

const model = new ChatOpenAI(
{ temperature: 0, modelName: config.modelName },
{ baseURL: process.env.OPENAI_PROXY_URL },
);

export const translateJSON = async (json, outputLocale, entryLocale = config.entryLocale) => {
consola.info('i18n generating...');
export const translateJSON = async (
filename,
json,
outputLocale,
entryLocale = config.entryLocale,
) => {
consola.info(colors.yellow(filename), `i18n generating...`);
const res = await model.call(
[
new SystemMessage(
[
`Translate the i18n JSON file from ${entryLocale} to ${outputLocale} according to the BCP 47 standard`,
`Keep the keys the same as the original file and make sure the output remains a valid i18n JSON file.`,
`Do not include any additional text or explanations outside the JSON object.Start directly with a left brace and end with a right brace.`,
].join('\n'),
),
new HumanMessage(JSON.stringify(json)),
Expand All @@ -26,5 +29,17 @@ export const translateJSON = async (json, outputLocale, entryLocale = config.ent
response_format: { type: 'json_object' },
},
);
return JSON.parse(res.content);
try {
return JSON.parse(res.content as string);
} catch {
consola.warn(colors.yellow(filename), 'i18n parse fail, try to use dirty json');
try {
const data = dJSON.parse(res.content as string);
console.info(JSON.stringify(data, null, 2));
return data;
} catch {
consola.error(colors.yellow(filename), 'i18n dirty json parse fail');
consola.error(res.content);
}
}
};
Loading

0 comments on commit 8d534ed

Please sign in to comment.