@gjsify/npm-registry 0.4.44 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/esm/index.js +1 -1
- package/package.json +3 -3
package/lib/esm/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./_virtual/_rolldown/runtime.js";const e=`https://registry.npmjs.org/`;function assertPackument(e,t){if(!t||typeof t!=`object`)throw TypeError(`registry: ${e} packument is not an object`);let n=t;if(typeof n.name!=`string`)throw TypeError(`registry: ${e} packument missing string name`);if(!n.versions||typeof n.versions!=`object`)throw TypeError(`registry: ${e} packument missing versions map`)}function registryFor(t,n){if(n&&t.startsWith(`@`)){let e=t.slice(0,t.indexOf(`/`)),r=n.scopes[e];if(r)return ensureTrailingSlash(r)}return n?.registry?ensureTrailingSlash(n.registry):e}function packumentUrl(e,t){let n=ensureTrailingSlash(t);if(e.startsWith(`@`)){let t=e.indexOf(`/`);if(t<0)throw TypeError(`Invalid scoped package name: ${e}`);let r=e.slice(0,t),i=e.slice(t+1);return`${n}${encodeURIComponent(r)}/${encodeURIComponent(i)}`}return`${n}${encodeURIComponent(e)}`}async function fetchPackumentConditional(e,t={}){let n=packumentUrl(e,t.registry??registryFor(e,t.npmrc)),r=buildHeaders(n,{...t,acceptEncoding:`gzip`});r.accept??=`application/vnd.npm.install-v1+json`,t.ifNoneMatch&&(r[`if-none-match`]=t.ifNoneMatch);let i=await fetchWithRetry(n,{headers:r,signal:t.signal,compress:!1},{fetch:t.fetch,retries:t.retries,retryDelayMs:t.retryDelayMs,timeoutMs:t.timeoutMs,onRetry:t.onRetry});if(i.status===304){try{await i.arrayBuffer()}catch{}return{status:`not-modified`,etag:t.ifNoneMatch}}if(!i.ok)throw i.status===404||i.status===406?new PackageNotFoundError(e,n):Error(`registry GET ${n} -> ${i.status} ${i.statusText}`);let a=i.headers.get(`etag`)??void 0,o=await decodeJsonBody(i);return assertPackument(e,o),{status:`fresh`,packument:o,etag:a}}async function decodeJsonBody(e){let t=new Uint8Array(await e.arrayBuffer()),n=t.length>=2&&t[0]===31&&t[1]===139?await gunzip(t):t;return JSON.parse(new TextDecoder().decode(n))}async function gunzip(e){let t=globalThis.DecompressionStream;if(typeof t!=`function`)throw Error(`@gjsify/npm-registry: globalThis.DecompressionStream is unavailable — cannot decode a gzip registry response (on GJS, register '@gjsify/compression-streams')`);let n=new Blob([new Uint8Array(e)]).stream().pipeThrough(new t(`gzip`)).getReader(),r=[],i=0;for(;;){let{value:e,done:t}=await n.read();if(t)break;let a=e instanceof Uint8Array?e:new Uint8Array(e);r.push(a),i+=a.length}let a=new Uint8Array(i),o=0;for(let e of r)a.set(e,o),o+=e.length;return a}async function fetchPackument(e,t={}){let n=await fetchPackumentConditional(e,t);if(!n.packument)throw Error(`registry: ${e} returned 304 Not Modified to an unconditional request`);return n.packument}async function fetchTarball(e,t={}){let n=buildHeaders(e,{...t,acceptEncoding:`identity`});n.accept??=`application/octet-stream`;let r=await fetchWithRetry(e,{headers:n,signal:t.signal},{fetch:t.fetch,retries:t.retries,retryDelayMs:t.retryDelayMs,timeoutMs:t.timeoutMs,onRetry:t.onRetry,retryNotFound:t.retryNotFound??!0});if(!r.ok)throw Error(`tarball GET ${e} -> ${r.status} ${r.statusText}`);let i=new Uint8Array(await r.arrayBuffer());if(t.integrity&&!await verifyIntegrity(i,t.integrity))throw new IntegrityError(e,t.integrity);return i}async function fetchWithRetry(e,t,n){let r=n.fetch??globalThis.fetch;if(!r)throw Error(`@gjsify/npm-registry: globalThis.fetch is missing`);let i=Math.max(0,n.retries??3),a=Math.max(0,n.retryDelayMs??250),o=Math.max(0,n.timeoutMs??3e4),s=n.retryNotFound??!1,c=0,l,u=0;for(;;){if(t.signal?.aborted)throw signalAbortError(t.signal);let d=o>0?new AbortController:null,f=d===null?null:setTimeout(()=>d.abort(Error(`@gjsify/npm-registry: per-request timeout ${o}ms`)),o),p=composeSignals(t.signal,d?.signal);try{let n=await r(e,{...t,signal:p}),a=isRetryableStatus(n.status)||s&&n.status===404;if(n.ok||!a||c>=i)return n;try{await n.arrayBuffer()}catch{}l=Error(`HTTP ${n.status} ${n.statusText}`)}catch(n){let r=d!==null&&d.signal.aborted,a=t.signal?.aborted===!0;if(r&&!a){if(u++,c>=i)throw new RegistryTimeoutError(e,o,u);l=n}else if(a)throw signalAbortError(t.signal);else{if(!isRetryableError(n)||c>=i)throw n;l=n}}finally{f!==null&&clearTimeout(f)}let m=Math.min(a*2**c,8e3);n.onRetry?.({attempt:c+1,error:l,delayMs:m}),await delay(m,t.signal),c++}}function composeSignals(e,t){return e?t?AbortSignal.any([e,t]):e:t}function isRetryableStatus(e){return e===408||e===425||e===429||e===500||e===502||e===503||e===504||e===521||e===522||e===524||e===525}function isRetryableError(e){if(e&&typeof e==`object`&&`name`in e&&e.name===`AbortError`)return!1;if(e instanceof TypeError)return!0;if(e&&typeof e==`object`&&`name`in e){let t=e.name;if(t===`FetchError`)return!0;if(t===`AbortError`)return!1}let t=e?.cause;if(t&&typeof t==`object`&&`code`in t){let e=t.code;if(typeof e==`string`)return e===`ECONNRESET`||e===`ECONNREFUSED`||e===`ENETUNREACH`||e===`ENOTFOUND`||e===`ETIMEDOUT`||e===`EAI_AGAIN`||e===`UND_ERR_SOCKET`||e===`UND_ERR_CONNECT_TIMEOUT`}return!1}function delay(e,t){return e<=0?Promise.resolve():new Promise((n,r)=>{let i=setTimeout(()=>{t?.removeEventListener?.(`abort`,onAbort),n()},e),onAbort=()=>{clearTimeout(i),r(signalAbortError(t))};if(t?.aborted){clearTimeout(i),r(signalAbortError(t));return}t?.addEventListener?.(`abort`,onAbort,{once:!0})})}function signalAbortError(e){let t=e&&`reason`in e?e.reason:void 0;if(t instanceof Error)return t;let n=Error(`Aborted`);return n.name=`AbortError`,n}async function verifyIntegrity(e,t){let n=t.trim().split(/\s+/);for(let t of n){let n=t.indexOf(`-`);if(n<0)continue;let r=t.slice(0,n).toLowerCase(),i=t.slice(n+1),a=globalThis.crypto?.subtle;if(!a)throw Error(`@gjsify/npm-registry: globalThis.crypto.subtle is missing`);let o=subriToWebCryptoAlgo(r);if(!o)continue;let s=await a.digest(o,dataAsArrayBuffer(e));if(bytesToBase64(new Uint8Array(s))===i)return!0}return!1}function subriToWebCryptoAlgo(e){switch(e){case`sha1`:return`SHA-1`;case`sha256`:return`SHA-256`;case`sha384`:return`SHA-384`;case`sha512`:return`SHA-512`;default:return null}}function dataAsArrayBuffer(e){if(e.byteOffset===0&&e.byteLength===e.buffer.byteLength)return e.buffer;let t=new Uint8Array(e.byteLength);return t.set(e),t.buffer}function bytesToBase64(e){let t=``;for(let n=0;n<e.length;n++)t+=String.fromCharCode(e[n]);return btoa(t)}function parseNpmrc(t){let n={registry:e,scopes:{},authTokens:{},basicAuth:{}},r=t.split(/\r?\n/),i={};for(let e of r){let t=e.replace(/^\s+|\s+$/g,``);if(!t||t.startsWith(`#`)||t.startsWith(`;`))continue;let r=t.indexOf(`=`);if(r<0)continue;let a=t.slice(0,r).trim(),o=expandEnv(stripQuotes(t.slice(r+1).trim()));if(a===`registry`){n.registry=ensureTrailingSlash(o);continue}let s=a.match(/^(@[^:]+):registry$/);if(s){n.scopes[s[1]]=ensureTrailingSlash(o);continue}let c=a.match(/^\/\/(.+):_authToken$/);if(c){n.authTokens[normalizeAuthHost(c[1])]=o;continue}let l=a.match(/^\/\/(.+):username$/);if(l){(i[normalizeAuthHost(l[1])]??={}).user=o;continue}let u=a.match(/^\/\/(.+):_password$/);if(u){let e=base64Decode(o);(i[normalizeAuthHost(u[1])]??={}).pass=e;continue}}for(let[e,t]of Object.entries(i))t.user&&t.pass!==void 0&&(n.basicAuth[e]={username:t.user,password:t.pass});return n}function buildHeaders(e,t){let n={"user-agent":`gjsify-install/0.3.7`,"accept-encoding":t.acceptEncoding??`identity`};if(t.npmrc){let r=resolveAuthForUrl(e,t.npmrc);r&&(n.authorization=r)}if(t.headers)for(let[e,r]of Object.entries(t.headers))n[e.toLowerCase()]=r;return n}function resolveAuthForUrl(e,t){let n=pathPrefixes(new URL(e));for(let e of n){let n=t.authTokens[e];if(n)return`Bearer ${n}`;let r=t.basicAuth[e];if(r)return`Basic ${btoa(`${r.username}:${r.password}`)}`}return null}function pathPrefixes(e){let t=e.pathname.split(`/`).filter(Boolean),n=[];for(let r=t.length;r>=0;r--){let i=t.slice(0,r).join(`/`);n.push(i?`//${e.host}/${i}`:`//${e.host}`)}return n}function normalizeAuthHost(e){return`//${e.replace(/\/+$/,``)}`}function ensureTrailingSlash(e){return e.endsWith(`/`)?e:e+`/`}function stripQuotes(e){return e.startsWith(`"`)&&e.endsWith(`"`)||e.startsWith(`'`)&&e.endsWith(`'`)?e.slice(1,-1):e}function expandEnv(e){return e.replace(/\$\{([A-Z0-9_]+)\}/gi,(e,t)=>globalThis.process?.env?.[t]??``)}function base64Decode(e){return atob(e)}async function whoami(e,t){let n=`${ensureTrailingSlash(e)}-/whoami`,r=buildHeaders(n,{npmrc:t});r.accept=`application/json`;let i=globalThis.fetch;if(!i)throw Error(`@gjsify/npm-registry: globalThis.fetch is missing`);let a=await i(n,{method:`GET`,headers:r});if(!a.ok)throw Error(`whoami GET ${n} -> ${a.status} ${a.statusText}`);let o=await a.json();if(o&&typeof o==`object`&&`username`in o){let e=o.username;if(typeof e==`string`&&e.length>0)return{username:e}}return{}}var PackageNotFoundError=class extends Error{
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";const e=`https://registry.npmjs.org/`;function assertPackument(e,t){if(!t||typeof t!=`object`)throw TypeError(`registry: ${e} packument is not an object`);let n=t;if(typeof n.name!=`string`)throw TypeError(`registry: ${e} packument missing string name`);if(!n.versions||typeof n.versions!=`object`)throw TypeError(`registry: ${e} packument missing versions map`)}function registryFor(t,n){if(n&&t.startsWith(`@`)){let e=t.slice(0,t.indexOf(`/`)),r=n.scopes[e];if(r)return ensureTrailingSlash(r)}return n?.registry?ensureTrailingSlash(n.registry):e}function packumentUrl(e,t){let n=ensureTrailingSlash(t);if(e.startsWith(`@`)){let t=e.indexOf(`/`);if(t<0)throw TypeError(`Invalid scoped package name: ${e}`);let r=e.slice(0,t),i=e.slice(t+1);return`${n}${encodeURIComponent(r)}/${encodeURIComponent(i)}`}return`${n}${encodeURIComponent(e)}`}async function fetchPackumentConditional(e,t={}){let n=packumentUrl(e,t.registry??registryFor(e,t.npmrc)),r=buildHeaders(n,{...t,acceptEncoding:`gzip`});r.accept??=`application/vnd.npm.install-v1+json`,t.ifNoneMatch&&(r[`if-none-match`]=t.ifNoneMatch);let i=await fetchWithRetry(n,{headers:r,signal:t.signal,compress:!1},{fetch:t.fetch,retries:t.retries,retryDelayMs:t.retryDelayMs,timeoutMs:t.timeoutMs,onRetry:t.onRetry});if(i.status===304){try{await i.arrayBuffer()}catch{}return{status:`not-modified`,etag:t.ifNoneMatch}}if(!i.ok)throw i.status===404||i.status===406?new PackageNotFoundError(e,n):Error(`registry GET ${n} -> ${i.status} ${i.statusText}`);let a=i.headers.get(`etag`)??void 0,o=await decodeJsonBody(i);return assertPackument(e,o),{status:`fresh`,packument:o,etag:a}}async function decodeJsonBody(e){let t=new Uint8Array(await e.arrayBuffer()),n=t.length>=2&&t[0]===31&&t[1]===139?await gunzip(t):t;return JSON.parse(new TextDecoder().decode(n))}async function gunzip(e){let t=globalThis.DecompressionStream;if(typeof t!=`function`)throw Error(`@gjsify/npm-registry: globalThis.DecompressionStream is unavailable — cannot decode a gzip registry response (on GJS, register '@gjsify/compression-streams')`);let n=new Blob([new Uint8Array(e)]).stream().pipeThrough(new t(`gzip`)).getReader(),r=[],i=0;for(;;){let{value:e,done:t}=await n.read();if(t)break;let a=e instanceof Uint8Array?e:new Uint8Array(e);r.push(a),i+=a.length}let a=new Uint8Array(i),o=0;for(let e of r)a.set(e,o),o+=e.length;return a}async function fetchPackument(e,t={}){let n=await fetchPackumentConditional(e,t);if(!n.packument)throw Error(`registry: ${e} returned 304 Not Modified to an unconditional request`);return n.packument}async function fetchTarball(e,t={}){let n=buildHeaders(e,{...t,acceptEncoding:`identity`});n.accept??=`application/octet-stream`;let r=await fetchWithRetry(e,{headers:n,signal:t.signal},{fetch:t.fetch,retries:t.retries,retryDelayMs:t.retryDelayMs,timeoutMs:t.timeoutMs,onRetry:t.onRetry,retryNotFound:t.retryNotFound??!0});if(!r.ok)throw Error(`tarball GET ${e} -> ${r.status} ${r.statusText}`);let i=new Uint8Array(await r.arrayBuffer());if(t.integrity&&!await verifyIntegrity(i,t.integrity))throw new IntegrityError(e,t.integrity);return i}async function fetchWithRetry(e,t,n){let r=n.fetch??globalThis.fetch;if(!r)throw Error(`@gjsify/npm-registry: globalThis.fetch is missing`);let i=Math.max(0,n.retries??3),a=Math.max(0,n.retryDelayMs??250),o=Math.max(0,n.timeoutMs??3e4),s=n.retryNotFound??!1,c=0,l,u=0;for(;;){if(t.signal?.aborted)throw signalAbortError(t.signal);let d=o>0?new AbortController:null,f=d===null?null:setTimeout(()=>d.abort(Error(`@gjsify/npm-registry: per-request timeout ${o}ms`)),o),p=composeSignals(t.signal,d?.signal);try{let n=await r(e,{...t,signal:p}),a=isRetryableStatus(n.status)||s&&n.status===404;if(n.ok||!a||c>=i)return n;try{await n.arrayBuffer()}catch{}l=Error(`HTTP ${n.status} ${n.statusText}`)}catch(n){let r=d!==null&&d.signal.aborted,a=t.signal?.aborted===!0;if(r&&!a){if(u++,c>=i)throw new RegistryTimeoutError(e,o,u);l=n}else if(a)throw signalAbortError(t.signal);else{if(!isRetryableError(n)||c>=i)throw n;l=n}}finally{f!==null&&clearTimeout(f)}let m=Math.min(a*2**c,8e3);n.onRetry?.({attempt:c+1,error:l,delayMs:m}),await delay(m,t.signal),c++}}function composeSignals(e,t){return e?t?AbortSignal.any([e,t]):e:t}function isRetryableStatus(e){return e===408||e===425||e===429||e===500||e===502||e===503||e===504||e===521||e===522||e===524||e===525}function isRetryableError(e){if(e&&typeof e==`object`&&`name`in e&&e.name===`AbortError`)return!1;if(e instanceof TypeError)return!0;if(e&&typeof e==`object`&&`name`in e){let t=e.name;if(t===`FetchError`)return!0;if(t===`AbortError`)return!1}let t=e?.cause;if(t&&typeof t==`object`&&`code`in t){let e=t.code;if(typeof e==`string`)return e===`ECONNRESET`||e===`ECONNREFUSED`||e===`ENETUNREACH`||e===`ENOTFOUND`||e===`ETIMEDOUT`||e===`EAI_AGAIN`||e===`UND_ERR_SOCKET`||e===`UND_ERR_CONNECT_TIMEOUT`}return!1}function delay(e,t){return e<=0?Promise.resolve():new Promise((n,r)=>{let i=setTimeout(()=>{t?.removeEventListener?.(`abort`,onAbort),n()},e),onAbort=()=>{clearTimeout(i),r(signalAbortError(t))};if(t?.aborted){clearTimeout(i),r(signalAbortError(t));return}t?.addEventListener?.(`abort`,onAbort,{once:!0})})}function signalAbortError(e){let t=e&&`reason`in e?e.reason:void 0;if(t instanceof Error)return t;let n=Error(`Aborted`);return n.name=`AbortError`,n}async function verifyIntegrity(e,t){let n=t.trim().split(/\s+/);for(let t of n){let n=t.indexOf(`-`);if(n<0)continue;let r=t.slice(0,n).toLowerCase(),i=t.slice(n+1),a=globalThis.crypto?.subtle;if(!a)throw Error(`@gjsify/npm-registry: globalThis.crypto.subtle is missing`);let o=subriToWebCryptoAlgo(r);if(!o)continue;let s=await a.digest(o,dataAsArrayBuffer(e));if(bytesToBase64(new Uint8Array(s))===i)return!0}return!1}function subriToWebCryptoAlgo(e){switch(e){case`sha1`:return`SHA-1`;case`sha256`:return`SHA-256`;case`sha384`:return`SHA-384`;case`sha512`:return`SHA-512`;default:return null}}function dataAsArrayBuffer(e){if(e.byteOffset===0&&e.byteLength===e.buffer.byteLength)return e.buffer;let t=new Uint8Array(e.byteLength);return t.set(e),t.buffer}function bytesToBase64(e){let t=``;for(let n=0;n<e.length;n++)t+=String.fromCharCode(e[n]);return btoa(t)}function parseNpmrc(t){let n={registry:e,scopes:{},authTokens:{},basicAuth:{}},r=t.split(/\r?\n/),i={};for(let e of r){let t=e.replace(/^\s+|\s+$/g,``);if(!t||t.startsWith(`#`)||t.startsWith(`;`))continue;let r=t.indexOf(`=`);if(r<0)continue;let a=t.slice(0,r).trim(),o=expandEnv(stripQuotes(t.slice(r+1).trim()));if(a===`registry`){n.registry=ensureTrailingSlash(o);continue}let s=a.match(/^(@[^:]+):registry$/);if(s){n.scopes[s[1]]=ensureTrailingSlash(o);continue}let c=a.match(/^\/\/(.+):_authToken$/);if(c){n.authTokens[normalizeAuthHost(c[1])]=o;continue}let l=a.match(/^\/\/(.+):username$/);if(l){(i[normalizeAuthHost(l[1])]??={}).user=o;continue}let u=a.match(/^\/\/(.+):_password$/);if(u){let e=base64Decode(o);(i[normalizeAuthHost(u[1])]??={}).pass=e;continue}}for(let[e,t]of Object.entries(i))t.user&&t.pass!==void 0&&(n.basicAuth[e]={username:t.user,password:t.pass});return n}function buildHeaders(e,t){let n={"user-agent":`gjsify-install/0.3.7`,"accept-encoding":t.acceptEncoding??`identity`};if(t.npmrc){let r=resolveAuthForUrl(e,t.npmrc);r&&(n.authorization=r)}if(t.headers)for(let[e,r]of Object.entries(t.headers))n[e.toLowerCase()]=r;return n}function resolveAuthForUrl(e,t){let n=pathPrefixes(new URL(e));for(let e of n){let n=t.authTokens[e];if(n)return`Bearer ${n}`;let r=t.basicAuth[e];if(r)return`Basic ${btoa(`${r.username}:${r.password}`)}`}return null}function pathPrefixes(e){let t=e.pathname.split(`/`).filter(Boolean),n=[];for(let r=t.length;r>=0;r--){let i=t.slice(0,r).join(`/`);n.push(i?`//${e.host}/${i}`:`//${e.host}`)}return n}function normalizeAuthHost(e){return`//${e.replace(/\/+$/,``)}`}function ensureTrailingSlash(e){return e.endsWith(`/`)?e:e+`/`}function stripQuotes(e){return e.startsWith(`"`)&&e.endsWith(`"`)||e.startsWith(`'`)&&e.endsWith(`'`)?e.slice(1,-1):e}function expandEnv(e){return e.replace(/\$\{([A-Z0-9_]+)\}/gi,(e,t)=>globalThis.process?.env?.[t]??``)}function base64Decode(e){return atob(e)}async function whoami(e,t){let n=`${ensureTrailingSlash(e)}-/whoami`,r=buildHeaders(n,{npmrc:t});r.accept=`application/json`;let i=globalThis.fetch;if(!i)throw Error(`@gjsify/npm-registry: globalThis.fetch is missing`);let a=await i(n,{method:`GET`,headers:r});if(!a.ok)throw Error(`whoami GET ${n} -> ${a.status} ${a.statusText}`);let o=await a.json();if(o&&typeof o==`object`&&`username`in o){let e=o.username;if(typeof e==`string`&&e.length>0)return{username:e}}return{}}var PackageNotFoundError=class extends Error{constructor(e,t){super(`Package not found in registry: ${e} (${t})`),this.name=e,this.url=t,this.name=`PackageNotFoundError`}},IntegrityError=class extends Error{constructor(e,t){super(`Tarball integrity mismatch for ${e} (expected ${t})`),this.url=e,this.integrity=t,this.name=`IntegrityError`}},RegistryTimeoutError=class extends Error{constructor(e,t,n){let r=Math.round(t/100)/10,i=Math.round(t*n/100)/10;super(`@gjsify/npm-registry: GET ${e} timed out after ${r}s × ${n} attempt(s) (total ~${i}s). This usually means the registry CDN is slow or unreachable.`),this.url=e,this.timeoutMs=t,this.attempts=n,this.name=`RegistryTimeoutError`}};export{e as DEFAULT_REGISTRY,IntegrityError,PackageNotFoundError,RegistryTimeoutError,assertPackument,buildHeaders,fetchPackument,fetchPackumentConditional,fetchTarball,fetchWithRetry,packumentUrl,parseNpmrc,registryFor,resolveAuthForUrl,verifyIntegrity,whoami};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gjsify/npm-registry",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"description": "npm registry client for the gjsify install backend — packuments, tarballs, .npmrc auth (Node + GJS)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "lib/esm/index.js",
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
],
|
|
38
38
|
"license": "MIT",
|
|
39
39
|
"devDependencies": {
|
|
40
|
-
"@gjsify/cli": "^0.
|
|
41
|
-
"@gjsify/unit": "^0.
|
|
40
|
+
"@gjsify/cli": "^0.5.1",
|
|
41
|
+
"@gjsify/unit": "^0.5.1",
|
|
42
42
|
"typescript": "^6.0.3"
|
|
43
43
|
},
|
|
44
44
|
"repository": {
|