UNPKG

2.19 kBPlain TextView Raw
1import * as fs from 'fs';
2import * as t from 'io-ts';
3import { isRight } from 'fp-ts/lib/Either';
4import { PathReporter } from 'io-ts/lib/PathReporter';
5
6const EmbellishOverridesProps = t.partial({
7 licenseHolder: t.string,
8});
9
10const RepositoryProps = t.union([
11 t.string,
12 t.type({
13 type: t.string,
14 url: t.string,
15 }),
16]);
17
18const PackageStabilityProps = t.keyof({
19 deprecated: null,
20 experimental: null,
21 unstable: null,
22 stable: null,
23 frozen: null,
24 locked: null,
25});
26
27const PackageDataOptionalProps = t.partial({
28 license: t.string,
29 embellish: EmbellishOverridesProps,
30 private: t.boolean,
31 repository: RepositoryProps,
32 stability: PackageStabilityProps,
33});
34
35const PackageDataProps = t.intersection([
36 t.type({
37 author: t.string,
38 name: t.string,
39 }),
40 PackageDataOptionalProps,
41]);
42
43const REPO_REGEXES = [
44 /^.*(github\.com)\/(.*)\.git.*$/, // github
45 /^.*(bitbucket\.org)\/(.*)\.git.*$/, // bitbucket
46];
47
48export type PackageData = t.TypeOf<typeof PackageDataProps>;
49
50export class Package {
51 constructor(public readonly data: PackageData) {}
52
53 static deserialize(json: unknown) {
54 const result = PackageDataProps.decode(json);
55 if (isRight(result)) {
56 return result.right;
57 }
58
59 throw new Error(`Unable to decode package data: ${PathReporter.report(result)}`);
60 }
61
62 static readFromFile(filename: string) {
63 return new Promise<PackageData>((resolve, reject) => {
64 fs.readFile(filename, 'utf-8', (err, content) => {
65 if (err) {
66 return reject(err);
67 }
68
69 try {
70 resolve(Package.deserialize(JSON.parse(content)));
71 } catch (e) {
72 reject(e);
73 }
74 });
75 });
76 }
77}
78
79export const getRepository = (data: PackageData) => {
80 const { repository } = data;
81 if (!repository) {
82 return undefined;
83 }
84
85 const url = typeof repository === 'string' ? repository : repository.url;
86 const match = REPO_REGEXES.reduce<RegExpExecArray | null>((memo, regex) => {
87 return memo || regex.exec(url);
88 }, null);
89
90 return match
91 ? {
92 host: match[1] as string,
93 path: match[2].split('/').splice(0, 2).join('/') as string,
94 }
95 : undefined;
96};
97
\No newline at end of file