Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[AssetMapper] jsdeliver format issue with supabase-js #52616

Closed
ogizanagi opened this issue Nov 16, 2023 · 0 comments · Fixed by #52617
Closed

[AssetMapper] jsdeliver format issue with supabase-js #52616

ogizanagi opened this issue Nov 16, 2023 · 0 comments · Fixed by #52617

Comments

@ogizanagi
Copy link
Member

ogizanagi commented Nov 16, 2023

Symfony version(s) affected

6.4-RC1

Description

It seems there is a case that is not resolved properly by the JsDelivrEsmResolver resolver, found in a project using @supabase/supabase-jshttps://cdn.jsdelivr.net/npm/@supabase/supabase-js@2.38.4/+esm

How to reproduce

In a project using the AssetMapper component:

symfony console importmap:require @supabase/supabase-js

in your app.js:

import { createClient } from '@supabase/supabase-js';

createClient('***', '***');

You'll get an error in your browser console:

GET http://localhost:15889/npm/@supabase/node-fetch@2.6.15/+esm net::ERR_ABORTED 404 (Not Found)

Possible Solution

The JsDelivrEsmResolver::IMPORT_REGEX regex might be fixed to handle this module properly, by supporting import i,{Headers as a}from"/npm/@supabase/node-fetch@2.6.14/+esm"

-    public const IMPORT_REGEX = '#(?:import\s*(?:(?:\{[^}]*\}|\w+|\*\s*as\s+\w+)\s*\bfrom\s*)?|export\s*(?:\{[^}]*\}|\*)\s*from\s*)("/npm/((?:@[^/]+/)?[^@]+?)(?:@([^/]+))?((?:/[^/]+)*?)/\+esm")#';
+    public const IMPORT_REGEX = '#(?:import\s*(?:\w+,)?(?:(?:\{[^}]*\}|\w+|\*\s*as\s+\w+)\s*\bfrom\s*)?|export\s*(?:\{[^}]*\}|\*)\s*from\s*)("/npm/((?:@[^/]+/)?[^@]+?)(?:@([^/]+))?((?:/[^/]+)*?)/\+esm")#';

The resulting file currently is:

/**
 * Bundled by jsDelivr using Rollup v2.79.1 and Terser v5.19.2.
 * Original file: /npm/@supabase/supabase-js@2.38.4/dist/module/index.js
 *
 * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
 */
import{FunctionsClient as e}from"@supabase/functions-js";export{FunctionsError,FunctionsFetchError,FunctionsHttpError,FunctionsRelayError}from"@supabase/functions-js";import{PostgrestClient as t}from"@supabase/postgrest-js";import{RealtimeClient as s}from"@supabase/realtime-js";export*from"@supabase/realtime-js";import{StorageClient as n}from"@supabase/storage-js";import i,{Headers as a}from"/npm/@supabase/node-fetch@2.6.15/+esm";import{GoTrueClient as r}from"@supabase/gotrue-js";export*from"@supabase/gotrue-js";let o="";o="undefined"!=typeof Deno?"deno":"undefined"!=typeof document?"web":"undefined"!=typeof navigator&&"ReactNative"===navigator.product?"react-native":"node";const h={"X-Client-Info":`supabase-js-${o}/2.38.4`};var u=function(e,t,s,n){return new(s||(s=Promise))((function(i,a){function r(e){try{h(n.next(e))}catch(e){a(e)}}function o(e){try{h(n.throw(e))}catch(e){a(e)}}function h(e){var t;e.done?i(e.value):(t=e.value,t instanceof s?t:new s((function(e){e(t)}))).then(r,o)}h((n=n.apply(e,t||[])).next())}))};const l=e=>{let t;return t=e||("undefined"==typeof fetch?i:fetch),(...e)=>t(...e)},c=(e,t,s)=>{const n=l(s),i="undefined"==typeof Headers?a:Headers;return(s,a)=>u(void 0,void 0,void 0,(function*(){var r;const o=null!==(r=yield t())&&void 0!==r?r:e;let h=new i(null==a?void 0:a.headers);return h.has("apikey")||h.set("apikey",e),h.has("Authorization")||h.set("Authorization",`Bearer ${o}`),n(s,Object.assign(Object.assign({},a),{headers:h}))}))};class d extends r{constructor(e){super(e)}}var p=function(e,t,s,n){return new(s||(s=Promise))((function(i,a){function r(e){try{h(n.next(e))}catch(e){a(e)}}function o(e){try{h(n.throw(e))}catch(e){a(e)}}function h(e){var t;e.done?i(e.value):(t=e.value,t instanceof s?t:new s((function(e){e(t)}))).then(r,o)}h((n=n.apply(e,t||[])).next())}))};const m={headers:h},f={schema:"public"},g={autoRefreshToken:!0,persistSession:!0,detectSessionInUrl:!0,flowType:"implicit"},b={};class v{constructor(e,s,n){var i,a,r,o,h,u,l,d;if(this.supabaseUrl=e,this.supabaseKey=s,!e)throw new Error("supabaseUrl is required.");if(!s)throw new Error("supabaseKey is required.");const p=e.replace(/\/$/,"");this.realtimeUrl=`${p}/realtime/v1`.replace(/^http/i,"ws"),this.authUrl=`${p}/auth/v1`,this.storageUrl=`${p}/storage/v1`,this.functionsUrl=`${p}/functions/v1`;const v=`sb-${new URL(this.authUrl).hostname.split(".")[0]}-auth-token`,y=function(e,t){const{db:s,auth:n,realtime:i,global:a}=e,{db:r,auth:o,realtime:h,global:u}=t;return{db:Object.assign(Object.assign({},r),s),auth:Object.assign(Object.assign({},o),n),realtime:Object.assign(Object.assign({},h),i),global:Object.assign(Object.assign({},u),a)}}(null!=n?n:{},{db:f,realtime:b,auth:Object.assign(Object.assign({},g),{storageKey:v}),global:m});this.storageKey=null!==(a=null===(i=y.auth)||void 0===i?void 0:i.storageKey)&&void 0!==a?a:"",this.headers=null!==(o=null===(r=y.global)||void 0===r?void 0:r.headers)&&void 0!==o?o:{},this.auth=this._initSupabaseAuthClient(null!==(h=y.auth)&&void 0!==h?h:{},this.headers,null===(u=y.global)||void 0===u?void 0:u.fetch),this.fetch=c(s,this._getAccessToken.bind(this),null===(l=y.global)||void 0===l?void 0:l.fetch),this.realtime=this._initRealtimeClient(Object.assign({headers:this.headers},y.realtime)),this.rest=new t(`${p}/rest/v1`,{headers:this.headers,schema:null===(d=y.db)||void 0===d?void 0:d.schema,fetch:this.fetch}),this._listenForAuthEvents()}get functions(){return new e(this.functionsUrl,{headers:this.headers,customFetch:this.fetch})}get storage(){return new n(this.storageUrl,this.headers,this.fetch)}from(e){return this.rest.from(e)}schema(e){return this.rest.schema(e)}rpc(e,t={},s){return this.rest.rpc(e,t,s)}channel(e,t={config:{}}){return this.realtime.channel(e,t)}getChannels(){return this.realtime.getChannels()}removeChannel(e){return this.realtime.removeChannel(e)}removeAllChannels(){return this.realtime.removeAllChannels()}_getAccessToken(){var e,t;return p(this,void 0,void 0,(function*(){const{data:s}=yield this.auth.getSession();return null!==(t=null===(e=s.session)||void 0===e?void 0:e.access_token)&&void 0!==t?t:null}))}_initSupabaseAuthClient({autoRefreshToken:e,persistSession:t,detectSessionInUrl:s,storage:n,storageKey:i,flowType:a,debug:r},o,h){const u={Authorization:`Bearer ${this.supabaseKey}`,apikey:`${this.supabaseKey}`};return new d({url:this.authUrl,headers:Object.assign(Object.assign({},u),o),storageKey:i,autoRefreshToken:e,persistSession:t,detectSessionInUrl:s,storage:n,flowType:a,debug:r,fetch:h})}_initRealtimeClient(e){return new s(this.realtimeUrl,Object.assign(Object.assign({},e),{params:Object.assign({apikey:this.supabaseKey},null==e?void 0:e.params)}))}_listenForAuthEvents(){return this.auth.onAuthStateChange(((e,t)=>{this._handleTokenChanged(e,"CLIENT",null==t?void 0:t.access_token)}))}_handleTokenChanged(e,t,s){"TOKEN_REFRESHED"!==e&&"SIGNED_IN"!==e||this.changedAccessToken===s?"SIGNED_OUT"===e&&(this.realtime.setAuth(this.supabaseKey),"STORAGE"==t&&this.auth.signOut(),this.changedAccessToken=void 0):(this.realtime.setAuth(null!=s?s:null),this.changedAccessToken=s)}}const y=(e,t,s)=>new v(e,t,s);export{v as SupabaseClient,y as createClient};export default null;

Caution

Note this part:

import i,{Headers as a}from"/npm/@supabase/node-fetch@2.6.15/+esm"

which seems not to be resolved properly and leads to the browser trying to fetch the module from http://localhost:15889/npm/@supabase/node-fetch@2.6.15/+esm

➜ I guess it should have been parsed and transformed to

import i,{Headers as a}from"@supabase/node-fetch"

as for the other imports in this file (but the i,{Headers as a} notation is not handled correctly by the regex).

Additional Context

Here is the generated importmap.php file:

importmap.php
return [
    'app' => [
        'path' => './assets/app.js',
        'entrypoint' => true,
    ],
    '@hotwired/stimulus' => [
        'version' => '3.2.2',
    ],
    '@symfony/stimulus-bundle' => [
        'path' => './vendor/symfony/stimulus-bundle/assets/dist/loader.js',
    ],
    '@supabase/supabase-js' => [
        'version' => '2.38.4',
    ],
    '@supabase/functions-js' => [
        'version' => '2.1.5',
    ],
    '@supabase/postgrest-js' => [
        'version' => '1.8.5',
    ],
    '@supabase/realtime-js' => [
        'version' => '2.8.4',
    ],
    '@supabase/storage-js' => [
        'version' => '2.5.4',
    ],
    '@supabase/gotrue-js' => [
        'version' => '2.57.0',
    ],
    '@supabase/node-fetch' => [
        'version' => '2.6.14',
    ],
    'websocket' => [
        'version' => '1.0.34',
    ],
];

and the resulting installed.php file:

installed.php
<?php return array (
  '@hotwired/stimulus' => 
  array (
    'version' => '3.2.2',
    'dependencies' => 
    array (
    ),
  ),
  '@supabase/supabase-js' => 
  array (
    'version' => '2.38.4',
    'dependencies' => 
    array (
      0 => '@supabase/functions-js',
      1 => '@supabase/functions-js',
      2 => '@supabase/postgrest-js',
      3 => '@supabase/realtime-js',
      4 => '@supabase/realtime-js',
      5 => '@supabase/storage-js',
      6 => '@supabase/gotrue-js',
      7 => '@supabase/gotrue-js',
    ),
  ),
  '@supabase/functions-js' => 
  array (
    'version' => '2.1.5',
    'dependencies' => 
    array (
    ),
  ),
  '@supabase/postgrest-js' => 
  array (
    'version' => '1.8.5',
    'dependencies' => 
    array (
      0 => '@supabase/node-fetch',
    ),
  ),
  '@supabase/realtime-js' => 
  array (
    'version' => '2.8.4',
    'dependencies' => 
    array (
      0 => 'websocket',
    ),
  ),
  '@supabase/storage-js' => 
  array (
    'version' => '2.5.4',
    'dependencies' => 
    array (
    ),
  ),
  '@supabase/gotrue-js' => 
  array (
    'version' => '2.57.0',
    'dependencies' => 
    array (
    ),
  ),
  '@supabase/node-fetch' => 
  array (
    'version' => '2.6.14',
    'dependencies' => 
    array (
    ),
  ),
  'websocket' => 
  array (
    'version' => '1.0.34',
    'dependencies' => 
    array (
    ),
  ),
);
@fabpot fabpot closed this as completed Nov 25, 2023
fabpot added a commit that referenced this issue Nov 25, 2023
…rts from modules (ogizanagi)

This PR was merged into the 6.4 branch.

Discussion
----------

[AssetMapper] Fix resolving jsdeliver default + other exports from modules

| Q             | A
| ------------- | ---
| Branch?       | 6.4 <!-- see below -->
| Bug fix?      | yes
| New feature?  | no <!-- please update src/**/CHANGELOG.md files -->
| Deprecations? | no <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files -->
| Issues        | Fix #52616
| License       | MIT

Fixes resolving:

```js
import i,{Headers as a}from"/npm/`@supabase`/node-fetch@2.6.14/+esm"
```

i.e both default export and other exports in a same `import`.

Commits
-------

916daf0 [AssetMapper] Fix resolving jsdeliver default + other exports from modules
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants