piral-cli 0.15.0-alpha.3548 → 0.15.0-alpha.3589

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "piral-cli",
3
- "version": "0.15.0-alpha.3548",
3
+ "version": "0.15.0-alpha.3589",
4
4
  "description": "The standard CLI for creating and building a Piral instance or a Pilet.",
5
5
  "keywords": [
6
6
  "portal",
@@ -77,5 +77,5 @@
77
77
  "typescript": "^4.0.2",
78
78
  "yargs": "^15.4.1"
79
79
  },
80
- "gitHead": "2edf7bbcee6a7e931348198d14139c7f958877e7"
80
+ "gitHead": "3de80e7857d8f95c5f7c6944dfad56d4a5e21f8d"
81
81
  }
@@ -4,7 +4,6 @@ import { Stream } from 'stream';
4
4
  import { platform, tmpdir } from 'os';
5
5
  import { createWriteStream } from 'fs';
6
6
  import { log } from './log';
7
- import { computeHash } from './hash';
8
7
  import { axios, FormData } from '../external';
9
8
 
10
9
  const os = platform();
@@ -40,18 +39,6 @@ function streamToFile(source: Stream, target: string) {
40
39
  });
41
40
  }
42
41
 
43
- export function getHashFromUrl(target: string): Promise<string> {
44
- return axios.default
45
- .get<Buffer>(target, {
46
- responseType: 'arraybuffer',
47
- headers: standardHeaders,
48
- })
49
- .then((res) => {
50
- log('generalDebug_0003', `Received the contents from "${target}" (status: ${res.status}).`);
51
- return computeHash(res.data);
52
- });
53
- }
54
-
55
42
  export function downloadFile(target: string, ca?: Buffer): Promise<Array<string>> {
56
43
  const httpsAgent = ca ? new Agent({ ca }) : undefined;
57
44
  return axios.default
@@ -0,0 +1,153 @@
1
+ import { resolve, dirname } from 'path';
2
+ import { log, fail } from './log';
3
+ import { satisfies, validate } from './version';
4
+ import { computeHash } from './hash';
5
+ import { getHash, readJson, findFile, checkExists, checkIsDirectory } from './io';
6
+ import { SharedDependency } from '../types';
7
+
8
+ interface Importmap {
9
+ imports: Record<string, string>;
10
+ }
11
+
12
+ function tryResolve(baseDir: string, name: string) {
13
+ try {
14
+ return require.resolve(name, {
15
+ paths: [baseDir],
16
+ });
17
+ } catch (ex) {
18
+ log('generalDebug_0003', `Could not resolve the package "${name}" in "${baseDir}": ${ex}`);
19
+ return undefined;
20
+ }
21
+ }
22
+
23
+ function getDependencyDetails(depName: string): [assetName: string, identifier: string, versionSpec: string] {
24
+ const sep = depName.indexOf('@', 1);
25
+ const version = sep > 0 ? depName.substring(sep + 1) : '';
26
+ const id = sep > 0 ? depName.substring(0, sep) : depName;
27
+ const assetName = (id.startsWith('@') ? id.substring(1) : id).replace(/[\/\.]/g, '-').replace(/(\-)+/, '-');
28
+ return [assetName, id, version];
29
+ }
30
+
31
+ function getLocalDependencyVersion(
32
+ packageJson: string,
33
+ depName: string,
34
+ versionSpec: string,
35
+ ): [offeredVersion: string, requiredVersion: string] {
36
+ const details = require(packageJson);
37
+
38
+ if (versionSpec) {
39
+ if (!validate(versionSpec)) {
40
+ fail('importMapVersionSpecInvalid_0026', depName);
41
+ }
42
+
43
+ if (!satisfies(details.version, versionSpec)) {
44
+ fail('importMapVersionSpecNotSatisfied_0025', depName, details.version);
45
+ }
46
+
47
+ return [details.version, versionSpec];
48
+ }
49
+
50
+ return [details.version, details.version];
51
+ }
52
+
53
+ async function resolveImportmap(dir: string, importmap: Importmap) {
54
+ const dependencies: Array<SharedDependency> = [];
55
+ const sharedImports = importmap?.imports;
56
+
57
+ if (typeof sharedImports === 'object' && sharedImports) {
58
+ for (const depName of Object.keys(sharedImports)) {
59
+ const url = sharedImports[depName];
60
+ const [assetName, identifier, versionSpec] = getDependencyDetails(depName);
61
+
62
+ if (typeof url !== 'string') {
63
+ log('generalInfo_0000', `The value of "${depName}" in the importmap is not a string and will be ignored.`);
64
+ } else if (/^https?:\/\//.test(url)) {
65
+ const hash = computeHash(url);
66
+
67
+ dependencies.push({
68
+ id: `${identifier}@${hash}`,
69
+ requireId: `${identifier}@${hash}`,
70
+ entry: url,
71
+ name: identifier,
72
+ ref: url,
73
+ type: 'remote',
74
+ });
75
+ } else if (url === identifier) {
76
+ const entry = tryResolve(dir, identifier);
77
+
78
+ if (entry) {
79
+ const packageJson = await findFile(dirname(entry), 'package.json');
80
+ const [version, requireVersion] = getLocalDependencyVersion(packageJson, depName, versionSpec);
81
+
82
+ dependencies.push({
83
+ id: `${identifier}@${version}`,
84
+ requireId: `${identifier}@${requireVersion}`,
85
+ entry,
86
+ name: identifier,
87
+ ref: `${assetName}.js`,
88
+ type: 'local',
89
+ });
90
+ } else {
91
+ fail('importMapReferenceNotFound_0027', dir, url);
92
+ }
93
+ } else {
94
+ const entry = resolve(dir, url);
95
+ const exists = await checkExists(entry);
96
+
97
+ if (exists) {
98
+ const isDirectory = await checkIsDirectory(entry);
99
+ const packageJson = isDirectory ? resolve(entry, 'package.json') : await findFile(dirname(entry), 'package.json');
100
+ const packageJsonExists = await checkExists(packageJson);
101
+
102
+ if (packageJsonExists) {
103
+ const [version, requireVersion] = getLocalDependencyVersion(packageJson, depName, versionSpec);
104
+
105
+ dependencies.push({
106
+ id: `${identifier}@${version}`,
107
+ requireId: `${identifier}@${requireVersion}`,
108
+ entry: isDirectory ? tryResolve(dir, entry) : entry,
109
+ name: identifier,
110
+ ref: `${assetName}.js`,
111
+ type: 'local',
112
+ });
113
+ } else if (isDirectory) {
114
+ fail('importMapReferenceNotFound_0027', entry, 'package.json');
115
+ } else {
116
+ const hash = await getHash(entry);
117
+
118
+ dependencies.push({
119
+ id: `${identifier}@${hash}`,
120
+ requireId: `${identifier}@${hash}`,
121
+ entry,
122
+ name: identifier,
123
+ ref: `${assetName}.js`,
124
+ type: 'local',
125
+ });
126
+ }
127
+ } else {
128
+ fail('importMapReferenceNotFound_0027', dir, url);
129
+ }
130
+ }
131
+ }
132
+ }
133
+
134
+ return dependencies;
135
+ }
136
+
137
+ export async function readImportmap(dir: string, packageDetails: any) {
138
+ const importmap = packageDetails.importmap;
139
+
140
+ if (typeof importmap === 'string') {
141
+ const notFound = {};
142
+ const content = await readJson(dir, importmap, notFound);
143
+
144
+ if (content === notFound) {
145
+ fail('importMapFileNotFound_0028', dir, importmap);
146
+ }
147
+
148
+ const baseDir = dirname(resolve(dir, importmap));
149
+ return resolveImportmap(baseDir, content);
150
+ }
151
+
152
+ return resolveImportmap(dir, importmap);
153
+ }
@@ -10,6 +10,7 @@ export * from './emoji';
10
10
  export * from './envs';
11
11
  export * from './hash';
12
12
  export * from './http';
13
+ export * from './importmap';
13
14
  export * from './info';
14
15
  export * from './injectors';
15
16
  export * from './io';
package/src/common/io.ts CHANGED
@@ -371,12 +371,21 @@ export async function mergeWithJson<T>(targetDir: string, fileName: string, newC
371
371
  return deepMerge(originalContent, newContent);
372
372
  }
373
373
 
374
- export async function readJson<T = any>(targetDir: string, fileName: string) {
374
+ export async function readJson<T = any>(targetDir: string, fileName: string, defaultValue = {}) {
375
375
  const targetFile = join(targetDir, fileName);
376
376
  const content = await new Promise<string>((resolve) => {
377
377
  readFile(targetFile, 'utf8', (err, c) => (err ? resolve('') : resolve(c)));
378
378
  });
379
- return JSON.parse(content || '{}') as T;
379
+
380
+ if (content) {
381
+ try {
382
+ return JSON.parse(content) as T;
383
+ } catch (ex) {
384
+ log('generalError_0002', `Invalid JSON found in file "${fileName}" at "${targetDir}".`);
385
+ }
386
+ }
387
+
388
+ return defaultValue as T;
380
389
  }
381
390
 
382
391
  export function readBinary(targetDir: string, fileName: string) {
@@ -6,13 +6,13 @@ import { getDependencies, getDevDependencies } from './language';
6
6
  import { SourceLanguage, ForceOverwrite } from './enums';
7
7
  import { checkAppShellCompatibility } from './compatibility';
8
8
  import { deepMerge } from './merge';
9
- import { getHashFromUrl } from './http';
10
9
  import { applyTemplate } from './template';
10
+ import { readImportmap } from './importmap';
11
11
  import { isGitPackage, isLocalPackage, makeGitUrl, makeFilePath, makePiletExternals, makeExternals } from './npm';
12
12
  import { filesTar, filesOnceTar, declarationEntryExtensions } from './constants';
13
13
  import { getHash, checkIsDirectory, matchFiles } from './io';
14
14
  import { readJson, copy, updateExistingJson, findFile, checkExists } from './io';
15
- import { Framework, FileInfo, PiletsInfo, TemplateFileLocation, SharedDependency } from '../types';
15
+ import { Framework, FileInfo, PiletsInfo, TemplateFileLocation } from '../types';
16
16
 
17
17
  function getDependencyVersion(
18
18
  name: string,
@@ -574,108 +574,6 @@ export function checkAppShellPackage(appPackage: any) {
574
574
  return false;
575
575
  }
576
576
 
577
- function tryResolve(baseDir: string, name: string) {
578
- try {
579
- return require.resolve(name, {
580
- paths: [baseDir],
581
- });
582
- } catch (ex) {
583
- log('generalDebug_0003', `Could not resolve the package "${name}" in "${baseDir}": ${ex}`);
584
- return undefined;
585
- }
586
- }
587
-
588
- interface Importmap {
589
- imports: Record<string, string>;
590
- }
591
-
592
- function normalizeDepName(s: string) {
593
- return (s.startsWith('@') ? s.substring(1) : s).replace(/[\/\.]/g, '-').replace(/(\-)+/, '-');
594
- }
595
-
596
- async function resolveImportmap(dir: string, importmap: Importmap) {
597
- const dependencies: Array<SharedDependency> = [];
598
- const sharedImports = importmap?.imports;
599
-
600
- if (typeof sharedImports === 'object' && sharedImports) {
601
- for (const depName of Object.keys(sharedImports)) {
602
- const url = sharedImports[depName];
603
- const assetName = normalizeDepName(depName);
604
-
605
- if (typeof url !== 'string') {
606
- } else if (/^https?:\/\//.test(url)) {
607
- const hash = await getHashFromUrl(url);
608
-
609
- dependencies.push({
610
- id: `${depName}@${hash}`,
611
- entry: url,
612
- name: depName,
613
- ref: url,
614
- type: 'remote',
615
- });
616
- } else if (url === depName) {
617
- const entry = tryResolve(dir, depName);
618
-
619
- if (entry) {
620
- const packageJson = await findFile(dirname(entry), 'package.json');
621
- const details = require(packageJson);
622
-
623
- dependencies.push({
624
- id: `${depName}@${details.version}`,
625
- entry,
626
- ref: `${assetName}.js`,
627
- name: depName,
628
- type: 'local',
629
- });
630
- }
631
- } else {
632
- const entry = resolve(dir, url);
633
- const exists = await checkExists(entry);
634
-
635
- if (exists) {
636
- const packageJson = await findFile(dirname(entry), 'package.json');
637
-
638
- if (packageJson) {
639
- const details = require(packageJson);
640
-
641
- dependencies.push({
642
- id: `${depName}@${details.version}`,
643
- entry,
644
- name: depName,
645
- ref: `${assetName}.js`,
646
- type: 'local',
647
- });
648
- } else {
649
- const hash = await getHash(entry);
650
-
651
- dependencies.push({
652
- id: `${depName}@${hash}`,
653
- entry,
654
- name: depName,
655
- ref: `${assetName}.js`,
656
- type: 'local',
657
- });
658
- }
659
- }
660
- }
661
- }
662
- }
663
-
664
- return dependencies;
665
- }
666
-
667
- export async function readImportmap(dir: string, packageDetails: any) {
668
- const importmap = packageDetails.importmap;
669
-
670
- if (typeof importmap === 'string') {
671
- const content = await readJson(dir, importmap);
672
- const baseDir = dirname(resolve(dir, importmap));
673
- return resolveImportmap(baseDir, content);
674
- }
675
-
676
- return resolveImportmap(dir, importmap);
677
- }
678
-
679
577
  export async function retrievePiletData(target: string, app?: string) {
680
578
  const packageJson = await findFile(target, 'package.json');
681
579
 
@@ -15,7 +15,7 @@ function resolveWinPath(specialFolder: string, subPath: string): string | undefi
15
15
  }
16
16
 
17
17
  export function runScript(script: string, cwd = process.cwd(), output: NodeJS.WritableStream = process.stdout) {
18
- const bin = resolve('./node_modules/.bin');
18
+ const bin = resolve(cwd, './node_modules/.bin');
19
19
  const sep = isWindows ? ';' : ':';
20
20
  const env = Object.assign({}, process.env);
21
21
 
@@ -0,0 +1,233 @@
1
+ import { satisfies, validate } from './version';
2
+
3
+ describe('semver check module', () => {
4
+ it('specific publish version is valid', () => {
5
+ const result = validate('1.2.3');
6
+ expect(result).toBeTruthy();
7
+ });
8
+
9
+ it('shortened publish version is valid', () => {
10
+ const result = validate('1.2');
11
+ expect(result).toBeTruthy();
12
+ });
13
+
14
+ it('some hash is invalid', () => {
15
+ const result = validate('fabcde');
16
+ expect(result).toBeFalsy();
17
+ });
18
+
19
+ it('some longer hash is invalid', () => {
20
+ const result = validate('123fabdef0012');
21
+ expect(result).toBeFalsy();
22
+ });
23
+
24
+ it('major publish version is valid', () => {
25
+ const result = validate('1');
26
+ expect(result).toBeTruthy();
27
+ });
28
+
29
+ it('any publish version is valid', () => {
30
+ const result = validate('1.2.x');
31
+ expect(result).toBeTruthy();
32
+ });
33
+
34
+ it('specific preview version is valid', () => {
35
+ const result = validate('1.2.3-pre.123');
36
+ expect(result).toBeTruthy();
37
+ });
38
+
39
+ it('caret version is specifier valid', () => {
40
+ const result = validate('^1.2.3');
41
+ expect(result).toBeTruthy();
42
+ });
43
+
44
+ it('tilde version is specifier valid', () => {
45
+ const result = validate('~1.2.3');
46
+ expect(result).toBeTruthy();
47
+ });
48
+
49
+ it('greater version is specifier valid', () => {
50
+ const result = validate('>1.2.3');
51
+ expect(result).toBeTruthy();
52
+ });
53
+
54
+ it('greater equals version is specifier valid', () => {
55
+ const result = validate('>=1.2.3');
56
+ expect(result).toBeTruthy();
57
+ });
58
+
59
+ it('greater equals with x version is specifier valid', () => {
60
+ const result = validate('>=1.x');
61
+ expect(result).toBeTruthy();
62
+ });
63
+
64
+ it('satisfies exact version match', () => {
65
+ const result = satisfies('1.2.3', '1.2.3');
66
+ expect(result).toBeTruthy();
67
+ });
68
+
69
+ it('does not satisfy exact version mismatch greater', () => {
70
+ const result = satisfies('1.2.3', '1.2.4');
71
+ expect(result).toBeFalsy();
72
+ });
73
+
74
+ it('does not satisfy exact version mismatch smaller', () => {
75
+ const result = satisfies('1.2.3', '1.2.2');
76
+ expect(result).toBeFalsy();
77
+ });
78
+
79
+ it('satisfies constraint with caret patch', () => {
80
+ const result = satisfies('1.2.3', '^1.2.0');
81
+ expect(result).toBeTruthy();
82
+ });
83
+
84
+ it('satisfies constraint with caret minor', () => {
85
+ const result = satisfies('1.3.0', '^1.2.0');
86
+ expect(result).toBeTruthy();
87
+ });
88
+
89
+ it('satisfies constraint with caret exact', () => {
90
+ const result = satisfies('1.3.0', '^1.3.0');
91
+ expect(result).toBeTruthy();
92
+ });
93
+
94
+ it('satisfies constraint with caret exact with dropped number', () => {
95
+ const result = satisfies('1.3.0', '^1.3');
96
+ expect(result).toBeTruthy();
97
+ });
98
+
99
+ it('satisfies constraint with caret exact with dropped numbers', () => {
100
+ const result = satisfies('1', '^1');
101
+ expect(result).toBeTruthy();
102
+ });
103
+
104
+ it('does not satisfy constraint with caret major', () => {
105
+ const result = satisfies('2.0.0', '^1.2.0');
106
+ expect(result).toBeFalsy();
107
+ });
108
+
109
+ it('satisfies constraint with tilde patch', () => {
110
+ const result = satisfies('1.2.3', '~1.2.0');
111
+ expect(result).toBeTruthy();
112
+ });
113
+
114
+ it('does not satisfy constraint with tilde minor', () => {
115
+ const result = satisfies('1.3.0', '~1.2.0');
116
+ expect(result).toBeFalsy();
117
+ });
118
+
119
+ it('does not satisfy constraint with tilde patch greater', () => {
120
+ const result = satisfies('1.3.0', '~1.3.2');
121
+ expect(result).toBeFalsy();
122
+ });
123
+
124
+ it('satisfies constraint with tilde patch lighter', () => {
125
+ const result = satisfies('1.3.3', '~1.3.2');
126
+ expect(result).toBeTruthy();
127
+ });
128
+
129
+ it('satisfies constraint with x patch', () => {
130
+ const result = satisfies('1.2.3', '1.x.3');
131
+ expect(result).toBeTruthy();
132
+ });
133
+
134
+ it('does not satisfy constraint x minor', () => {
135
+ const result = satisfies('1.3.0', '1.2.x');
136
+ expect(result).toBeFalsy();
137
+ });
138
+
139
+ it('satsfies greater than matching', () => {
140
+ const result = satisfies('1.3.0', '>=1.2.0');
141
+ expect(result).toBeTruthy();
142
+ });
143
+
144
+ it('satsfies less than matching', () => {
145
+ const result = satisfies('1.3.0', '<=1.3.0');
146
+ expect(result).toBeTruthy();
147
+ });
148
+
149
+ it('does not satisfy only greater than non-matching', () => {
150
+ const result = satisfies('1.3.0', '>1.3.0');
151
+ expect(result).toBeFalsy();
152
+ });
153
+
154
+ it('does not satisfy greater than non-matching', () => {
155
+ const result = satisfies('1.3.0', '>=1.3.1');
156
+ expect(result).toBeFalsy();
157
+ });
158
+
159
+ it('does not satisfy less than non-matching', () => {
160
+ const result = satisfies('1.3.0', '<=1.2.0');
161
+ expect(result).toBeFalsy();
162
+ });
163
+
164
+ it('does not satisfy less than non-matching', () => {
165
+ const result = satisfies('1.3.0', '<1.3.0');
166
+ expect(result).toBeFalsy();
167
+ });
168
+
169
+ it('does not satisfy less than non-matching', () => {
170
+ const result = satisfies('1.3.0', '<=1.2.0');
171
+ expect(result).toBeFalsy();
172
+ });
173
+
174
+ it('satisfies exact version match with previews', () => {
175
+ const result = satisfies('1.2.3-pre.5', '1.2.3-pre.5');
176
+ expect(result).toBeTruthy();
177
+ });
178
+
179
+ it('satisfies exact version match with dropped number', () => {
180
+ const result = satisfies('1.0', '1');
181
+ expect(result).toBeTruthy();
182
+ });
183
+
184
+ it('satisfies exact version match with dropped numbers', () => {
185
+ const result = satisfies('1', '1.0.0');
186
+ expect(result).toBeTruthy();
187
+ });
188
+
189
+ it('does not satisfy exact version mismatch preview', () => {
190
+ const result = satisfies('1.2.4-pre.5', '1.2.4-pre.6');
191
+ expect(result).toBeFalsy();
192
+ });
193
+
194
+ it('does not satisfy exact version mismatch preview version offered', () => {
195
+ const result = satisfies('1.2.4-beta', '1.2.4-beta.5');
196
+ expect(result).toBeFalsy();
197
+ });
198
+
199
+ it('does not satisfy exact version mismatch preview version demanded', () => {
200
+ const result = satisfies('1.2.4-beta.5', '1.2.4-beta');
201
+ expect(result).toBeFalsy();
202
+ });
203
+
204
+ it('does not satisfy exact version mismatch preview higher', () => {
205
+ const result = satisfies('1.2.4-gamma', '1.2.4-beta');
206
+ expect(result).toBeFalsy();
207
+ });
208
+
209
+ it('does not satisfy exact version mismatch preview smaller', () => {
210
+ const result = satisfies('1.2.4-alpha', '1.2.4-beta');
211
+ expect(result).toBeFalsy();
212
+ });
213
+
214
+ it('does not satisfy exact and preview mismatch', () => {
215
+ const result = satisfies('1.2.4-pre.5', '1.2.4');
216
+ expect(result).toBeFalsy();
217
+ });
218
+
219
+ it('satisfies just an x', () => {
220
+ const result = satisfies('1.2.3', 'x');
221
+ expect(result).toBeTruthy();
222
+ });
223
+
224
+ it('satisfies just a *', () => {
225
+ const result = satisfies('1.2.3', '*');
226
+ expect(result).toBeTruthy();
227
+ });
228
+
229
+ it('satisfies just a >=0', () => {
230
+ const result = satisfies('1.2.3', '>=0');
231
+ expect(result).toBeTruthy();
232
+ });
233
+ });