diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index 8c52968..0000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1 +0,0 @@ -custom: ['https://yookassa.ru/my/i/aYMO3MZMJpw7/l'] diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 07ce102..1a739b4 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -1,39 +1,74 @@ ---- name: Bug Report -about: Report a bug or unexpected behavior -labels: ["bug"] +description: Report a bug or unexpected behavior +labels: ['bug'] assignees: [] ---- -## Bug Description +body: + - type: textarea + attributes: + label: Bug Description + description: | + Please describe the bug you encountered in as much detail as possible. -Please describe the bug you encountered in as much detail as possible. + - What happened? + - What did you expect to happen? + - Are there any error messages shown? + placeholder: | + Describe the bug clearly and concisely. + validations: + required: true -- What happened? -- What did you expect to happen? -- Are there any error messages shown? + - type: textarea + attributes: + label: Steps to Reproduce + description: | + Please include exact steps so we can reproduce the issue. + placeholder: | + 1. + 2. + 3. + 4. + validations: + required: true -## Steps to Reproduce + - type: textarea + attributes: + label: Screenshots / Logs + description: | + If applicable, add screenshots or logs to help explain your problem. + placeholder: | + Paste logs here or attach screenshots. -1. -2. -3. -4. + - type: markdown + attributes: + value: | + ## Environment -_(Please include exact steps so we can reproduce the issue.)_ + - type: input + attributes: + label: OS + placeholder: macOS / Windows / Linux + validations: + required: true -## Screenshots / Logs + - type: input + attributes: + label: Datary Version + placeholder: 0.0.1 + validations: + required: true -If applicable, add screenshots or logs to help explain your problem. + - type: input + attributes: + label: Database + placeholder: PostgreSQL / MySQL / MariaDB / Microsoft SQL Server + validations: + required: true -## Environment - -| Feature | Details | -|---------|---------| -| OS | | -| Datary Version | | -| Database | | - -## Additional Context - -Add any other context about the problem here. + - type: textarea + attributes: + label: Additional Context + description: | + Add any other context about the problem here. + placeholder: | + Any extra information that may help. diff --git a/.github/ISSUE_TEMPLATE/feature-request.yml b/.github/ISSUE_TEMPLATE/feature-request.yml deleted file mode 100644 index d38cf65..0000000 --- a/.github/ISSUE_TEMPLATE/feature-request.yml +++ /dev/null @@ -1,24 +0,0 @@ ---- -name: Feature Request -about: Suggest a new idea or improvement -labels: ["enhancement"] -assignees: [] ---- - -## Feature Description - -What feature are you requesting? -Please explain why this would be useful and who would benefit from it. - -## Use Case / Motivation - -- What problem does this solve? -- How is it useful? - -## Suggested Implementation - -If you have ideas about how this could work (UI, behavior, API), describe them here. - -## Examples / References - -If this idea exists in other tools or contexts, include links, screenshots, or examples. diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..864fa3f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,56 @@ +name: Feature Request +description: Suggest a new idea or improvement for Datary +labels: ['enhancement'] +assignees: [] + +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to suggest an improvement! + Datary is a database management tool, so features related to databases, UX, performance, or integrations are especially welcome. + + - type: textarea + attributes: + label: Feature description + description: | + What feature are you requesting? + Explain what it does and why it would be valuable. + placeholder: | + Example: + Add support for exporting query results to CSV/JSON directly from the results table. + validations: + required: true + + - type: textarea + attributes: + label: Use case / motivation + description: | + Describe the problem this feature solves and who would benefit from it. + placeholder: | + Example: + When working with large datasets, I often need to share query results with teammates. + Currently, I have to copy data manually or use external tools. + validations: + required: true + + - type: textarea + attributes: + label: Suggested implementation + description: | + If you have ideas on how this could work (UI, behavior, API), describe them here. + This is optional but very helpful. + placeholder: | + Example: + - Add an "Export" button near the results table + - Allow selecting format (CSV / JSON) + - Save file via native OS dialog + + - type: textarea + attributes: + label: Examples / references + description: | + If similar functionality exists in other tools, add links, screenshots, or descriptions. + placeholder: | + Example: + DBeaver has a similar export dialog with format selection and preview. diff --git a/.github/scripts/telegram-notify.js b/.github/scripts/telegram-notify.js new file mode 100644 index 0000000..ec6a928 --- /dev/null +++ b/.github/scripts/telegram-notify.js @@ -0,0 +1,63 @@ +import fetch from 'node-fetch' +import fs from 'fs' + +const { + TELEGRAM_BOT_TOKEN, + TELEGRAM_CHAT_ID, + GITHUB_EVENT_NAME, + GITHUB_EVENT_PATH, + GITHUB_REPOSITORY, + GITHUB_ACTOR, + GITHUB_REF, +} = process.env + +if (!TELEGRAM_BOT_TOKEN || !TELEGRAM_CHAT_ID) { + console.error('Telegram env vars are missing') + process.exit(1) +} + +let message = `*GitHub Notification*\n\n` +message += `Repo: ${GITHUB_REPOSITORY}\n` +message += `Actor: ${GITHUB_ACTOR}\n` +message += `Event: ${GITHUB_EVENT_NAME}\n` + +if (GITHUB_EVENT_PATH && fs.existsSync(GITHUB_EVENT_PATH)) { + const payload = JSON.parse(fs.readFileSync(GITHUB_EVENT_PATH, 'utf8')) + + if (GITHUB_EVENT_NAME === 'push') { + message += `\n*Push*\n` + message += `Branch: ${GITHUB_REF?.replace('refs/heads/', '')}\n` + + payload.commits?.slice(0, 3).forEach((c, i) => { + message += `${i + 1}. ${c.message.split('\n')[0]}\n` + }) + } + + if (GITHUB_EVENT_NAME === 'pull_request' || GITHUB_EVENT_NAME === 'pull_request_target') { + const pr = payload.pull_request + message += `\n*Pull Request*\n` + message += `Title: ${pr.title}\n` + message += `Action: ${payload.action}\n` + message += `URL: ${pr.html_url}\n` + } + + if (GITHUB_EVENT_NAME === 'issues') { + const issue = payload.issue + message += `\n*Issue*\n` + message += `Title: ${issue.title}\n` + message += `Action: ${payload.action}\n` + message += `URL: ${issue.html_url}\n` + } +} + +await fetch(`https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + chat_id: TELEGRAM_CHAT_ID, + text: message, + parse_mode: 'Markdown' + }) +}) diff --git a/.github/workflows/notify.yml b/.github/workflows/notify.yml index 34a8327..c3fcced 100644 --- a/.github/workflows/notify.yml +++ b/.github/workflows/notify.yml @@ -5,8 +5,8 @@ on: branches: - main - develop - pull_request: - types: [opened, closed, reopened, merged] + pull_request_target: + types: [opened, reopened, closed] issues: types: [opened, closed, reopened] @@ -41,4 +41,4 @@ jobs: run: npm install node-fetch - name: Send Telegram notification - run: node scripts/telegram-notify.js + run: node .github/scripts/telegram-notify.js diff --git a/apps/desktop/main/app/window.manager.ts b/apps/desktop/main/app/window.manager.ts index 3ba8086..91c80d2 100644 --- a/apps/desktop/main/app/window.manager.ts +++ b/apps/desktop/main/app/window.manager.ts @@ -9,8 +9,6 @@ import { mainWindow } from './app.state' export function createMainWindow() { const preloadPath = getPreloadPath(__dirname) - console.log('preloadPath: ', preloadPath) - const win = new BrowserWindow({ width: 1200, height: 800, @@ -28,6 +26,9 @@ export function createMainWindow() { mainWindow.set(win) if (isDev && DEV_SERVER_URL) { + win.webContents.closeDevTools() + win.webContents.setVisualZoomLevelLimits(1, 1) + win.loadURL(DEV_SERVER_URL) } else { win.loadFile(getRendererIndex(__dirname)) diff --git a/apps/desktop/main/ipc/handlers/connection.handler.ts b/apps/desktop/main/ipc/handlers/connection.handler.ts index 78b9f21..e37a23b 100644 --- a/apps/desktop/main/ipc/handlers/connection.handler.ts +++ b/apps/desktop/main/ipc/handlers/connection.handler.ts @@ -2,71 +2,83 @@ import { IPC_CHANNELS } from '@datary/ipc' import { ipcMain } from 'electron' import Store from 'electron-store' +import { buildCredentialId } from '../../services/credential/credential.utils' +import { CredentialVault } from '../../services/credential/credential.vault' import { logger } from '../../utils/logger' export interface ConnectionHistoryItem { - id?: string + id: string name?: string host: string port: number user: string - password?: string database: string type: 'postgresql' | 'mysql' | 'mariadb' | 'mssql' ssl?: boolean lastUsed?: number } -const ENCRYPTION_KEY = 'datary-secret-key-123' const store = new Store<{ history: ConnectionHistoryItem[] }>({ name: 'connections', - defaults: { history: [] }, - encryptionKey: ENCRYPTION_KEY + defaults: { history: [] } }) +const vault = new CredentialVault() + export function registerConnectionHandlers() { ipcMain.handle(IPC_CHANNELS.CONNECTIONS.GET, () => { return store.get('history') ?? [] }) - ipcMain.handle(IPC_CHANNELS.CONNECTIONS.ADD, (_, connection: ConnectionHistoryItem) => { - const history = store.get('history') ?? [] - const index = history.findIndex( - c => - c.host === connection.host && - c.port === connection.port && - c.user === connection.user && - c.database === connection.database && - c.type === connection.type - ) - - const newConnection = { ...connection, lastUsed: Date.now() } - - if (index > -1) { - history[index] = newConnection - } else { - history.unshift(newConnection) - } + ipcMain.handle( + IPC_CHANNELS.CONNECTIONS.ADD, + async (_, connection: ConnectionHistoryItem & { password?: string }) => { + const history = store.get('history') ?? [] - store.set('history', history) - return history - }) + const credentialId = buildCredentialId(connection) + + if (connection.password) await vault.save(credentialId, connection.password) - ipcMain.handle(IPC_CHANNELS.CONNECTIONS.DELETE, (_, connection: ConnectionHistoryItem) => { - const history = store.get('history') ?? [] - const filtered = history.filter( - c => - !( + const index = history.findIndex( + c => c.host === connection.host && c.port === connection.port && c.user === connection.user && c.database === connection.database && c.type === connection.type - ) - ) - store.set('history', filtered) - return filtered - }) + ) + + const newConnection = { ...connection, lastUsed: Date.now() } + + if (index > -1) history[index] = newConnection + else history.unshift(newConnection) + + store.set('history', history) + return history + } + ) + + ipcMain.handle( + IPC_CHANNELS.CONNECTIONS.DELETE, + async (_, connection: ConnectionHistoryItem) => { + if (connection.id) await vault.delete(connection.id) + + const history = store.get('history') ?? [] + const filtered = history.filter( + c => + !( + c.host === connection.host && + c.port === connection.port && + c.user === connection.user && + c.database === connection.database && + c.type === connection.type + ) + ) + + store.set('history', filtered) + return filtered + } + ) ipcMain.handle(IPC_CHANNELS.CONNECTIONS.CLEAR, () => { store.set('history', []) diff --git a/apps/desktop/main/services/credential/credential.types.ts b/apps/desktop/main/services/credential/credential.types.ts new file mode 100644 index 0000000..3ef1197 --- /dev/null +++ b/apps/desktop/main/services/credential/credential.types.ts @@ -0,0 +1,8 @@ +import type { ConnectionType } from '@datary/core' + +export interface DbCredential { + id: string + username: string + password: string + type: ConnectionType +} diff --git a/apps/desktop/main/services/credential/credential.utils.ts b/apps/desktop/main/services/credential/credential.utils.ts new file mode 100644 index 0000000..27dec75 --- /dev/null +++ b/apps/desktop/main/services/credential/credential.utils.ts @@ -0,0 +1,5 @@ +import type { ConnectionHistoryItem } from '../../ipc/handlers/connection.handler' + +export function buildCredentialId(connection: ConnectionHistoryItem) { + return `${connection.type}::/${connection.user}@${connection.host}:${connection.port}/${connection.database}` +} diff --git a/apps/desktop/main/services/credential/credential.vault.ts b/apps/desktop/main/services/credential/credential.vault.ts new file mode 100644 index 0000000..6908163 --- /dev/null +++ b/apps/desktop/main/services/credential/credential.vault.ts @@ -0,0 +1,17 @@ +import keytar from 'keytar' + +const SERVICE_NAME = 'datary' + +export class CredentialVault { + public async save(id: string, value: string): Promise { + await keytar.setPassword(SERVICE_NAME, id, value) + } + + public async get(id: string): Promise { + return keytar.getPassword(SERVICE_NAME, id) + } + + public async delete(id: string): Promise { + await keytar.deletePassword(SERVICE_NAME, id) + } +} diff --git a/apps/desktop/package.json b/apps/desktop/package.json index bf15f86..4784a87 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -2,15 +2,8 @@ "name": "@datary/desktop", "version": "0.0.1", "main": "dist/main/index.js", - "author": { - "name": "Vadim (TeaCoder)", - "url": "https://github.com/TeaCoder52" - }, - "repository": { - "type": "git", - "url": "https://github.com/TeaCoder52/datary.git" - }, "scripts": { + "postinstall": "node node_modules/electron/install.js && pnpm exec electron-rebuild -f -w keytar", "dev": "concurrently \"pnpm dev:preload\" \"pnpm dev:renderer\" \"pnpm dev:main\" \"pnpm dev:electron\"", "dev:renderer": "pnpm --filter @datary/renderer dev", "dev:preload": "tsc -p preload/tsconfig.json --watch", @@ -26,7 +19,9 @@ "@datary/core": "workspace:*", "@datary/db": "workspace:*", "@datary/ipc": "workspace:*", - "electron-store": "^11.0.2" + "add": "^2.0.6", + "electron-store": "^11.0.2", + "keytar": "^7.9.0" }, "devDependencies": { "concurrently": "^9.2.1", @@ -42,7 +37,11 @@ "dist/**/*", "preload/**/*", "renderer/dist/**/*", - "assets/icons/**/*" + "assets/icons/**/*", + "!**/*.map", + "!**/tests/**", + "!**/__mocks__/**", + "!**/*.spec.ts" ], "directories": { "output": "build" diff --git a/apps/desktop/renderer/vite.config.ts b/apps/desktop/renderer/vite.config.ts index 868d494..788a023 100644 --- a/apps/desktop/renderer/vite.config.ts +++ b/apps/desktop/renderer/vite.config.ts @@ -14,5 +14,16 @@ export default defineConfig({ alias: { '@': '/src' } + }, + build: { + minify: 'esbuild', + sourcemap: false, + rollupOptions: { + output: { + manualChunks: { + vendor: ['react', 'react-dom'] + } + } + } } }) diff --git a/package.json b/package.json index ba3a99e..cf8fa0a 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,30 @@ "name": "datary", "version": "0.0.1", "description": "A modern cross-platform database explorer", + "author": { + "name": "Vadim (TeaCoder)", + "url": "https://github.com/TeaCoder52" + }, + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/TeaCoder52/datary.git" + }, + "homepage": "https://github.com/TeaCoder52/datary#readme", + "bugs": { + "url": "https://github.com/TeaCoder52/datary/issues" + }, + "keywords": [ + "electron", + "desktop", + "database", + "explorer", + "postgresql", + "mysql", + "mariadb", + "mssql" + ], + "packageManager": "pnpm@10.0.0", "scripts": { "build": "pnpm run build:packages && pnpm --filter @datary/desktop build", "build:windows": "pnpm run build && pnpm --filter @datary/desktop dist --win", @@ -17,11 +41,11 @@ "lint-staged": { "{apps,packages}/**/*.{ts,tsx,json,md}": "prettier --write" }, - "packageManager": "pnpm@10.0.0", "devDependencies": { "@commitlint/cli": "^20.3.1", "@commitlint/config-conventional": "^20.3.1", "@commitlint/types": "^20.3.1", + "@electron/rebuild": "^4.0.3", "@trivago/prettier-plugin-sort-imports": "^6.0.2", "@types/electron-builder": "^2.8.2", "@types/node": "^24.10.9", diff --git a/packages/core/src/application/ports/credential.port.ts b/packages/core/src/application/ports/credential.port.ts deleted file mode 100644 index bcb4689..0000000 --- a/packages/core/src/application/ports/credential.port.ts +++ /dev/null @@ -1,4 +0,0 @@ -export interface CredentialPort { - encrypt?(plain: string): Promise - decrypt(encrypted: string): Promise -} diff --git a/packages/core/src/application/ports/db.adapter.port.ts b/packages/core/src/application/ports/db.adapter.port.ts index 7229d0a..8ae2f8d 100644 --- a/packages/core/src/application/ports/db.adapter.port.ts +++ b/packages/core/src/application/ports/db.adapter.port.ts @@ -1,4 +1,3 @@ -import { DatabaseMetadataContract } from '../../contracts/metadata.contract' import type { QueryResult } from '../../domain/query/query.types' export interface DbAdapterPort { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6d3b8dd..cfa88c6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -17,6 +17,9 @@ importers: '@commitlint/types': specifier: ^20.3.1 version: 20.3.1 + '@electron/rebuild': + specifier: ^4.0.3 + version: 4.0.3 '@trivago/prettier-plugin-sort-imports': specifier: ^6.0.2 version: 6.0.2(prettier@3.8.1) @@ -65,9 +68,15 @@ importers: '@datary/ipc': specifier: workspace:* version: link:../../packages/ipc + add: + specifier: ^2.0.6 + version: 2.0.6 electron-store: specifier: ^11.0.2 version: 11.0.2 + keytar: + specifier: ^7.9.0 + version: 7.9.0 devDependencies: concurrently: specifier: ^9.2.1 @@ -467,6 +476,11 @@ packages: engines: {node: '>=22.12.0'} hasBin: true + '@electron/rebuild@4.0.3': + resolution: {integrity: sha512-u9vpTHRMkOYCs/1FLiSVAFZ7FbjsXK+bQuzviJZa+lG7BHZl1nz52/IcGvwa3sk80/fc3llutBkbCq10Vh8WQA==} + engines: {node: '>=22.12.0'} + hasBin: true + '@electron/universal@2.0.3': resolution: {integrity: sha512-Wn9sPYIVFRFl5HmwMJkARCCf7rqK/EurkfQ/rJZ14mHP3iYTjZSIOSVonEAnhWeAXwtw7zOekGRlc6yTtZ0t+g==} engines: {node: '>=16.4'} @@ -2078,6 +2092,9 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + add@2.0.6: + resolution: {integrity: sha512-j5QzrmsokwWWp6kUcJQySpbG+xfOBqqKnup3OIk1pz+kB/80SLorZ9V8zHFLO92Lcd+hbvq8bT+zOGoPkmBV0Q==} + agent-base@7.1.4: resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} engines: {node: '>= 14'} @@ -2291,6 +2308,9 @@ packages: resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==} engines: {node: '>= 20.19.0'} + chownr@1.1.4: + resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} + chownr@2.0.0: resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} engines: {node: '>=10'} @@ -2502,6 +2522,10 @@ packages: resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} engines: {node: '>=10'} + deep-extend@0.6.0: + resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} + engines: {node: '>=4.0.0'} + deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} @@ -2785,6 +2809,10 @@ packages: resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} engines: {node: '>=16.17'} + expand-template@2.0.3: + resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} + engines: {node: '>=6'} + exponential-backoff@3.1.3: resolution: {integrity: sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==} @@ -2861,6 +2889,9 @@ packages: resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} engines: {node: '>= 6'} + fs-constants@1.0.0: + resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} + fs-extra@10.1.0: resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} engines: {node: '>=12'} @@ -2954,6 +2985,9 @@ packages: git-url-parse@16.1.0: resolution: {integrity: sha512-cPLz4HuK86wClEW7iDdeAKcCVlWXmrLpb2L+G9goW0Z1dtpNS6BXXSOckUTlJT/LDQViE1QZKstNORzHsLnobw==} + github-from-package@0.0.0: + resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} + glob-parent@6.0.2: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} @@ -3105,6 +3139,9 @@ packages: inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + ini@4.1.1: resolution: {integrity: sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -3288,6 +3325,9 @@ packages: jws@4.0.1: resolution: {integrity: sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==} + keytar@7.9.0: + resolution: {integrity: sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ==} + keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} @@ -3623,6 +3663,9 @@ packages: resolution: {integrity: sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==} engines: {node: '>= 18'} + mkdirp-classic@0.5.3: + resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} + mkdirp@0.5.6: resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} hasBin: true @@ -3661,6 +3704,9 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + napi-build-utils@2.0.0: + resolution: {integrity: sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==} + native-duplexpair@1.0.0: resolution: {integrity: sha512-E7QQoM+3jvNtlmyfqRZ0/U75VFgCls+fSkbml2MpgWkWyz3ox8Y58gNhfuziuQYGNNQAbFZJQck55LHCnCK6CA==} @@ -3679,6 +3725,10 @@ packages: resolution: {integrity: sha512-NHDDGYudnvRutt/VhKFlX26IotXe1w0cmkDm6JGquh5bz/bDTw0LufSmH/GxTjEdpHEO+bVKFTwdrcGa/9XlKQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + node-abi@3.87.0: + resolution: {integrity: sha512-+CGM1L1CgmtheLcBuleyYOn7NWPVu0s0EJH2C4puxgEZb9h8QpR9G2dBfZJOAUhi7VQxuBPMd0hiISWcTyiYyQ==} + engines: {node: '>=10'} + node-abi@4.26.0: resolution: {integrity: sha512-8QwIZqikRvDIkXS2S93LjzhsSPJuIbfaMETWH+Bx8oOT9Sa9UsUtBFQlc3gBNd1+QINjaTloitXr1W3dQLi9Iw==} engines: {node: '>=22.12.0'} @@ -3686,6 +3736,9 @@ packages: node-addon-api@1.7.2: resolution: {integrity: sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==} + node-addon-api@4.3.0: + resolution: {integrity: sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==} + node-api-version@0.2.1: resolution: {integrity: sha512-2xP/IGGMmmSQpI1+O/k72jF/ykvZ89JeuKX3TLJAYPDVLUalrshrLHkeVcCCZqG/eEa635cr8IBYzgnDvM2O8Q==} @@ -3943,6 +3996,11 @@ packages: engines: {node: '>=14.0.0'} hasBin: true + prebuild-install@7.1.3: + resolution: {integrity: sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==} + engines: {node: '>=10'} + hasBin: true + prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} @@ -4060,6 +4118,10 @@ packages: rc9@2.1.2: resolution: {integrity: sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==} + rc@1.2.8: + resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} + hasBin: true + react-dom@19.2.3: resolution: {integrity: sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==} peerDependencies: @@ -4295,6 +4357,12 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} + simple-concat@1.0.1: + resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} + + simple-get@4.0.1: + resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==} + simple-update-notifier@2.0.0: resolution: {integrity: sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==} engines: {node: '>=10'} @@ -4388,6 +4456,10 @@ packages: resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} engines: {node: '>=12'} + strip-json-comments@2.0.1: + resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} + engines: {node: '>=0.10.0'} + strip-json-comments@3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} @@ -4424,14 +4496,22 @@ packages: resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==} engines: {node: '>=6'} + tar-fs@2.1.4: + resolution: {integrity: sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==} + + tar-stream@2.2.0: + resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} + engines: {node: '>=6'} + tar@6.2.1: resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} engines: {node: '>=10'} - deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exhorbitant rates) by contacting i@izs.me + deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me tar@7.5.6: resolution: {integrity: sha512-xqUeu2JAIJpXyvskvU3uvQW8PAmHrtXp2KDuMJwQqW8Sqq0CaZBAQ+dKS3RBXVhU4wC5NjAdKrmh84241gO9cA==} engines: {node: '>=18'} + deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me tarn@3.0.2: resolution: {integrity: sha512-51LAVKUSZSVfI05vjPESNc5vwqqZpbXCsU+/+wxlOrUjk2SnFTt97v9ZgQrD4YmxYW1Px6w2KjaDitCfkvgxMQ==} @@ -4503,6 +4583,9 @@ packages: tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + tunnel-agent@0.6.0: + resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} + tw-animate-css@1.4.0: resolution: {integrity: sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ==} @@ -5236,6 +5319,24 @@ snapshots: transitivePeerDependencies: - supports-color + '@electron/rebuild@4.0.3': + dependencies: + '@malept/cross-spawn-promise': 2.0.0 + debug: 4.4.3 + detect-libc: 2.1.2 + got: 11.8.6 + graceful-fs: 4.2.11 + node-abi: 4.26.0 + node-api-version: 0.2.1 + node-gyp: 11.5.0 + ora: 5.4.1 + read-binary-file-arch: 1.0.6 + semver: 7.7.3 + tar: 7.5.6 + yargs: 17.7.2 + transitivePeerDependencies: + - supports-color + '@electron/universal@2.0.3': dependencies: '@electron/asar': 3.4.1 @@ -6842,6 +6943,8 @@ snapshots: acorn@8.15.0: {} + add@2.0.6: {} + agent-base@7.1.4: {} ajv-formats@3.0.1(ajv@8.17.1): @@ -7119,6 +7222,8 @@ snapshots: dependencies: readdirp: 5.0.0 + chownr@1.1.4: {} + chownr@2.0.0: {} chownr@3.0.0: {} @@ -7310,6 +7415,8 @@ snapshots: dependencies: mimic-response: 3.1.0 + deep-extend@0.6.0: {} + deep-is@0.1.4: {} default-browser-id@5.0.1: {} @@ -7685,6 +7792,8 @@ snapshots: signal-exit: 4.1.0 strip-final-newline: 3.0.0 + expand-template@2.0.3: {} + exponential-backoff@3.1.3: {} exsolve@1.0.8: {} @@ -7763,6 +7872,8 @@ snapshots: hasown: 2.0.2 mime-types: 2.1.35 + fs-constants@1.0.0: {} + fs-extra@10.1.0: dependencies: graceful-fs: 4.2.11 @@ -7877,6 +7988,8 @@ snapshots: dependencies: git-up: 8.1.1 + github-from-package@0.0.0: {} + glob-parent@6.0.2: dependencies: is-glob: 4.0.3 @@ -8041,6 +8154,8 @@ snapshots: inherits@2.0.4: {} + ini@1.3.8: {} + ini@4.1.1: {} inquirer@12.11.1(@types/node@24.10.9): @@ -8200,6 +8315,11 @@ snapshots: jwa: 2.0.1 safe-buffer: 5.2.1 + keytar@7.9.0: + dependencies: + node-addon-api: 4.3.0 + prebuild-install: 7.1.3 + keyv@4.5.4: dependencies: json-buffer: 3.0.1 @@ -8492,6 +8612,8 @@ snapshots: dependencies: minipass: 7.1.2 + mkdirp-classic@0.5.3: {} + mkdirp@0.5.6: dependencies: minimist: 1.2.8 @@ -8532,6 +8654,8 @@ snapshots: nanoid@3.3.11: {} + napi-build-utils@2.0.0: {} + native-duplexpair@1.0.0: {} natural-compare@1.4.0: {} @@ -8544,6 +8668,10 @@ snapshots: dependencies: type-fest: 2.19.0 + node-abi@3.87.0: + dependencies: + semver: 7.7.3 + node-abi@4.26.0: dependencies: semver: 7.7.3 @@ -8551,6 +8679,8 @@ snapshots: node-addon-api@1.7.2: optional: true + node-addon-api@4.3.0: {} + node-api-version@0.2.1: dependencies: semver: 7.7.3 @@ -8828,6 +8958,21 @@ snapshots: commander: 9.5.0 optional: true + prebuild-install@7.1.3: + dependencies: + detect-libc: 2.1.2 + expand-template: 2.0.3 + github-from-package: 0.0.0 + minimist: 1.2.8 + mkdirp-classic: 0.5.3 + napi-build-utils: 2.0.0 + node-abi: 3.87.0 + pump: 3.0.3 + rc: 1.2.8 + simple-get: 4.0.1 + tar-fs: 2.1.4 + tunnel-agent: 0.6.0 + prelude-ls@1.2.1: {} prettier-plugin-tailwindcss@0.7.2(@trivago/prettier-plugin-sort-imports@6.0.2(prettier@3.8.1))(prettier@3.8.1): @@ -8943,6 +9088,13 @@ snapshots: defu: 6.1.4 destr: 2.0.5 + rc@1.2.8: + dependencies: + deep-extend: 0.6.0 + ini: 1.3.8 + minimist: 1.2.8 + strip-json-comments: 2.0.1 + react-dom@19.2.3(react@19.2.3): dependencies: react: 19.2.3 @@ -9194,6 +9346,14 @@ snapshots: signal-exit@4.1.0: {} + simple-concat@1.0.1: {} + + simple-get@4.0.1: + dependencies: + decompress-response: 6.0.0 + once: 1.4.0 + simple-concat: 1.0.1 + simple-update-notifier@2.0.0: dependencies: semver: 7.7.3 @@ -9287,6 +9447,8 @@ snapshots: strip-final-newline@3.0.0: {} + strip-json-comments@2.0.1: {} + strip-json-comments@3.1.1: {} stubborn-fs@2.0.0: @@ -9317,6 +9479,21 @@ snapshots: tapable@2.3.0: {} + tar-fs@2.1.4: + dependencies: + chownr: 1.1.4 + mkdirp-classic: 0.5.3 + pump: 3.0.3 + tar-stream: 2.2.0 + + tar-stream@2.2.0: + dependencies: + bl: 4.1.0 + end-of-stream: 1.4.5 + fs-constants: 1.0.0 + inherits: 2.0.4 + readable-stream: 3.6.2 + tar@6.2.1: dependencies: chownr: 2.0.0 @@ -9402,6 +9579,10 @@ snapshots: tslib@2.8.1: {} + tunnel-agent@0.6.0: + dependencies: + safe-buffer: 5.2.1 + tw-animate-css@1.4.0: {} type-check@0.4.0: diff --git a/scripts/telegram-notify.js b/scripts/telegram-notify.js deleted file mode 100644 index c83494f..0000000 --- a/scripts/telegram-notify.js +++ /dev/null @@ -1,38 +0,0 @@ -import fetch from 'node-fetch'; -import fs from 'fs'; - -const token = process.env.TELEGRAM_BOT_TOKEN; -const chatId = process.env.TELEGRAM_CHAT_ID; -const actor = process.env.GITHUB_ACTOR; -const event = process.env.GITHUB_EVENT_NAME; -const repo = process.env.GITHUB_REPOSITORY; -const ref = process.env.GITHUB_REF; -const sha = process.env.GITHUB_SHA; -const payloadPath = process.env.GITHUB_EVENT_PATH; - -let message = `*GitHub Notification*\n\nRepository: ${repo}\nActor: ${actor}\nEvent: ${event}\nRef: ${ref}\nSHA: ${sha}`; - -if (payloadPath && fs.existsSync(payloadPath)) { - const payload = JSON.parse(fs.readFileSync(payloadPath, 'utf8')); - - if (event === 'pull_request') { - const pr = payload.pull_request; - message += `\nPR Title: ${pr.title}\nAction: ${payload.action}\nURL: ${pr.html_url}`; - } - - if (event === 'issues') { - const issue = payload.issue; - message += `\nIssue Title: ${issue.title}\nAction: ${payload.action}\nURL: ${issue.html_url}`; - } -} - -await fetch(`https://api.telegram.org/bot${token}/sendMessage`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - chat_id: chatId, - text: message, - parse_mode: 'Markdown' - }) -}); -