From e947b0f172b3155c9e32a289a3775cf05e048b50 Mon Sep 17 00:00:00 2001 From: matteo-cristino Date: Thu, 8 Aug 2024 11:56:48 +0200 Subject: [PATCH 1/6] refactor(git): make git plugin usable on browser --- pkg/git/src/plugin.ts | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/pkg/git/src/plugin.ts b/pkg/git/src/plugin.ts index 174713ed..d0784c13 100644 --- a/pkg/git/src/plugin.ts +++ b/pkg/git/src/plugin.ts @@ -4,20 +4,19 @@ import { Plugin } from '@slangroom/core'; import gitpkg from 'isomorphic-git'; -// TODO: why does this require index.js? -import http from 'isomorphic-git/http/node/index.js'; -import * as fs from 'node:fs/promises'; -import * as path from 'node:path'; +import http from 'isomorphic-git/http/web/index.js'; +import { promises as fs } from 'fs'; +import * as path from 'path'; // read the version from the package.json import packageJson from '@slangroom/git/package.json' with { type: 'json' }; export const version = packageJson.version; export class GitError extends Error { - constructor(e: string) { - super(e) - this.name = 'Slangroom @slangroom/git@' + packageJson.version + ' Error' - } + constructor(e: string) { + super(e) + this.name = 'Slangroom @slangroom/git@' + packageJson.version + ' Error' + } } /** From 2093d2100c6488640bd0b25cdaa5b08dc8def89d Mon Sep 17 00:00:00 2001 From: matteo-cristino Date: Mon, 19 Aug 2024 15:17:26 +0200 Subject: [PATCH 2/6] feat(git): use ZenFS instead of fs and path-browserify instead of path to make git plugin really working on browser --- pkg/git/package.json | 7 ++- pkg/git/src/plugin.ts | 4 +- pnpm-lock.yaml | 119 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 127 insertions(+), 3 deletions(-) diff --git a/pkg/git/package.json b/pkg/git/package.json index 28f71eb0..741abe37 100644 --- a/pkg/git/package.json +++ b/pkg/git/package.json @@ -3,7 +3,9 @@ "version": "1.38.1", "dependencies": { "@slangroom/core": "workspace:*", - "isomorphic-git": "^1.25.10" + "@zenfs/core": "^0.16.3", + "isomorphic-git": "^1.25.10", + "path-browserify": "^1.0.1" }, "repository": "https://github.com/dyne/slangroom", "license": "AGPL-3.0-only", @@ -38,5 +40,8 @@ }, "engines": { "node": "^18.20.0 || ^20.10.0 || >=22.0.0 <22.3.0 || ^22.4.0" + }, + "devDependencies": { + "@types/path-browserify": "^1.0.2" } } diff --git a/pkg/git/src/plugin.ts b/pkg/git/src/plugin.ts index d0784c13..3d8e0705 100644 --- a/pkg/git/src/plugin.ts +++ b/pkg/git/src/plugin.ts @@ -5,8 +5,8 @@ import { Plugin } from '@slangroom/core'; import gitpkg from 'isomorphic-git'; import http from 'isomorphic-git/http/web/index.js'; -import { promises as fs } from 'fs'; -import * as path from 'path'; +import { promises as fs } from '@zenfs/core'; +import * as path from 'path-browserify'; // read the version from the package.json import packageJson from '@slangroom/git/package.json' with { type: 'json' }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 242a61aa..7a7a4948 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -222,9 +222,19 @@ importers: '@slangroom/core': specifier: workspace:* version: link:../core + '@zenfs/core': + specifier: ^0.16.3 + version: 0.16.3 isomorphic-git: specifier: ^1.25.10 version: 1.25.10 + path-browserify: + specifier: ^1.0.1 + version: 1.0.1 + devDependencies: + '@types/path-browserify': + specifier: ^1.0.2 + version: 1.0.2 pkg/helpers: dependencies: @@ -861,6 +871,7 @@ packages: '@humanwhocodes/config-array@0.11.14': resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} engines: {node: '>=10.10.0'} + deprecated: Use @eslint/config-array instead '@humanwhocodes/module-importer@1.0.1': resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} @@ -868,6 +879,7 @@ packages: '@humanwhocodes/object-schema@2.0.2': resolution: {integrity: sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==} + deprecated: Use @eslint/object-schema instead '@hutson/parse-repository-url@5.0.0': resolution: {integrity: sha512-e5+YUKENATs1JgYHMzTr2MW/NDcXGfYFAuOQU8gJgF/kEh4EqKgfGrfLI67bMD4tbhZVlkigz/9YYwWcbOFthg==} @@ -1283,12 +1295,21 @@ packages: '@types/node@20.11.30': resolution: {integrity: sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw==} + '@types/node@20.16.1': + resolution: {integrity: sha512-zJDo7wEadFtSyNz5QITDfRcrhqDvQI1xQNQ0VoizPjM/dVAODqqIUWbJPkvsxmTI0MYRGRikcdjMPhOssnPejQ==} + '@types/normalize-package-data@2.4.4': resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} + '@types/path-browserify@1.0.2': + resolution: {integrity: sha512-ZkC5IUqqIFPXx3ASTTybTzmQdwHwe2C0u3eL75ldQ6T9E9IWFJodn6hIfbZGab73DfyiHN4Xw15gNxUq2FbvBA==} + '@types/qrcode@1.5.5': resolution: {integrity: sha512-CdfBi/e3Qk+3Z/fXYShipBT13OJ2fDO2Q2w5CIP5anLTLIndQG9z6P1cnm+8zCWSpm5dnxMFd/uREtb0EXuQzg==} + '@types/readable-stream@4.0.15': + resolution: {integrity: sha512-oAZ3kw+kJFkEqyh7xORZOku1YAKvsFTogRY8kVl4vHpEKiDkfnSA/My8haRE7fvmix5Zyy+1pwzOi7yycGLBJw==} + '@types/semver@7.5.8': resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} @@ -1467,6 +1488,11 @@ packages: '@vueuse/shared@10.9.0': resolution: {integrity: sha512-Uud2IWncmAfJvRaFYzv5OHDli+FbOzxiVEQdLCKQKLyhz94PIyFC3CHcH7EDMwIn8NPtD06+PNbC/PiO0LGLtw==} + '@zenfs/core@0.16.3': + resolution: {integrity: sha512-Tg0o1pz11myVJh5iPPOA8QNprm0iVwTiJZRa7vMTPPkPCt8d9FM0723bGRsfmxUi1Hl13a12tTqV6JHDQGt/Mg==} + engines: {node: '>= 16'} + hasBin: true + JSONStream@1.3.5: resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} hasBin: true @@ -1487,6 +1513,10 @@ packages: zod: optional: true + abort-controller@3.0.0: + resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} + engines: {node: '>=6.5'} + acorn-import-attributes@1.9.2: resolution: {integrity: sha512-O+nfJwNolEA771IYJaiLWK1UAwjNsQmZbTRqqwBYxCgVQTmpFEMvBw6LOIQV0Me339L5UMVYFyRohGnGlQDdIQ==} peerDependencies: @@ -1581,10 +1611,12 @@ packages: are-we-there-yet@3.0.1: resolution: {integrity: sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + deprecated: This package is no longer supported. are-we-there-yet@4.0.2: resolution: {integrity: sha512-ncSWAawFhKMJDTdoAeOV+jyW1VCMj5QIAwULIBV0SSR7B/RLPPEQiknKcg/RIIZlUQrxELpsxMiTUoAQ4sIUyg==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + deprecated: This package is no longer supported. arg@4.1.3: resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} @@ -1688,6 +1720,9 @@ packages: buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + buffer@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + builtins@5.0.1: resolution: {integrity: sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==} @@ -2181,9 +2216,17 @@ packages: ethereum-cryptography@2.1.2: resolution: {integrity: sha512-Z5Ba0T0ImZ8fqXrJbpHcbpAvIswRte2wGNR/KePnu8GbbvgJ47lMxT/ZZPG6i9Jaht4azPDop4HaM00J0J59ug==} + event-target-shim@5.0.1: + resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} + engines: {node: '>=6'} + eventemitter3@5.0.1: resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + events@3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + execa@8.0.1: resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} engines: {node: '>=16.17'} @@ -2338,10 +2381,12 @@ packages: gauge@4.0.4: resolution: {integrity: sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + deprecated: This package is no longer supported. gauge@5.0.1: resolution: {integrity: sha512-CmykPMJGuNan/3S4kZOpvvPYSNqSHANiWnh9XcMU2pSjtBfF0XzZ2p1bFAxTbnFxyBuPxQYHhzwaoOmUdqzvxQ==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + deprecated: This package is no longer supported. generic-pool@3.9.0: resolution: {integrity: sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==} @@ -2404,6 +2449,7 @@ packages: glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported globals@13.24.0: resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} @@ -2565,6 +2611,7 @@ packages: inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} @@ -3158,10 +3205,12 @@ packages: npmlog@6.0.2: resolution: {integrity: sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + deprecated: This package is no longer supported. npmlog@7.0.1: resolution: {integrity: sha512-uJ0YFk/mCQpLBt+bxN88AKd+gyqZvZDbtiNxk6Waqcj2aPRyfVx8ITawkyQynxUagInjdYT1+qj4NfA5KJJUxg==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + deprecated: This package is no longer supported. object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} @@ -3280,6 +3329,9 @@ packages: parse-url@8.1.0: resolution: {integrity: sha512-xDvOoLU5XRrcOZvnI6b8zA6n9O9ejNk/GExuz1yBuWUGn9KA97GI6HTs6u02wKara1CeVmZhH+0TZFdWScR89w==} + path-browserify@1.0.1: + resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} + path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} @@ -3398,6 +3450,10 @@ packages: resolution: {integrity: sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + process@0.11.10: + resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} + engines: {node: '>= 0.6.0'} + promise-all-reject-late@1.0.1: resolution: {integrity: sha512-vuf0Lf0lOxyQREH7GDIOUMLS7kz+gs8i6B+Yi8dC68a2sychGrHTJYghMBD6k7eUcH0H5P73EckCA48xijWqXw==} @@ -3472,6 +3528,10 @@ packages: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} + readable-stream@4.5.2: + resolution: {integrity: sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + regexp-to-ast@0.5.0: resolution: {integrity: sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw==} @@ -3518,6 +3578,7 @@ packages: rimraf@3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true rollup@4.13.0: @@ -3929,6 +3990,9 @@ packages: undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + undici-types@6.19.6: + resolution: {integrity: sha512-e/vggGopEfTKSvj4ihnOLTsqhrKRN3LeO6qSN/GxohhuRv8qH9bNQ4B8W7e/vFL+0XTnmHPB4/kegunZGA4Org==} + unicorn-magic@0.1.0: resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} engines: {node: '>=18'} @@ -3963,6 +4027,9 @@ packages: util@0.12.5: resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} + utilium@0.4.4: + resolution: {integrity: sha512-TjhvLLoSi3WmzAR1QMFwGykW31cEOzbVoPqqopY6UYcm+5MfsF0ep3+DuJmAnOlU/zglGDwR96j0hjiHfwP4og==} + uuid@8.3.2: resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} hasBin: true @@ -5224,12 +5291,23 @@ snapshots: dependencies: undici-types: 5.26.5 + '@types/node@20.16.1': + dependencies: + undici-types: 6.19.6 + '@types/normalize-package-data@2.4.4': {} + '@types/path-browserify@1.0.2': {} + '@types/qrcode@1.5.5': dependencies: '@types/node': 20.11.30 + '@types/readable-stream@4.0.15': + dependencies: + '@types/node': 20.16.1 + safe-buffer: 5.1.2 + '@types/semver@7.5.8': {} '@types/validator@13.11.9': {} @@ -5460,6 +5538,16 @@ snapshots: - '@vue/composition-api' - vue + '@zenfs/core@0.16.3': + dependencies: + '@types/node': 20.16.1 + '@types/readable-stream': 4.0.15 + buffer: 6.0.3 + eventemitter3: 5.0.1 + minimatch: 9.0.3 + readable-stream: 4.5.2 + utilium: 0.4.4 + JSONStream@1.3.5: dependencies: jsonparse: 1.3.1 @@ -5475,6 +5563,10 @@ snapshots: optionalDependencies: zod: 3.22.4 + abort-controller@3.0.0: + dependencies: + event-target-shim: 5.0.1 + acorn-import-attributes@1.9.2(acorn@8.11.3): dependencies: acorn: 8.11.3 @@ -5716,6 +5808,11 @@ snapshots: base64-js: 1.5.1 ieee754: 1.2.1 + buffer@6.0.3: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + builtins@5.0.1: dependencies: semver: 7.6.0 @@ -6275,8 +6372,12 @@ snapshots: '@scure/bip32': 1.3.1 '@scure/bip39': 1.2.1 + event-target-shim@5.0.1: {} + eventemitter3@5.0.1: {} + events@3.3.0: {} + execa@8.0.1: dependencies: cross-spawn: 7.0.3 @@ -7461,6 +7562,8 @@ snapshots: dependencies: parse-path: 7.0.0 + path-browserify@1.0.1: {} + path-exists@4.0.0: {} path-exists@5.0.0: {} @@ -7554,6 +7657,8 @@ snapshots: proc-log@3.0.0: {} + process@0.11.10: {} + promise-all-reject-late@1.0.1: {} promise-call-limit@3.0.1: {} @@ -7629,6 +7734,14 @@ snapshots: string_decoder: 1.3.0 util-deprecate: 1.0.2 + readable-stream@4.5.2: + dependencies: + abort-controller: 3.0.0 + buffer: 6.0.3 + events: 3.3.0 + process: 0.11.10 + string_decoder: 1.3.0 + regexp-to-ast@0.5.0: {} require-directory@2.1.1: {} @@ -8084,6 +8197,8 @@ snapshots: undici-types@5.26.5: {} + undici-types@6.19.6: {} + unicorn-magic@0.1.0: {} unique-filename@1.1.1: @@ -8122,6 +8237,10 @@ snapshots: is-typed-array: 1.1.12 which-typed-array: 1.1.13 + utilium@0.4.4: + dependencies: + eventemitter3: 5.0.1 + uuid@8.3.2: {} uuid@9.0.1: {} From 3ced751b346323ba189faf5923c1b9f612686635 Mon Sep 17 00:00:00 2001 From: matteo-cristino Date: Mon, 19 Aug 2024 15:18:57 +0200 Subject: [PATCH 3/6] chore: add @slangroom/git to @slangroom/browser Tests are still missing --- pkg/browser/package.json | 3 ++- pkg/browser/src/index.ts | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/pkg/browser/package.json b/pkg/browser/package.json index 5188f435..f8fe7701 100644 --- a/pkg/browser/package.json +++ b/pkg/browser/package.json @@ -3,6 +3,7 @@ "dependencies": { "@slangroom/core": "workspace:*", "@slangroom/deps": "workspace:*", + "@slangroom/git": "workspace:*", "@slangroom/helpers": "workspace:*", "@slangroom/http": "workspace:*", "@slangroom/json-schema": "workspace:*", @@ -43,7 +44,7 @@ "esbuild": "^0.21.4" }, "scripts": { - "build": "pnpm exec esbuild --bundle src/index.ts --outfile=build/slangroom.js --target=es2016 --external:fs --external:path --external:crypto && cp build/slangroom.js public" + "build": "pnpm exec esbuild --bundle src/index.ts --outfile=build/slangroom.js --target=ESNext --external:fs --external:path --external:crypto && cp build/slangroom.js public" }, "engines": { "node": "^18.20.0 || ^20.10.0 || ^22" diff --git a/pkg/browser/src/index.ts b/pkg/browser/src/index.ts index 51986419..06f65ded 100644 --- a/pkg/browser/src/index.ts +++ b/pkg/browser/src/index.ts @@ -4,6 +4,7 @@ import { Slangroom, version as coreVersion } from '@slangroom/core'; import { qrcode, version as qrcodeVersion } from '@slangroom/qrcode'; +import { git, version as gitVersion } from '@slangroom/git'; import { http, version as httpVersion } from '@slangroom/http'; import { pocketbase, version as pocketbaseVersion } from '@slangroom/pocketbase'; import { helpers, version as helpersVersion } from '@slangroom/helpers'; @@ -14,6 +15,10 @@ import packageJson from '@slangroom/browser/package.json' with { type: 'json' }; export const version = packageJson.version; const plugins_dict = { + git: { + plugin: git, + version: gitVersion + }, http: { plugin: http, version: httpVersion From 19090f1679867bc320f8100d6379e83fbe4b75fe Mon Sep 17 00:00:00 2001 From: matteo-cristino Date: Mon, 19 Aug 2024 16:05:00 +0200 Subject: [PATCH 4/6] chore(pnpm-lock): add @slangroom/git as @slangroom/browser dependency --- pnpm-lock.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7a7a4948..dd799652 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -119,6 +119,9 @@ importers: '@slangroom/deps': specifier: workspace:* version: link:../deps + '@slangroom/git': + specifier: workspace:* + version: link:../git '@slangroom/helpers': specifier: workspace:* version: link:../helpers From 4334d4ebaf6395db538605dbb9ca17726ac8092a Mon Sep 17 00:00:00 2001 From: matteo-cristino Date: Fri, 23 Aug 2024 16:23:32 +0200 Subject: [PATCH 5/6] fix: import path in the correct way from path-browserify Also formatted correctly the code --- pkg/git/src/plugin.ts | 107 ++++++++++++++++++++++-------------------- 1 file changed, 57 insertions(+), 50 deletions(-) diff --git a/pkg/git/src/plugin.ts b/pkg/git/src/plugin.ts index 3d8e0705..21fb3814 100644 --- a/pkg/git/src/plugin.ts +++ b/pkg/git/src/plugin.ts @@ -6,7 +6,7 @@ import { Plugin } from '@slangroom/core'; import gitpkg from 'isomorphic-git'; import http from 'isomorphic-git/http/web/index.js'; import { promises as fs } from '@zenfs/core'; -import * as path from 'path-browserify'; +import path from 'path-browserify'; // read the version from the package.json import packageJson from '@slangroom/git/package.json' with { type: 'json' }; @@ -14,11 +14,13 @@ export const version = packageJson.version; export class GitError extends Error { constructor(e: string) { - super(e) - this.name = 'Slangroom @slangroom/git@' + packageJson.version + ' Error' + super(e); + this.name = 'Slangroom @slangroom/git@' + packageJson.version + ' Error'; } } +type dirResponse = { ok: true; dirpath: string } | { ok: false; error: string }; +type fileResponse = { ok: true; filepath: string } | { ok: false; error: string }; /** * @internal */ @@ -27,7 +29,7 @@ export const sandboxDir = () => { return process.env['FILES_DIR']; }; -const sandboxizeDir = (unsafe: string): ({ok: true, dirpath: string} | {ok: false, error: string}) => { +const sandboxizeDir = (unsafe: string): dirResponse => { const normalized = path.normalize(unsafe); // `/` and `..` prevent directory traversal const doesDirectoryTraversal = normalized.startsWith('/') || normalized.startsWith('..'); @@ -38,7 +40,7 @@ const sandboxizeDir = (unsafe: string): ({ok: true, dirpath: string} | {ok: fals return { ok: true, dirpath: path.join(sandboxdir, normalized) }; }; -const sandboxizeFile = (sandboxdir: string, unsafe: string): ({ok: true, filepath: string} | {ok: false, error: string}) => { +const sandboxizeFile = (sandboxdir: string, unsafe: string): fileResponse => { const normalized = path.normalize(unsafe); // `/` and `..` prevent directory traversal const doesDirectoryTraversal = normalized.startsWith('/') || normalized.startsWith('..'); @@ -78,7 +80,7 @@ export const cloneRepository = p.new('connect', ['path'], 'clone repository', as const res = sandboxizeDir(unsafe); if (!res.ok) return ctx.fail(new GitError(res.error)); - try { + try { await gitpkg.clone({ fs: fs, http: http, dir: res.dirpath, url: repoUrl }); return ctx.pass(null); } catch (e) { @@ -89,49 +91,54 @@ export const cloneRepository = p.new('connect', ['path'], 'clone repository', as /* * @internal */ -export const createNewGitCommit = p.new('open', ['commit'], 'create new git commit', async (ctx) => { - const unsafe = ctx.fetchOpen()[0]; - const res = sandboxizeDir(unsafe); - if (!res.ok) return ctx.fail(new GitError(res.error)); - - const commit = ctx.fetch('commit') as { - message: string; - author: string; - email: string; - files: string[]; - }; - - try { - commit.files.map((unsafe) => { - const r = sandboxizeFile(res.dirpath, unsafe); - if (!r.ok) throw new Error(r.error); - return r.filepath; - }); - - await Promise.all( - commit.files.map((safe) => { - return gitpkg.add({ - fs: fs, - dir: res.dirpath, - filepath: safe, - }); - }), - ); - - const hash = await gitpkg.commit({ - fs: fs, - dir: res.dirpath, - message: commit.message, - author: { - name: commit.author, - email: commit.email, - }, - }); - - return ctx.pass(hash); - } catch (e) { - return ctx.fail(new GitError(e.message)); - } -}); +export const createNewGitCommit = p.new( + 'open', + ['commit'], + 'create new git commit', + async (ctx) => { + const unsafe = ctx.fetchOpen()[0]; + const res = sandboxizeDir(unsafe); + if (!res.ok) return ctx.fail(new GitError(res.error)); + + const commit = ctx.fetch('commit') as { + message: string; + author: string; + email: string; + files: string[]; + }; + + try { + commit.files.map((unsafe) => { + const r = sandboxizeFile(res.dirpath, unsafe); + if (!r.ok) throw new Error(r.error); + return r.filepath; + }); + + await Promise.all( + commit.files.map((safe) => { + return gitpkg.add({ + fs: fs, + dir: res.dirpath, + filepath: safe, + }); + }), + ); + + const hash = await gitpkg.commit({ + fs: fs, + dir: res.dirpath, + message: commit.message, + author: { + name: commit.author, + email: commit.email, + }, + }); + + return ctx.pass(hash); + } catch (e) { + return ctx.fail(new GitError(e.message)); + } + }, +); export const git = p; From c76c76c62790e1bad5496d213562a9cc6c904a35 Mon Sep 17 00:00:00 2001 From: matteo-cristino Date: Fri, 23 Aug 2024 16:34:16 +0200 Subject: [PATCH 6/6] test(git): use zenFS and path-browserify Waiting for the release that fix recursively removal (commit already done) --- pkg/git/test/e2e.ts | 52 ++++++++++++++++++++++-------------------- pkg/git/test/plugin.ts | 13 +++++++---- 2 files changed, 35 insertions(+), 30 deletions(-) diff --git a/pkg/git/test/e2e.ts b/pkg/git/test/e2e.ts index a8f6f301..496ea874 100644 --- a/pkg/git/test/e2e.ts +++ b/pkg/git/test/e2e.ts @@ -5,21 +5,22 @@ import test from 'ava'; import { Slangroom } from '@slangroom/core'; import { git } from '@slangroom/git'; -import * as fs from 'node:fs/promises'; +import { promises as fs } from '@zenfs/core'; // read the version from the package.json import packageJson from '@slangroom/git/package.json' with { type: 'json' }; -process.env['FILES_DIR'] = "./test"; +process.env['FILES_DIR'] = './test'; -const stripAnsiCodes = (str: string) => str.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, ''); +const stripAnsiCodes = (str: string) => + str.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, ''); test('Should fail to check non existing repository', async (t) => { const slangroom = new Slangroom(git); const data = { path: 'some/dumb/path', - verified_git_repo: 'true' + verified_git_repo: 'true', }; - const zen =`Rule unknown ignore + const zen = `Rule unknown ignore Given I open 'path' and verify git repository Given I have a 'string' named 'verified_git_repo' Then print the data`; @@ -27,8 +28,9 @@ test('Should fail to check non existing repository', async (t) => { data, }); const error = await t.throwsAsync(fn); - t.is(stripAnsiCodes((error as Error).message), -`0 | Rule unknown ignore + t.is( + stripAnsiCodes((error as Error).message), + `0 | Rule unknown ignore 1 | Given I open 'path' and verify git repository ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 2 | Given I have a 'string' named 'verified_git_repo' @@ -47,8 +49,9 @@ Heap: "path": "some/dumb/path", "verified_git_repo": "true" } -`); -}) +`, + ); +}); test('Should not clone a not exitsting repository', async (t) => { const slangroom = new Slangroom(git); @@ -66,8 +69,9 @@ test('Should not clone a not exitsting repository', async (t) => { data, }); const error = await t.throwsAsync(fn); - t.is(stripAnsiCodes((error as Error).message), -`0 | Rule unknown ignore + t.is( + stripAnsiCodes((error as Error).message), + `0 | Rule unknown ignore 1 | Given I connect to 'url' and send path 'path' and clone repository ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 2 | Given I have a 'string' named 'cloned_repository' @@ -87,9 +91,9 @@ Heap: "path": "another/dumb/path", "cloned_repository": "true" } -`); -}) - +`, + ); +}); test.serial('Should clone a repository', async (t) => { const slangroom = new Slangroom(git); @@ -113,15 +117,15 @@ test.serial('Should clone a repository', async (t) => { }, res.logs, ); -}) +}); test.serial('Should verify git repository', async (t) => { const slangroom = new Slangroom(git); const data = { path: 'dumb', - verified_git_repo: 'true' + verified_git_repo: 'true', }; - const zen =`Rule unknown ignore + const zen = `Rule unknown ignore Given I open 'path' and verify git repository Given I have a 'string' named 'verified_git_repo' Then print data`; @@ -135,7 +139,7 @@ test.serial('Should verify git repository', async (t) => { }, res.logs, ); -}) +}); test.serial('Should create a new git commit', async (t) => { const slangroom = new Slangroom(git); @@ -145,22 +149,20 @@ test.serial('Should create a new git commit', async (t) => { author: 'Jhon Doe', message: 'docs: update readme', email: 'jhon.doe@example.com', - files: [ - 'README.md' - ] + files: ['README.md'], }, }; - const zen =`Rule unknown ignore + const zen = `Rule unknown ignore Given I open 'path' and send commit 'commit' and create new git commit and output into 'commit_hash' Given I have a 'string' named 'commit hash' Then print data`; - await fs.appendFile('./test/dumb/README.md', '\nChanged the README\n') + await fs.appendFile('./test/dumb/README.md', '\nChanged the README\n'); const res = await slangroom.execute(zen, { data, }); t.truthy(typeof res.result['commit_hash'] === 'string'); -}) +}); test.after.always('guaranteed cleanup', async () => { - await fs.rm('./test/dumb', { recursive: true }) + await fs.rm('./test/dumb', { recursive: true }); }); diff --git a/pkg/git/test/plugin.ts b/pkg/git/test/plugin.ts index 5faa715d..33119aa0 100644 --- a/pkg/git/test/plugin.ts +++ b/pkg/git/test/plugin.ts @@ -3,22 +3,25 @@ // SPDX-License-Identifier: AGPL-3.0-or-later import ava, { type TestFn } from 'ava'; -import * as fs from 'node:fs/promises'; -import { join } from 'node:path'; -import * as os from 'node:os'; +import { promises as fs } from '@zenfs/core'; +import path from 'path-browserify'; import git from 'isomorphic-git'; import { PluginContextTest } from '@slangroom/core'; import { cloneRepository, createNewGitCommit, verifyGitRepository } from '@slangroom/git'; const test = ava as TestFn; +const join = path.join; test.beforeEach(async (t) => { - const tmpdir = await fs.mkdtemp(join(os.tmpdir(), 'slangroom-test-')); + await fs.mkdir('/tmp'); + const tmpdir = await fs.mkdtemp('slangroom-test-'); process.env['FILES_DIR'] = tmpdir; t.context = tmpdir; }); -test.afterEach(async (t) => await fs.rm(t.context, { recursive: true })); +test.afterEach(async (t) => { + await fs.rm(t.context, { recursive: true }); +}); test.serial('verifyGitRepository works', async (t) => { const path = join('foo', 'bar');