• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

supabase / edge-runtime / 16868291202

11 Aug 2025 12:41AM UTC coverage: 51.754% (+0.02%) from 51.733%
16868291202

push

github

web-flow
fix: if runtime is created with old eszip, emit warning message (#581)

* fix: if runtime is created with old eszip, emit warning message

* stamp: wording

24 of 24 new or added lines in 4 files covered. (100.0%)

4 existing lines in 4 files now uncovered.

18290 of 35340 relevant lines covered (51.75%)

5571.86 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.43
/crates/deno_facade/eszip/migrate.rs
1
use std::borrow::Cow;
2

3
use anyhow::anyhow;
4
use deno_core::error::AnyError;
5
use eszip_trait::SUPABASE_ESZIP_VERSION;
6
use log::warn;
7

8
use crate::errors::EszipError;
9
use crate::eszip::LazyLoadableEszip;
10

11
pub struct MigrateOptions {
12
  pub maybe_import_map_path: Option<String>,
13
}
14

15
pub async fn try_migrate_if_needed(
1,942✔
16
  mut eszip: LazyLoadableEszip,
1,942✔
17
  options: Option<MigrateOptions>,
1,942✔
18
) -> Result<LazyLoadableEszip, AnyError> {
1,942✔
19
  if let Err(err) = eszip.ensure_version().await {
1,942✔
20
    match err.downcast_ref::<EszipError>() {
1,573✔
21
      Some(err) => {
1,573✔
22
        warn!("{}: will attempt migration", err);
1,573✔
23

24
        macro_rules! cont {
25
          ($name: ident, $label:tt, $expr:expr) => {
26
            #[allow(unused_mut)]
27
            let mut $name = {
28
              match $expr {
29
                Ok(v) => v,
30
                err @ Err(_) => break $label err,
31
              }
32
            };
33
          };
34
        }
35

36
        let options = options.as_ref();
1,573✔
37
        let result = match err {
1,573✔
38
          EszipError::UnsupportedVersion { expected, found } => {
1,573✔
39
            debug_assert_eq!(*expected, SUPABASE_ESZIP_VERSION);
1,573✔
40
            match found.as_deref() {
1,573✔
41
              None => 'scope: {
42
                cont!(v1, 'scope, v1::try_migrate_v0_v1(&mut eszip, options).await);
653✔
43
                cont!(v1_1, 'scope, v1_1::try_migrate_v1_v1_1(&mut v1, options).await);
652✔
44
                v2::try_migrate_v1_1_v2(&mut v1_1, options).await
652✔
45
              }
46
              Some(b"1") => 'scope: {
920✔
47
                cont!(v1_1, 'scope, v1_1::try_migrate_v1_v1_1(&mut eszip, options).await);
8✔
48
                v2::try_migrate_v1_1_v2(&mut v1_1, options).await
6✔
49
              }
50
              Some(b"1.1") => {
912✔
51
                v2::try_migrate_v1_1_v2(&mut eszip, options).await
912✔
52
              }
53
              found => Err(anyhow!(
×
54
                "migration is not supported for this version: {}",
×
55
                found
×
56
                  .map(String::from_utf8_lossy)
×
57
                  .unwrap_or(Cow::Borrowed("unknown"))
×
58
              )),
×
59
            }
60
          }
61
        };
62

63
        result.map(|mut it| {
1,573✔
64
          it.set_migrated(true);
1,570✔
65
          it
1,570✔
66
        })
1,573✔
67
      }
68

69
      None => Err(anyhow!("failed to migrate (found unexpected error)")),
×
70
    }
71
  } else {
72
    Ok(eszip)
369✔
73
  }
74
}
1,942✔
75

76
mod v0 {
77
  use serde::Deserialize;
78
  use serde::Serialize;
79

80
  #[derive(Serialize, Deserialize, Debug)]
5,784✔
81
  pub struct Directory {
82
    pub name: String,
83
    pub entries: Vec<Entry>,
84
  }
85

86
  #[derive(Serialize, Deserialize, Debug, Clone)]
66,610✔
87
  pub struct File {
88
    pub name: String,
89
    pub offset: u64,
90
    pub len: u64,
91
    pub content: Option<Vec<u8>>,
92
  }
93

94
  #[derive(Serialize, Deserialize, Debug)]
×
95
  pub struct Symlink {
96
    pub name: String,
97
    pub dest_parts: Vec<String>,
98
  }
99

100
  #[derive(Serialize, Deserialize, Debug)]
30,472✔
101
  pub enum Entry {
102
    Dir(Directory),
103
    File(File),
104
    Symlink(Symlink),
105
  }
106
}
107

108
mod v1 {
109
  use std::collections::HashSet;
110
  use std::sync::Arc;
111

112
  use anyhow::Context;
113
  use deno_core::serde_json;
114
  use eszip::v2::EszipV2Modules;
115
  use eszip::EszipV2;
116
  use eszip_trait::AsyncEszipDataRead;
117
  use eszip_trait::SUPABASE_ESZIP_VERSION_KEY;
118
  use futures::future::OptionFuture;
119
  use once_cell::sync::Lazy;
120
  use rkyv::Archive;
121
  use rkyv::Deserialize;
122
  use rkyv::Serialize;
123

124
  use crate::migrate::v0;
125
  use crate::LazyLoadableEszip;
126

127
  use super::MigrateOptions;
128

129
  #[derive(Archive, Serialize, Deserialize, Debug)]
4,234✔
130
  #[archive(
131
    check_bytes,
132
    bound(serialize = "__S: rkyv::ser::ScratchSpace + rkyv::ser::Serializer")
133
  )]
134
  #[archive_attr(check_bytes(
135
    bound = "__C: rkyv::validation::ArchiveContext, <__C as rkyv::Fallible>::Error: std::error::Error"
136
  ))]
137
  pub struct Directory {
138
    pub name: String,
139
    // should be sorted by name
140
    #[omit_bounds]
141
    #[archive_attr(omit_bounds)]
142
    pub entries: Vec<Entry>,
143
  }
144

145
  #[derive(Archive, Serialize, Deserialize, Debug, Clone)]
29,456✔
146
  #[archive(check_bytes)]
147
  pub struct File {
148
    pub key: String,
149
    pub name: String,
150
    pub offset: u64,
151
    pub len: u64,
152
  }
153

154
  #[derive(Archive, Serialize, Deserialize, Debug)]
×
155
  #[archive(check_bytes)]
156
  pub struct Symlink {
157
    pub name: String,
158
    pub dest_parts: Vec<String>,
159
  }
160

161
  #[derive(Archive, Serialize, Deserialize, Debug)]
33,658✔
162
  #[cfg_attr(test, derive(enum_as_inner::EnumAsInner))]
4✔
163
  #[archive(check_bytes)]
164
  pub enum Entry {
165
    Dir(Directory),
166
    File(File),
167
    Symlink(Symlink),
168
  }
169

170
  pub async fn try_migrate_v0_v1(
653✔
171
    v0_eszip: &mut LazyLoadableEszip,
653✔
172
    _options: Option<&MigrateOptions>,
653✔
173
  ) -> Result<LazyLoadableEszip, anyhow::Error> {
653✔
174
    use eszip_trait::v1::VFS_ESZIP_KEY;
175

176
    let mut v1_eszip = LazyLoadableEszip::new(
653✔
177
      EszipV2 {
653✔
178
        modules: EszipV2Modules::default(),
653✔
179
        npm_snapshot: v0_eszip.npm_snapshot.take(),
653✔
180
        options: v0_eszip.options,
653✔
181
      },
653✔
182
      None,
653✔
183
    );
653✔
184

653✔
185
    v0_eszip
653✔
186
      .ensure_read_all()
653✔
187
      .await
×
188
      .with_context(|| "failed to load v0 eszip data")?;
653✔
189

190
    let vfs_mod_data = OptionFuture::<_>::from(
652✔
191
      v0_eszip
652✔
192
        .ensure_module(VFS_ESZIP_KEY)
652✔
193
        .map(|it| async move { it.source().await }),
652✔
194
    )
652✔
195
    .await
×
196
    .flatten();
652✔
197

198
    //STATIC_FILES_ESZIP_KEY
199

200
    let v1_dir = if let Some(data) = vfs_mod_data {
652✔
201
      let mut count = 0;
102✔
202
      let v0_dir =
102✔
203
        serde_json::from_slice::<Option<v0::Directory>>(data.as_ref())
102✔
204
          .with_context(|| "failed to parse v0 structure")?;
102✔
205

206
      fn migrate_dir_v0_v1(
1,928✔
207
        v0_dir: v0::Directory,
1,928✔
208
        v1_eszip: &mut LazyLoadableEszip,
1,928✔
209
        count: &mut i32,
1,928✔
210
      ) -> Directory {
1,928✔
211
        let mut v1_dir = Directory {
1,928✔
212
          name: v0_dir.name.clone(),
1,928✔
213
          entries: vec![],
1,928✔
214
        };
1,928✔
215

1,928✔
216
        let v1_dir_entries = &mut v1_dir.entries;
1,928✔
217

218
        for entry in v0_dir.entries.into_iter() {
15,236✔
219
          match entry {
15,236✔
220
            v0::Entry::Dir(v0_sub_dir) => {
1,914✔
221
              v1_dir_entries.push(Entry::Dir(migrate_dir_v0_v1(
1,914✔
222
                v0_sub_dir, v1_eszip, count,
1,914✔
223
              )));
1,914✔
224
            }
1,914✔
225

226
            v0::Entry::File(v0_sub_file) => {
13,322✔
227
              let key = format!("vfs://{}", *count);
13,322✔
228
              let data = v0_sub_file.content;
13,322✔
229

13,322✔
230
              *count += 1;
13,322✔
231
              v1_dir_entries.push(Entry::File(File {
13,322✔
232
                key: key.clone(),
13,322✔
233
                name: v0_sub_file.name,
13,322✔
234
                offset: v0_sub_file.offset,
13,322✔
235
                len: v0_sub_file.len,
13,322✔
236
              }));
13,322✔
237

238
              if let Some(data) = data {
13,322✔
239
                v1_eszip.add_opaque_data(key, data.into());
13,322✔
240
              }
13,322✔
241
            }
242

243
            v0::Entry::Symlink(v0_sub_symlink) => {
×
244
              v1_dir_entries.push(Entry::Symlink(Symlink {
×
245
                name: v0_sub_symlink.name,
×
246
                dest_parts: v0_sub_symlink.dest_parts,
×
247
              }));
×
248
            }
×
249
          }
250
        }
251

252
        v1_dir
1,928✔
253
      }
1,928✔
254

255
      v0_dir.map(|it| migrate_dir_v0_v1(it, &mut v1_eszip, &mut count))
102✔
256
    } else {
257
      None
550✔
258
    };
259

260
    let v1_vfs_data = rkyv::to_bytes::<_, 1024>(&v1_dir)
652✔
261
      .with_context(|| "failed to serialize v1 vfs data")?;
652✔
262

263
    v1_eszip.add_opaque_data(
652✔
264
      String::from(SUPABASE_ESZIP_VERSION_KEY),
652✔
265
      Arc::from(b"1" as &[u8]),
652✔
266
    );
652✔
267

652✔
268
    v1_eszip.add_opaque_data(
652✔
269
      String::from(VFS_ESZIP_KEY),
652✔
270
      Arc::from(v1_vfs_data.into_boxed_slice()),
652✔
271
    );
652✔
272

273
    static BLOCKLIST: Lazy<HashSet<&str>> =
274
      Lazy::new(|| HashSet::from([SUPABASE_ESZIP_VERSION_KEY, VFS_ESZIP_KEY]));
2✔
275

276
    let specifiers = v0_eszip.specifiers();
652✔
277
    let mut v0_modules = v0_eszip.modules.0.lock().unwrap();
652✔
278
    let mut v1_modules = v1_eszip.modules.0.lock().unwrap();
652✔
279

280
    for specifier in specifiers {
25,442✔
281
      if BLOCKLIST.contains(specifier.as_str()) {
24,790✔
282
        continue;
102✔
283
      }
24,688✔
284

24,688✔
285
      let module = v0_modules.remove(&specifier).unwrap();
24,688✔
286

24,688✔
287
      v1_modules.insert(specifier, module);
24,688✔
288
    }
289

290
    drop(v1_modules);
652✔
291

652✔
292
    Ok(v1_eszip)
652✔
293
  }
653✔
294
}
295

296
mod v1_1 {
297
  use std::sync::Arc;
298

299
  use anyhow::bail;
300
  use anyhow::Context;
301
  use eszip::v2::Checksum;
302
  use eszip::EszipV2;
303
  use eszip_trait::AsyncEszipDataRead;
304
  use eszip_trait::SUPABASE_ESZIP_VERSION_KEY;
305
  use futures::future::OptionFuture;
306

307
  use crate::eszip::LazyLoadableEszip;
308

309
  use super::v1;
310
  use super::MigrateOptions;
311

312
  pub async fn try_migrate_v1_v1_1(
660✔
313
    v1_eszip: &mut LazyLoadableEszip,
660✔
314
    _options: Option<&MigrateOptions>,
660✔
315
  ) -> Result<LazyLoadableEszip, anyhow::Error> {
660✔
316
    use eszip_trait::v1::VFS_ESZIP_KEY;
317

318
    let mut v1_1_eszip = LazyLoadableEszip::new(
660✔
319
      EszipV2 {
660✔
320
        modules: v1_eszip.modules.clone(),
660✔
321
        npm_snapshot: v1_eszip.npm_snapshot.take(),
660✔
322
        options: v1_eszip.options,
660✔
323
      },
660✔
324
      None,
660✔
325
    );
660✔
326

660✔
327
    v1_eszip
660✔
328
      .ensure_read_all()
660✔
UNCOV
329
      .await
×
330
      .with_context(|| "failed to load v1 eszip data")?;
660✔
331

332
    v1_1_eszip.set_checksum(Checksum::NoChecksum);
658✔
333
    v1_1_eszip.add_opaque_data(
658✔
334
      String::from(SUPABASE_ESZIP_VERSION_KEY),
658✔
335
      Arc::from(b"1.1" as &[u8]),
658✔
336
    );
658✔
337

338
    let v1_dir = {
658✔
339
      let Some(vfs_mod_data) = OptionFuture::<_>::from(
658✔
340
        v1_eszip
658✔
341
          .ensure_module(VFS_ESZIP_KEY)
658✔
342
          .map(|it| async move { it.take_source().await }),
1,316✔
343
      )
658✔
344
      .await
×
345
      .flatten() else {
658✔
346
        return Ok(v1_1_eszip);
×
347
      };
348

349
      let Ok(v1_dir) = rkyv::from_bytes::<Option<v1::Directory>>(&vfs_mod_data)
658✔
350
      else {
351
        bail!("cannot deserialize vfs data");
×
352
      };
353

354
      v1_dir
658✔
355
    };
356

357
    let v1_1_dir = if let Some(mut v1_dir) = v1_dir {
658✔
358
      if v1_dir.name != "node_modules" {
18✔
359
        bail!("malformed vfs data (expected node_modules)");
×
360
      }
18✔
361

18✔
362
      v1_dir.name = "localhost".into();
18✔
363

18✔
364
      Some(v1::Directory {
18✔
365
        name: "node_modules".into(),
18✔
366
        entries: vec![v1::Entry::Dir(v1_dir)],
18✔
367
      })
18✔
368
    } else {
369
      None
640✔
370
    };
371

372
    let v1_1_vfs_data = rkyv::to_bytes::<_, 1024>(&v1_1_dir)
658✔
373
      .with_context(|| "failed to serialize v1.1 vfs data")?;
658✔
374

375
    v1_1_eszip.add_opaque_data(
658✔
376
      String::from(VFS_ESZIP_KEY),
658✔
377
      Arc::from(v1_1_vfs_data.into_boxed_slice()),
658✔
378
    );
658✔
379

658✔
380
    Ok(v1_1_eszip)
658✔
381
  }
660✔
382
}
383

384
mod v2 {
385
  use std::sync::Arc;
386

387
  use anyhow::anyhow;
388
  use anyhow::Context;
389
  use deno::standalone::binary::SerializedWorkspaceResolver;
390
  use deno::standalone::binary::SerializedWorkspaceResolverImportMap;
391
  use deno_core::serde_json;
392
  use deno_core::ModuleSpecifier;
393
  use eszip::v2::Checksum;
394
  use eszip::EszipV2;
395
  use eszip_trait::v1;
396
  use eszip_trait::v2;
397
  use eszip_trait::AsyncEszipDataRead;
398
  use eszip_trait::SUPABASE_ESZIP_VERSION_KEY;
399
  use futures::future::OptionFuture;
400

401
  use crate::metadata::Entrypoint;
402
  use crate::metadata::Metadata;
403
  use crate::LazyLoadableEszip;
404

405
  use super::MigrateOptions;
406

407
  pub async fn try_migrate_v1_1_v2(
1,570✔
408
    v1_1_eszip: &mut LazyLoadableEszip,
1,570✔
409
    options: Option<&MigrateOptions>,
1,570✔
410
  ) -> Result<LazyLoadableEszip, anyhow::Error> {
1,570✔
411
    // In v2, almost everything is managed in the Metadata struct. This reduces
1,570✔
412
    // the effort required to serialize/deserialize.
1,570✔
413
    let mut v2_eszip = LazyLoadableEszip::new(
1,570✔
414
      EszipV2 {
1,570✔
415
        modules: v1_1_eszip.modules.clone(),
1,570✔
416
        npm_snapshot: v1_1_eszip.npm_snapshot.take(),
1,570✔
417
        options: v1_1_eszip.options,
1,570✔
418
      },
1,570✔
419
      None,
1,570✔
420
    );
1,570✔
421

1,570✔
422
    v1_1_eszip
1,570✔
423
      .ensure_read_all()
1,570✔
424
      .await
1✔
425
      .with_context(|| "failed to load v1.1 eszip data")?;
1,570✔
426

427
    v2_eszip.set_checksum(Checksum::NoChecksum);
1,570✔
428
    v2_eszip.add_opaque_data(
1,570✔
429
      String::from(SUPABASE_ESZIP_VERSION_KEY),
1,570✔
430
      Arc::from(b"2.0" as &[u8]),
1,570✔
431
    );
1,570✔
432

433
    let entrypoint =
1,570✔
434
      get_binary_from_eszip(v1_1_eszip, v1::SOURCE_CODE_ESZIP_KEY)
1,570✔
435
        .await
×
436
        .map(|it| String::from_utf8_lossy(it.as_ref()).into_owned())
1,570✔
437
        .map(Entrypoint::ModuleCode);
1,570✔
438

439
    let static_asset_specifiers =
1,570✔
440
      get_binary_from_eszip(v1_1_eszip, v1::STATIC_FILES_ESZIP_KEY)
1,570✔
441
        .await
×
442
        .map(|it| {
1,570✔
443
          rkyv::from_bytes(it.as_ref()).map_err(|_| {
84✔
444
            anyhow!("failed to deserialize specifiers for static files")
×
445
          })
84✔
446
        })
1,570✔
447
        .transpose()?
1,570✔
448
        .unwrap_or_default();
1,570✔
449

450
    let virtual_dir = get_binary_from_eszip(v1_1_eszip, v1::VFS_ESZIP_KEY)
1,570✔
451
      .await
×
452
      .map(|it| {
1,570✔
453
        rkyv::from_bytes(it.as_ref())
1,570✔
454
          .map_err(|_| anyhow!("failed to deserialize virtual directory"))
1,570✔
455
      })
1,570✔
456
      .transpose()?
1,570✔
457
      .flatten();
1,570✔
458

459
    let npmrc_scopes = get_binary_from_eszip(v1_1_eszip, v1::NPM_RC_SCOPES_KEY)
1,570✔
460
      .await
×
461
      .map(|it| {
1,570✔
462
        rkyv::from_bytes(it.as_ref())
904✔
463
          .map_err(|_| anyhow!("failed to deserialize npm scopes"))
904✔
464
      })
1,570✔
465
      .transpose()?;
1,570✔
466

467
    let serialized_workspace_resolver_raw = if let Some(import_map_path) =
1,570✔
468
      options.and_then(|it| it.maybe_import_map_path.as_ref())
1,570✔
469
    {
470
      let mut result = None;
532✔
471
      let import_map_url = ModuleSpecifier::parse(import_map_path.as_str())?;
532✔
472
      if let Some(import_map_module) =
532✔
473
        v1_1_eszip.ensure_import_map(import_map_url.as_str())
532✔
474
      {
475
        if let Some(source) = import_map_module.source().await {
532✔
476
          let source = String::from_utf8_lossy(&source);
532✔
477
          let import_map =
532✔
478
            import_map::parse_from_json(import_map_url.clone(), &source)?;
532✔
479
          let resolver = SerializedWorkspaceResolver {
532✔
480
            import_map: Some(SerializedWorkspaceResolverImportMap {
532✔
481
              specifier: import_map_url.to_string(),
532✔
482
              json: import_map.import_map.to_json(),
532✔
483
            }),
532✔
484
            ..Default::default()
532✔
485
          };
532✔
486
          result = Some(
532✔
487
            serde_json::to_vec(&resolver)
532✔
488
              .with_context(|| "failed to serialize workspace resolver")?,
532✔
489
          );
490
        }
×
491
      }
×
492
      result
532✔
493
    } else {
494
      None
1,038✔
495
    };
496

497
    let metadata = Metadata {
1,570✔
498
      entrypoint,
1,570✔
499
      serialized_workspace_resolver_raw,
1,570✔
500
      npmrc_scopes,
1,570✔
501
      static_asset_specifiers,
1,570✔
502
      virtual_dir,
1,570✔
503
      ca_stores: None,
1,570✔
504
      ca_data: None,
1,570✔
505
      unsafely_ignore_certificate_errors: None,
1,570✔
506
      node_modules: None,
1,570✔
507
    };
1,570✔
508

1,570✔
509
    v2_eszip.add_opaque_data(
1,570✔
510
      String::from(v2::METADATA_KEY),
1,570✔
511
      Arc::from(
1,570✔
512
        rkyv::to_bytes::<_, 1024>(&metadata)
1,570✔
513
          .with_context(|| "cannot serialize metadata")?
1,570✔
514
          .into_boxed_slice(),
1,570✔
515
      ),
1,570✔
516
    );
1,570✔
517

1,570✔
518
    Ok(v2_eszip)
1,570✔
519
  }
1,570✔
520

521
  async fn get_binary_from_eszip(
6,280✔
522
    eszip: &LazyLoadableEszip,
6,280✔
523
    specifier: &str,
6,280✔
524
  ) -> Option<Arc<[u8]>> {
6,280✔
525
    OptionFuture::<_>::from(
6,280✔
526
      eszip
6,280✔
527
        .ensure_module(specifier)
6,280✔
528
        .map(|it| async move { it.source().await }),
7,156✔
529
    )
6,280✔
530
    .await
×
531
    .flatten()
6,280✔
532
  }
6,280✔
533
}
534

535
#[cfg(test)]
536
mod test {
537
  use std::path::PathBuf;
538

539
  use eszip_trait::AsyncEszipDataRead;
540
  use tokio::fs;
541

542
  use crate::eszip::extract_eszip;
543
  use crate::eszip::migrate::try_migrate_if_needed;
544
  use crate::eszip::payload_to_eszip;
545
  use crate::eszip::EszipPayloadKind;
546
  use crate::eszip::ExtractEszipPayload;
547

548
  const MIGRATE_TEST_DIR: &str = "../base/test_cases/eszip-migration";
549

550
  async fn test_extract_eszip(orig: PathBuf, target: PathBuf) {
4✔
551
    let tmp_dir = tempfile::tempdir().unwrap();
4✔
552
    let (_orig_buf, target_buf) = {
4✔
553
      (
554
        fs::read(orig).await.unwrap(),
4✔
555
        fs::read(target).await.unwrap(),
4✔
556
      )
4✔
557
    };
4✔
558

4✔
559
    let payload = ExtractEszipPayload {
4✔
560
      data: EszipPayloadKind::VecKind(target_buf),
4✔
561
      folder: tmp_dir.path().to_path_buf(),
4✔
562
    };
4✔
563

4✔
564
    assert!(extract_eszip(payload).await);
4✔
565

566
    // TODO(Nyannyacha): It seems to be returning a buffer for the transpiled source rather than
567
    // the original source. Fix that issue and uncomment below.
568

569
    // let tmp_file_buf = fs::read(tmp_dir.path().join("index.ts")).await.unwrap();
570
    // assert_eq!(orig_buf, tmp_file_buf);
571
  }
2✔
572

573
  #[tokio::test]
574
  async fn test_extract_v0() {
1✔
575
    test_extract_eszip(
1✔
576
      PathBuf::from(format!("{}/npm-supabase-js/index.ts", MIGRATE_TEST_DIR)),
1✔
577
      PathBuf::from(format!("{}/npm-supabase-js/v0.eszip", MIGRATE_TEST_DIR)),
1✔
578
    )
1✔
579
    .await;
2✔
580
  }
1✔
581

582
  #[tokio::test]
583
  async fn test_extract_v1() {
1✔
584
    test_extract_eszip(
1✔
585
      PathBuf::from(format!("{}/npm-supabase-js/index.ts", MIGRATE_TEST_DIR)),
1✔
586
      PathBuf::from(format!("{}/npm-supabase-js/v1.eszip", MIGRATE_TEST_DIR)),
1✔
587
    )
1✔
588
    .await;
3✔
589
  }
1✔
590

591
  #[tokio::test]
592
  #[should_panic]
593
  async fn test_extract_v0_corrupted() {
1✔
594
    test_extract_eszip(
1✔
595
      PathBuf::from(format!("{}/npm-supabase-js/index.ts", MIGRATE_TEST_DIR)),
1✔
596
      PathBuf::from(format!(
1✔
597
        "{}/npm-supabase-js/v0_corrupted.eszip",
1✔
598
        MIGRATE_TEST_DIR
1✔
599
      )),
1✔
600
    )
1✔
601
    .await;
2✔
602
  }
1✔
603

604
  #[tokio::test]
605
  #[should_panic]
606
  async fn test_extract_v1_corrupted() {
1✔
607
    test_extract_eszip(
1✔
608
      PathBuf::from(format!("{}/npm-supabase-js/index.ts", MIGRATE_TEST_DIR)),
1✔
609
      PathBuf::from(format!(
1✔
610
        "{}/npm-supabase-js/v1_corrupted.eszip",
1✔
611
        MIGRATE_TEST_DIR
1✔
612
      )),
1✔
613
    )
1✔
614
    .await;
3✔
615
  }
1✔
616

617
  async fn test_vfs_npm_registry_migration_1_45_x(buf: Vec<u8>) {
4✔
618
    use eszip_trait::v1::VFS_ESZIP_KEY;
619

620
    let eszip = payload_to_eszip(EszipPayloadKind::VecKind(buf))
4✔
621
      .await
×
622
      .unwrap();
4✔
623
    let migrated = try_migrate_if_needed(eszip, None).await.unwrap();
4✔
624

625
    let vfs_data = migrated
4✔
626
      .ensure_module(VFS_ESZIP_KEY)
4✔
627
      .unwrap()
4✔
628
      .source()
4✔
629
      .await
×
630
      .unwrap();
4✔
631

4✔
632
    let dir = rkyv::from_bytes::<Option<super::v1::Directory>>(&vfs_data)
4✔
633
      .unwrap()
4✔
634
      .unwrap();
4✔
635

4✔
636
    assert_eq!(dir.name, "node_modules");
4✔
637

638
    let first_child = dir.entries.first().unwrap().as_dir().unwrap();
4✔
639

4✔
640
    assert_eq!(first_child.name, "localhost");
4✔
641
  }
4✔
642

643
  #[tokio::test]
644
  async fn test_vfs_registry_migration_v0() {
1✔
645
    test_vfs_npm_registry_migration_1_45_x(
1✔
646
      fs::read(PathBuf::from(format!(
1✔
647
        "{}/npm-supabase-js/v0.eszip",
1✔
648
        MIGRATE_TEST_DIR
1✔
649
      )))
1✔
650
      .await
1✔
651
      .unwrap(),
1✔
652
    )
1✔
653
    .await;
1✔
654
  }
1✔
655

656
  #[tokio::test]
657
  async fn test_vfs_registry_migration_v1() {
1✔
658
    test_vfs_npm_registry_migration_1_45_x(
1✔
659
      fs::read(PathBuf::from(format!(
1✔
660
        "{}/npm-supabase-js/v1.eszip",
1✔
661
        MIGRATE_TEST_DIR
1✔
662
      )))
1✔
663
      .await
1✔
664
      .unwrap(),
1✔
665
    )
1✔
666
    .await;
1✔
667
  }
1✔
668

669
  #[tokio::test]
670
  async fn test_vfs_registry_migration_v1_1_xx_hash3() {
1✔
671
    test_vfs_npm_registry_migration_1_45_x(
1✔
672
      fs::read(PathBuf::from(format!(
1✔
673
        "{}/npm-supabase-js/v1_1_xx_hash3.eszip",
1✔
674
        MIGRATE_TEST_DIR
1✔
675
      )))
1✔
676
      .await
1✔
677
      .unwrap(),
1✔
678
    )
1✔
679
    .await;
1✔
680
  }
1✔
681

682
  #[tokio::test]
683
  async fn test_vfs_registry_migration_v1_1_no_checksum() {
1✔
684
    test_vfs_npm_registry_migration_1_45_x(
1✔
685
      fs::read(PathBuf::from(format!(
1✔
686
        "{}/npm-supabase-js/v1_1_no_checksum.eszip",
1✔
687
        MIGRATE_TEST_DIR
1✔
688
      )))
1✔
689
      .await
1✔
690
      .unwrap(),
1✔
691
    )
1✔
692
    .await;
2✔
693
  }
1✔
694
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc