@gravity-ui/data-source 0.10.0-alpha.7 → 0.10.0-alpha.9

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.
@@ -1,4 +1,4 @@
1
- const require_factory = require("./factory-Dq6kUGl-.cjs");
1
+ const require_factory = require("./factory-amr4dgO8.cjs");
2
2
  //#region src/plugin/esbuild.ts
3
3
  var esbuild_default = (0, require("unplugin").createEsbuildPlugin)(require_factory.dataSourceLazyUnpluginFactory);
4
4
  //#endregion
@@ -1,4 +1,4 @@
1
- import { n as dataSourceLazyUnpluginFactory } from "./factory-Ds3_-8kv.mjs";
1
+ import { n as dataSourceLazyUnpluginFactory } from "./factory-BxKix--T.mjs";
2
2
  import { createEsbuildPlugin } from "unplugin";
3
3
  //#region src/plugin/esbuild.ts
4
4
  var esbuild_default = createEsbuildPlugin(dataSourceLazyUnpluginFactory);
@@ -102,7 +102,7 @@ function extractHocInfo(hocsSet, filename, source) {
102
102
  for (const node of program.body) {
103
103
  if (node.type !== "ExportNamedDeclaration" || node.exportKind === "type" || node.declaration?.type !== "VariableDeclaration") continue;
104
104
  for (const decl of node.declaration.declarations) {
105
- if (decl.id.type !== "Identifier" || !decl.init || decl.init.type !== "CallExpression" || decl.init.callee.type !== "Identifier" || decl.init.arguments.length !== 3) continue;
105
+ if (decl.id.type !== "Identifier" || !decl.init || decl.init.type !== "CallExpression" || decl.init.callee.type !== "Identifier" || decl.init.arguments.length < 2) continue;
106
106
  const hocEntry = trackedHocs.get(decl.init.callee.name);
107
107
  if (!hocEntry) continue;
108
108
  const [contentArg, loadingArg, errorArg] = decl.init.arguments;
@@ -128,12 +128,12 @@ function extractHocInfo(hocsSet, filename, source) {
128
128
  argEnd: loadingArg.end,
129
129
  imports: filterNeededImports(importDecls, collectIdentifiers(loadingArg))
130
130
  },
131
- error: {
131
+ error: errorArg ? {
132
132
  argSource: source.slice(errorArg.start, errorArg.end),
133
133
  argStart: errorArg.start,
134
134
  argEnd: errorArg.end,
135
135
  imports: filterNeededImports(importDecls, collectIdentifiers(errorArg))
136
- }
136
+ } : null
137
137
  };
138
138
  }
139
139
  }
@@ -318,39 +318,49 @@ function parseProgram(filename, source) {
318
318
  }
319
319
  //#endregion
320
320
  //#region src/plugin/core/generate.ts
321
- function generateAuxModule(sourceFile, info, type, options = {}) {
322
- const auxInfo = info[type];
323
- const name = info.exportedName;
321
+ function assembleAuxModuleSource(exportedName, info, type) {
324
322
  const suffix = COMPANION_TYPES[type];
325
- const cleanSourceFile = stripQuery(sourceFile);
326
- const code = [
327
- renderImports(auxInfo.imports),
323
+ return [
324
+ renderImports(info.imports),
328
325
  "",
329
- `export const ${name}${suffix} = ${auxInfo.argSource};`,
326
+ `export const ${exportedName}${suffix} = ${info.argSource};`,
330
327
  ""
331
328
  ].join("\n").trimStart();
332
- return transformJsx(makeCompanionId(type, cleanSourceFile), code, options);
329
+ }
330
+ function compileAuxJsx(filename, code, options = {}) {
331
+ const result = transformSync(filename, code, {
332
+ lang: "tsx",
333
+ jsx: options.jsx,
334
+ target: options.target,
335
+ sourcemap: true
336
+ });
337
+ if (result.errors.length > 0) {
338
+ const error = result.errors[0];
339
+ throw new Error(error.codeframe ?? error.message);
340
+ }
341
+ return {
342
+ code: result.code,
343
+ map: JSON.stringify(result.map)
344
+ };
333
345
  }
334
346
  function generateLazyModule(sourceFile, info, options = {}) {
335
347
  const importSource = options.jsx?.importSource ?? "react";
336
348
  const name = info.exportedName;
337
349
  const cleanSourceFile = stripQuery(sourceFile);
338
350
  const base = `./${path.basename(cleanSourceFile, path.extname(cleanSourceFile))}`;
339
- const code = [
351
+ const hocBinding = info.hocImportedName === "default" ? info.hocLocalName : info.hocImportedName;
352
+ const lines = [
340
353
  `import {lazy} from '${importSource}';`,
341
354
  "",
342
355
  info.hocImportedName === "default" ? `import ${info.hocLocalName} from '${info.hocImportSource}';` : `import {${info.hocImportedName}} from '${info.hocImportSource}';`,
343
356
  "",
344
- `import {${name}Loading} from '${base}.Loading';`,
345
- `import {${name}Error} from '${base}.Error';`,
346
- ``,
347
- `export const ${name}Lazy = ${info.hocImportedName === "default" ? info.hocLocalName : info.hocImportedName}(`,
348
- ` lazy(() => import('${base}').then((m) => ({default: m.${name}Content}))),`,
349
- ` ${name}Loading,`,
350
- ` ${name}Error,`,
351
- `);`,
352
- ``
353
- ].join("\n");
357
+ `import {${name}Loading} from '${base}.Loading';`
358
+ ];
359
+ if (info.error) lines.push(`import {${name}Error} from '${base}.Error';`);
360
+ lines.push("", `export const ${name}Lazy = ${hocBinding}(`, ` lazy(() => import('${base}').then((m) => ({default: m.${name}Content}))),`, ` ${name}Loading,`);
361
+ if (info.error) lines.push(` ${name}Error,`);
362
+ lines.push(`);`, ``);
363
+ const code = lines.join("\n");
354
364
  const filename = makeCompanionId("lazy", cleanSourceFile);
355
365
  return {
356
366
  code,
@@ -361,22 +371,6 @@ function generateLazyModule(sourceFile, info, options = {}) {
361
371
  }).toString()
362
372
  };
363
373
  }
364
- function transformJsx(filename, code, options) {
365
- const result = transformSync(filename, code, {
366
- lang: "tsx",
367
- jsx: options.jsx,
368
- target: options.target,
369
- sourcemap: true
370
- });
371
- if (result.errors.length > 0) {
372
- const error = result.errors[0];
373
- throw new Error(error.codeframe ?? error.message);
374
- }
375
- return {
376
- code: result.code,
377
- map: JSON.stringify(result.map)
378
- };
379
- }
380
374
  function renderImport(decl) {
381
375
  const parts = [];
382
376
  const named = [];
@@ -431,9 +425,11 @@ function transformDefinitionModule(s, filename, info) {
431
425
  const name = info.exportedName;
432
426
  const cleanFilename = stripQuery(filename);
433
427
  const localSource = `./${path.basename(cleanFilename, path.extname(cleanFilename))}`;
434
- s.prepend(`${renderNamedImport(`${name}Loading`, `${name}Loading`, makeCompanionId("loading", localSource))}\n${renderNamedImport(`${name}Error`, `${name}Error`, makeCompanionId("error", localSource))}\n`);
428
+ const prependImports = [renderNamedImport(`${name}Loading`, `${name}Loading`, makeCompanionId("loading", localSource))];
429
+ if (info.error) prependImports.push(renderNamedImport(`${name}Error`, `${name}Error`, makeCompanionId("error", localSource)));
430
+ s.prepend(prependImports.join("\n") + "\n");
435
431
  s.overwrite(info.loading.argStart, info.loading.argEnd, `${name}Loading`);
436
- s.overwrite(info.error.argStart, info.error.argEnd, `${name}Error`);
432
+ if (info.error) s.overwrite(info.error.argStart, info.error.argEnd, `${name}Error`);
437
433
  if (info.content.kind === "identifier") s.append(`\nexport {${info.content.name} as ${name}Content};\n`);
438
434
  else {
439
435
  s.appendLeft(info.hocExportStart, `const ${name}Content = ${info.content.argSource};\n\n`);
@@ -477,13 +473,20 @@ function renderNamedImport(local, imported, source) {
477
473
  }
478
474
  //#endregion
479
475
  //#region src/plugin/core/factory.ts
480
- const DEFAULT_HOCS = [{
481
- from: "@gravity-ui/data-source",
482
- name: "withAsyncBoundary"
483
- }, {
484
- from: "@gravity-ui/data-source",
485
- name: "withQueryAsyncBoundary"
486
- }];
476
+ const DEFAULT_HOCS = [
477
+ {
478
+ from: "@gravity-ui/data-source",
479
+ name: "withAsync"
480
+ },
481
+ {
482
+ from: "@gravity-ui/data-source",
483
+ name: "withAsyncBoundary"
484
+ },
485
+ {
486
+ from: "@gravity-ui/data-source",
487
+ name: "withQueryAsyncBoundary"
488
+ }
489
+ ];
487
490
  const DEFAULT_INCLUDE = /\.(tsx?|jsx?)$/;
488
491
  const VIRTUAL_EXCLUDE = new RegExp(`${VIRTUAL_PREFIX}|${encodeURIComponent(VIRTUAL_PREFIX)}`);
489
492
  const dataSourceLazyUnpluginFactory = (options = {}) => {
@@ -513,6 +516,45 @@ const dataSourceLazyUnpluginFactory = (options = {}) => {
513
516
  reExportsCache.set(key, reExports);
514
517
  return reExports;
515
518
  };
519
+ const resolveHocSourceFile = async (ctx, file, importedName, visited = /* @__PURE__ */ new Set()) => {
520
+ const visitKey = `${file}\0${importedName}`;
521
+ if (visited.has(visitKey)) return null;
522
+ visited.add(visitKey);
523
+ const directInfo = getHocInfo(file);
524
+ if (directInfo && directInfo.exportedName === importedName) return {
525
+ file,
526
+ info: directInfo
527
+ };
528
+ const reExports = getReExports(file);
529
+ const named = reExports.named.get(importedName);
530
+ if (named) {
531
+ const resolved = await resolveSourceFile(ctx, named.source, file);
532
+ if (resolved) {
533
+ const next = await resolveHocSourceFile(ctx, resolved, named.importedName, visited);
534
+ if (next) return next;
535
+ }
536
+ }
537
+ for (const starSource of reExports.stars) {
538
+ const resolved = await resolveSourceFile(ctx, starSource, file);
539
+ if (!resolved) continue;
540
+ const next = await resolveHocSourceFile(ctx, resolved, importedName, visited);
541
+ if (next) return next;
542
+ }
543
+ return null;
544
+ };
545
+ const validateUsages = async (ctx, usages, importerId) => {
546
+ return (await Promise.all(usages.map(async (usage) => {
547
+ const resolvedSourceFile = await resolveSourceFile(ctx, usage.decl.source, importerId);
548
+ if (!resolvedSourceFile) return null;
549
+ const target = await resolveHocSourceFile(ctx, resolvedSourceFile, usage.spec.importedName);
550
+ if (!target) return null;
551
+ return {
552
+ usage,
553
+ hocImportSource: toRelativeImportSource(importerId, target.file),
554
+ hocExportedName: target.info.exportedName
555
+ };
556
+ }))).filter((usage) => usage !== null);
557
+ };
516
558
  return {
517
559
  name: "data-source-lazy",
518
560
  enforce: "pre",
@@ -531,18 +573,30 @@ const dataSourceLazyUnpluginFactory = (options = {}) => {
531
573
  },
532
574
  load: {
533
575
  filter: { id: new RegExp(VIRTUAL_PREFIX) },
534
- handler(id) {
576
+ async handler(id) {
535
577
  const parsedId = parseVirtualId(id);
536
578
  if (!parsedId) return null;
537
579
  this.addWatchFile(parsedId.sourceFile);
538
580
  const info = getHocInfo(parsedId.sourceFile);
539
581
  if (!info) return null;
540
- switch (parsedId.type) {
541
- case "loading":
542
- case "error": return generateAuxModule(parsedId.sourceFile, info, parsedId.type, options.generateOptions);
543
- case "lazy": return generateLazyModule(parsedId.sourceFile, info, options.generateOptions);
544
- default: return assertNever(parsedId.type);
582
+ if (parsedId.type === "loading" || parsedId.type === "error") {
583
+ const auxInfo = info[parsedId.type];
584
+ if (!auxInfo) return null;
585
+ const cleanSourceFile = stripQuery(parsedId.sourceFile);
586
+ const auxFilename = makeCompanionId(parsedId.type, cleanSourceFile);
587
+ const assembled = assembleAuxModuleSource(info.exportedName, auxInfo, parsedId.type);
588
+ const usages = extractUsages(auxFilename, assembled);
589
+ const verifiedUsages = await validateUsages(this, usages, parsedId.sourceFile);
590
+ let auxCode = assembled;
591
+ if (verifiedUsages.length > 0) {
592
+ const s = new MagicString(assembled);
593
+ transformUsages(s, verifiedUsages);
594
+ auxCode = s.toString();
595
+ }
596
+ return compileAuxJsx(auxFilename, auxCode, options.generateOptions);
545
597
  }
598
+ if (parsedId.type === "lazy") return generateLazyModule(parsedId.sourceFile, info, options.generateOptions);
599
+ return assertNever(parsedId.type);
546
600
  }
547
601
  },
548
602
  transform: {
@@ -555,43 +609,7 @@ const dataSourceLazyUnpluginFactory = (options = {}) => {
555
609
  const usages = extractUsages(id, code);
556
610
  if (!info && usages.length === 0) return null;
557
611
  const filteredUsages = info ? dropAccessesInsideHocArgs(info, usages) : usages;
558
- const resolveHocSourceFile = async (file, importedName, visited = /* @__PURE__ */ new Set()) => {
559
- const visitKey = `${file}\0${importedName}`;
560
- if (visited.has(visitKey)) return null;
561
- visited.add(visitKey);
562
- const directInfo = getHocInfo(file);
563
- if (directInfo && directInfo.exportedName === importedName) return {
564
- file,
565
- info: directInfo
566
- };
567
- const reExports = getReExports(file);
568
- const named = reExports.named.get(importedName);
569
- if (named) {
570
- const resolved = await resolveSourceFile(this, named.source, file);
571
- if (resolved) {
572
- const next = await resolveHocSourceFile(resolved, named.importedName, visited);
573
- if (next) return next;
574
- }
575
- }
576
- for (const starSource of reExports.stars) {
577
- const resolved = await resolveSourceFile(this, starSource, file);
578
- if (!resolved) continue;
579
- const next = await resolveHocSourceFile(resolved, importedName, visited);
580
- if (next) return next;
581
- }
582
- return null;
583
- };
584
- const verifiedUsages = (await Promise.all(filteredUsages.map(async (usage) => {
585
- const resolvedSourceFile = await resolveSourceFile(this, usage.decl.source, id);
586
- if (!resolvedSourceFile) return null;
587
- const target = await resolveHocSourceFile(resolvedSourceFile, usage.spec.importedName);
588
- if (!target) return null;
589
- return {
590
- usage,
591
- hocImportSource: toRelativeImportSource(id, target.file),
592
- hocExportedName: target.info.exportedName
593
- };
594
- }))).filter((usage) => usage !== null);
612
+ const verifiedUsages = await validateUsages(this, filteredUsages, id);
595
613
  if (!info && verifiedUsages.length === 0) return null;
596
614
  const s = new MagicString(code);
597
615
  if (info) transformDefinitionModule(s, id, info);
@@ -619,7 +637,7 @@ function isInside(info, access) {
619
637
  function dropAccessesInsideHocArgs(info, usages) {
620
638
  const result = [];
621
639
  for (const usage of usages) {
622
- const accesses = usage.accesses.filter((access) => !isInside(info.loading, access) && !isInside(info.error, access) && !(info.content.kind === "inline" && isInside(info.content, access)));
640
+ const accesses = usage.accesses.filter((access) => !isInside(info.loading, access) && !(info.error && isInside(info.error, access)) && !(info.content.kind === "inline" && isInside(info.content, access)));
623
641
  if (accesses.length === 0) continue;
624
642
  if (accesses.length === usage.accesses.length) {
625
643
  result.push(usage);
@@ -127,7 +127,7 @@ function extractHocInfo(hocsSet, filename, source) {
127
127
  for (const node of program.body) {
128
128
  if (node.type !== "ExportNamedDeclaration" || node.exportKind === "type" || node.declaration?.type !== "VariableDeclaration") continue;
129
129
  for (const decl of node.declaration.declarations) {
130
- if (decl.id.type !== "Identifier" || !decl.init || decl.init.type !== "CallExpression" || decl.init.callee.type !== "Identifier" || decl.init.arguments.length !== 3) continue;
130
+ if (decl.id.type !== "Identifier" || !decl.init || decl.init.type !== "CallExpression" || decl.init.callee.type !== "Identifier" || decl.init.arguments.length < 2) continue;
131
131
  const hocEntry = trackedHocs.get(decl.init.callee.name);
132
132
  if (!hocEntry) continue;
133
133
  const [contentArg, loadingArg, errorArg] = decl.init.arguments;
@@ -153,12 +153,12 @@ function extractHocInfo(hocsSet, filename, source) {
153
153
  argEnd: loadingArg.end,
154
154
  imports: filterNeededImports(importDecls, collectIdentifiers(loadingArg))
155
155
  },
156
- error: {
156
+ error: errorArg ? {
157
157
  argSource: source.slice(errorArg.start, errorArg.end),
158
158
  argStart: errorArg.start,
159
159
  argEnd: errorArg.end,
160
160
  imports: filterNeededImports(importDecls, collectIdentifiers(errorArg))
161
- }
161
+ } : null
162
162
  };
163
163
  }
164
164
  }
@@ -343,39 +343,49 @@ function parseProgram(filename, source) {
343
343
  }
344
344
  //#endregion
345
345
  //#region src/plugin/core/generate.ts
346
- function generateAuxModule(sourceFile, info, type, options = {}) {
347
- const auxInfo = info[type];
348
- const name = info.exportedName;
346
+ function assembleAuxModuleSource(exportedName, info, type) {
349
347
  const suffix = COMPANION_TYPES[type];
350
- const cleanSourceFile = stripQuery(sourceFile);
351
- const code = [
352
- renderImports(auxInfo.imports),
348
+ return [
349
+ renderImports(info.imports),
353
350
  "",
354
- `export const ${name}${suffix} = ${auxInfo.argSource};`,
351
+ `export const ${exportedName}${suffix} = ${info.argSource};`,
355
352
  ""
356
353
  ].join("\n").trimStart();
357
- return transformJsx(makeCompanionId(type, cleanSourceFile), code, options);
354
+ }
355
+ function compileAuxJsx(filename, code, options = {}) {
356
+ const result = (0, oxc_transform.transformSync)(filename, code, {
357
+ lang: "tsx",
358
+ jsx: options.jsx,
359
+ target: options.target,
360
+ sourcemap: true
361
+ });
362
+ if (result.errors.length > 0) {
363
+ const error = result.errors[0];
364
+ throw new Error(error.codeframe ?? error.message);
365
+ }
366
+ return {
367
+ code: result.code,
368
+ map: JSON.stringify(result.map)
369
+ };
358
370
  }
359
371
  function generateLazyModule(sourceFile, info, options = {}) {
360
372
  const importSource = options.jsx?.importSource ?? "react";
361
373
  const name = info.exportedName;
362
374
  const cleanSourceFile = stripQuery(sourceFile);
363
375
  const base = `./${node_path.default.basename(cleanSourceFile, node_path.default.extname(cleanSourceFile))}`;
364
- const code = [
376
+ const hocBinding = info.hocImportedName === "default" ? info.hocLocalName : info.hocImportedName;
377
+ const lines = [
365
378
  `import {lazy} from '${importSource}';`,
366
379
  "",
367
380
  info.hocImportedName === "default" ? `import ${info.hocLocalName} from '${info.hocImportSource}';` : `import {${info.hocImportedName}} from '${info.hocImportSource}';`,
368
381
  "",
369
- `import {${name}Loading} from '${base}.Loading';`,
370
- `import {${name}Error} from '${base}.Error';`,
371
- ``,
372
- `export const ${name}Lazy = ${info.hocImportedName === "default" ? info.hocLocalName : info.hocImportedName}(`,
373
- ` lazy(() => import('${base}').then((m) => ({default: m.${name}Content}))),`,
374
- ` ${name}Loading,`,
375
- ` ${name}Error,`,
376
- `);`,
377
- ``
378
- ].join("\n");
382
+ `import {${name}Loading} from '${base}.Loading';`
383
+ ];
384
+ if (info.error) lines.push(`import {${name}Error} from '${base}.Error';`);
385
+ lines.push("", `export const ${name}Lazy = ${hocBinding}(`, ` lazy(() => import('${base}').then((m) => ({default: m.${name}Content}))),`, ` ${name}Loading,`);
386
+ if (info.error) lines.push(` ${name}Error,`);
387
+ lines.push(`);`, ``);
388
+ const code = lines.join("\n");
379
389
  const filename = makeCompanionId("lazy", cleanSourceFile);
380
390
  return {
381
391
  code,
@@ -386,22 +396,6 @@ function generateLazyModule(sourceFile, info, options = {}) {
386
396
  }).toString()
387
397
  };
388
398
  }
389
- function transformJsx(filename, code, options) {
390
- const result = (0, oxc_transform.transformSync)(filename, code, {
391
- lang: "tsx",
392
- jsx: options.jsx,
393
- target: options.target,
394
- sourcemap: true
395
- });
396
- if (result.errors.length > 0) {
397
- const error = result.errors[0];
398
- throw new Error(error.codeframe ?? error.message);
399
- }
400
- return {
401
- code: result.code,
402
- map: JSON.stringify(result.map)
403
- };
404
- }
405
399
  function renderImport(decl) {
406
400
  const parts = [];
407
401
  const named = [];
@@ -456,9 +450,11 @@ function transformDefinitionModule(s, filename, info) {
456
450
  const name = info.exportedName;
457
451
  const cleanFilename = stripQuery(filename);
458
452
  const localSource = `./${node_path.default.basename(cleanFilename, node_path.default.extname(cleanFilename))}`;
459
- s.prepend(`${renderNamedImport(`${name}Loading`, `${name}Loading`, makeCompanionId("loading", localSource))}\n${renderNamedImport(`${name}Error`, `${name}Error`, makeCompanionId("error", localSource))}\n`);
453
+ const prependImports = [renderNamedImport(`${name}Loading`, `${name}Loading`, makeCompanionId("loading", localSource))];
454
+ if (info.error) prependImports.push(renderNamedImport(`${name}Error`, `${name}Error`, makeCompanionId("error", localSource)));
455
+ s.prepend(prependImports.join("\n") + "\n");
460
456
  s.overwrite(info.loading.argStart, info.loading.argEnd, `${name}Loading`);
461
- s.overwrite(info.error.argStart, info.error.argEnd, `${name}Error`);
457
+ if (info.error) s.overwrite(info.error.argStart, info.error.argEnd, `${name}Error`);
462
458
  if (info.content.kind === "identifier") s.append(`\nexport {${info.content.name} as ${name}Content};\n`);
463
459
  else {
464
460
  s.appendLeft(info.hocExportStart, `const ${name}Content = ${info.content.argSource};\n\n`);
@@ -502,13 +498,20 @@ function renderNamedImport(local, imported, source) {
502
498
  }
503
499
  //#endregion
504
500
  //#region src/plugin/core/factory.ts
505
- const DEFAULT_HOCS = [{
506
- from: "@gravity-ui/data-source",
507
- name: "withAsyncBoundary"
508
- }, {
509
- from: "@gravity-ui/data-source",
510
- name: "withQueryAsyncBoundary"
511
- }];
501
+ const DEFAULT_HOCS = [
502
+ {
503
+ from: "@gravity-ui/data-source",
504
+ name: "withAsync"
505
+ },
506
+ {
507
+ from: "@gravity-ui/data-source",
508
+ name: "withAsyncBoundary"
509
+ },
510
+ {
511
+ from: "@gravity-ui/data-source",
512
+ name: "withQueryAsyncBoundary"
513
+ }
514
+ ];
512
515
  const DEFAULT_INCLUDE = /\.(tsx?|jsx?)$/;
513
516
  const VIRTUAL_EXCLUDE = new RegExp(`${VIRTUAL_PREFIX}|${encodeURIComponent(VIRTUAL_PREFIX)}`);
514
517
  const dataSourceLazyUnpluginFactory = (options = {}) => {
@@ -538,6 +541,45 @@ const dataSourceLazyUnpluginFactory = (options = {}) => {
538
541
  reExportsCache.set(key, reExports);
539
542
  return reExports;
540
543
  };
544
+ const resolveHocSourceFile = async (ctx, file, importedName, visited = /* @__PURE__ */ new Set()) => {
545
+ const visitKey = `${file}\0${importedName}`;
546
+ if (visited.has(visitKey)) return null;
547
+ visited.add(visitKey);
548
+ const directInfo = getHocInfo(file);
549
+ if (directInfo && directInfo.exportedName === importedName) return {
550
+ file,
551
+ info: directInfo
552
+ };
553
+ const reExports = getReExports(file);
554
+ const named = reExports.named.get(importedName);
555
+ if (named) {
556
+ const resolved = await resolveSourceFile(ctx, named.source, file);
557
+ if (resolved) {
558
+ const next = await resolveHocSourceFile(ctx, resolved, named.importedName, visited);
559
+ if (next) return next;
560
+ }
561
+ }
562
+ for (const starSource of reExports.stars) {
563
+ const resolved = await resolveSourceFile(ctx, starSource, file);
564
+ if (!resolved) continue;
565
+ const next = await resolveHocSourceFile(ctx, resolved, importedName, visited);
566
+ if (next) return next;
567
+ }
568
+ return null;
569
+ };
570
+ const validateUsages = async (ctx, usages, importerId) => {
571
+ return (await Promise.all(usages.map(async (usage) => {
572
+ const resolvedSourceFile = await resolveSourceFile(ctx, usage.decl.source, importerId);
573
+ if (!resolvedSourceFile) return null;
574
+ const target = await resolveHocSourceFile(ctx, resolvedSourceFile, usage.spec.importedName);
575
+ if (!target) return null;
576
+ return {
577
+ usage,
578
+ hocImportSource: toRelativeImportSource(importerId, target.file),
579
+ hocExportedName: target.info.exportedName
580
+ };
581
+ }))).filter((usage) => usage !== null);
582
+ };
541
583
  return {
542
584
  name: "data-source-lazy",
543
585
  enforce: "pre",
@@ -556,18 +598,30 @@ const dataSourceLazyUnpluginFactory = (options = {}) => {
556
598
  },
557
599
  load: {
558
600
  filter: { id: new RegExp(VIRTUAL_PREFIX) },
559
- handler(id) {
601
+ async handler(id) {
560
602
  const parsedId = parseVirtualId(id);
561
603
  if (!parsedId) return null;
562
604
  this.addWatchFile(parsedId.sourceFile);
563
605
  const info = getHocInfo(parsedId.sourceFile);
564
606
  if (!info) return null;
565
- switch (parsedId.type) {
566
- case "loading":
567
- case "error": return generateAuxModule(parsedId.sourceFile, info, parsedId.type, options.generateOptions);
568
- case "lazy": return generateLazyModule(parsedId.sourceFile, info, options.generateOptions);
569
- default: return assertNever(parsedId.type);
607
+ if (parsedId.type === "loading" || parsedId.type === "error") {
608
+ const auxInfo = info[parsedId.type];
609
+ if (!auxInfo) return null;
610
+ const cleanSourceFile = stripQuery(parsedId.sourceFile);
611
+ const auxFilename = makeCompanionId(parsedId.type, cleanSourceFile);
612
+ const assembled = assembleAuxModuleSource(info.exportedName, auxInfo, parsedId.type);
613
+ const usages = extractUsages(auxFilename, assembled);
614
+ const verifiedUsages = await validateUsages(this, usages, parsedId.sourceFile);
615
+ let auxCode = assembled;
616
+ if (verifiedUsages.length > 0) {
617
+ const s = new magic_string.default(assembled);
618
+ transformUsages(s, verifiedUsages);
619
+ auxCode = s.toString();
620
+ }
621
+ return compileAuxJsx(auxFilename, auxCode, options.generateOptions);
570
622
  }
623
+ if (parsedId.type === "lazy") return generateLazyModule(parsedId.sourceFile, info, options.generateOptions);
624
+ return assertNever(parsedId.type);
571
625
  }
572
626
  },
573
627
  transform: {
@@ -580,43 +634,7 @@ const dataSourceLazyUnpluginFactory = (options = {}) => {
580
634
  const usages = extractUsages(id, code);
581
635
  if (!info && usages.length === 0) return null;
582
636
  const filteredUsages = info ? dropAccessesInsideHocArgs(info, usages) : usages;
583
- const resolveHocSourceFile = async (file, importedName, visited = /* @__PURE__ */ new Set()) => {
584
- const visitKey = `${file}\0${importedName}`;
585
- if (visited.has(visitKey)) return null;
586
- visited.add(visitKey);
587
- const directInfo = getHocInfo(file);
588
- if (directInfo && directInfo.exportedName === importedName) return {
589
- file,
590
- info: directInfo
591
- };
592
- const reExports = getReExports(file);
593
- const named = reExports.named.get(importedName);
594
- if (named) {
595
- const resolved = await resolveSourceFile(this, named.source, file);
596
- if (resolved) {
597
- const next = await resolveHocSourceFile(resolved, named.importedName, visited);
598
- if (next) return next;
599
- }
600
- }
601
- for (const starSource of reExports.stars) {
602
- const resolved = await resolveSourceFile(this, starSource, file);
603
- if (!resolved) continue;
604
- const next = await resolveHocSourceFile(resolved, importedName, visited);
605
- if (next) return next;
606
- }
607
- return null;
608
- };
609
- const verifiedUsages = (await Promise.all(filteredUsages.map(async (usage) => {
610
- const resolvedSourceFile = await resolveSourceFile(this, usage.decl.source, id);
611
- if (!resolvedSourceFile) return null;
612
- const target = await resolveHocSourceFile(resolvedSourceFile, usage.spec.importedName);
613
- if (!target) return null;
614
- return {
615
- usage,
616
- hocImportSource: toRelativeImportSource(id, target.file),
617
- hocExportedName: target.info.exportedName
618
- };
619
- }))).filter((usage) => usage !== null);
637
+ const verifiedUsages = await validateUsages(this, filteredUsages, id);
620
638
  if (!info && verifiedUsages.length === 0) return null;
621
639
  const s = new magic_string.default(code);
622
640
  if (info) transformDefinitionModule(s, id, info);
@@ -644,7 +662,7 @@ function isInside(info, access) {
644
662
  function dropAccessesInsideHocArgs(info, usages) {
645
663
  const result = [];
646
664
  for (const usage of usages) {
647
- const accesses = usage.accesses.filter((access) => !isInside(info.loading, access) && !isInside(info.error, access) && !(info.content.kind === "inline" && isInside(info.content, access)));
665
+ const accesses = usage.accesses.filter((access) => !isInside(info.loading, access) && !(info.error && isInside(info.error, access)) && !(info.content.kind === "inline" && isInside(info.content, access)));
648
666
  if (accesses.length === 0) continue;
649
667
  if (accesses.length === usage.accesses.length) {
650
668
  result.push(usage);
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_factory = require("./factory-Dq6kUGl-.cjs");
5
+ const require_factory = require("./factory-amr4dgO8.cjs");
6
6
  //#region src/plugin/index.ts
7
7
  const DataSourceLazyPlugin = /* @__PURE__ */ (0, require("unplugin").createUnplugin)(require_factory.dataSourceLazyUnpluginFactory);
8
8
  //#endregion
@@ -1,4 +1,4 @@
1
- import { n as dataSourceLazyUnpluginFactory, t as DEFAULT_HOCS } from "./factory-Ds3_-8kv.mjs";
1
+ import { n as dataSourceLazyUnpluginFactory, t as DEFAULT_HOCS } from "./factory-BxKix--T.mjs";
2
2
  import { createUnplugin } from "unplugin";
3
3
  //#region src/plugin/index.ts
4
4
  const DataSourceLazyPlugin = /* @__PURE__ */ createUnplugin(dataSourceLazyUnpluginFactory);
@@ -1,4 +1,4 @@
1
- const require_factory = require("./factory-Dq6kUGl-.cjs");
1
+ const require_factory = require("./factory-amr4dgO8.cjs");
2
2
  //#region src/plugin/rollup.ts
3
3
  var rollup_default = (0, require("unplugin").createRollupPlugin)(require_factory.dataSourceLazyUnpluginFactory);
4
4
  //#endregion
@@ -1,4 +1,4 @@
1
- import { n as dataSourceLazyUnpluginFactory } from "./factory-Ds3_-8kv.mjs";
1
+ import { n as dataSourceLazyUnpluginFactory } from "./factory-BxKix--T.mjs";
2
2
  import { createRollupPlugin } from "unplugin";
3
3
  //#region src/plugin/rollup.ts
4
4
  var rollup_default = createRollupPlugin(dataSourceLazyUnpluginFactory);
@@ -1,4 +1,4 @@
1
- const require_factory = require("./factory-Dq6kUGl-.cjs");
1
+ const require_factory = require("./factory-amr4dgO8.cjs");
2
2
  //#region src/plugin/rspack.ts
3
3
  var rspack_default = (0, require("unplugin").createRspackPlugin)(require_factory.dataSourceLazyUnpluginFactory);
4
4
  //#endregion
@@ -1,4 +1,4 @@
1
- import { n as dataSourceLazyUnpluginFactory } from "./factory-Ds3_-8kv.mjs";
1
+ import { n as dataSourceLazyUnpluginFactory } from "./factory-BxKix--T.mjs";
2
2
  import { createRspackPlugin } from "unplugin";
3
3
  //#region src/plugin/rspack.ts
4
4
  var rspack_default = createRspackPlugin(dataSourceLazyUnpluginFactory);
@@ -1,6 +1,10 @@
1
1
  import type {ComponentType} from 'react';
2
2
 
3
3
  declare module '@gravity-ui/data-source' {
4
+ export interface AsyncComponent<TProps extends object = {}, TLoadingProps extends object = {}> {
5
+ Lazy: ComponentType<TProps & TLoadingProps>;
6
+ }
7
+
4
8
  interface AsyncBoundaryComponent<
5
9
  TProps extends object = {},
6
10
  TLoadingProps extends object = {},
@@ -1,4 +1,4 @@
1
- const require_factory = require("./factory-Dq6kUGl-.cjs");
1
+ const require_factory = require("./factory-amr4dgO8.cjs");
2
2
  //#region src/plugin/vite.ts
3
3
  var vite_default = (0, require("unplugin").createVitePlugin)(require_factory.dataSourceLazyUnpluginFactory);
4
4
  //#endregion
@@ -1,4 +1,4 @@
1
- import { n as dataSourceLazyUnpluginFactory } from "./factory-Ds3_-8kv.mjs";
1
+ import { n as dataSourceLazyUnpluginFactory } from "./factory-BxKix--T.mjs";
2
2
  import { createVitePlugin } from "unplugin";
3
3
  //#region src/plugin/vite.ts
4
4
  var vite_default = createVitePlugin(dataSourceLazyUnpluginFactory);
@@ -1,4 +1,4 @@
1
- const require_factory = require("./factory-Dq6kUGl-.cjs");
1
+ const require_factory = require("./factory-amr4dgO8.cjs");
2
2
  //#region src/plugin/webpack.ts
3
3
  var webpack_default = (0, require("unplugin").createWebpackPlugin)(require_factory.dataSourceLazyUnpluginFactory);
4
4
  //#endregion
@@ -1,4 +1,4 @@
1
- import { n as dataSourceLazyUnpluginFactory } from "./factory-Ds3_-8kv.mjs";
1
+ import { n as dataSourceLazyUnpluginFactory } from "./factory-BxKix--T.mjs";
2
2
  import { createWebpackPlugin } from "unplugin";
3
3
  //#region src/plugin/webpack.ts
4
4
  var webpack_default = createWebpackPlugin(dataSourceLazyUnpluginFactory);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ui/data-source",
3
- "version": "0.10.0-alpha.7",
3
+ "version": "0.10.0-alpha.9",
4
4
  "description": "A wrapper around data fetching",
5
5
  "keywords": [
6
6
  "data-fetching",