@hienlh/ppm 0.9.3 → 0.9.5
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/CHANGELOG.md +19 -0
- package/dist/web/assets/{browser-tab-LFNnCzgB.js → browser-tab-D2Z_380K.js} +1 -1
- package/dist/web/assets/{chat-tab-rYBo5Mff.js → chat-tab-DyCHqHNy.js} +1 -1
- package/dist/web/assets/{code-editor-BdM11-0K.js → code-editor-CLBY3U7l.js} +1 -1
- package/dist/web/assets/{database-viewer-CINo6teP.js → database-viewer-BWGt4Ufn.js} +1 -1
- package/dist/web/assets/{diff-viewer-_MPL-DRu.js → diff-viewer-CsPH6s_E.js} +1 -1
- package/dist/web/assets/{extension-webview-BU1T2a8n.js → extension-webview-DYuYgKhD.js} +1 -1
- package/dist/web/assets/{git-graph-Dde-j8cK.js → git-graph-XDyQYPZk.js} +1 -1
- package/dist/web/assets/{index-CyXEMb4g.js → index-BffsIdqe.js} +4 -4
- package/dist/web/assets/index-Dx21KBME.css +2 -0
- package/dist/web/assets/keybindings-store-B7gFbUFf.js +1 -0
- package/dist/web/assets/{markdown-renderer-Djgmbi23.js → markdown-renderer-C1hJEMtm.js} +1 -1
- package/dist/web/assets/{postgres-viewer-FCpA6nh4.js → postgres-viewer-BXJLyZp4.js} +1 -1
- package/dist/web/assets/{settings-tab-Y37tD1kM.js → settings-tab-C_jaua57.js} +1 -1
- package/dist/web/assets/{sqlite-viewer-Cjl4uXyo.js → sqlite-viewer-BFdZBZgC.js} +1 -1
- package/dist/web/assets/{terminal-tab-CnYqGghP.js → terminal-tab-COW3438-.js} +1 -1
- package/dist/web/assets/{use-monaco-theme-DGjkK3eO.js → use-monaco-theme-DqA6WXo2.js} +1 -1
- package/dist/web/index.html +2 -2
- package/dist/web/sw.js +1 -1
- package/package.json +1 -1
- package/packages/ext-database/package.json +9 -2
- package/packages/ext-database/src/connection-tree.ts +64 -5
- package/packages/ext-database/src/extension.ts +234 -2
- package/packages/ext-database/src/query-panel.ts +29 -16
- package/packages/ext-database/src/table-viewer-panel.ts +16 -6
- package/src/server/ws/chat.ts +10 -13
- package/src/web/components/layout/mobile-nav.tsx +5 -5
- package/src/web/lib/ws-client.ts +15 -0
- package/dist/web/assets/index-BkidPsSC.css +0 -2
- package/dist/web/assets/keybindings-store-6_p_JT0B.js +0 -1
package/dist/web/sw.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
try{self[`workbox:core:7.3.0`]&&_()}catch{}var e=(e,...t)=>{let n=e;return t.length>0&&(n+=` :: ${JSON.stringify(t)}`),n},t=class extends Error{constructor(t,n){let r=e(t,n);super(r),this.name=t,this.details=n}},n={googleAnalytics:`googleAnalytics`,precache:`precache-v2`,prefix:`workbox`,runtime:`runtime`,suffix:typeof registration<`u`?registration.scope:``},r=e=>[n.prefix,e,n.suffix].filter(e=>e&&e.length>0).join(`-`),i=e=>{for(let t of Object.keys(n))e(t)},a={updateDetails:e=>{i(t=>{typeof e[t]==`string`&&(n[t]=e[t])})},getGoogleAnalyticsName:e=>e||r(n.googleAnalytics),getPrecacheName:e=>e||r(n.precache),getPrefix:()=>n.prefix,getRuntimeName:e=>e||r(n.runtime),getSuffix:()=>n.suffix};function o(e,t){let n=t();return e.waitUntil(n),n}try{self[`workbox:precaching:7.3.0`]&&_()}catch{}var s=`__WB_REVISION__`;function c(e){if(!e)throw new t(`add-to-cache-list-unexpected-type`,{entry:e});if(typeof e==`string`){let t=new URL(e,location.href);return{cacheKey:t.href,url:t.href}}let{revision:n,url:r}=e;if(!r)throw new t(`add-to-cache-list-unexpected-type`,{entry:e});if(!n){let e=new URL(r,location.href);return{cacheKey:e.href,url:e.href}}let i=new URL(r,location.href),a=new URL(r,location.href);return i.searchParams.set(s,n),{cacheKey:i.href,url:a.href}}var l=class{constructor(){this.updatedURLs=[],this.notUpdatedURLs=[],this.handlerWillStart=async({request:e,state:t})=>{t&&(t.originalRequest=e)},this.cachedResponseWillBeUsed=async({event:e,state:t,cachedResponse:n})=>{if(e.type===`install`&&t&&t.originalRequest&&t.originalRequest instanceof Request){let e=t.originalRequest.url;n?this.notUpdatedURLs.push(e):this.updatedURLs.push(e)}return n}}},u=class{constructor({precacheController:e}){this.cacheKeyWillBeUsed=async({request:e,params:t})=>{let n=t?.cacheKey||this._precacheController.getCacheKeyForURL(e.url);return n?new Request(n,{headers:e.headers}):e},this._precacheController=e}},d;function f(){if(d===void 0){let e=new Response(``);if(`body`in e)try{new Response(e.body),d=!0}catch{d=!1}d=!1}return d}async function p(e,n){let r=null;if(e.url&&(r=new URL(e.url).origin),r!==self.location.origin)throw new t(`cross-origin-copy-response`,{origin:r});let i=e.clone(),a={headers:new Headers(i.headers),status:i.status,statusText:i.statusText},o=n?n(a):a,s=f()?i.body:await i.blob();return new Response(s,o)}var m=e=>new URL(String(e),location.href).href.replace(RegExp(`^${location.origin}`),``);function h(e,t){let n=new URL(e);for(let e of t)n.searchParams.delete(e);return n.href}async function g(e,t,n,r){let i=h(t.url,n);if(t.url===i)return e.match(t,r);let a=Object.assign(Object.assign({},r),{ignoreSearch:!0}),o=await e.keys(t,a);for(let t of o)if(i===h(t.url,n))return e.match(t,r)}var v=class{constructor(){this.promise=new Promise((e,t)=>{this.resolve=e,this.reject=t})}},y=new Set;async function b(){for(let e of y)await e()}function x(e){return new Promise(t=>setTimeout(t,e))}try{self[`workbox:strategies:7.3.0`]&&_()}catch{}function S(e){return typeof e==`string`?new Request(e):e}var C=class{constructor(e,t){this._cacheKeys={},Object.assign(this,t),this.event=t.event,this._strategy=e,this._handlerDeferred=new v,this._extendLifetimePromises=[],this._plugins=[...e.plugins],this._pluginStateMap=new Map;for(let e of this._plugins)this._pluginStateMap.set(e,{});this.event.waitUntil(this._handlerDeferred.promise)}async fetch(e){let{event:n}=this,r=S(e);if(r.mode===`navigate`&&n instanceof FetchEvent&&n.preloadResponse){let e=await n.preloadResponse;if(e)return e}let i=this.hasCallback(`fetchDidFail`)?r.clone():null;try{for(let e of this.iterateCallbacks(`requestWillFetch`))r=await e({request:r.clone(),event:n})}catch(e){if(e instanceof Error)throw new t(`plugin-error-request-will-fetch`,{thrownErrorMessage:e.message})}let a=r.clone();try{let e;e=await fetch(r,r.mode===`navigate`?void 0:this._strategy.fetchOptions);for(let t of this.iterateCallbacks(`fetchDidSucceed`))e=await t({event:n,request:a,response:e});return e}catch(e){throw i&&await this.runCallbacks(`fetchDidFail`,{error:e,event:n,originalRequest:i.clone(),request:a.clone()}),e}}async fetchAndCachePut(e){let t=await this.fetch(e),n=t.clone();return this.waitUntil(this.cachePut(e,n)),t}async cacheMatch(e){let t=S(e),n,{cacheName:r,matchOptions:i}=this._strategy,a=await this.getCacheKey(t,`read`),o=Object.assign(Object.assign({},i),{cacheName:r});n=await caches.match(a,o);for(let e of this.iterateCallbacks(`cachedResponseWillBeUsed`))n=await e({cacheName:r,matchOptions:i,cachedResponse:n,request:a,event:this.event})||void 0;return n}async cachePut(e,n){let r=S(e);await x(0);let i=await this.getCacheKey(r,`write`);if(!n)throw new t(`cache-put-with-no-response`,{url:m(i.url)});let a=await this._ensureResponseSafeToCache(n);if(!a)return!1;let{cacheName:o,matchOptions:s}=this._strategy,c=await self.caches.open(o),l=this.hasCallback(`cacheDidUpdate`),u=l?await g(c,i.clone(),[`__WB_REVISION__`],s):null;try{await c.put(i,l?a.clone():a)}catch(e){if(e instanceof Error)throw e.name===`QuotaExceededError`&&await b(),e}for(let e of this.iterateCallbacks(`cacheDidUpdate`))await e({cacheName:o,oldResponse:u,newResponse:a.clone(),request:i,event:this.event});return!0}async getCacheKey(e,t){let n=`${e.url} | ${t}`;if(!this._cacheKeys[n]){let r=e;for(let e of this.iterateCallbacks(`cacheKeyWillBeUsed`))r=S(await e({mode:t,request:r,event:this.event,params:this.params}));this._cacheKeys[n]=r}return this._cacheKeys[n]}hasCallback(e){for(let t of this._strategy.plugins)if(e in t)return!0;return!1}async runCallbacks(e,t){for(let n of this.iterateCallbacks(e))await n(t)}*iterateCallbacks(e){for(let t of this._strategy.plugins)if(typeof t[e]==`function`){let n=this._pluginStateMap.get(t);yield r=>{let i=Object.assign(Object.assign({},r),{state:n});return t[e](i)}}}waitUntil(e){return this._extendLifetimePromises.push(e),e}async doneWaiting(){for(;this._extendLifetimePromises.length;){let e=this._extendLifetimePromises.splice(0),t=(await Promise.allSettled(e)).find(e=>e.status===`rejected`);if(t)throw t.reason}}destroy(){this._handlerDeferred.resolve(null)}async _ensureResponseSafeToCache(e){let t=e,n=!1;for(let e of this.iterateCallbacks(`cacheWillUpdate`))if(t=await e({request:this.request,response:t,event:this.event})||void 0,n=!0,!t)break;return n||t&&t.status!==200&&(t=void 0),t}},w=class{constructor(e={}){this.cacheName=a.getRuntimeName(e.cacheName),this.plugins=e.plugins||[],this.fetchOptions=e.fetchOptions,this.matchOptions=e.matchOptions}handle(e){let[t]=this.handleAll(e);return t}handleAll(e){e instanceof FetchEvent&&(e={event:e,request:e.request});let t=e.event,n=typeof e.request==`string`?new Request(e.request):e.request,r=`params`in e?e.params:void 0,i=new C(this,{event:t,request:n,params:r}),a=this._getResponse(i,n,t);return[a,this._awaitComplete(a,i,n,t)]}async _getResponse(e,n,r){await e.runCallbacks(`handlerWillStart`,{event:r,request:n});let i;try{if(i=await this._handle(n,e),!i||i.type===`error`)throw new t(`no-response`,{url:n.url})}catch(t){if(t instanceof Error){for(let a of e.iterateCallbacks(`handlerDidError`))if(i=await a({error:t,event:r,request:n}),i)break}if(!i)throw t}for(let t of e.iterateCallbacks(`handlerWillRespond`))i=await t({event:r,request:n,response:i});return i}async _awaitComplete(e,t,n,r){let i,a;try{i=await e}catch{}try{await t.runCallbacks(`handlerDidRespond`,{event:r,request:n,response:i}),await t.doneWaiting()}catch(e){e instanceof Error&&(a=e)}if(await t.runCallbacks(`handlerDidComplete`,{event:r,request:n,response:i,error:a}),t.destroy(),a)throw a}},T=class e extends w{constructor(t={}){t.cacheName=a.getPrecacheName(t.cacheName),super(t),this._fallbackToNetwork=t.fallbackToNetwork!==!1,this.plugins.push(e.copyRedirectedCacheableResponsesPlugin)}async _handle(e,t){return await t.cacheMatch(e)||(t.event&&t.event.type===`install`?await this._handleInstall(e,t):await this._handleFetch(e,t))}async _handleFetch(e,n){let r,i=n.params||{};if(this._fallbackToNetwork){let t=i.integrity,a=e.integrity,o=!a||a===t;r=await n.fetch(new Request(e,{integrity:e.mode===`no-cors`?void 0:a||t})),t&&o&&e.mode!==`no-cors`&&(this._useDefaultCacheabilityPluginIfNeeded(),await n.cachePut(e,r.clone()))}else throw new t(`missing-precache-entry`,{cacheName:this.cacheName,url:e.url});return r}async _handleInstall(e,n){this._useDefaultCacheabilityPluginIfNeeded();let r=await n.fetch(e);if(!await n.cachePut(e,r.clone()))throw new t(`bad-precaching-response`,{url:e.url,status:r.status});return r}_useDefaultCacheabilityPluginIfNeeded(){let t=null,n=0;for(let[r,i]of this.plugins.entries())i!==e.copyRedirectedCacheableResponsesPlugin&&(i===e.defaultPrecacheCacheabilityPlugin&&(t=r),i.cacheWillUpdate&&n++);n===0?this.plugins.push(e.defaultPrecacheCacheabilityPlugin):n>1&&t!==null&&this.plugins.splice(t,1)}};T.defaultPrecacheCacheabilityPlugin={async cacheWillUpdate({response:e}){return!e||e.status>=400?null:e}},T.copyRedirectedCacheableResponsesPlugin={async cacheWillUpdate({response:e}){return e.redirected?await p(e):e}};var E=class{constructor({cacheName:e,plugins:t=[],fallbackToNetwork:n=!0}={}){this._urlsToCacheKeys=new Map,this._urlsToCacheModes=new Map,this._cacheKeysToIntegrities=new Map,this._strategy=new T({cacheName:a.getPrecacheName(e),plugins:[...t,new u({precacheController:this})],fallbackToNetwork:n}),this.install=this.install.bind(this),this.activate=this.activate.bind(this)}get strategy(){return this._strategy}precache(e){this.addToCacheList(e),this._installAndActiveListenersAdded||=(self.addEventListener(`install`,this.install),self.addEventListener(`activate`,this.activate),!0)}addToCacheList(e){let n=[];for(let r of e){typeof r==`string`?n.push(r):r&&r.revision===void 0&&n.push(r.url);let{cacheKey:e,url:i}=c(r),a=typeof r!=`string`&&r.revision?`reload`:`default`;if(this._urlsToCacheKeys.has(i)&&this._urlsToCacheKeys.get(i)!==e)throw new t(`add-to-cache-list-conflicting-entries`,{firstEntry:this._urlsToCacheKeys.get(i),secondEntry:e});if(typeof r!=`string`&&r.integrity){if(this._cacheKeysToIntegrities.has(e)&&this._cacheKeysToIntegrities.get(e)!==r.integrity)throw new t(`add-to-cache-list-conflicting-integrities`,{url:i});this._cacheKeysToIntegrities.set(e,r.integrity)}if(this._urlsToCacheKeys.set(i,e),this._urlsToCacheModes.set(i,a),n.length>0){let e=`Workbox is precaching URLs without revision info: ${n.join(`, `)}\nThis is generally NOT safe. Learn more at https://bit.ly/wb-precache`;console.warn(e)}}}install(e){return o(e,async()=>{let t=new l;this.strategy.plugins.push(t);for(let[t,n]of this._urlsToCacheKeys){let r=this._cacheKeysToIntegrities.get(n),i=this._urlsToCacheModes.get(t),a=new Request(t,{integrity:r,cache:i,credentials:`same-origin`});await Promise.all(this.strategy.handleAll({params:{cacheKey:n},request:a,event:e}))}let{updatedURLs:n,notUpdatedURLs:r}=t;return{updatedURLs:n,notUpdatedURLs:r}})}activate(e){return o(e,async()=>{let e=await self.caches.open(this.strategy.cacheName),t=await e.keys(),n=new Set(this._urlsToCacheKeys.values()),r=[];for(let i of t)n.has(i.url)||(await e.delete(i),r.push(i.url));return{deletedURLs:r}})}getURLsToCacheKeys(){return this._urlsToCacheKeys}getCachedURLs(){return[...this._urlsToCacheKeys.keys()]}getCacheKeyForURL(e){let t=new URL(e,location.href);return this._urlsToCacheKeys.get(t.href)}getIntegrityForCacheKey(e){return this._cacheKeysToIntegrities.get(e)}async matchPrecache(e){let t=e instanceof Request?e.url:e,n=this.getCacheKeyForURL(t);if(n)return(await self.caches.open(this.strategy.cacheName)).match(n)}createHandlerBoundToURL(e){let n=this.getCacheKeyForURL(e);if(!n)throw new t(`non-precached-url`,{url:e});return t=>(t.request=new Request(e),t.params=Object.assign({cacheKey:n},t.params),this.strategy.handle(t))}},D,O=()=>(D||=new E,D);try{self[`workbox:routing:7.3.0`]&&_()}catch{}var k=e=>e&&typeof e==`object`?e:{handle:e},A=class{constructor(e,t,n=`GET`){this.handler=k(t),this.match=e,this.method=n}setCatchHandler(e){this.catchHandler=k(e)}},j=class extends A{constructor(e,t,n){super(({url:t})=>{let n=e.exec(t.href);if(n&&!(t.origin!==location.origin&&n.index!==0))return n.slice(1)},t,n)}},M=class{constructor(){this._routes=new Map,this._defaultHandlerMap=new Map}get routes(){return this._routes}addFetchListener(){self.addEventListener(`fetch`,(e=>{let{request:t}=e,n=this.handleRequest({request:t,event:e});n&&e.respondWith(n)}))}addCacheListener(){self.addEventListener(`message`,(e=>{if(e.data&&e.data.type===`CACHE_URLS`){let{payload:t}=e.data,n=Promise.all(t.urlsToCache.map(t=>{typeof t==`string`&&(t=[t]);let n=new Request(...t);return this.handleRequest({request:n,event:e})}));e.waitUntil(n),e.ports&&e.ports[0]&&n.then(()=>e.ports[0].postMessage(!0))}}))}handleRequest({request:e,event:t}){let n=new URL(e.url,location.href);if(!n.protocol.startsWith(`http`))return;let r=n.origin===location.origin,{params:i,route:a}=this.findMatchingRoute({event:t,request:e,sameOrigin:r,url:n}),o=a&&a.handler,s=e.method;if(!o&&this._defaultHandlerMap.has(s)&&(o=this._defaultHandlerMap.get(s)),!o)return;let c;try{c=o.handle({url:n,request:e,event:t,params:i})}catch(e){c=Promise.reject(e)}let l=a&&a.catchHandler;return c instanceof Promise&&(this._catchHandler||l)&&(c=c.catch(async r=>{if(l)try{return await l.handle({url:n,request:e,event:t,params:i})}catch(e){e instanceof Error&&(r=e)}if(this._catchHandler)return this._catchHandler.handle({url:n,request:e,event:t});throw r})),c}findMatchingRoute({url:e,sameOrigin:t,request:n,event:r}){let i=this._routes.get(n.method)||[];for(let a of i){let i,o=a.match({url:e,sameOrigin:t,request:n,event:r});if(o)return i=o,(Array.isArray(i)&&i.length===0||o.constructor===Object&&Object.keys(o).length===0||typeof o==`boolean`)&&(i=void 0),{route:a,params:i}}return{}}setDefaultHandler(e,t=`GET`){this._defaultHandlerMap.set(t,k(e))}setCatchHandler(e){this._catchHandler=k(e)}registerRoute(e){this._routes.has(e.method)||this._routes.set(e.method,[]),this._routes.get(e.method).push(e)}unregisterRoute(e){if(!this._routes.has(e.method))throw new t(`unregister-route-but-not-found-with-method`,{method:e.method});let n=this._routes.get(e.method).indexOf(e);if(n>-1)this._routes.get(e.method).splice(n,1);else throw new t(`unregister-route-route-not-registered`)}},N,P=()=>(N||(N=new M,N.addFetchListener(),N.addCacheListener()),N);function F(e,n,r){let i;if(typeof e==`string`){let t=new URL(e,location.href);i=new A(({url:e})=>e.href===t.href,n,r)}else if(e instanceof RegExp)i=new j(e,n,r);else if(typeof e==`function`)i=new A(e,n,r);else if(e instanceof A)i=e;else throw new t(`unsupported-route-type`,{moduleName:`workbox-routing`,funcName:`registerRoute`,paramName:`capture`});return P().registerRoute(i),i}function I(e,t=[]){for(let n of[...e.searchParams.keys()])t.some(e=>e.test(n))&&e.searchParams.delete(n);return e}function*L(e,{ignoreURLParametersMatching:t=[/^utm_/,/^fbclid$/],directoryIndex:n=`index.html`,cleanURLs:r=!0,urlManipulation:i}={}){let a=new URL(e,location.href);a.hash=``,yield a.href;let o=I(a,t);if(yield o.href,n&&o.pathname.endsWith(`/`)){let e=new URL(o.href);e.pathname+=n,yield e.href}if(r){let e=new URL(o.href);e.pathname+=`.html`,yield e.href}if(i){let e=i({url:a});for(let t of e)yield t.href}}var R=class extends A{constructor(e,t){super(({request:n})=>{let r=e.getURLsToCacheKeys();for(let i of L(n.url,t)){let t=r.get(i);if(t)return{cacheKey:t,integrity:e.getIntegrityForCacheKey(t)}}},e.strategy)}};function z(e){F(new R(O(),e))}function B(e){O().precache(e)}function V(e,t){B(e),z(t)}V([{"revision":"1872c500de691dce40960bb85481de07","url":"registerSW.js"},{"revision":"78e9ddb337f8fad69c24ac9ff2c8a3f7","url":"index.html"},{"revision":"a0fb34fc84eb148d51812cd62669f20d","url":"icon-512.svg"},{"revision":"a0fb34fc84eb148d51812cd62669f20d","url":"icon-192.svg"},{"revision":"948e060affb598c339be40d69e1f6f9c","url":"monacoeditorwork/ts.worker.bundle.js"},{"revision":"a5d8a1acfc29c2a4c882a54ffc93def3","url":"monacoeditorwork/json.worker.bundle.js"},{"revision":"d0f94ce046cf8cf09605ee7664dac557","url":"monacoeditorwork/html.worker.bundle.js"},{"revision":"a424156a79b9c1b907db93aa3180585a","url":"monacoeditorwork/editor.worker.bundle.js"},{"revision":"b3a7f967560c9816492a1567b3f7f0dc","url":"monacoeditorwork/css.worker.bundle.js"},{"revision":null,"url":"assets/xychartDiagram-JWTSCODW-DRa_TH4B.js"},{"revision":null,"url":"assets/vennDiagram-LZ73GAT5-s9Z71fz-.js"},{"revision":null,"url":"assets/utils-BNytJOb1.js"},{"revision":null,"url":"assets/use-monaco-theme-DGjkK3eO.js"},{"revision":null,"url":"assets/treemap-KZPCXAKY-B2Xkyv-K.js"},{"revision":null,"url":"assets/timeline-definition-YZTLITO2-DwZqB3nn.js"},{"revision":null,"url":"assets/terminal-tab-CnYqGghP.js"},{"revision":null,"url":"assets/terminal-tab-BrP-ENHg.css"},{"revision":null,"url":"assets/tag-CXMT0QB6.js"},{"revision":null,"url":"assets/table-DFevCOMd.js"},{"revision":null,"url":"assets/tab-store-BOgTrqRr.js"},{"revision":null,"url":"assets/stateDiagram-v2-FVOUBMTO-BGVqj_g9.js"},{"revision":null,"url":"assets/stateDiagram-RAJIS63D-66vhiIuk.js"},{"revision":null,"url":"assets/src-BqX54PbV.js"},{"revision":null,"url":"assets/sqlite-viewer-Cjl4uXyo.js"},{"revision":null,"url":"assets/settings-tab-Y37tD1kM.js"},{"revision":null,"url":"assets/sequenceDiagram-2WXFIKYE-BQDJ4CVs.js"},{"revision":null,"url":"assets/sankeyDiagram-WA2Y5GQK-T6RgG-N8.js"},{"revision":null,"url":"assets/rough.esm-JX0wREDd.js"},{"revision":null,"url":"assets/requirementDiagram-Z7DCOOCP-pQyah6WB.js"},{"revision":null,"url":"assets/react-nm2Ru1Pt.js"},{"revision":null,"url":"assets/react-dom-Bpkvzu3U.js"},{"revision":null,"url":"assets/react-SKk5z-bm.js"},{"revision":null,"url":"assets/radar-KQ55EAFF-DH0AOkUy.js"},{"revision":null,"url":"assets/quadrantDiagram-337W2JSQ-C8bzJCjQ.js"},{"revision":null,"url":"assets/preload-helper-Bf_JiD2A.js"},{"revision":null,"url":"assets/postgres-viewer-FCpA6nh4.js"},{"revision":null,"url":"assets/pieDiagram-SKSYHLDU-C1Gjrtzy.js"},{"revision":null,"url":"assets/pie-UPGHQEXC-BHncZutv.js"},{"revision":null,"url":"assets/path-6uRLdFF7.js"},{"revision":null,"url":"assets/packet-RMMSAZCW-DY5PNnZU.js"},{"revision":null,"url":"assets/ordinal-_K3x1fkz.js"},{"revision":null,"url":"assets/mindmap-definition-YRQLILUH-x0MTutJp.js"},{"revision":null,"url":"assets/mermaid-parser.core-C7UwoIh6.js"},{"revision":null,"url":"assets/math-069Z4SuC.js"},{"revision":null,"url":"assets/markdown-renderer-Djgmbi23.js"},{"revision":null,"url":"assets/linear-DP4mkX3m.js"},{"revision":null,"url":"assets/line-CVvo3dRu.js"},{"revision":null,"url":"assets/lib-BQ34Db2e.js"},{"revision":null,"url":"assets/keybindings-store-6_p_JT0B.js"},{"revision":null,"url":"assets/katex-Bqvo_ZG0.js"},{"revision":null,"url":"assets/kanban-definition-K7BYSVSG-CZ535BbZ.js"},{"revision":null,"url":"assets/jsx-runtime-kMwlnEGE.js"},{"revision":null,"url":"assets/journeyDiagram-4ABVD52K-B_L20qMe.js"},{"revision":null,"url":"assets/ishikawaDiagram-PHBUUO56-D05_LyL7.js"},{"revision":null,"url":"assets/isEmpty-bnrF3Qbc.js"},{"revision":null,"url":"assets/isArrayLikeObject-B_v2FtYn.js"},{"revision":null,"url":"assets/init-DlZdxViB.js"},{"revision":null,"url":"assets/infoDiagram-LFFYTUFH-DWwumDkq.js"},{"revision":null,"url":"assets/info-3K5VOQVL-_vRxVNUm.js"},{"revision":null,"url":"assets/index-CyXEMb4g.js"},{"revision":null,"url":"assets/index-BkidPsSC.css"},{"revision":null,"url":"assets/graphlib-BcsNnGcW.js"},{"revision":null,"url":"assets/gitGraphDiagram-K3NZZRJ6-CMoukSrY.js"},{"revision":null,"url":"assets/gitGraph-HDMCJU4V-Bwna3and.js"},{"revision":null,"url":"assets/git-graph-Dde-j8cK.js"},{"revision":null,"url":"assets/ganttDiagram-A5KZAMGK-DmL26q2P.js"},{"revision":null,"url":"assets/flowDiagram-PKNHOUZH-oYaovqyp.js"},{"revision":null,"url":"assets/extension-webview-BU1T2a8n.js"},{"revision":null,"url":"assets/erDiagram-INFDFZHY-BSh2z9Df.js"},{"revision":null,"url":"assets/dist-ovWkrgO-.js"},{"revision":null,"url":"assets/dist-DIV6WgAG.js"},{"revision":null,"url":"assets/dist-CSJdAyA9.js"},{"revision":null,"url":"assets/diff-viewer-_MPL-DRu.js"},{"revision":null,"url":"assets/diagram-P4PSJMXO-C8tjJsev.js"},{"revision":null,"url":"assets/diagram-IFDJBPK2-xKoeuiJx.js"},{"revision":null,"url":"assets/diagram-E7M64L7V-_db4pBVA.js"},{"revision":null,"url":"assets/defaultLocale-5eAKkKJC.js"},{"revision":null,"url":"assets/database-viewer-CINo6teP.js"},{"revision":null,"url":"assets/dagre-KLK3FWXG-BdJr7Byp.js"},{"revision":null,"url":"assets/dagre-DHq9bhnd.js"},{"revision":null,"url":"assets/cytoscape.esm-BW-DbntU.js"},{"revision":null,"url":"assets/csv-preview-ncSOnJSC.js"},{"revision":null,"url":"assets/createLucideIcon-PuMiQgHl.js"},{"revision":null,"url":"assets/cose-bilkent-S5V4N54A-B_AWZsOP.js"},{"revision":null,"url":"assets/columns-2-cEVJHYd7.js"},{"revision":null,"url":"assets/code-editor-BdM11-0K.js"},{"revision":null,"url":"assets/clone-LRxlvnMj.js"},{"revision":null,"url":"assets/classDiagram-v2-RAHNMMFH-DjYu-6mn.js"},{"revision":null,"url":"assets/classDiagram-VBA2DB6C-BA8Nj-_C.js"},{"revision":null,"url":"assets/chunk-YBOYWFTD-rQG3QH5s.js"},{"revision":null,"url":"assets/chunk-XZSTWKYB-DxAOx4hG.js"},{"revision":null,"url":"assets/chunk-XPW4576I-BPQQBakK.js"},{"revision":null,"url":"assets/chunk-XIRO2GV7-Djlmrely.js"},{"revision":null,"url":"assets/chunk-WL4C6EOR-ByUrSRin.js"},{"revision":null,"url":"assets/chunk-R5LLSJPH-CFwSJijQ.js"},{"revision":null,"url":"assets/chunk-QZHKN3VN-CYaTbeZf.js"},{"revision":null,"url":"assets/chunk-PU5JKC2W-ek7k4QVB.js"},{"revision":null,"url":"assets/chunk-PQ6SQG4A-TF58UVMU.js"},{"revision":null,"url":"assets/chunk-OZEHJAEY-BXhYx3nO.js"},{"revision":null,"url":"assets/chunk-O4XLMI2P-nDhi_cVu.js"},{"revision":null,"url":"assets/chunk-NQ4KR5QH-z_blpjxi.js"},{"revision":null,"url":"assets/chunk-MX3YWQON-BpS_PtKp.js"},{"revision":null,"url":"assets/chunk-L3YUKLVL-C7qGJrfV.js"},{"revision":null,"url":"assets/chunk-KYZI473N-Bb0MCaIO.js"},{"revision":null,"url":"assets/chunk-KX2RTZJC-CRq1OBZv.js"},{"revision":null,"url":"assets/chunk-JSJVCQXG-99JzIdPr.js"},{"revision":null,"url":"assets/chunk-HHEYEP7N-C7vxA5i9.js"},{"revision":null,"url":"assets/chunk-GLR3WWYH-DKikpoJM.js"},{"revision":null,"url":"assets/chunk-GEFDOKGD-D-pKjlVd.js"},{"revision":null,"url":"assets/chunk-FMBD7UC4-DXncblvW.js"},{"revision":null,"url":"assets/chunk-EGIJ26TM-DzqmU2Z7.js"},{"revision":null,"url":"assets/chunk-CFjPhJqf.js"},{"revision":null,"url":"assets/chunk-C72U2L5F-D21mS_6G.js"},{"revision":null,"url":"assets/chunk-7R4GIKGN-Dv-4cAYn.js"},{"revision":null,"url":"assets/chunk-7E7YKBS2-CiyUJxNI.js"},{"revision":null,"url":"assets/chunk-55IACEB6-DJ6BynZ4.js"},{"revision":null,"url":"assets/chunk-4BX2VUAB-D4tOov49.js"},{"revision":null,"url":"assets/chevron-right-5HgK6l7K.js"},{"revision":null,"url":"assets/chat-tab-rYBo5Mff.js"},{"revision":null,"url":"assets/channel-By7bn0Yq.js"},{"revision":null,"url":"assets/c4Diagram-IC4MRINW-0Vp0Jeas.js"},{"revision":null,"url":"assets/browser-tab-LFNnCzgB.js"},{"revision":null,"url":"assets/blockDiagram-WCTKOSBZ-BCLqzhuZ.js"},{"revision":null,"url":"assets/arrow-up-BYhx9ckd.js"},{"revision":null,"url":"assets/array-B9UHiPd-.js"},{"revision":null,"url":"assets/architectureDiagram-2XIMDMQ5-Z-4eN4za.js"},{"revision":null,"url":"assets/architecture-PBZL5I3N-DEO2f3VD.js"},{"revision":null,"url":"assets/arc-BAOivWpI.js"},{"revision":null,"url":"assets/api-settings-BUvk6Saw.js"},{"revision":null,"url":"assets/api-client-BfBM3I7n.js"},{"revision":null,"url":"assets/_baseUniq-BT4Ow4Kk.js"},{"revision":null,"url":"assets/_basePickBy-5PGDJbfF.js"},{"revision":"79c8870653c8f419f2e3323085e1f4be","url":"manifest.webmanifest"}]),self.addEventListener(`push`,e=>{e.waitUntil(self.clients.matchAll({type:`window`,includeUncontrolled:!0}).then(t=>{if(t.some(e=>e.visibilityState===`visible`))return;let n=e.data?.json()??{title:`PPM`,body:`Chat completed`};return self.registration.showNotification(n.title,{body:n.body,icon:`/icon-192.png`,badge:`/icon-192.png`,tag:`ppm-chat-done`,silent:!1,data:{url:self.location.origin}})}))}),self.addEventListener(`notificationclick`,e=>{e.notification.close(),e.waitUntil(self.clients.matchAll({type:`window`,includeUncontrolled:!0}).then(t=>{for(let e of t)if(e.url.includes(self.location.origin)&&`focus`in e)return e.focus();return self.clients.openWindow(e.notification.data?.url||`/`)}))});
|
|
1
|
+
try{self[`workbox:core:7.3.0`]&&_()}catch{}var e=(e,...t)=>{let n=e;return t.length>0&&(n+=` :: ${JSON.stringify(t)}`),n},t=class extends Error{constructor(t,n){let r=e(t,n);super(r),this.name=t,this.details=n}},n={googleAnalytics:`googleAnalytics`,precache:`precache-v2`,prefix:`workbox`,runtime:`runtime`,suffix:typeof registration<`u`?registration.scope:``},r=e=>[n.prefix,e,n.suffix].filter(e=>e&&e.length>0).join(`-`),i=e=>{for(let t of Object.keys(n))e(t)},a={updateDetails:e=>{i(t=>{typeof e[t]==`string`&&(n[t]=e[t])})},getGoogleAnalyticsName:e=>e||r(n.googleAnalytics),getPrecacheName:e=>e||r(n.precache),getPrefix:()=>n.prefix,getRuntimeName:e=>e||r(n.runtime),getSuffix:()=>n.suffix};function o(e,t){let n=t();return e.waitUntil(n),n}try{self[`workbox:precaching:7.3.0`]&&_()}catch{}var s=`__WB_REVISION__`;function c(e){if(!e)throw new t(`add-to-cache-list-unexpected-type`,{entry:e});if(typeof e==`string`){let t=new URL(e,location.href);return{cacheKey:t.href,url:t.href}}let{revision:n,url:r}=e;if(!r)throw new t(`add-to-cache-list-unexpected-type`,{entry:e});if(!n){let e=new URL(r,location.href);return{cacheKey:e.href,url:e.href}}let i=new URL(r,location.href),a=new URL(r,location.href);return i.searchParams.set(s,n),{cacheKey:i.href,url:a.href}}var l=class{constructor(){this.updatedURLs=[],this.notUpdatedURLs=[],this.handlerWillStart=async({request:e,state:t})=>{t&&(t.originalRequest=e)},this.cachedResponseWillBeUsed=async({event:e,state:t,cachedResponse:n})=>{if(e.type===`install`&&t&&t.originalRequest&&t.originalRequest instanceof Request){let e=t.originalRequest.url;n?this.notUpdatedURLs.push(e):this.updatedURLs.push(e)}return n}}},u=class{constructor({precacheController:e}){this.cacheKeyWillBeUsed=async({request:e,params:t})=>{let n=t?.cacheKey||this._precacheController.getCacheKeyForURL(e.url);return n?new Request(n,{headers:e.headers}):e},this._precacheController=e}},d;function f(){if(d===void 0){let e=new Response(``);if(`body`in e)try{new Response(e.body),d=!0}catch{d=!1}d=!1}return d}async function p(e,n){let r=null;if(e.url&&(r=new URL(e.url).origin),r!==self.location.origin)throw new t(`cross-origin-copy-response`,{origin:r});let i=e.clone(),a={headers:new Headers(i.headers),status:i.status,statusText:i.statusText},o=n?n(a):a,s=f()?i.body:await i.blob();return new Response(s,o)}var m=e=>new URL(String(e),location.href).href.replace(RegExp(`^${location.origin}`),``);function h(e,t){let n=new URL(e);for(let e of t)n.searchParams.delete(e);return n.href}async function g(e,t,n,r){let i=h(t.url,n);if(t.url===i)return e.match(t,r);let a=Object.assign(Object.assign({},r),{ignoreSearch:!0}),o=await e.keys(t,a);for(let t of o)if(i===h(t.url,n))return e.match(t,r)}var v=class{constructor(){this.promise=new Promise((e,t)=>{this.resolve=e,this.reject=t})}},y=new Set;async function b(){for(let e of y)await e()}function x(e){return new Promise(t=>setTimeout(t,e))}try{self[`workbox:strategies:7.3.0`]&&_()}catch{}function S(e){return typeof e==`string`?new Request(e):e}var C=class{constructor(e,t){this._cacheKeys={},Object.assign(this,t),this.event=t.event,this._strategy=e,this._handlerDeferred=new v,this._extendLifetimePromises=[],this._plugins=[...e.plugins],this._pluginStateMap=new Map;for(let e of this._plugins)this._pluginStateMap.set(e,{});this.event.waitUntil(this._handlerDeferred.promise)}async fetch(e){let{event:n}=this,r=S(e);if(r.mode===`navigate`&&n instanceof FetchEvent&&n.preloadResponse){let e=await n.preloadResponse;if(e)return e}let i=this.hasCallback(`fetchDidFail`)?r.clone():null;try{for(let e of this.iterateCallbacks(`requestWillFetch`))r=await e({request:r.clone(),event:n})}catch(e){if(e instanceof Error)throw new t(`plugin-error-request-will-fetch`,{thrownErrorMessage:e.message})}let a=r.clone();try{let e;e=await fetch(r,r.mode===`navigate`?void 0:this._strategy.fetchOptions);for(let t of this.iterateCallbacks(`fetchDidSucceed`))e=await t({event:n,request:a,response:e});return e}catch(e){throw i&&await this.runCallbacks(`fetchDidFail`,{error:e,event:n,originalRequest:i.clone(),request:a.clone()}),e}}async fetchAndCachePut(e){let t=await this.fetch(e),n=t.clone();return this.waitUntil(this.cachePut(e,n)),t}async cacheMatch(e){let t=S(e),n,{cacheName:r,matchOptions:i}=this._strategy,a=await this.getCacheKey(t,`read`),o=Object.assign(Object.assign({},i),{cacheName:r});n=await caches.match(a,o);for(let e of this.iterateCallbacks(`cachedResponseWillBeUsed`))n=await e({cacheName:r,matchOptions:i,cachedResponse:n,request:a,event:this.event})||void 0;return n}async cachePut(e,n){let r=S(e);await x(0);let i=await this.getCacheKey(r,`write`);if(!n)throw new t(`cache-put-with-no-response`,{url:m(i.url)});let a=await this._ensureResponseSafeToCache(n);if(!a)return!1;let{cacheName:o,matchOptions:s}=this._strategy,c=await self.caches.open(o),l=this.hasCallback(`cacheDidUpdate`),u=l?await g(c,i.clone(),[`__WB_REVISION__`],s):null;try{await c.put(i,l?a.clone():a)}catch(e){if(e instanceof Error)throw e.name===`QuotaExceededError`&&await b(),e}for(let e of this.iterateCallbacks(`cacheDidUpdate`))await e({cacheName:o,oldResponse:u,newResponse:a.clone(),request:i,event:this.event});return!0}async getCacheKey(e,t){let n=`${e.url} | ${t}`;if(!this._cacheKeys[n]){let r=e;for(let e of this.iterateCallbacks(`cacheKeyWillBeUsed`))r=S(await e({mode:t,request:r,event:this.event,params:this.params}));this._cacheKeys[n]=r}return this._cacheKeys[n]}hasCallback(e){for(let t of this._strategy.plugins)if(e in t)return!0;return!1}async runCallbacks(e,t){for(let n of this.iterateCallbacks(e))await n(t)}*iterateCallbacks(e){for(let t of this._strategy.plugins)if(typeof t[e]==`function`){let n=this._pluginStateMap.get(t);yield r=>{let i=Object.assign(Object.assign({},r),{state:n});return t[e](i)}}}waitUntil(e){return this._extendLifetimePromises.push(e),e}async doneWaiting(){for(;this._extendLifetimePromises.length;){let e=this._extendLifetimePromises.splice(0),t=(await Promise.allSettled(e)).find(e=>e.status===`rejected`);if(t)throw t.reason}}destroy(){this._handlerDeferred.resolve(null)}async _ensureResponseSafeToCache(e){let t=e,n=!1;for(let e of this.iterateCallbacks(`cacheWillUpdate`))if(t=await e({request:this.request,response:t,event:this.event})||void 0,n=!0,!t)break;return n||t&&t.status!==200&&(t=void 0),t}},w=class{constructor(e={}){this.cacheName=a.getRuntimeName(e.cacheName),this.plugins=e.plugins||[],this.fetchOptions=e.fetchOptions,this.matchOptions=e.matchOptions}handle(e){let[t]=this.handleAll(e);return t}handleAll(e){e instanceof FetchEvent&&(e={event:e,request:e.request});let t=e.event,n=typeof e.request==`string`?new Request(e.request):e.request,r=`params`in e?e.params:void 0,i=new C(this,{event:t,request:n,params:r}),a=this._getResponse(i,n,t);return[a,this._awaitComplete(a,i,n,t)]}async _getResponse(e,n,r){await e.runCallbacks(`handlerWillStart`,{event:r,request:n});let i;try{if(i=await this._handle(n,e),!i||i.type===`error`)throw new t(`no-response`,{url:n.url})}catch(t){if(t instanceof Error){for(let a of e.iterateCallbacks(`handlerDidError`))if(i=await a({error:t,event:r,request:n}),i)break}if(!i)throw t}for(let t of e.iterateCallbacks(`handlerWillRespond`))i=await t({event:r,request:n,response:i});return i}async _awaitComplete(e,t,n,r){let i,a;try{i=await e}catch{}try{await t.runCallbacks(`handlerDidRespond`,{event:r,request:n,response:i}),await t.doneWaiting()}catch(e){e instanceof Error&&(a=e)}if(await t.runCallbacks(`handlerDidComplete`,{event:r,request:n,response:i,error:a}),t.destroy(),a)throw a}},T=class e extends w{constructor(t={}){t.cacheName=a.getPrecacheName(t.cacheName),super(t),this._fallbackToNetwork=t.fallbackToNetwork!==!1,this.plugins.push(e.copyRedirectedCacheableResponsesPlugin)}async _handle(e,t){return await t.cacheMatch(e)||(t.event&&t.event.type===`install`?await this._handleInstall(e,t):await this._handleFetch(e,t))}async _handleFetch(e,n){let r,i=n.params||{};if(this._fallbackToNetwork){let t=i.integrity,a=e.integrity,o=!a||a===t;r=await n.fetch(new Request(e,{integrity:e.mode===`no-cors`?void 0:a||t})),t&&o&&e.mode!==`no-cors`&&(this._useDefaultCacheabilityPluginIfNeeded(),await n.cachePut(e,r.clone()))}else throw new t(`missing-precache-entry`,{cacheName:this.cacheName,url:e.url});return r}async _handleInstall(e,n){this._useDefaultCacheabilityPluginIfNeeded();let r=await n.fetch(e);if(!await n.cachePut(e,r.clone()))throw new t(`bad-precaching-response`,{url:e.url,status:r.status});return r}_useDefaultCacheabilityPluginIfNeeded(){let t=null,n=0;for(let[r,i]of this.plugins.entries())i!==e.copyRedirectedCacheableResponsesPlugin&&(i===e.defaultPrecacheCacheabilityPlugin&&(t=r),i.cacheWillUpdate&&n++);n===0?this.plugins.push(e.defaultPrecacheCacheabilityPlugin):n>1&&t!==null&&this.plugins.splice(t,1)}};T.defaultPrecacheCacheabilityPlugin={async cacheWillUpdate({response:e}){return!e||e.status>=400?null:e}},T.copyRedirectedCacheableResponsesPlugin={async cacheWillUpdate({response:e}){return e.redirected?await p(e):e}};var E=class{constructor({cacheName:e,plugins:t=[],fallbackToNetwork:n=!0}={}){this._urlsToCacheKeys=new Map,this._urlsToCacheModes=new Map,this._cacheKeysToIntegrities=new Map,this._strategy=new T({cacheName:a.getPrecacheName(e),plugins:[...t,new u({precacheController:this})],fallbackToNetwork:n}),this.install=this.install.bind(this),this.activate=this.activate.bind(this)}get strategy(){return this._strategy}precache(e){this.addToCacheList(e),this._installAndActiveListenersAdded||=(self.addEventListener(`install`,this.install),self.addEventListener(`activate`,this.activate),!0)}addToCacheList(e){let n=[];for(let r of e){typeof r==`string`?n.push(r):r&&r.revision===void 0&&n.push(r.url);let{cacheKey:e,url:i}=c(r),a=typeof r!=`string`&&r.revision?`reload`:`default`;if(this._urlsToCacheKeys.has(i)&&this._urlsToCacheKeys.get(i)!==e)throw new t(`add-to-cache-list-conflicting-entries`,{firstEntry:this._urlsToCacheKeys.get(i),secondEntry:e});if(typeof r!=`string`&&r.integrity){if(this._cacheKeysToIntegrities.has(e)&&this._cacheKeysToIntegrities.get(e)!==r.integrity)throw new t(`add-to-cache-list-conflicting-integrities`,{url:i});this._cacheKeysToIntegrities.set(e,r.integrity)}if(this._urlsToCacheKeys.set(i,e),this._urlsToCacheModes.set(i,a),n.length>0){let e=`Workbox is precaching URLs without revision info: ${n.join(`, `)}\nThis is generally NOT safe. Learn more at https://bit.ly/wb-precache`;console.warn(e)}}}install(e){return o(e,async()=>{let t=new l;this.strategy.plugins.push(t);for(let[t,n]of this._urlsToCacheKeys){let r=this._cacheKeysToIntegrities.get(n),i=this._urlsToCacheModes.get(t),a=new Request(t,{integrity:r,cache:i,credentials:`same-origin`});await Promise.all(this.strategy.handleAll({params:{cacheKey:n},request:a,event:e}))}let{updatedURLs:n,notUpdatedURLs:r}=t;return{updatedURLs:n,notUpdatedURLs:r}})}activate(e){return o(e,async()=>{let e=await self.caches.open(this.strategy.cacheName),t=await e.keys(),n=new Set(this._urlsToCacheKeys.values()),r=[];for(let i of t)n.has(i.url)||(await e.delete(i),r.push(i.url));return{deletedURLs:r}})}getURLsToCacheKeys(){return this._urlsToCacheKeys}getCachedURLs(){return[...this._urlsToCacheKeys.keys()]}getCacheKeyForURL(e){let t=new URL(e,location.href);return this._urlsToCacheKeys.get(t.href)}getIntegrityForCacheKey(e){return this._cacheKeysToIntegrities.get(e)}async matchPrecache(e){let t=e instanceof Request?e.url:e,n=this.getCacheKeyForURL(t);if(n)return(await self.caches.open(this.strategy.cacheName)).match(n)}createHandlerBoundToURL(e){let n=this.getCacheKeyForURL(e);if(!n)throw new t(`non-precached-url`,{url:e});return t=>(t.request=new Request(e),t.params=Object.assign({cacheKey:n},t.params),this.strategy.handle(t))}},D,O=()=>(D||=new E,D);try{self[`workbox:routing:7.3.0`]&&_()}catch{}var k=e=>e&&typeof e==`object`?e:{handle:e},A=class{constructor(e,t,n=`GET`){this.handler=k(t),this.match=e,this.method=n}setCatchHandler(e){this.catchHandler=k(e)}},j=class extends A{constructor(e,t,n){super(({url:t})=>{let n=e.exec(t.href);if(n&&!(t.origin!==location.origin&&n.index!==0))return n.slice(1)},t,n)}},M=class{constructor(){this._routes=new Map,this._defaultHandlerMap=new Map}get routes(){return this._routes}addFetchListener(){self.addEventListener(`fetch`,(e=>{let{request:t}=e,n=this.handleRequest({request:t,event:e});n&&e.respondWith(n)}))}addCacheListener(){self.addEventListener(`message`,(e=>{if(e.data&&e.data.type===`CACHE_URLS`){let{payload:t}=e.data,n=Promise.all(t.urlsToCache.map(t=>{typeof t==`string`&&(t=[t]);let n=new Request(...t);return this.handleRequest({request:n,event:e})}));e.waitUntil(n),e.ports&&e.ports[0]&&n.then(()=>e.ports[0].postMessage(!0))}}))}handleRequest({request:e,event:t}){let n=new URL(e.url,location.href);if(!n.protocol.startsWith(`http`))return;let r=n.origin===location.origin,{params:i,route:a}=this.findMatchingRoute({event:t,request:e,sameOrigin:r,url:n}),o=a&&a.handler,s=e.method;if(!o&&this._defaultHandlerMap.has(s)&&(o=this._defaultHandlerMap.get(s)),!o)return;let c;try{c=o.handle({url:n,request:e,event:t,params:i})}catch(e){c=Promise.reject(e)}let l=a&&a.catchHandler;return c instanceof Promise&&(this._catchHandler||l)&&(c=c.catch(async r=>{if(l)try{return await l.handle({url:n,request:e,event:t,params:i})}catch(e){e instanceof Error&&(r=e)}if(this._catchHandler)return this._catchHandler.handle({url:n,request:e,event:t});throw r})),c}findMatchingRoute({url:e,sameOrigin:t,request:n,event:r}){let i=this._routes.get(n.method)||[];for(let a of i){let i,o=a.match({url:e,sameOrigin:t,request:n,event:r});if(o)return i=o,(Array.isArray(i)&&i.length===0||o.constructor===Object&&Object.keys(o).length===0||typeof o==`boolean`)&&(i=void 0),{route:a,params:i}}return{}}setDefaultHandler(e,t=`GET`){this._defaultHandlerMap.set(t,k(e))}setCatchHandler(e){this._catchHandler=k(e)}registerRoute(e){this._routes.has(e.method)||this._routes.set(e.method,[]),this._routes.get(e.method).push(e)}unregisterRoute(e){if(!this._routes.has(e.method))throw new t(`unregister-route-but-not-found-with-method`,{method:e.method});let n=this._routes.get(e.method).indexOf(e);if(n>-1)this._routes.get(e.method).splice(n,1);else throw new t(`unregister-route-route-not-registered`)}},N,P=()=>(N||(N=new M,N.addFetchListener(),N.addCacheListener()),N);function F(e,n,r){let i;if(typeof e==`string`){let t=new URL(e,location.href);i=new A(({url:e})=>e.href===t.href,n,r)}else if(e instanceof RegExp)i=new j(e,n,r);else if(typeof e==`function`)i=new A(e,n,r);else if(e instanceof A)i=e;else throw new t(`unsupported-route-type`,{moduleName:`workbox-routing`,funcName:`registerRoute`,paramName:`capture`});return P().registerRoute(i),i}function I(e,t=[]){for(let n of[...e.searchParams.keys()])t.some(e=>e.test(n))&&e.searchParams.delete(n);return e}function*L(e,{ignoreURLParametersMatching:t=[/^utm_/,/^fbclid$/],directoryIndex:n=`index.html`,cleanURLs:r=!0,urlManipulation:i}={}){let a=new URL(e,location.href);a.hash=``,yield a.href;let o=I(a,t);if(yield o.href,n&&o.pathname.endsWith(`/`)){let e=new URL(o.href);e.pathname+=n,yield e.href}if(r){let e=new URL(o.href);e.pathname+=`.html`,yield e.href}if(i){let e=i({url:a});for(let t of e)yield t.href}}var R=class extends A{constructor(e,t){super(({request:n})=>{let r=e.getURLsToCacheKeys();for(let i of L(n.url,t)){let t=r.get(i);if(t)return{cacheKey:t,integrity:e.getIntegrityForCacheKey(t)}}},e.strategy)}};function z(e){F(new R(O(),e))}function B(e){O().precache(e)}function V(e,t){B(e),z(t)}V([{"revision":"1872c500de691dce40960bb85481de07","url":"registerSW.js"},{"revision":"fad83859fcbc83cfa1d4c3fd5ebec12e","url":"index.html"},{"revision":"a0fb34fc84eb148d51812cd62669f20d","url":"icon-512.svg"},{"revision":"a0fb34fc84eb148d51812cd62669f20d","url":"icon-192.svg"},{"revision":"948e060affb598c339be40d69e1f6f9c","url":"monacoeditorwork/ts.worker.bundle.js"},{"revision":"a5d8a1acfc29c2a4c882a54ffc93def3","url":"monacoeditorwork/json.worker.bundle.js"},{"revision":"d0f94ce046cf8cf09605ee7664dac557","url":"monacoeditorwork/html.worker.bundle.js"},{"revision":"a424156a79b9c1b907db93aa3180585a","url":"monacoeditorwork/editor.worker.bundle.js"},{"revision":"b3a7f967560c9816492a1567b3f7f0dc","url":"monacoeditorwork/css.worker.bundle.js"},{"revision":null,"url":"assets/xychartDiagram-JWTSCODW-DRa_TH4B.js"},{"revision":null,"url":"assets/vennDiagram-LZ73GAT5-s9Z71fz-.js"},{"revision":null,"url":"assets/utils-BNytJOb1.js"},{"revision":null,"url":"assets/use-monaco-theme-DqA6WXo2.js"},{"revision":null,"url":"assets/treemap-KZPCXAKY-B2Xkyv-K.js"},{"revision":null,"url":"assets/timeline-definition-YZTLITO2-DwZqB3nn.js"},{"revision":null,"url":"assets/terminal-tab-COW3438-.js"},{"revision":null,"url":"assets/terminal-tab-BrP-ENHg.css"},{"revision":null,"url":"assets/tag-CXMT0QB6.js"},{"revision":null,"url":"assets/table-DFevCOMd.js"},{"revision":null,"url":"assets/tab-store-BOgTrqRr.js"},{"revision":null,"url":"assets/stateDiagram-v2-FVOUBMTO-BGVqj_g9.js"},{"revision":null,"url":"assets/stateDiagram-RAJIS63D-66vhiIuk.js"},{"revision":null,"url":"assets/src-BqX54PbV.js"},{"revision":null,"url":"assets/sqlite-viewer-BFdZBZgC.js"},{"revision":null,"url":"assets/settings-tab-C_jaua57.js"},{"revision":null,"url":"assets/sequenceDiagram-2WXFIKYE-BQDJ4CVs.js"},{"revision":null,"url":"assets/sankeyDiagram-WA2Y5GQK-T6RgG-N8.js"},{"revision":null,"url":"assets/rough.esm-JX0wREDd.js"},{"revision":null,"url":"assets/requirementDiagram-Z7DCOOCP-pQyah6WB.js"},{"revision":null,"url":"assets/react-nm2Ru1Pt.js"},{"revision":null,"url":"assets/react-dom-Bpkvzu3U.js"},{"revision":null,"url":"assets/react-SKk5z-bm.js"},{"revision":null,"url":"assets/radar-KQ55EAFF-DH0AOkUy.js"},{"revision":null,"url":"assets/quadrantDiagram-337W2JSQ-C8bzJCjQ.js"},{"revision":null,"url":"assets/preload-helper-Bf_JiD2A.js"},{"revision":null,"url":"assets/postgres-viewer-BXJLyZp4.js"},{"revision":null,"url":"assets/pieDiagram-SKSYHLDU-C1Gjrtzy.js"},{"revision":null,"url":"assets/pie-UPGHQEXC-BHncZutv.js"},{"revision":null,"url":"assets/path-6uRLdFF7.js"},{"revision":null,"url":"assets/packet-RMMSAZCW-DY5PNnZU.js"},{"revision":null,"url":"assets/ordinal-_K3x1fkz.js"},{"revision":null,"url":"assets/mindmap-definition-YRQLILUH-x0MTutJp.js"},{"revision":null,"url":"assets/mermaid-parser.core-C7UwoIh6.js"},{"revision":null,"url":"assets/math-069Z4SuC.js"},{"revision":null,"url":"assets/markdown-renderer-C1hJEMtm.js"},{"revision":null,"url":"assets/linear-DP4mkX3m.js"},{"revision":null,"url":"assets/line-CVvo3dRu.js"},{"revision":null,"url":"assets/lib-BQ34Db2e.js"},{"revision":null,"url":"assets/keybindings-store-B7gFbUFf.js"},{"revision":null,"url":"assets/katex-Bqvo_ZG0.js"},{"revision":null,"url":"assets/kanban-definition-K7BYSVSG-CZ535BbZ.js"},{"revision":null,"url":"assets/jsx-runtime-kMwlnEGE.js"},{"revision":null,"url":"assets/journeyDiagram-4ABVD52K-B_L20qMe.js"},{"revision":null,"url":"assets/ishikawaDiagram-PHBUUO56-D05_LyL7.js"},{"revision":null,"url":"assets/isEmpty-bnrF3Qbc.js"},{"revision":null,"url":"assets/isArrayLikeObject-B_v2FtYn.js"},{"revision":null,"url":"assets/init-DlZdxViB.js"},{"revision":null,"url":"assets/infoDiagram-LFFYTUFH-DWwumDkq.js"},{"revision":null,"url":"assets/info-3K5VOQVL-_vRxVNUm.js"},{"revision":null,"url":"assets/index-Dx21KBME.css"},{"revision":null,"url":"assets/index-BffsIdqe.js"},{"revision":null,"url":"assets/graphlib-BcsNnGcW.js"},{"revision":null,"url":"assets/gitGraphDiagram-K3NZZRJ6-CMoukSrY.js"},{"revision":null,"url":"assets/gitGraph-HDMCJU4V-Bwna3and.js"},{"revision":null,"url":"assets/git-graph-XDyQYPZk.js"},{"revision":null,"url":"assets/ganttDiagram-A5KZAMGK-DmL26q2P.js"},{"revision":null,"url":"assets/flowDiagram-PKNHOUZH-oYaovqyp.js"},{"revision":null,"url":"assets/extension-webview-DYuYgKhD.js"},{"revision":null,"url":"assets/erDiagram-INFDFZHY-BSh2z9Df.js"},{"revision":null,"url":"assets/dist-ovWkrgO-.js"},{"revision":null,"url":"assets/dist-DIV6WgAG.js"},{"revision":null,"url":"assets/dist-CSJdAyA9.js"},{"revision":null,"url":"assets/diff-viewer-CsPH6s_E.js"},{"revision":null,"url":"assets/diagram-P4PSJMXO-C8tjJsev.js"},{"revision":null,"url":"assets/diagram-IFDJBPK2-xKoeuiJx.js"},{"revision":null,"url":"assets/diagram-E7M64L7V-_db4pBVA.js"},{"revision":null,"url":"assets/defaultLocale-5eAKkKJC.js"},{"revision":null,"url":"assets/database-viewer-BWGt4Ufn.js"},{"revision":null,"url":"assets/dagre-KLK3FWXG-BdJr7Byp.js"},{"revision":null,"url":"assets/dagre-DHq9bhnd.js"},{"revision":null,"url":"assets/cytoscape.esm-BW-DbntU.js"},{"revision":null,"url":"assets/csv-preview-ncSOnJSC.js"},{"revision":null,"url":"assets/createLucideIcon-PuMiQgHl.js"},{"revision":null,"url":"assets/cose-bilkent-S5V4N54A-B_AWZsOP.js"},{"revision":null,"url":"assets/columns-2-cEVJHYd7.js"},{"revision":null,"url":"assets/code-editor-CLBY3U7l.js"},{"revision":null,"url":"assets/clone-LRxlvnMj.js"},{"revision":null,"url":"assets/classDiagram-v2-RAHNMMFH-DjYu-6mn.js"},{"revision":null,"url":"assets/classDiagram-VBA2DB6C-BA8Nj-_C.js"},{"revision":null,"url":"assets/chunk-YBOYWFTD-rQG3QH5s.js"},{"revision":null,"url":"assets/chunk-XZSTWKYB-DxAOx4hG.js"},{"revision":null,"url":"assets/chunk-XPW4576I-BPQQBakK.js"},{"revision":null,"url":"assets/chunk-XIRO2GV7-Djlmrely.js"},{"revision":null,"url":"assets/chunk-WL4C6EOR-ByUrSRin.js"},{"revision":null,"url":"assets/chunk-R5LLSJPH-CFwSJijQ.js"},{"revision":null,"url":"assets/chunk-QZHKN3VN-CYaTbeZf.js"},{"revision":null,"url":"assets/chunk-PU5JKC2W-ek7k4QVB.js"},{"revision":null,"url":"assets/chunk-PQ6SQG4A-TF58UVMU.js"},{"revision":null,"url":"assets/chunk-OZEHJAEY-BXhYx3nO.js"},{"revision":null,"url":"assets/chunk-O4XLMI2P-nDhi_cVu.js"},{"revision":null,"url":"assets/chunk-NQ4KR5QH-z_blpjxi.js"},{"revision":null,"url":"assets/chunk-MX3YWQON-BpS_PtKp.js"},{"revision":null,"url":"assets/chunk-L3YUKLVL-C7qGJrfV.js"},{"revision":null,"url":"assets/chunk-KYZI473N-Bb0MCaIO.js"},{"revision":null,"url":"assets/chunk-KX2RTZJC-CRq1OBZv.js"},{"revision":null,"url":"assets/chunk-JSJVCQXG-99JzIdPr.js"},{"revision":null,"url":"assets/chunk-HHEYEP7N-C7vxA5i9.js"},{"revision":null,"url":"assets/chunk-GLR3WWYH-DKikpoJM.js"},{"revision":null,"url":"assets/chunk-GEFDOKGD-D-pKjlVd.js"},{"revision":null,"url":"assets/chunk-FMBD7UC4-DXncblvW.js"},{"revision":null,"url":"assets/chunk-EGIJ26TM-DzqmU2Z7.js"},{"revision":null,"url":"assets/chunk-CFjPhJqf.js"},{"revision":null,"url":"assets/chunk-C72U2L5F-D21mS_6G.js"},{"revision":null,"url":"assets/chunk-7R4GIKGN-Dv-4cAYn.js"},{"revision":null,"url":"assets/chunk-7E7YKBS2-CiyUJxNI.js"},{"revision":null,"url":"assets/chunk-55IACEB6-DJ6BynZ4.js"},{"revision":null,"url":"assets/chunk-4BX2VUAB-D4tOov49.js"},{"revision":null,"url":"assets/chevron-right-5HgK6l7K.js"},{"revision":null,"url":"assets/chat-tab-DyCHqHNy.js"},{"revision":null,"url":"assets/channel-By7bn0Yq.js"},{"revision":null,"url":"assets/c4Diagram-IC4MRINW-0Vp0Jeas.js"},{"revision":null,"url":"assets/browser-tab-D2Z_380K.js"},{"revision":null,"url":"assets/blockDiagram-WCTKOSBZ-BCLqzhuZ.js"},{"revision":null,"url":"assets/arrow-up-BYhx9ckd.js"},{"revision":null,"url":"assets/array-B9UHiPd-.js"},{"revision":null,"url":"assets/architectureDiagram-2XIMDMQ5-Z-4eN4za.js"},{"revision":null,"url":"assets/architecture-PBZL5I3N-DEO2f3VD.js"},{"revision":null,"url":"assets/arc-BAOivWpI.js"},{"revision":null,"url":"assets/api-settings-BUvk6Saw.js"},{"revision":null,"url":"assets/api-client-BfBM3I7n.js"},{"revision":null,"url":"assets/_baseUniq-BT4Ow4Kk.js"},{"revision":null,"url":"assets/_basePickBy-5PGDJbfF.js"},{"revision":"79c8870653c8f419f2e3323085e1f4be","url":"manifest.webmanifest"}]),self.addEventListener(`push`,e=>{e.waitUntil(self.clients.matchAll({type:`window`,includeUncontrolled:!0}).then(t=>{if(t.some(e=>e.visibilityState===`visible`))return;let n=e.data?.json()??{title:`PPM`,body:`Chat completed`};return self.registration.showNotification(n.title,{body:n.body,icon:`/icon-192.png`,badge:`/icon-192.png`,tag:`ppm-chat-done`,silent:!1,data:{url:self.location.origin}})}))}),self.addEventListener(`notificationclick`,e=>{e.notification.close(),e.waitUntil(self.clients.matchAll({type:`window`,includeUncontrolled:!0}).then(t=>{for(let e of t)if(e.url.includes(self.location.origin)&&`focus`in e)return e.focus();return self.clients.openWindow(e.notification.data?.url||`/`)}))});
|
package/package.json
CHANGED
|
@@ -9,7 +9,12 @@
|
|
|
9
9
|
{ "command": "ppm-db.openViewer", "title": "Database: Open Viewer" },
|
|
10
10
|
{ "command": "ppm-db.runQuery", "title": "Database: Run SQL Query" },
|
|
11
11
|
{ "command": "ppm-db.refreshConnections", "title": "Database: Refresh Connections", "icon": "refresh" },
|
|
12
|
-
{ "command": "ppm-db.addConnection", "title": "Add connection", "icon": "plus" }
|
|
12
|
+
{ "command": "ppm-db.addConnection", "title": "Add connection", "icon": "plus" },
|
|
13
|
+
{ "command": "ppm-db.editConnection", "title": "Database: Edit Connection" },
|
|
14
|
+
{ "command": "ppm-db.deleteConnection", "title": "Database: Delete Connection" },
|
|
15
|
+
{ "command": "ppm-db.testConnection", "title": "Database: Test Connection" },
|
|
16
|
+
{ "command": "ppm-db.exportConnections", "title": "Database: Export Connections" },
|
|
17
|
+
{ "command": "ppm-db.importConnections", "title": "Database: Import Connections" }
|
|
13
18
|
],
|
|
14
19
|
"views": {
|
|
15
20
|
"sidebar": [
|
|
@@ -19,7 +24,9 @@
|
|
|
19
24
|
"menus": {
|
|
20
25
|
"commandPalette": [
|
|
21
26
|
{ "command": "ppm-db.openViewer" },
|
|
22
|
-
{ "command": "ppm-db.runQuery" }
|
|
27
|
+
{ "command": "ppm-db.runQuery" },
|
|
28
|
+
{ "command": "ppm-db.exportConnections" },
|
|
29
|
+
{ "command": "ppm-db.importConnections" }
|
|
23
30
|
],
|
|
24
31
|
"view/title": [
|
|
25
32
|
{ "command": "ppm-db.refreshConnections", "when": "view == ppm-db.connections", "group": "navigation" },
|
|
@@ -6,13 +6,17 @@
|
|
|
6
6
|
interface ConnectionNode {
|
|
7
7
|
id: string;
|
|
8
8
|
name: string;
|
|
9
|
-
type: "connection" | "table" | "column";
|
|
9
|
+
type: "connection" | "group" | "table" | "column";
|
|
10
10
|
connectionId?: number;
|
|
11
11
|
connectionName?: string;
|
|
12
12
|
connectionType?: string;
|
|
13
13
|
connectionColor?: string | null;
|
|
14
|
+
connectionReadonly?: number;
|
|
15
|
+
groupName?: string | null;
|
|
14
16
|
schemaName?: string;
|
|
15
17
|
dataType?: string;
|
|
18
|
+
rowCount?: number;
|
|
19
|
+
children?: ConnectionNode[];
|
|
16
20
|
}
|
|
17
21
|
|
|
18
22
|
interface ApiConnection {
|
|
@@ -20,6 +24,8 @@ interface ApiConnection {
|
|
|
20
24
|
name: string;
|
|
21
25
|
type: string;
|
|
22
26
|
color: string | null;
|
|
27
|
+
readonly: number;
|
|
28
|
+
group_name: string | null;
|
|
23
29
|
}
|
|
24
30
|
|
|
25
31
|
interface ApiTable {
|
|
@@ -54,7 +60,8 @@ export class ConnectionTreeProvider {
|
|
|
54
60
|
}
|
|
55
61
|
|
|
56
62
|
async getChildren(element?: ConnectionNode): Promise<ConnectionNode[]> {
|
|
57
|
-
if (!element) return this.
|
|
63
|
+
if (!element) return this.getRootNodes();
|
|
64
|
+
if (element.type === "group") return element.children ?? [];
|
|
58
65
|
if (element.type === "connection") return this.getTables(element);
|
|
59
66
|
if (element.type === "table") return this.getColumns(element);
|
|
60
67
|
return [];
|
|
@@ -62,13 +69,26 @@ export class ConnectionTreeProvider {
|
|
|
62
69
|
|
|
63
70
|
getTreeItem(element: ConnectionNode): Record<string, unknown> {
|
|
64
71
|
const isConn = element.type === "connection";
|
|
72
|
+
const isGroup = element.type === "group";
|
|
65
73
|
const isTable = element.type === "table";
|
|
66
74
|
const isCol = element.type === "column";
|
|
67
75
|
|
|
76
|
+
// Table description: row count
|
|
77
|
+
let description: string | undefined;
|
|
78
|
+
if (isCol) description = element.dataType;
|
|
79
|
+
else if (isTable && element.rowCount !== undefined) description = `${element.rowCount.toLocaleString()} rows`;
|
|
80
|
+
|
|
81
|
+
// Connection badge: type + readonly
|
|
82
|
+
let badge: string | undefined;
|
|
83
|
+
if (isConn) {
|
|
84
|
+
badge = element.connectionType === "postgres" ? "PG" : "DB";
|
|
85
|
+
if (element.connectionReadonly === 1) badge += " 🔒";
|
|
86
|
+
}
|
|
87
|
+
|
|
68
88
|
return {
|
|
69
89
|
id: element.id,
|
|
70
90
|
label: element.name,
|
|
71
|
-
description
|
|
91
|
+
description,
|
|
72
92
|
collapsibleState: isCol ? "none" : "collapsed",
|
|
73
93
|
contextValue: element.type,
|
|
74
94
|
command: isTable ? "ppm-db.openViewer" : undefined,
|
|
@@ -76,13 +96,49 @@ export class ConnectionTreeProvider {
|
|
|
76
96
|
? [element.connectionId, element.connectionName ?? "Database", element.name, element.schemaName ?? "public"]
|
|
77
97
|
: undefined,
|
|
78
98
|
color: isConn ? (element.connectionColor ?? undefined) : undefined,
|
|
79
|
-
badge
|
|
99
|
+
badge,
|
|
80
100
|
actions: isConn ? [
|
|
81
101
|
{ icon: "refresh", tooltip: "Refresh tables", command: "ppm-db.refreshConnection", commandArgs: [element.connectionId] },
|
|
82
|
-
|
|
102
|
+
{ icon: "edit", tooltip: "Edit connection", command: "ppm-db.editConnection", commandArgs: [element.connectionId] },
|
|
103
|
+
{ icon: "trash", tooltip: "Delete connection", command: "ppm-db.deleteConnection", commandArgs: [element.connectionId, element.name] },
|
|
104
|
+
] : isGroup ? [] : undefined,
|
|
83
105
|
};
|
|
84
106
|
}
|
|
85
107
|
|
|
108
|
+
/** Build root tree: group nodes wrapping connection nodes, or flat if no groups */
|
|
109
|
+
private async getRootNodes(): Promise<ConnectionNode[]> {
|
|
110
|
+
const connections = await this.getConnections();
|
|
111
|
+
// Group by group_name
|
|
112
|
+
const groups = new Map<string, ConnectionNode[]>();
|
|
113
|
+
for (const conn of connections) {
|
|
114
|
+
const key = conn.groupName ?? "__ungrouped__";
|
|
115
|
+
const list = groups.get(key) ?? [];
|
|
116
|
+
list.push(conn);
|
|
117
|
+
groups.set(key, list);
|
|
118
|
+
}
|
|
119
|
+
// If only one group (ungrouped), return connections flat
|
|
120
|
+
if (groups.size <= 1 && groups.has("__ungrouped__")) {
|
|
121
|
+
return connections;
|
|
122
|
+
}
|
|
123
|
+
// Build group nodes
|
|
124
|
+
const result: ConnectionNode[] = [];
|
|
125
|
+
const sortedKeys = Array.from(groups.keys()).sort((a, b) => {
|
|
126
|
+
if (a === "__ungrouped__") return 1;
|
|
127
|
+
if (b === "__ungrouped__") return -1;
|
|
128
|
+
return a.localeCompare(b);
|
|
129
|
+
});
|
|
130
|
+
for (const key of sortedKeys) {
|
|
131
|
+
const label = key === "__ungrouped__" ? "Ungrouped" : key;
|
|
132
|
+
result.push({
|
|
133
|
+
id: `group:${key}`,
|
|
134
|
+
name: label,
|
|
135
|
+
type: "group",
|
|
136
|
+
children: groups.get(key) ?? [],
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
return result;
|
|
140
|
+
}
|
|
141
|
+
|
|
86
142
|
private async getConnections(): Promise<ConnectionNode[]> {
|
|
87
143
|
try {
|
|
88
144
|
const res = await fetch(`${this.baseUrl}/api/db/connections`);
|
|
@@ -95,6 +151,8 @@ export class ConnectionTreeProvider {
|
|
|
95
151
|
connectionId: c.id,
|
|
96
152
|
connectionType: c.type,
|
|
97
153
|
connectionColor: c.color,
|
|
154
|
+
connectionReadonly: c.readonly,
|
|
155
|
+
groupName: c.group_name,
|
|
98
156
|
}));
|
|
99
157
|
} catch {
|
|
100
158
|
return [];
|
|
@@ -114,6 +172,7 @@ export class ConnectionTreeProvider {
|
|
|
114
172
|
connectionName: conn.name,
|
|
115
173
|
connectionType: conn.connectionType,
|
|
116
174
|
schemaName: t.schema,
|
|
175
|
+
rowCount: t.rowCount,
|
|
117
176
|
}));
|
|
118
177
|
} catch {
|
|
119
178
|
return [];
|
|
@@ -96,6 +96,67 @@ export function activate(context: ExtensionContext, vscode: VscodeApi): void {
|
|
|
96
96
|
}),
|
|
97
97
|
);
|
|
98
98
|
|
|
99
|
+
context.subscriptions.push(
|
|
100
|
+
vscode.commands.registerCommand("ppm-db.editConnection", async (...args: unknown[]) => {
|
|
101
|
+
const connectionId = args[0] as number;
|
|
102
|
+
if (connectionId) await editConnection(vscode, treeProvider, connectionId);
|
|
103
|
+
}),
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
context.subscriptions.push(
|
|
107
|
+
vscode.commands.registerCommand("ppm-db.deleteConnection", async (...args: unknown[]) => {
|
|
108
|
+
const connectionId = args[0] as number;
|
|
109
|
+
const connectionName = (args[1] as string) ?? "this connection";
|
|
110
|
+
if (!connectionId) return;
|
|
111
|
+
const confirm = await vscode.window.showQuickPick(["Yes, delete", "Cancel"], {
|
|
112
|
+
placeHolder: `Delete "${connectionName}"?`,
|
|
113
|
+
});
|
|
114
|
+
if (confirm !== "Yes, delete") return;
|
|
115
|
+
try {
|
|
116
|
+
const res = await fetch(`${baseUrl}/api/db/connections/${connectionId}`, { method: "DELETE" });
|
|
117
|
+
const json = await res.json() as { ok: boolean; error?: string };
|
|
118
|
+
if (json.ok) {
|
|
119
|
+
await vscode.window.showInformationMessage(`Connection "${connectionName}" deleted`);
|
|
120
|
+
treeProvider.refresh();
|
|
121
|
+
} else {
|
|
122
|
+
await vscode.window.showErrorMessage(json.error ?? "Failed to delete connection");
|
|
123
|
+
}
|
|
124
|
+
} catch (e) {
|
|
125
|
+
await vscode.window.showErrorMessage(`Error: ${e instanceof Error ? e.message : String(e)}`);
|
|
126
|
+
}
|
|
127
|
+
}),
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
context.subscriptions.push(
|
|
131
|
+
vscode.commands.registerCommand("ppm-db.testConnection", async (...args: unknown[]) => {
|
|
132
|
+
const connectionId = args[0] as number;
|
|
133
|
+
if (!connectionId) return;
|
|
134
|
+
try {
|
|
135
|
+
const res = await fetch(`${baseUrl}/api/db/connections/${connectionId}/test`, { method: "POST" });
|
|
136
|
+
const json = await res.json() as { ok: boolean; data?: { ok: boolean; error?: string } };
|
|
137
|
+
if (json.ok && json.data?.ok) {
|
|
138
|
+
await vscode.window.showInformationMessage("Connection successful");
|
|
139
|
+
} else {
|
|
140
|
+
await vscode.window.showErrorMessage(`Connection failed: ${json.data?.error ?? "Unknown error"}`);
|
|
141
|
+
}
|
|
142
|
+
} catch (e) {
|
|
143
|
+
await vscode.window.showErrorMessage(`Error: ${e instanceof Error ? e.message : String(e)}`);
|
|
144
|
+
}
|
|
145
|
+
}),
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
context.subscriptions.push(
|
|
149
|
+
vscode.commands.registerCommand("ppm-db.exportConnections", async () => {
|
|
150
|
+
await exportConnections(vscode);
|
|
151
|
+
}),
|
|
152
|
+
);
|
|
153
|
+
|
|
154
|
+
context.subscriptions.push(
|
|
155
|
+
vscode.commands.registerCommand("ppm-db.importConnections", async () => {
|
|
156
|
+
await importConnections(vscode, treeProvider);
|
|
157
|
+
}),
|
|
158
|
+
);
|
|
159
|
+
|
|
99
160
|
// --- Status Bar ---
|
|
100
161
|
const statusItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 10);
|
|
101
162
|
statusItem.text = "DB";
|
|
@@ -297,6 +358,27 @@ function openQueryPanel(
|
|
|
297
358
|
// Add Connection — collect info via QuickPick + InputBox, then POST to API
|
|
298
359
|
// ---------------------------------------------------------------------------
|
|
299
360
|
|
|
361
|
+
/** Collect optional group/color/readonly via InputBox + QuickPick */
|
|
362
|
+
async function collectConnectionExtras(vscode: VscodeApi): Promise<{ groupName?: string; color?: string; readonly?: number } | null> {
|
|
363
|
+
const groupName = await vscode.window.showInputBox({ prompt: "Group name (optional)", placeHolder: "e.g. Production" });
|
|
364
|
+
if (groupName === undefined) return null; // cancelled
|
|
365
|
+
|
|
366
|
+
const COLOR_OPTIONS = ["None", "#ef4444", "#f97316", "#eab308", "#22c55e", "#06b6d4", "#3b82f6", "#8b5cf6", "#ec4899"];
|
|
367
|
+
const color = await vscode.window.showQuickPick(COLOR_OPTIONS, { placeHolder: "Pick a color (optional)" });
|
|
368
|
+
if (color === undefined) return null;
|
|
369
|
+
|
|
370
|
+
const readonlyChoice = await vscode.window.showQuickPick(["Yes (recommended)", "No"], {
|
|
371
|
+
placeHolder: "Readonly mode? (blocks write queries)",
|
|
372
|
+
});
|
|
373
|
+
if (readonlyChoice === undefined) return null;
|
|
374
|
+
|
|
375
|
+
return {
|
|
376
|
+
groupName: groupName || undefined,
|
|
377
|
+
color: color === "None" ? undefined : color,
|
|
378
|
+
readonly: readonlyChoice.startsWith("Yes") ? 1 : 0,
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
|
|
300
382
|
async function addConnection(
|
|
301
383
|
vscode: VscodeApi,
|
|
302
384
|
treeProvider: ConnectionTreeProvider,
|
|
@@ -326,12 +408,16 @@ async function addConnection(
|
|
|
326
408
|
connectionConfig = { type: "postgres", connectionString: connStr };
|
|
327
409
|
}
|
|
328
410
|
|
|
329
|
-
// 4.
|
|
411
|
+
// 4. Group, color, readonly
|
|
412
|
+
const extras = await collectConnectionExtras(vscode);
|
|
413
|
+
if (extras === null) return;
|
|
414
|
+
|
|
415
|
+
// 5. Create via API
|
|
330
416
|
try {
|
|
331
417
|
const res = await fetch(`${baseUrl}/api/db/connections`, {
|
|
332
418
|
method: "POST",
|
|
333
419
|
headers: { "Content-Type": "application/json" },
|
|
334
|
-
body: JSON.stringify({ type, name, connectionConfig }),
|
|
420
|
+
body: JSON.stringify({ type, name, connectionConfig, ...extras }),
|
|
335
421
|
});
|
|
336
422
|
const json = await res.json() as { ok: boolean; error?: string };
|
|
337
423
|
if (json.ok) {
|
|
@@ -344,3 +430,149 @@ async function addConnection(
|
|
|
344
430
|
await vscode.window.showErrorMessage(`Error: ${e instanceof Error ? e.message : String(e)}`);
|
|
345
431
|
}
|
|
346
432
|
}
|
|
433
|
+
|
|
434
|
+
// ---------------------------------------------------------------------------
|
|
435
|
+
// Edit Connection — update name, group, color, readonly via QuickPick/InputBox
|
|
436
|
+
// ---------------------------------------------------------------------------
|
|
437
|
+
|
|
438
|
+
async function editConnection(
|
|
439
|
+
vscode: VscodeApi,
|
|
440
|
+
treeProvider: ConnectionTreeProvider,
|
|
441
|
+
connectionId: number,
|
|
442
|
+
): Promise<void> {
|
|
443
|
+
// Fetch current connection data
|
|
444
|
+
let conn: { id: number; name: string; type: string; group_name?: string; color?: string; readonly?: number };
|
|
445
|
+
try {
|
|
446
|
+
const res = await fetch(`${baseUrl}/api/db/connections/${connectionId}`);
|
|
447
|
+
const json = await res.json() as { ok: boolean; data?: typeof conn };
|
|
448
|
+
if (!json.ok || !json.data) {
|
|
449
|
+
await vscode.window.showErrorMessage("Failed to load connection");
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
452
|
+
conn = json.data;
|
|
453
|
+
} catch (e) {
|
|
454
|
+
await vscode.window.showErrorMessage(`Error: ${e instanceof Error ? e.message : String(e)}`);
|
|
455
|
+
return;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// Name
|
|
459
|
+
const name = await vscode.window.showInputBox({ prompt: "Connection name", value: conn.name });
|
|
460
|
+
if (name === undefined) return;
|
|
461
|
+
|
|
462
|
+
// Connection config (optional update)
|
|
463
|
+
let connectionConfig: Record<string, string> | undefined;
|
|
464
|
+
const updateConfig = await vscode.window.showQuickPick(["Keep current", "Update connection config"], {
|
|
465
|
+
placeHolder: "Connection config",
|
|
466
|
+
});
|
|
467
|
+
if (updateConfig === undefined) return;
|
|
468
|
+
if (updateConfig === "Update connection config") {
|
|
469
|
+
if (conn.type === "sqlite") {
|
|
470
|
+
const path = await vscode.window.showInputBox({ prompt: "SQLite file path", placeHolder: "/path/to/database.db" });
|
|
471
|
+
if (path === undefined) return;
|
|
472
|
+
if (path) connectionConfig = { type: "sqlite", path };
|
|
473
|
+
} else {
|
|
474
|
+
const connStr = await vscode.window.showInputBox({ prompt: "PostgreSQL connection string", placeHolder: "postgres://user:pass@host:5432/dbname" });
|
|
475
|
+
if (connStr === undefined) return;
|
|
476
|
+
if (connStr) connectionConfig = { type: "postgres", connectionString: connStr };
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
// Group, color, readonly
|
|
481
|
+
const groupName = await vscode.window.showInputBox({ prompt: "Group name", value: conn.group_name ?? "" });
|
|
482
|
+
if (groupName === undefined) return;
|
|
483
|
+
|
|
484
|
+
const COLOR_OPTIONS = ["None", "#ef4444", "#f97316", "#eab308", "#22c55e", "#06b6d4", "#3b82f6", "#8b5cf6", "#ec4899"];
|
|
485
|
+
const color = await vscode.window.showQuickPick(COLOR_OPTIONS, { placeHolder: `Current color: ${conn.color ?? "None"}` });
|
|
486
|
+
if (color === undefined) return;
|
|
487
|
+
|
|
488
|
+
const readonlyChoice = await vscode.window.showQuickPick(["Yes (recommended)", "No"], {
|
|
489
|
+
placeHolder: `Readonly? (current: ${conn.readonly === 1 ? "Yes" : "No"})`,
|
|
490
|
+
});
|
|
491
|
+
if (readonlyChoice === undefined) return;
|
|
492
|
+
|
|
493
|
+
// Update via API
|
|
494
|
+
try {
|
|
495
|
+
const body: Record<string, unknown> = {
|
|
496
|
+
name: name || conn.name,
|
|
497
|
+
groupName: groupName || null,
|
|
498
|
+
color: color === "None" ? null : color,
|
|
499
|
+
readonly: readonlyChoice.startsWith("Yes") ? 1 : 0,
|
|
500
|
+
};
|
|
501
|
+
if (connectionConfig) body.connectionConfig = connectionConfig;
|
|
502
|
+
|
|
503
|
+
const res = await fetch(`${baseUrl}/api/db/connections/${connectionId}`, {
|
|
504
|
+
method: "PUT",
|
|
505
|
+
headers: { "Content-Type": "application/json" },
|
|
506
|
+
body: JSON.stringify(body),
|
|
507
|
+
});
|
|
508
|
+
const json = await res.json() as { ok: boolean; error?: string };
|
|
509
|
+
if (json.ok) {
|
|
510
|
+
await vscode.window.showInformationMessage(`Connection "${name || conn.name}" updated`);
|
|
511
|
+
treeProvider.refresh();
|
|
512
|
+
} else {
|
|
513
|
+
await vscode.window.showErrorMessage(json.error ?? "Failed to update connection");
|
|
514
|
+
}
|
|
515
|
+
} catch (e) {
|
|
516
|
+
await vscode.window.showErrorMessage(`Error: ${e instanceof Error ? e.message : String(e)}`);
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
// ---------------------------------------------------------------------------
|
|
521
|
+
// Export Connections — copy JSON to clipboard via showInformationMessage
|
|
522
|
+
// ---------------------------------------------------------------------------
|
|
523
|
+
|
|
524
|
+
async function exportConnections(vscode: VscodeApi): Promise<void> {
|
|
525
|
+
try {
|
|
526
|
+
const res = await fetch(`${baseUrl}/api/db/connections/export`);
|
|
527
|
+
const json = await res.json() as { ok: boolean; data?: unknown };
|
|
528
|
+
if (!json.ok || !json.data) {
|
|
529
|
+
await vscode.window.showErrorMessage("Failed to export connections");
|
|
530
|
+
return;
|
|
531
|
+
}
|
|
532
|
+
// In extension context, we can't write to clipboard directly — show data as info
|
|
533
|
+
const data = json.data as { connections: unknown[] };
|
|
534
|
+
await vscode.window.showInformationMessage(`Exported ${data.connections.length} connection(s). Use built-in UI for file export.`);
|
|
535
|
+
} catch (e) {
|
|
536
|
+
await vscode.window.showErrorMessage(`Error: ${e instanceof Error ? e.message : String(e)}`);
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
// ---------------------------------------------------------------------------
|
|
541
|
+
// Import Connections — paste JSON via InputBox
|
|
542
|
+
// ---------------------------------------------------------------------------
|
|
543
|
+
|
|
544
|
+
async function importConnections(
|
|
545
|
+
vscode: VscodeApi,
|
|
546
|
+
treeProvider: ConnectionTreeProvider,
|
|
547
|
+
): Promise<void> {
|
|
548
|
+
const jsonStr = await vscode.window.showInputBox({
|
|
549
|
+
prompt: "Paste connections JSON (from export)",
|
|
550
|
+
placeHolder: '{"connections": [...]}',
|
|
551
|
+
});
|
|
552
|
+
if (!jsonStr) return;
|
|
553
|
+
|
|
554
|
+
try {
|
|
555
|
+
const data = JSON.parse(jsonStr);
|
|
556
|
+
const conns = data.connections ?? data;
|
|
557
|
+
if (!Array.isArray(conns)) {
|
|
558
|
+
await vscode.window.showErrorMessage("Invalid format: expected connections array");
|
|
559
|
+
return;
|
|
560
|
+
}
|
|
561
|
+
const res = await fetch(`${baseUrl}/api/db/connections/import`, {
|
|
562
|
+
method: "POST",
|
|
563
|
+
headers: { "Content-Type": "application/json" },
|
|
564
|
+
body: JSON.stringify({ connections: conns }),
|
|
565
|
+
});
|
|
566
|
+
const json = await res.json() as { ok: boolean; data?: { imported: number; skipped: number; errors: string[] } };
|
|
567
|
+
if (json.ok && json.data) {
|
|
568
|
+
let msg = `Imported ${json.data.imported} connection(s)`;
|
|
569
|
+
if (json.data.skipped > 0) msg += `, ${json.data.skipped} skipped`;
|
|
570
|
+
await vscode.window.showInformationMessage(msg);
|
|
571
|
+
treeProvider.refresh();
|
|
572
|
+
} else {
|
|
573
|
+
await vscode.window.showErrorMessage("Import failed");
|
|
574
|
+
}
|
|
575
|
+
} catch (e) {
|
|
576
|
+
await vscode.window.showErrorMessage(`Error: ${e instanceof Error ? e.message : String(e)}`);
|
|
577
|
+
}
|
|
578
|
+
}
|
|
@@ -15,25 +15,38 @@ export function getQueryPanelHtml(connectionName: string, tableName?: string): s
|
|
|
15
15
|
<head>
|
|
16
16
|
<meta charset="utf-8">
|
|
17
17
|
<style>
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
|
19
|
+
:root {
|
|
20
|
+
--bg: #ffffff; --surface: #f4f4f5; --text: #09090b; --subtext: #71717a; --subtle: #a1a1aa;
|
|
21
|
+
--border: #e4e4e7; --border2: #d4d4d8; --blue: #3b82f6; --red: #ef4444; --green: #22c55e;
|
|
22
|
+
--surface-hover: #f4f4f5;
|
|
23
|
+
}
|
|
24
|
+
@media (prefers-color-scheme: dark) {
|
|
25
|
+
:root {
|
|
26
|
+
--bg: #09090b; --surface: #18181b; --text: #fafafa; --subtext: #a1a1aa; --subtle: #52525b;
|
|
27
|
+
--border: #27272a; --border2: #3f3f46; --blue: #3b82f6; --red: #ef4444; --green: #22c55e;
|
|
28
|
+
--surface-hover: #27272a;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
body { font-family: -apple-system, BlinkMacSystemFont, sans-serif; background: var(--bg); color: var(--text); padding: 12px; font-size: 13px; }
|
|
20
32
|
.header { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
|
|
21
33
|
.header h3 { font-size: 14px; font-weight: 600; }
|
|
22
|
-
.header .badge { background:
|
|
23
|
-
textarea { width: 100%; height: 80px; background:
|
|
24
|
-
textarea:focus { outline: none; border-color:
|
|
34
|
+
.header .badge { background: var(--surface); padding: 2px 8px; border-radius: 4px; font-size: 11px; color: var(--subtext); }
|
|
35
|
+
textarea { width: 100%; height: 80px; background: var(--surface); border: 1px solid var(--border2); border-radius: 6px; color: var(--text); padding: 8px; font-family: 'SF Mono', 'Fira Code', monospace; font-size: 12px; resize: vertical; }
|
|
36
|
+
textarea:focus { outline: none; border-color: var(--blue); }
|
|
25
37
|
.actions { display: flex; gap: 8px; margin: 8px 0; }
|
|
26
|
-
button { background:
|
|
27
|
-
button:hover {
|
|
28
|
-
button.secondary { background:
|
|
29
|
-
.status { font-size: 11px; color:
|
|
30
|
-
.error { color:
|
|
38
|
+
button { background: var(--blue); color: #fff; border: none; padding: 6px 16px; border-radius: 4px; font-size: 12px; font-weight: 600; cursor: pointer; }
|
|
39
|
+
button:hover { opacity: 0.9; }
|
|
40
|
+
button.secondary { background: var(--surface); color: var(--text); }
|
|
41
|
+
.status { font-size: 11px; color: var(--subtext); margin: 4px 0; }
|
|
42
|
+
.error { color: var(--red); background: var(--surface); padding: 8px; border-radius: 4px; margin: 8px 0; font-size: 12px; }
|
|
31
43
|
table { width: 100%; border-collapse: collapse; margin-top: 8px; font-size: 12px; }
|
|
32
|
-
th { background:
|
|
33
|
-
td { padding: 4px 8px; border-bottom: 1px solid
|
|
34
|
-
tr:hover td { background:
|
|
35
|
-
.results { max-height: 60vh; overflow: auto; border: 1px solid
|
|
36
|
-
.empty { text-align: center; padding: 24px; color:
|
|
44
|
+
th { background: var(--surface); text-align: left; padding: 6px 8px; border-bottom: 1px solid var(--border2); font-weight: 600; position: sticky; top: 0; color: var(--subtext); }
|
|
45
|
+
td { padding: 4px 8px; border-bottom: 1px solid var(--border); max-width: 300px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
46
|
+
tr:hover td { background: var(--surface-hover); }
|
|
47
|
+
.results { max-height: 60vh; overflow: auto; border: 1px solid var(--border2); border-radius: 6px; }
|
|
48
|
+
.empty { text-align: center; padding: 24px; color: var(--subtle); }
|
|
49
|
+
.null-val { color: var(--subtle); font-style: italic; }
|
|
37
50
|
</style>
|
|
38
51
|
</head>
|
|
39
52
|
<body>
|
|
@@ -101,7 +114,7 @@ export function getQueryPanelHtml(connectionName: string, tableName?: string): s
|
|
|
101
114
|
html += '<tr>';
|
|
102
115
|
cols.forEach(c => {
|
|
103
116
|
const v = row[c];
|
|
104
|
-
html +=
|
|
117
|
+
html += v === null ? '<td class="null-val">NULL</td>' : '<td>' + esc(v) + '</td>';
|
|
105
118
|
});
|
|
106
119
|
html += '</tr>';
|
|
107
120
|
});
|