diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b20dc61..2c15a6f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -15,16 +15,13 @@ jobs: cache: true - run: vp build --mode prod - name: Validate version + id: validate run: | - tag_version="${GITHUB_REF#refs/tags/}" - manifest_version="$(jq -r .version < dist/manifest.json)" - if [[ "$tag_version" != "$manifest_version" ]]; then - echo "Version mismatch found: tag $tag_version, manifest $manifest_version" - exit 1 - fi + vp exec node ./tool/validate_ci.ts - uses: softprops/action-gh-release@v2 with: draft: true + prerelease: ${{ steps.validate.outputs.prerelease == 'true' }} working_directory: dist files: | main.js diff --git a/package.json b/package.json index bc8453a..158c296 100644 --- a/package.json +++ b/package.json @@ -11,10 +11,16 @@ "obsidian": "^1.12.3" }, "devDependencies": { + "@optique/core": "^1.0.2", + "@optique/run": "^1.0.2", + "@types/node": "^25.6.0", + "@types/semver": "^7.7.1", + "dax": "^0.45.0", "eslint-plugin-obsidianmd": "^0.2.4", + "semver": "^7.7.4", "typescript": "~6.0.3", "vite": "catalog:", "vite-plus": "catalog:" }, - "packageManager": "pnpm@10.33.0" + "packageManager": "pnpm@10.33.2" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1c46a42..fe71baf 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -31,18 +31,36 @@ importers: specifier: ^1.12.3 version: 1.12.3(@codemirror/state@6.6.0)(@codemirror/view@6.41.1) devDependencies: + '@optique/core': + specifier: ^1.0.2 + version: 1.0.2 + '@optique/run': + specifier: ^1.0.2 + version: 1.0.2 + '@types/node': + specifier: ^25.6.0 + version: 25.6.0 + '@types/semver': + specifier: ^7.7.1 + version: 7.7.1 + dax: + specifier: ^0.45.0 + version: 0.45.0 eslint-plugin-obsidianmd: specifier: ^0.2.4 version: 0.2.4(@eslint/js@9.39.4)(@eslint/json@0.14.0)(@typescript-eslint/parser@8.58.1(eslint@9.39.4)(typescript@6.0.3))(eslint@9.39.4)(obsidian@1.12.3(@codemirror/state@6.6.0)(@codemirror/view@6.41.1))(typescript-eslint@8.58.1(eslint@9.39.4)(typescript@6.0.3)) + semver: + specifier: ^7.7.4 + version: 7.7.4 typescript: specifier: ~6.0.3 version: 6.0.3 vite: specifier: npm:@voidzero-dev/vite-plus-core@latest - version: '@voidzero-dev/vite-plus-core@0.1.19(typescript@6.0.3)(yaml@2.8.3)' + version: '@voidzero-dev/vite-plus-core@0.1.19(@types/node@25.6.0)(typescript@6.0.3)(yaml@2.8.3)' vite-plus: specifier: 'catalog:' - version: 0.1.19(@voidzero-dev/vite-plus-core@0.1.19(typescript@6.0.3)(yaml@2.8.3))(typescript@6.0.3)(yaml@2.8.3) + version: 0.1.19(@types/node@25.6.0)(@voidzero-dev/vite-plus-core@0.1.19(@types/node@25.6.0)(typescript@6.0.3)(yaml@2.8.3))(typescript@6.0.3)(yaml@2.8.3) packages: @@ -55,6 +73,12 @@ packages: '@codemirror/view@6.41.1': resolution: {integrity: sha512-ToDnWKbBnke+ZLrP6vgTTDScGi5H37YYuZGniQaBzxMVdtCxMrslsmtnOvbPZk4RX9bvkQqnWR/WS/35tJA0qg==} + '@deno/shim-deno-test@0.5.0': + resolution: {integrity: sha512-4nMhecpGlPi0cSzT67L+Tm+GOJqvuk8gqHBziqcUQOarnuIax1z96/gJHCSIz2Z0zhxE6Rzwb3IZXPtFh51j+w==} + + '@deno/shim-deno@0.19.2': + resolution: {integrity: sha512-q3VTHl44ad8T2Tw2SpeAvghdGOjlnLPDNO2cpOxwMrBE/PVas6geWpbpIgrM+czOCH0yejp0yi8OaTuB+NU40Q==} + '@eslint-community/eslint-utils@4.9.1': resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -151,6 +175,14 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} + '@optique/core@1.0.2': + resolution: {integrity: sha512-znsqMmjAdeOgSJzdJlpZpgAscojwQmeQYXzYnuEKllz5VCj6WyEkdzU4QuvJQtWQY3ve2taXwudEBRur0VHBOQ==} + engines: {bun: '>=1.2.0', deno: '>=2.3.0', node: '>=20.0.0'} + + '@optique/run@1.0.2': + resolution: {integrity: sha512-0Wc+zC8SLGV8zXQX+pk+o0c6wE/ddx/36CHZ0toTh5lApsjruUuGhqbxvljerAAG5un1xQbOLxzksBVC6UPgSg==} + engines: {bun: '>=1.2.0', deno: '>=2.3.0', node: '>=20.0.0'} + '@oxc-project/runtime@0.126.0': resolution: {integrity: sha512-oksjxfqDNmIYMGlIgLzYgnz5YjZax27RtQezsPpKEGo9AC5LOaIGHsivCCeaAWdCtPnRyjZXM/7svreCC8kZVQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -469,6 +501,12 @@ packages: '@types/node@20.12.12': resolution: {integrity: sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==} + '@types/node@25.6.0': + resolution: {integrity: sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ==} + + '@types/semver@7.7.1': + resolution: {integrity: sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==} + '@types/tern@0.23.9': resolution: {integrity: sha512-ypzHFE/wBzh+BlH6rrBgS5I/Z7RD21pGhZ2rltb/+ZrVM1awdZwjx7hE5XfuYgHWk9uvV5HLZN3SloevCAp3Bw==} @@ -848,6 +886,9 @@ packages: resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} engines: {node: '>= 0.4'} + dax@0.45.0: + resolution: {integrity: sha512-y/47GKisPkHCtkDQVr3yfJEtVTuXqMVXhU4Au8Xrzu4s+s9eQUBGuCFHBwrfUrsry0Or6NyusHl0DSi6qj7/4w==} + debug@3.2.7: resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} peerDependencies: @@ -1339,6 +1380,10 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + isexe@3.1.5: + resolution: {integrity: sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w==} + engines: {node: '>=18'} + iterator.prototype@1.1.5: resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==} engines: {node: '>= 0.4'} @@ -1911,6 +1956,9 @@ packages: undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + undici-types@7.19.2: + resolution: {integrity: sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==} + uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} @@ -1943,6 +1991,11 @@ packages: engines: {node: '>= 8'} hasBin: true + which@4.0.0: + resolution: {integrity: sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==} + engines: {node: ^16.13.0 || >=18.0.0} + hasBin: true + word-wrap@1.2.5: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} @@ -1994,6 +2047,13 @@ snapshots: style-mod: 4.1.3 w3c-keyname: 2.2.8 + '@deno/shim-deno-test@0.5.0': {} + + '@deno/shim-deno@0.19.2': + dependencies: + '@deno/shim-deno-test': 0.5.0 + which: 4.0.0 + '@eslint-community/eslint-utils@4.9.1(eslint@9.39.4)': dependencies: eslint: 9.39.4 @@ -2096,6 +2156,12 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.20.1 + '@optique/core@1.0.2': {} + + '@optique/run@1.0.2': + dependencies: + '@optique/core': 1.0.2 + '@oxc-project/runtime@0.126.0': {} '@oxc-project/types@0.126.0': {} @@ -2266,6 +2332,12 @@ snapshots: dependencies: undici-types: 5.26.5 + '@types/node@25.6.0': + dependencies: + undici-types: 7.19.2 + + '@types/semver@7.7.1': {} + '@types/tern@0.23.9': dependencies: '@types/estree': 1.0.8 @@ -2413,13 +2485,14 @@ snapshots: '@typescript-eslint/types': 8.58.1 eslint-visitor-keys: 5.0.1 - '@voidzero-dev/vite-plus-core@0.1.19(typescript@6.0.3)(yaml@2.8.3)': + '@voidzero-dev/vite-plus-core@0.1.19(@types/node@25.6.0)(typescript@6.0.3)(yaml@2.8.3)': dependencies: '@oxc-project/runtime': 0.126.0 '@oxc-project/types': 0.126.0 lightningcss: 1.32.0 postcss: 8.5.10 optionalDependencies: + '@types/node': 25.6.0 fsevents: 2.3.3 typescript: 6.0.3 yaml: 2.8.3 @@ -2442,11 +2515,11 @@ snapshots: '@voidzero-dev/vite-plus-linux-x64-musl@0.1.19': optional: true - '@voidzero-dev/vite-plus-test@0.1.19(@voidzero-dev/vite-plus-core@0.1.19(typescript@6.0.3)(yaml@2.8.3))(typescript@6.0.3)(yaml@2.8.3)': + '@voidzero-dev/vite-plus-test@0.1.19(@types/node@25.6.0)(@voidzero-dev/vite-plus-core@0.1.19(@types/node@25.6.0)(typescript@6.0.3)(yaml@2.8.3))(typescript@6.0.3)(yaml@2.8.3)': dependencies: '@standard-schema/spec': 1.1.0 '@types/chai': 5.2.3 - '@voidzero-dev/vite-plus-core': 0.1.19(typescript@6.0.3)(yaml@2.8.3) + '@voidzero-dev/vite-plus-core': 0.1.19(@types/node@25.6.0)(typescript@6.0.3)(yaml@2.8.3) es-module-lexer: 1.7.0 obug: 2.1.1 pixelmatch: 7.1.0 @@ -2456,8 +2529,10 @@ snapshots: tinybench: 2.9.0 tinyexec: 1.1.1 tinyglobby: 0.2.16 - vite: '@voidzero-dev/vite-plus-core@0.1.19(typescript@6.0.3)(yaml@2.8.3)' + vite: '@voidzero-dev/vite-plus-core@0.1.19(@types/node@25.6.0)(typescript@6.0.3)(yaml@2.8.3)' ws: 8.20.0 + optionalDependencies: + '@types/node': 25.6.0 transitivePeerDependencies: - '@arethetypeswrong/core' - '@tsdown/css' @@ -2665,6 +2740,11 @@ snapshots: es-errors: 1.3.0 is-data-view: 1.0.2 + dax@0.45.0: + dependencies: + '@deno/shim-deno': 0.19.2 + undici-types: 5.26.5 + debug@3.2.7: dependencies: ms: 2.1.3 @@ -3305,6 +3385,8 @@ snapshots: isexe@2.0.0: {} + isexe@3.1.5: {} + iterator.prototype@1.1.5: dependencies: define-data-property: 1.1.4 @@ -3953,15 +4035,17 @@ snapshots: undici-types@5.26.5: {} + undici-types@7.19.2: {} + uri-js@4.4.1: dependencies: punycode: 2.3.1 - vite-plus@0.1.19(@voidzero-dev/vite-plus-core@0.1.19(typescript@6.0.3)(yaml@2.8.3))(typescript@6.0.3)(yaml@2.8.3): + vite-plus@0.1.19(@types/node@25.6.0)(@voidzero-dev/vite-plus-core@0.1.19(@types/node@25.6.0)(typescript@6.0.3)(yaml@2.8.3))(typescript@6.0.3)(yaml@2.8.3): dependencies: '@oxc-project/types': 0.126.0 - '@voidzero-dev/vite-plus-core': 0.1.19(typescript@6.0.3)(yaml@2.8.3) - '@voidzero-dev/vite-plus-test': 0.1.19(@voidzero-dev/vite-plus-core@0.1.19(typescript@6.0.3)(yaml@2.8.3))(typescript@6.0.3)(yaml@2.8.3) + '@voidzero-dev/vite-plus-core': 0.1.19(@types/node@25.6.0)(typescript@6.0.3)(yaml@2.8.3) + '@voidzero-dev/vite-plus-test': 0.1.19(@types/node@25.6.0)(@voidzero-dev/vite-plus-core@0.1.19(@types/node@25.6.0)(typescript@6.0.3)(yaml@2.8.3))(typescript@6.0.3)(yaml@2.8.3) oxfmt: 0.45.0 oxlint: 1.60.0(oxlint-tsgolint@0.21.1) oxlint-tsgolint: 0.21.1 @@ -4051,6 +4135,10 @@ snapshots: dependencies: isexe: 2.0.0 + which@4.0.0: + dependencies: + isexe: 3.1.5 + word-wrap@1.2.5: {} ws@8.20.0: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index debad8c..8bf4678 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -12,4 +12,3 @@ peerDependencyRules: allowedVersions: vite: "*" vitest: "*" -tagVersionPrefix: "" diff --git a/tool/bump_version.ts b/tool/bump_version.ts new file mode 100644 index 0000000..59248c9 --- /dev/null +++ b/tool/bump_version.ts @@ -0,0 +1,37 @@ +import { object } from "@optique/core/constructs"; +import { argument, option } from "@optique/core/primitives"; +import { choice, string } from "@optique/core/valueparser"; +import { optional } from "@optique/core/modifiers"; +import { run } from "@optique/run"; +import $ from "dax"; +import semver from "semver"; +import manifest from "../manifest.json" with { type: "json" }; + +const parser = object({ + release: argument(choice(semver.RELEASE_TYPES)), + preId: optional(option("--preid", string())), + dryRun: option("--dry-run"), +}); +const config = run(parser, { help: "option" }); + +$.setPrintCommand(true); + +const incremented = new semver.SemVer(manifest.version).inc(config.release, config.preId).version; + +const patch = ` +diff --git a/manifest.json b/manifest.json +--- a/manifest.json ++++ b/manifest.json +@@ -1 +1 @@ +- "version": "${manifest.version}", ++ "version": "${incremented}", +`; + +if (config.dryRun) { + console.log(patch); + process.exit(0); +} + +await $`git apply --cached --index --unidiff-zero`.stdinText(patch); +await $`git commit -m "chore: Bump version to ${incremented}"`; +await $`git tag -a ${incremented} -m ${incremented}`; diff --git a/tool/test_local.ts b/tool/test_local.ts new file mode 100644 index 0000000..50c93ca --- /dev/null +++ b/tool/test_local.ts @@ -0,0 +1,29 @@ +import { object } from "@optique/core/constructs"; +import { option } from "@optique/core/primitives"; +import { run } from "@optique/run"; +import $ from "dax"; + +const parser = object({ + reload: option("--reload"), +}); +const config = run(parser, { help: "option" }); + +$.setPrintCommand(true); + +const isRunning = await $`obsidian eval code=true`.stderr("null").timeout(1000).noThrow().text(); +if (isRunning !== "=> true") { + console.log("Obsidian is not running"); + process.exit(1); +} + +const vault = await $`obsidian vault info=path`.stderr("null").text(); +const configDir = await $`obsidian eval code=app.vault.configDir` + .stderr("null") + .text() + .then((text) => text.replace(/^=>\s*/, "")); +const pluginDir = $.path(vault).join(configDir, "plugins", "embed-plus"); +await $`cp dist/* ${pluginDir}`; + +if (config.reload) { + await $`obsidian plugin:reload id=embed-plus`.stderr("null"); +} diff --git a/tool/validate_ci.ts b/tool/validate_ci.ts new file mode 100644 index 0000000..b1d557f --- /dev/null +++ b/tool/validate_ci.ts @@ -0,0 +1,14 @@ +import $ from "dax"; +import semver from "semver"; +import manifest from "../manifest.json" with { type: "json" }; + +$.setPrintCommand(true); + +const tag = process.env.GITHUB_REF?.replace("refs/tags/", "") ?? ""; +if (manifest.version !== tag) { + await $`echo "::error::Version mismatch: manifest version ${manifest.version} does not match tag ${tag}"`; + process.exit(1); +} + +const version = new semver.SemVer(manifest.version); +await $`echo prerelease=${version.prerelease.length > 0} > "$GITHUB_OUTPUT"`; diff --git a/tsconfig.json b/tsconfig.json index ef9e98a..fe467e0 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,7 +3,7 @@ "target": "es2025", "module": "esnext", "lib": ["es2025", "dom"], - "types": ["vite/client"], + "types": ["vite/client", "node"], "skipLibCheck": true, /* Bundler mode */ @@ -21,6 +21,5 @@ "noFallthroughCasesInSwitch": true, "exactOptionalPropertyTypes": true, "noUncheckedIndexedAccess": true - }, - "include": ["src"] + } } diff --git a/vite.config.ts b/vite.config.ts index 4548b42..3feb75a 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -43,6 +43,9 @@ function copyManifest(): Plugin { const manifest = JSON.parse( await this.fs.readFile(join(root, "manifest.json"), { encoding: "utf8" }), ); + if (mode !== "prod") { + manifest.version += "+dev"; + } this.emitFile({ type: "asset", fileName: "manifest.json", @@ -92,4 +95,13 @@ export default defineConfig({ }, }, }, + run: { + tasks: { + "bump-version": { command: "node ./tool/bump_version.ts" }, + "test-local": { + command: "node ./tool/test_local.ts", + input: ["dist/main.js", "dist/manifest.json", "dist/styles.css"], + }, + }, + }, });