flatten plugin/ into repo root for obsidian community plugin layout

- move src/, test/, esbuild.config.mjs, styles.css, tsconfig.json,
  package.json, package-lock.json from plugin/ to repo root
- merge plugin/package.json into root package.json (deps + scripts)
- drop esbuild mirror-files plugin (manifest.json/versions.json no
  longer need to be copied; they live next to the build output)
- update release workflow, gitignore, README, scripts to match
- swap fetch() for obsidian's requestUrl in setupBot per plugin
  guidelines
This commit is contained in:
tmlnv 2026-04-29 22:35:55 +03:00
parent 890ea9da84
commit b70131db90
23 changed files with 71 additions and 91 deletions

View file

@ -20,15 +20,12 @@ jobs:
with:
node-version: "20"
cache: "npm"
cache-dependency-path: plugin/package-lock.json
- name: Install plugin dependencies
- name: Install dependencies
run: npm ci
working-directory: plugin
- name: Build plugin
run: npm run build
working-directory: plugin
- name: Verify manifest version matches tag
run: |
@ -43,8 +40,8 @@ jobs:
run: |
mkdir -p release
cp manifest.json release/manifest.json
cp plugin/main.js release/main.js
cp plugin/styles.css release/styles.css
cp main.js release/main.js
cp styles.css release/styles.css
- name: Create GitHub release
uses: softprops/action-gh-release@v2

7
.gitignore vendored
View file

@ -3,10 +3,7 @@ dist/
.DS_Store
.env
.env.*
plugin/main.js
plugin/manifest.json
plugin/versions.json
plugin/node_modules/
plugin/coverage/
main.js
coverage/
supabase/.temp/
testing/

View file

@ -141,17 +141,17 @@ Until this plugin is published to the Obsidian community registry, install it ma
1. Build the plugin:
```bash
npm install --prefix plugin
npm run build:plugin
npm install
npm run build
```
2. Copy the output files into your vault's plugin folder:
```
<vault>/.obsidian/plugins/telegram-bridge/
├── main.js (from plugin/main.js)
├── manifest.json (from repo root)
└── styles.css (from plugin/styles.css)
├── main.js
├── manifest.json
└── styles.css
```
3. In Obsidian → **Settings → Community plugins**, enable **Telegram Bridge**.
@ -325,21 +325,22 @@ The Telegram Bot API limits file downloads to **20 MB**. Anything larger cannot
## Repository layout
```
obsidian-telegram/
├── manifest.json Obsidian plugin manifest (release source of truth)
obsidian-telegram-bridge/
├── manifest.json Obsidian plugin manifest
├── versions.json Plugin → min Obsidian app version map
├── plugin/ Obsidian plugin (TypeScript + esbuild)
│ ├── manifest.json Copied from root manifest by esbuild (gitignored)
│ ├── styles.css Plugin styles
│ └── src/
│ ├── main.ts Plugin entry point
│ ├── sync-engine.ts Polling, cursor management, Realtime
│ ├── vault-writer.ts File creation and editing in the vault
│ ├── message-renderer.ts Markdown rendering with block markers
│ ├── template-engine.ts Template variable expansion
│ ├── distribution-rules.ts Filter query evaluation
│ ├── settings-tab.ts Settings UI
│ └── types.ts Shared TypeScript types
├── styles.css Plugin styles
├── esbuild.config.mjs Build config
├── tsconfig.json TypeScript config
├── src/
│ ├── main.ts Plugin entry point
│ ├── sync-engine.ts Polling, cursor management, Realtime
│ ├── vault-writer.ts File creation and editing in the vault
│ ├── message-renderer.ts Markdown rendering with block markers
│ ├── template-engine.ts Template variable expansion
│ ├── distribution-rules.ts Filter query evaluation
│ ├── settings-tab.ts Settings UI
│ └── types.ts Shared TypeScript types
├── test/ Vitest unit tests
├── supabase/
│ ├── config.toml Local dev config
│ ├── functions/

View file

@ -1,6 +1,5 @@
import esbuild from "esbuild";
import process from "process";
import { copyFileSync } from "node:fs";
import builtins from "builtin-modules";
const banner = `/*
@ -11,19 +10,6 @@ if you want to view the source, please visit the github repository of this plugi
const isProduction = process.argv[2] === "production";
const filesToMirror = ["manifest.json", "versions.json"];
const mirrorRootFilesPlugin = {
name: "mirror-root-files",
setup(build) {
build.onEnd(() => {
for (const file of filesToMirror) {
copyFileSync(`../${file}`, file);
}
});
},
};
const context = await esbuild.context({
banner: { js: banner },
entryPoints: ["src/main.ts"],
@ -50,7 +36,6 @@ const context = await esbuild.context({
sourcemap: isProduction ? false : "inline",
treeShaking: true,
outfile: "main.js",
plugins: [mirrorRootFilesPlugin],
});
if (isProduction) {

View file

@ -1,11 +1,11 @@
{
"name": "obsidian-telegram-plugin",
"name": "telegram-bridge",
"version": "0.1.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "obsidian-telegram-plugin",
"name": "telegram-bridge",
"version": "0.1.0",
"dependencies": {
"@supabase/supabase-js": "^2.49.8"
@ -17,6 +17,9 @@
"obsidian": "latest",
"typescript": "^5.8.2",
"vitest": "^3.0.8"
},
"engines": {
"node": ">=20"
}
},
"node_modules/@codemirror/state": {
@ -498,7 +501,8 @@
"resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz",
"integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==",
"dev": true,
"license": "MIT"
"license": "MIT",
"peer": true
},
"node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.59.0",
@ -1179,7 +1183,8 @@
"resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz",
"integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==",
"dev": true,
"license": "MIT"
"license": "MIT",
"peer": true
},
"node_modules/debug": {
"version": "4.4.3",
@ -1425,7 +1430,6 @@
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true,
"license": "MIT",
"peer": true,
"engines": {
"node": ">=12"
},
@ -1556,7 +1560,8 @@
"resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.3.tgz",
"integrity": "sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ==",
"dev": true,
"license": "MIT"
"license": "MIT",
"peer": true
},
"node_modules/tinybench": {
"version": "2.9.0",
@ -2305,7 +2310,8 @@
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz",
"integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==",
"dev": true,
"license": "MIT"
"license": "MIT",
"peer": true
},
"node_modules/why-is-node-running": {
"version": "2.3.0",

View file

@ -1,16 +1,28 @@
{
"name": "telegram-bridge",
"version": "0.1.0",
"private": true,
"description": "Monorepo for the Telegram Bridge Obsidian plugin and Supabase backend",
"description": "Sync messages from Telegram into your vault through a self-hosted Supabase backend.",
"main": "main.js",
"scripts": {
"dev": "node esbuild.config.mjs",
"build": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production",
"test": "vitest run",
"test:watch": "vitest",
"verify": "node scripts/verify-local-env.mjs",
"bootstrap:supabase": "node scripts/bootstrap-supabase.mjs",
"build:plugin": "npm run build --prefix plugin",
"dev:plugin": "npm run dev --prefix plugin",
"test:plugin": "npm run test --prefix plugin"
"bootstrap:supabase": "node scripts/bootstrap-supabase.mjs"
},
"engines": {
"node": ">=20"
},
"devDependencies": {
"@types/node": "^20.17.30",
"builtin-modules": "^3.3.0",
"esbuild": "^0.25.1",
"obsidian": "latest",
"typescript": "^5.8.2",
"vitest": "^3.0.8"
},
"dependencies": {
"@supabase/supabase-js": "^2.49.8"
}
}

View file

@ -1,23 +0,0 @@
{
"name": "telegram-bridge-plugin",
"version": "0.1.0",
"description": "Telegram Bridge Obsidian plugin backed by Supabase",
"main": "main.js",
"scripts": {
"dev": "node esbuild.config.mjs",
"build": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production",
"test": "vitest run",
"test:watch": "vitest"
},
"devDependencies": {
"@types/node": "^20.17.30",
"builtin-modules": "^3.3.0",
"esbuild": "^0.25.1",
"obsidian": "latest",
"typescript": "^5.8.2",
"vitest": "^3.0.8"
},
"dependencies": {
"@supabase/supabase-js": "^2.49.8"
}
}

View file

@ -51,8 +51,8 @@ function main() {
console.log("supabase secrets set SUPABASE_ANON_KEY=<value> SUPABASE_SERVICE_ROLE_KEY=<value>");
console.log("");
console.log("After deployment:");
console.log("1. Install plugin dependencies with: npm install --prefix plugin");
console.log("2. Build the plugin with: npm run build:plugin");
console.log("1. Install plugin dependencies with: npm install");
console.log("2. Build the plugin with: npm run build");
console.log("3. Open Obsidian and complete bot setup in the plugin settings.");
}

View file

@ -5,8 +5,8 @@ import { constants } from "node:fs";
import { spawnSync } from "node:child_process";
const requiredFiles = [
"plugin/manifest.json",
"plugin/package.json",
"manifest.json",
"package.json",
"supabase/config.toml",
"supabase/migrations/202603030001_initial_schema.sql",
];

View file

@ -1,4 +1,4 @@
import { Notice, Platform, Plugin } from "obsidian";
import { Notice, Platform, Plugin, requestUrl } from "obsidian";
import {
createDefaultDistributionRule,
DEFAULT_SETTINGS,
@ -234,7 +234,8 @@ export default class ObsidianTelegramPlugin extends Plugin {
throw new Error("Sign in before setting up the Telegram bot.");
}
const response = await fetch(`${this.settings.supabase_url}/functions/v1/setup-bot`, {
const response = await requestUrl({
url: `${this.settings.supabase_url}/functions/v1/setup-bot`,
method: "POST",
headers: {
"Content-Type": "application/json",
@ -242,13 +243,17 @@ export default class ObsidianTelegramPlugin extends Plugin {
apikey: this.settings.supabase_anon_key,
},
body: JSON.stringify({ bot_token: botToken }),
throw: false,
});
const payload = (await response.json().catch(() => null)) as
| { error?: string; bot_username?: string; webhook_url?: string }
| null;
let payload: { error?: string; bot_username?: string; webhook_url?: string } | null = null;
try {
payload = response.json as { error?: string; bot_username?: string; webhook_url?: string };
} catch {
payload = null;
}
if (!response.ok) {
if (response.status < 200 || response.status >= 300) {
throw new Error(payload?.error ?? `Bot setup failed with status ${response.status}.`);
}