-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathindex.ts
More file actions
143 lines (135 loc) · 5.98 KB
/
index.ts
File metadata and controls
143 lines (135 loc) · 5.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
import path from 'path';
import fs from 'fs-extra';
import { get, includes, find, split, filter, isEmpty } from 'lodash';
import axios from 'axios';
import { getRootHome, getYamlContent, registry } from '@serverless-devs/utils';
import { BASE_URL } from '../constant';
import assert from 'assert';
const debug = require('@serverless-cd/debug')('serverless-devs:load-component');
const getUrlWithLatest = (name: string) => `${BASE_URL}/packages/${name}/release/latest`;
const getUrlWithVersion = (name: string, versionId: string) => `${BASE_URL}/packages/${name}/release/tags/${encodeURIComponent(versionId)}`;
export function readJsonFile(filePath: string) {
if (fs.existsSync(filePath)) {
const data = fs.readFileSync(filePath, 'utf8');
try {
return JSON.parse(data);
} catch (error) { }
}
}
const getEntryFile = async (componentPath: string, logger: any) => {
try {
const fsStat = await fs.stat(componentPath);
if (fsStat.isFile() || !fsStat.isDirectory()) return componentPath;
const packageInfo: any = readJsonFile(path.resolve(componentPath, 'package.json'));
// First look for main under the package json file
let entry = get(packageInfo, 'main');
if (entry) return path.resolve(componentPath, entry);
// Second check the out dir under the tsconfig json file
const tsconfigPath = path.resolve(componentPath, 'tsconfig.json');
const tsconfigInfo = readJsonFile(tsconfigPath);
entry = get(tsconfigInfo, 'compilerOptions.outDir');
if (entry) return path.resolve(componentPath, entry);
// Third look for src index js
const srcIndexPath = path.resolve(componentPath, './src/index.js');
if (fs.existsSync(srcIndexPath)) return srcIndexPath;
const indexPath = path.resolve(componentPath, './index.js');
if (fs.existsSync(indexPath)) return indexPath;
// No valid entry file found
console.log(`fsStat: ${JSON.stringify(fsStat)}`);
console.log(`packageInfo: ${JSON.stringify(packageInfo)}`);
console.log(`tsconfigPath: ${tsconfigPath}`);
console.log(`tsconfigInfo: ${JSON.stringify(tsconfigInfo)}`);
console.log(`srcIndexPath: ${srcIndexPath}`);
console.log(`indexPath: ${indexPath}`);
throw new Error('No valid entry file found');
} catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
console.log(errorMessage);
throw new Error(
'The component cannot be required. Please check whether the setting of the component entry file is correct. In the current directory, first look for main under the package json file, secondly look for compiler options out dir under the tsconfig json file, thirdly look for src index js, and finally look for index js',
);
}
};
export const buildComponentInstance = async (componentPath: string, params?: any, cleanCache: boolean = false) => {
const requirePath = await getEntryFile(componentPath, params.logger || console);
// bug: `- component: fc invoke` timeout. Delete require cache
if (cleanCache && require.cache[requirePath]) {
try {
delete require.cache[requirePath];
} catch {}
}
const baseChildComponent = await require(requirePath);
const ChildComponent = baseChildComponent.default || baseChildComponent;
try {
const componentInstance = new ChildComponent(params);
if (componentInstance) {
componentInstance.__path = componentPath;
const publishData = getYamlContent(path.join(componentPath, 'publish.yaml'));
const schema = get(publishData, 'Schema');
componentInstance.schemaPath = schema ? path.join(componentPath, schema) : undefined;
const version = get(publishData, 'Version');
if (version) {
componentInstance.__version = version;
componentInstance.__info = `${get(publishData, 'Name')}@${version}`;
}
}
return componentInstance;
} catch (error) {
return ChildComponent;
}
};
export function getProvider(name: string) {
if (isValidUrl(name)) {
return [name, 'CUSTOM'];
}
assert(!includes(name, '/'), `The component name ${name} cannot contain /`);
const [componentName, componentVersion] = split(name, '@');
const { core_load_serverless_devs_component } = process.env;
if (core_load_serverless_devs_component) {
const componentList = filter(split(core_load_serverless_devs_component, ';'), v => includes(v, '@'));
const componentNames = [];
const obj: any = {};
for (const item of componentList) {
const [n, v] = split(item, '@');
componentNames.push(n);
obj[n] = v;
}
const key = componentName;
if (find(componentNames, v => v === key)) {
return [componentName, obj[key]];
}
}
return [componentName, componentVersion];
}
export const getZipballUrl = async (componentName: string, componentVersion?: string) => {
if(componentVersion === 'CUSTOM') {
return {};
}
const url = componentVersion ? getUrlWithVersion(componentName, componentVersion) : getUrlWithLatest(componentName);
debug(`url: ${url}`);
try {
const res = await axios.get(url, { headers: registry.getSignHeaders() });
debug(`res: ${JSON.stringify(res.data)}`);
const zipball_url = get(res, 'data.body.zipball_url');
if (isEmpty(zipball_url)) throw new Error(`url: ${url} is not found`);
return { zipballUrl: zipball_url, version: get(res, 'data.body.tag_name') };
} catch (error) {
if (get(error, 'response.status') === 404) {
const name = componentVersion ? `${componentName}@${componentVersion}` : componentName;
throw new Error(`Component or plugin ${name} is not found`);
}
throw error;
}
};
export const getComponentCachePath = (componentName: string, componentVersion?: string) => {
componentName = isValidUrl(componentName) ? componentName.split('/').pop()?.split('.')[0] || '' : componentName;
return path.join(getRootHome(), 'components', 'devsapp.cn', 'v3', componentVersion ? `${componentName}@${componentVersion}` : componentName);
};
export function isValidUrl(s: string) {
try {
new URL(s);
return true;
} catch (err) {
return false;
}
}