piral-cli 1.4.0-beta.6247 → 1.4.0-beta.6250

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.
Files changed (35) hide show
  1. package/lib/apps/add-piral-instance-pilet.js +1 -4
  2. package/lib/apps/add-piral-instance-pilet.js.map +1 -1
  3. package/lib/apps/new-pilet.js +4 -3
  4. package/lib/apps/new-pilet.js.map +1 -1
  5. package/lib/apps/run-emulator-piral.js +1 -1
  6. package/lib/apps/run-emulator-piral.js.map +1 -1
  7. package/lib/apps/upgrade-pilet.js +3 -2
  8. package/lib/apps/upgrade-pilet.js.map +1 -1
  9. package/lib/common/package.d.ts +1 -2
  10. package/lib/common/package.js +25 -33
  11. package/lib/common/package.js.map +1 -1
  12. package/lib/common/shell.d.ts +2 -2
  13. package/lib/common/shell.js +45 -14
  14. package/lib/common/shell.js.map +1 -1
  15. package/lib/common/website.d.ts +1 -2
  16. package/lib/common/website.js +6 -4
  17. package/lib/common/website.js.map +1 -1
  18. package/lib/injectors/pilet-injector.d.ts +12 -10
  19. package/lib/injectors/pilet-injector.js +103 -60
  20. package/lib/injectors/pilet-injector.js.map +1 -1
  21. package/lib/injectors/piral-injector.d.ts +5 -5
  22. package/lib/injectors/piral-injector.js +64 -34
  23. package/lib/injectors/piral-injector.js.map +1 -1
  24. package/package.json +2 -2
  25. package/src/apps/add-piral-instance-pilet.ts +1 -16
  26. package/src/apps/new-pilet.ts +4 -10
  27. package/src/apps/run-emulator-piral.ts +1 -1
  28. package/src/apps/upgrade-pilet.ts +3 -2
  29. package/src/common/package.ts +20 -35
  30. package/src/common/shell.ts +59 -18
  31. package/src/common/website.ts +6 -4
  32. package/src/injectors/pilet-injector.test.ts +4 -4
  33. package/src/injectors/pilet-injector.ts +87 -41
  34. package/src/injectors/piral-injector.test.ts +2 -2
  35. package/src/injectors/piral-injector.ts +31 -20
@@ -14,8 +14,8 @@ import { makePiletExternals, makeExternals, findPackageRoot, findSpecificVersion
14
14
  import { scaffoldFromEmulatorWebsite } from './website';
15
15
  import { getDependencies, getDependencyPackages, getDevDependencies } from './language';
16
16
  import { getDevDependencyPackages, getFrameworkDependencies } from './language';
17
- import { piralJsonSchemaUrl, piletJsonSchemaUrl, filesTar, filesOnceTar, bundlerNames } from './constants';
18
- import { frameworkLibs, declarationEntryExtensions, piralJson, piletJson, packageJson } from './constants';
17
+ import { piralJsonSchemaUrl, filesTar, filesOnceTar, bundlerNames, packageJson } from './constants';
18
+ import { frameworkLibs, declarationEntryExtensions, piralJson, piletJson } from './constants';
19
19
  import { getModulePath } from '../external';
20
20
  import { PiletsInfo, SharedDependency, PiletDefinition, AppDefinition } from '../types';
21
21
  import { SourceLanguage, PiralInstancePackageData, PiralInstanceDetails } from '../types';
@@ -216,11 +216,11 @@ export async function patchPiralPackage(
216
216
  version: string,
217
217
  bundler?: string,
218
218
  ) {
219
- log('generalDebug_0003', `Patching the package.json in "${root}" ...`);
219
+ log('generalDebug_0003', `Patching the ${packageJson} in "${root}" ...`);
220
220
  const pkg = await getPiralPackage(app, data, version, bundler);
221
221
 
222
- await updateExistingJson(root, 'package.json', pkg);
223
- log('generalDebug_0003', `Succesfully patched the package.json.`);
222
+ await updateExistingJson(root, packageJson, pkg);
223
+ log('generalDebug_0003', `Succesfully patched the ${packageJson}.`);
224
224
 
225
225
  await updateExistingJson(root, piralJson, {
226
226
  $schema: piralJsonSchemaUrl,
@@ -353,7 +353,7 @@ export async function copyScaffoldingFiles(
353
353
  }
354
354
 
355
355
  async function extendPackageOverridesFromTemplateFragment(root: string, piralInfo: any, files: Array<FileDescriptor>) {
356
- const packageTarget = resolve(root, 'package.json');
356
+ const packageTarget = resolve(root, packageJson);
357
357
 
358
358
  for (let i = files.length; i--; ) {
359
359
  const file = files[i];
@@ -384,7 +384,7 @@ function isTemplateFileLocation(item: string | TemplateFileLocation): item is Te
384
384
 
385
385
  function tryFindPackageVersion(packageName: string): string {
386
386
  try {
387
- const { version } = require(`${packageName}/package.json`);
387
+ const { version } = require(`${packageName}/${packageJson}`);
388
388
  return version;
389
389
  } catch {
390
390
  return undefined;
@@ -447,7 +447,7 @@ export async function retrievePiralRoot(baseDir: string, entry: string) {
447
447
  log('generalDebug_0003', `Retrieving Piral root from "${rootDir}" ...`);
448
448
 
449
449
  if (!declarationEntryExtensions.includes(extname(rootDir).toLowerCase())) {
450
- const packageName = basename(rootDir) === 'package.json' ? rootDir : join(rootDir, 'package.json');
450
+ const packageName = basename(rootDir) === packageJson ? rootDir : join(rootDir, packageJson);
451
451
  log('generalDebug_0003', `Trying to get entry point from "${packageName}".`);
452
452
  const exists = await checkExists(packageName);
453
453
 
@@ -527,9 +527,9 @@ export async function findPackageVersion(rootPath: string, packageName: string |
527
527
  try {
528
528
  log('generalDebug_0003', `Finding the version of "${packageName}" in "${rootPath}".`);
529
529
  const moduleName = getModulePath(rootPath, pckg);
530
- const packageJson = await findFile(moduleName, 'package.json');
531
- const root = dirname(packageJson);
532
- const { version } = await readJson(root, 'package.json');
530
+ const packageJsonPath = await findFile(moduleName, packageJson);
531
+ const root = dirname(packageJsonPath);
532
+ const { version } = await readJson(root, packageJson);
533
533
  return version;
534
534
  } catch {}
535
535
  }
@@ -635,31 +635,18 @@ export function isValidDependency(name: string) {
635
635
 
636
636
  export async function patchPiletPackage(
637
637
  root: string,
638
- name: string,
639
- version: string,
640
638
  piralInfo: PiralPackageData,
641
639
  fromEmulator: boolean,
642
- newInfo?: { language: SourceLanguage; bundler: string; details: PiralInstanceDetails },
640
+ newInfo?: { language: SourceLanguage; bundler: string },
643
641
  ) {
644
- log('generalDebug_0003', `Patching the package.json in "${root}" ...`);
645
- const pkg = await getPiletPackage(root, name, version, piralInfo, fromEmulator, newInfo);
646
-
642
+ log('generalDebug_0003', `Patching the ${packageJson} in "${root}" ...`);
643
+ const pkg = await getPiletPackage(root, piralInfo, fromEmulator, newInfo);
647
644
  await updateExistingJson(root, packageJson, pkg);
648
- log('generalDebug_0003', `Succesfully patched the package.json.`);
649
-
650
- await updateExistingJson(root, piletJson, {
651
- $schema: piletJsonSchemaUrl,
652
- piralInstances: {
653
- [name]: newInfo?.details || {},
654
- },
655
- });
656
- log('generalDebug_0003', `Succesfully patched the pilet.json.`);
645
+ log('generalDebug_0003', `Succesfully patched the ${packageJson}.`);
657
646
  }
658
647
 
659
648
  async function getPiletPackage(
660
649
  root: string,
661
- name: string,
662
- version: string,
663
650
  piralInfo: PiralPackageData,
664
651
  fromEmulator: boolean,
665
652
  newInfo?: { language: SourceLanguage; bundler: string },
@@ -701,11 +688,9 @@ async function getPiletPackage(
701
688
 
702
689
  return deps;
703
690
  }, {}),
704
- [name]: `${version || piralInfo.version}`,
705
691
  ['piral-cli']: toolVersion,
706
692
  };
707
693
  const dependencies: Record<string, string> = {
708
- [name]: undefined,
709
694
  ['piral-cli']: undefined,
710
695
  };
711
696
 
@@ -716,7 +701,7 @@ async function getPiletPackage(
716
701
  return deepMerge(packageOverrides, {
717
702
  importmap: {
718
703
  imports: {},
719
- inherit: [name],
704
+ inherit: [],
720
705
  },
721
706
  devDependencies,
722
707
  dependencies,
@@ -768,20 +753,20 @@ export function combinePiletExternals(
768
753
  }
769
754
 
770
755
  export async function findPiletRoot(proposedRoot: string) {
771
- const packageJson = await findFile(proposedRoot, 'package.json');
756
+ const packageJsonPath = await findFile(proposedRoot, packageJson);
772
757
 
773
- if (!packageJson) {
758
+ if (!packageJsonPath) {
774
759
  fail('packageJsonMissing_0075');
775
760
  }
776
761
 
777
- return dirname(packageJson);
762
+ return dirname(packageJsonPath);
778
763
  }
779
764
 
780
765
  export async function retrievePiletData(target: string, app?: string) {
781
766
  const piletJsonPath = await findFile(target, piletJson);
782
767
  const proposedRoot = piletJsonPath ? dirname(piletJsonPath) : target;
783
768
  const root = await findPiletRoot(proposedRoot);
784
- const piletPackage = await readJson(root, 'package.json');
769
+ const piletPackage = await readJson(root, packageJson);
785
770
  const piletDefinition: PiletDefinition = piletJsonPath && (await readJson(proposedRoot, piletJson));
786
771
  const appPackages = await findPiralInstances(app && [app], piletPackage, piletDefinition, root);
787
772
  const apps: Array<AppDefinition> = [];
@@ -1,35 +1,76 @@
1
1
  import { progress } from './log';
2
+ import { packageJson, piletJson } from './constants';
3
+ import { readJson, updateExistingJson, writeJson } from './io';
2
4
  import { scaffoldFromEmulatorWebsite } from './website';
3
5
  import { combinePackageRef, getPackageName, getPackageVersion } from './npm';
4
6
  import { dissectPackageName, installNpmPackage, isLinkedPackage } from './npm';
5
- import { NpmClientType, PiralInstanceDetails } from '../types';
7
+ import { NpmClientType, PackageType, PiralInstanceDetails } from '../types';
8
+
9
+ async function updatePiletJson(target: string, appName: string, appDetails: PiralInstanceDetails) {
10
+ const oldContent = await readJson(target, piletJson);
11
+ const newContent = {
12
+ ...oldContent,
13
+ piralInstances: {
14
+ ...oldContent.piralInstances,
15
+ [appName]: appDetails,
16
+ },
17
+ };
18
+ await writeJson(target, piletJson, newContent, true);
19
+ await updateExistingJson(target, packageJson, {
20
+ importmap: {
21
+ inherit: [appName],
22
+ },
23
+ });
24
+ }
25
+
26
+ async function setupPiralInstance(
27
+ sourceName: string,
28
+ type: PackageType,
29
+ hadVersion: boolean,
30
+ rootDir: string,
31
+ sourceVersion: string,
32
+ npmClient: NpmClientType,
33
+ ) {
34
+ if (!isLinkedPackage(sourceName, type, hadVersion, rootDir)) {
35
+ const packageRef = combinePackageRef(sourceName, sourceVersion, type);
36
+
37
+ progress(`Installing npm package %s ...`, packageRef);
38
+ await installNpmPackage(npmClient, packageRef, rootDir, '--save-dev', '--save-exact');
39
+ return await getPackageName(rootDir, sourceName, type);
40
+ } else {
41
+ progress(`Using locally available npm package %s ...`, sourceName);
42
+ const packageName = await getPackageName(rootDir, sourceName, type);
43
+ const packageVersion = getPackageVersion(hadVersion, sourceName, sourceVersion, type, rootDir);
44
+ await updateExistingJson(rootDir, packageJson, {
45
+ devDependencies: {
46
+ [packageName]: packageVersion,
47
+ },
48
+ });
49
+ return packageName;
50
+ }
51
+ }
6
52
 
7
53
  export async function installPiralInstance(
8
54
  usedSource: string,
9
55
  baseDir: string,
10
56
  rootDir: string,
11
57
  npmClient: NpmClientType,
12
- ): Promise<[name: string, version: string, details: PiralInstanceDetails]> {
58
+ selected?: boolean,
59
+ ): Promise<string> {
13
60
  const [sourceName, sourceVersion, hadVersion, type] = await dissectPackageName(baseDir, usedSource);
14
61
 
15
62
  if (type === 'remote') {
16
- progress(`Downloading emulator from %s ...`, sourceName);
17
- const emulatorJson = await scaffoldFromEmulatorWebsite(rootDir, sourceName);
18
- const details = {
63
+ const packageName = await scaffoldFromEmulatorWebsite(rootDir, sourceName);
64
+ await updatePiletJson(rootDir, packageName, {
65
+ selected,
19
66
  url: sourceName,
20
- };
21
-
22
- return [emulatorJson.name, emulatorJson.version, details];
23
- } else if (!isLinkedPackage(sourceName, type, hadVersion, rootDir)) {
24
- const packageRef = combinePackageRef(sourceName, sourceVersion, type);
25
-
26
- progress(`Installing npm package %s ...`, packageRef);
27
- await installNpmPackage(npmClient, packageRef, rootDir, '--save-dev', '--save-exact');
67
+ });
68
+ return packageName;
28
69
  } else {
29
- progress(`Using locally available npm package %s ...`, sourceName);
70
+ const packageName = await setupPiralInstance(sourceName, type, hadVersion, rootDir, sourceVersion, npmClient);
71
+ await updatePiletJson(rootDir, packageName, {
72
+ selected,
73
+ });
74
+ return packageName;
30
75
  }
31
-
32
- const packageName = await getPackageName(rootDir, sourceName, type);
33
- const packageVersion = getPackageVersion(hadVersion, sourceName, sourceVersion, type, rootDir);
34
- return [packageName, packageVersion, {}];
35
76
  }
@@ -1,10 +1,10 @@
1
- import { resolve as resolveUrl } from 'url';
2
1
  import { join, resolve } from 'path';
3
2
  import { createPiralStubIndexIfNotExists } from './template';
4
3
  import { packageJson } from './constants';
5
4
  import { ForceOverwrite } from './enums';
6
5
  import { createDirectory, writeBinary } from './io';
7
6
  import { writeJson } from './io';
7
+ import { progress } from './log';
8
8
  import { axios } from '../external';
9
9
  import { EmulatorWebsiteManifestFiles, EmulatorWebsiteManifest } from '../types';
10
10
 
@@ -13,7 +13,8 @@ async function downloadEmulatorFiles(manifestUrl: string, target: string, files:
13
13
 
14
14
  await Promise.all(
15
15
  requiredFiles.map(async (file) => {
16
- const res = await axios.default.get(resolveUrl(manifestUrl, file), { responseType: 'arraybuffer' });
16
+ const url = new URL(file, manifestUrl);
17
+ const res = await axios.default.get(url.href, { responseType: 'arraybuffer' });
17
18
  const data: Buffer = res.data;
18
19
  await writeBinary(target, file, data);
19
20
  }),
@@ -21,6 +22,7 @@ async function downloadEmulatorFiles(manifestUrl: string, target: string, files:
21
22
  }
22
23
 
23
24
  export async function scaffoldFromEmulatorWebsite(rootDir: string, manifestUrl: string) {
25
+ progress(`Downloading emulator from %s ...`, manifestUrl);
24
26
  const response = await axios.default.get(manifestUrl);
25
27
  const emulatorJson: EmulatorWebsiteManifest = response.data;
26
28
 
@@ -45,7 +47,7 @@ export async function scaffoldFromEmulatorWebsite(rootDir: string, manifestUrl:
45
47
  source: manifestUrl,
46
48
  generated: true,
47
49
  },
48
- files: emulatorJson.files,
50
+ files: emulatorJson.files.assets,
49
51
  main: `./${join(appDirName, mainFile)}`,
50
52
  typings: `./${join(appDirName, emulatorJson.files.typings)}`,
51
53
  app: `./${join(appDirName, emulatorJson.files.app)}`,
@@ -63,5 +65,5 @@ export async function scaffoldFromEmulatorWebsite(rootDir: string, manifestUrl:
63
65
  });
64
66
 
65
67
  await downloadEmulatorFiles(manifestUrl, appDir, emulatorJson.files);
66
- return emulatorJson;
68
+ return emulatorJson.name;
67
69
  }
@@ -40,7 +40,7 @@ describe('Piral-CLI pilet injector', () => {
40
40
  expect(injector.active).toBeFalsy();
41
41
  });
42
42
 
43
- it('PiletInjector does not send empty content', () => {
43
+ it('PiletInjector does not send empty content', async () => {
44
44
  // Arrange
45
45
  const core = new EventEmitter();
46
46
  const injector = new PiletInjector(optionsMock, configMock, core);
@@ -51,7 +51,7 @@ describe('Piral-CLI pilet injector', () => {
51
51
 
52
52
  // Act
53
53
  try {
54
- injector.sendFile(target, url); // this file does not exist
54
+ await injector.sendFile(target, url); // this file does not exist
55
55
  } catch {
56
56
  hasFailed = true;
57
57
  }
@@ -113,7 +113,7 @@ describe('Piral-CLI pilet injector', () => {
113
113
  expect(res).toBeUndefined();
114
114
  });
115
115
 
116
- it('PiletInjector wont crash on request with no target', () => {
116
+ it('PiletInjector wont crash on request with no target', async () => {
117
117
  // Arrange
118
118
  const optionsMock = {
119
119
  pilets: [],
@@ -136,7 +136,7 @@ describe('Piral-CLI pilet injector', () => {
136
136
  } as KrasRequest;
137
137
 
138
138
  // Act
139
- const res = injector.handle(request);
139
+ const res = await injector.handle(request);
140
140
 
141
141
  // Assert
142
142
  expect(res).toBeUndefined();
@@ -1,20 +1,14 @@
1
1
  import { URL } from 'url';
2
2
  import { join } from 'path';
3
3
  import { EventEmitter } from 'events';
4
- import { readFileSync, existsSync, statSync } from 'fs';
5
- import { KrasInjector, KrasResponse, KrasRequest, KrasInjectorConfig, KrasConfiguration, KrasResult } from 'kras';
4
+ import { readFile, stat, writeFile } from 'fs/promises';
5
+ import { KrasInjector, KrasRequest, KrasInjectorConfig, KrasConfiguration, KrasResult } from 'kras';
6
6
  import { log } from '../common/log';
7
7
  import { getPiletSpecMeta } from '../common/spec';
8
8
  import { config as commonConfig } from '../common/config';
9
9
  import { axios, mime, jju } from '../external';
10
10
  import { Bundler } from '../types';
11
11
 
12
- interface Pilet {
13
- bundler: Bundler;
14
- root: string;
15
- getMeta(basePath: string): PiletMetadata;
16
- }
17
-
18
12
  export interface PiletInjectorConfig extends KrasInjectorConfig {
19
13
  /**
20
14
  * The pilets to serve.
@@ -54,31 +48,43 @@ export interface PiletInjectorConfig extends KrasInjectorConfig {
54
48
  headers?: Record<string, string>;
55
49
  }
56
50
 
51
+ interface Pilet {
52
+ bundler: Bundler;
53
+ root: string;
54
+ getMeta(basePath: string): PiletMetadata;
55
+ }
56
+
57
57
  interface PiletMetadata {
58
58
  name?: string;
59
59
  config?: Record<string, any>;
60
60
  [key: string]: unknown;
61
61
  }
62
62
 
63
- function getMetaOverride(root: string, metaFile: string) {
63
+ async function getMetaOverride(root: string, metaFile: string) {
64
64
  if (metaFile) {
65
65
  const metaPath = join(root, metaFile);
66
+ const exists = await stat(metaPath).then(
67
+ () => true,
68
+ () => false,
69
+ );
66
70
 
67
- if (existsSync(metaPath)) {
68
- return jju.parse(readFileSync(metaPath, 'utf8'));
71
+ if (exists) {
72
+ const metaContent = await readFile(metaPath, 'utf8');
73
+ return jju.parse(metaContent);
69
74
  }
70
75
  }
71
76
 
72
77
  return undefined;
73
78
  }
74
79
 
75
- function fillPiletMeta(pilet: Pilet, metaFile: string, subPath: string) {
80
+ async function fillPiletMeta(pilet: Pilet, metaFile: string, subPath: string) {
76
81
  const { root, bundler } = pilet;
77
82
  const packagePath = join(root, 'package.json');
78
- const def = jju.parse(readFileSync(packagePath, 'utf8'));
83
+ const jsonContent = await readFile(packagePath, 'utf8');
84
+ const def = jju.parse(jsonContent);
79
85
  const file = bundler.bundle.name.replace(/^[\/\\]/, '');
80
86
  const target = join(bundler.bundle.dir, file);
81
- const metaOverride = getMetaOverride(root, metaFile);
87
+ const metaOverride = await getMetaOverride(root, metaFile);
82
88
 
83
89
  pilet.getMeta = (parentPath) => {
84
90
  const basePath = `${parentPath}${subPath}`;
@@ -96,11 +102,11 @@ function fillPiletMeta(pilet: Pilet, metaFile: string, subPath: string) {
96
102
  };
97
103
  }
98
104
 
105
+ type FeedResponse = { items?: Array<PiletMetadata> } | Array<PiletMetadata> | PiletMetadata;
106
+
99
107
  async function loadFeed(feed: string) {
100
108
  try {
101
- const response = await axios.default.get<{ items?: Array<PiletMetadata> } | Array<PiletMetadata> | PiletMetadata>(
102
- feed,
103
- );
109
+ const response = await axios.default.get<FeedResponse>(feed);
104
110
 
105
111
  if (Array.isArray(response.data)) {
106
112
  return response.data;
@@ -118,16 +124,33 @@ export default class PiletInjector implements KrasInjector {
118
124
  public config: PiletInjectorConfig;
119
125
  private serverConfig: KrasConfiguration;
120
126
  private indexPath: string;
127
+ private proxyInfo?: {
128
+ source: string;
129
+ files: Array<string>;
130
+ date: Date;
131
+ };
121
132
 
122
133
  constructor(config: PiletInjectorConfig, serverConfig: KrasConfiguration, core: EventEmitter) {
123
134
  this.config = config;
124
135
  this.serverConfig = serverConfig;
125
136
 
126
137
  if (this.config.active) {
127
- const { pilets, api, publicUrl, assetUrl } = config;
138
+ const { pilets, api, app, publicUrl, assetUrl } = config;
128
139
  this.indexPath = `${publicUrl}index.html`;
129
140
  const cbs = {};
130
141
 
142
+ if (app.endsWith('/app')) {
143
+ const packageJson = require(`${app}/../package.json`);
144
+
145
+ if (typeof packageJson.piralCLI.source === 'string') {
146
+ this.proxyInfo = {
147
+ source: packageJson.piralCLI.source,
148
+ files: packageJson.files,
149
+ date: new Date(packageJson.piralCLI.timestamp),
150
+ };
151
+ }
152
+ }
153
+
131
154
  core.on('user-connected', (e) => {
132
155
  const baseUrl = assetUrl || e.req.headers.origin;
133
156
 
@@ -144,8 +167,8 @@ export default class PiletInjector implements KrasInjector {
144
167
  });
145
168
 
146
169
  pilets.forEach((p, i) =>
147
- p.bundler.on(() => {
148
- fillPiletMeta(p, config.meta, `/${i}/`);
170
+ p.bundler.on(async () => {
171
+ await fillPiletMeta(p, config.meta, `/${i}/`);
149
172
 
150
173
  for (const id of Object.keys(cbs)) {
151
174
  const { baseUrl, notify } = cbs[id];
@@ -251,7 +274,7 @@ export default class PiletInjector implements KrasInjector {
251
274
  return merged;
252
275
  }
253
276
 
254
- sendContent(content: Buffer | string, type: string, url: string): KrasResponse {
277
+ sendContent(content: Buffer | string, type: string, url: string): KrasResult {
255
278
  const { headers } = this.config;
256
279
 
257
280
  return {
@@ -269,8 +292,8 @@ export default class PiletInjector implements KrasInjector {
269
292
  };
270
293
  }
271
294
 
272
- sendFile(target: string, url: string): KrasResponse {
273
- const content = readFileSync(target);
295
+ async sendFile(target: string, url: string): Promise<KrasResult> {
296
+ const content = await readFile(target);
274
297
  const type = mime.getType(target) ?? 'application/octet-stream';
275
298
  return this.sendContent(content, type, url);
276
299
  }
@@ -281,23 +304,25 @@ export default class PiletInjector implements KrasInjector {
281
304
  const pilet = pilets[+index];
282
305
  const bundler = pilet?.bundler;
283
306
 
307
+ await bundler?.ready();
308
+
284
309
  if (!path) {
285
- await bundler?.ready();
286
310
  const content = await this.getIndexMeta(baseUrl);
287
311
  return this.sendContent(content, 'application/json', url);
288
- } else {
289
- return bundler?.ready().then(() => {
290
- const target = join(bundler.bundle.dir, rest.join('/'));
312
+ } else if (bundler?.bundle) {
313
+ const target = join(bundler.bundle.dir, rest.join('/'));
314
+ const info = await stat(target).catch(() => undefined);
291
315
 
292
- if (existsSync(target) && statSync(target).isFile()) {
293
- return this.sendFile(target, url);
294
- }
295
- });
316
+ if (info && info.isFile()) {
317
+ return await this.sendFile(target, url);
318
+ }
296
319
  }
320
+
321
+ return undefined;
297
322
  }
298
323
 
299
- sendIndexFile(target: string, url: string, baseUrl: string): KrasResponse {
300
- const indexHtml = readFileSync(target, 'utf8');
324
+ async sendIndexFile(target: string, url: string, baseUrl: string): Promise<KrasResult> {
325
+ const indexHtml = await readFile(target, 'utf8');
301
326
 
302
327
  // mechanism to inject server side debug piletApi config into piral emulator
303
328
  const windowInjectionScript = `window['dbg:pilet-api'] = '${this.getPiletApi(baseUrl)}';`;
@@ -308,29 +333,50 @@ export default class PiletInjector implements KrasInjector {
308
333
  return this.sendContent(content, mime.getType(target), url);
309
334
  }
310
335
 
311
- handle(req: KrasRequest): KrasResponse {
336
+ private async shouldLoad(target: string, path: string) {
337
+ if (this.proxyInfo) {
338
+ if (!this.proxyInfo.files.includes(path)) {
339
+ return false;
340
+ }
341
+
342
+ const fileInfo = await stat(target).catch(() => undefined);
343
+
344
+ if (!fileInfo || fileInfo.mtime < this.proxyInfo.date) {
345
+ const url = new URL(path, this.proxyInfo.source);
346
+ const response = await axios.default.get(url.href, { responseType: 'arraybuffer' });
347
+ await writeFile(target, response.data);
348
+ }
349
+
350
+ return true;
351
+ } else {
352
+ const fileInfo = await stat(target).catch(() => undefined);
353
+ return fileInfo && fileInfo.isFile();
354
+ }
355
+ }
356
+
357
+ async handle(req: KrasRequest): Promise<KrasResult> {
312
358
  const { app, api, publicUrl, assetUrl } = this.config;
313
359
  const baseUrl =
314
360
  assetUrl || (req.headers.host ? `${req.encrypted ? 'https' : 'http'}://${req.headers.host}` : undefined);
315
361
 
316
362
  if (!req.target) {
317
363
  if (req.url.startsWith(publicUrl)) {
318
- const path = req.url.substring(publicUrl.length).split('?')[0];
364
+ const path = req.url.substring(publicUrl.length).split('?').shift();
319
365
 
320
366
  if (app) {
321
367
  const target = join(app, path);
322
368
 
323
- if (existsSync(target) && statSync(target).isFile()) {
369
+ if (await this.shouldLoad(target, path)) {
324
370
  if (req.url === this.indexPath) {
325
- return this.sendIndexFile(target, req.url, baseUrl);
371
+ return await this.sendIndexFile(target, req.url, baseUrl);
326
372
  }
327
373
 
328
- return this.sendFile(target, req.url);
374
+ return await this.sendFile(target, req.url);
329
375
  }
330
376
  }
331
377
 
332
378
  if (req.url !== this.indexPath) {
333
- return this.handle({
379
+ return await this.handle({
334
380
  ...req,
335
381
  url: this.indexPath,
336
382
  });
@@ -339,8 +385,8 @@ export default class PiletInjector implements KrasInjector {
339
385
 
340
386
  return undefined;
341
387
  } else if (req.target === api) {
342
- const path = req.url.substring(1).split('?')[0];
343
- return this.sendResponse(path, req.url, baseUrl);
388
+ const path = req.url.substring(1).split('?').shift();
389
+ return await this.sendResponse(path, req.url, baseUrl);
344
390
  }
345
391
  }
346
392
  }
@@ -64,7 +64,7 @@ describe('Piral-CLI piral injector', () => {
64
64
  expect(injector.active).toBeFalsy();
65
65
  });
66
66
 
67
- it('PiralInjector can send reponse and fails with invalid path', () => {
67
+ it('PiralInjector can send reponse and fails with invalid path', async () => {
68
68
  // Arrange
69
69
  const config = {
70
70
  bundler: bundlerMock,
@@ -75,7 +75,7 @@ describe('Piral-CLI piral injector', () => {
75
75
  const injector = new PiralInjector(config, undefined as any, new EventEmitter());
76
76
 
77
77
  // Act
78
- const res = injector.sendResponse('some/nice/invalid/path', 'sometarget.file', 'someDir', 'localhost:1234');
78
+ const res = await injector.sendResponse('some/nice/invalid/path', 'sometarget.file', 'someDir', 'localhost:1234');
79
79
 
80
80
  // Assert
81
81
  expect(res).toBeUndefined();