mirror of
https://github.com/serverless/serverless.git
synced 2025-12-08 19:46:03 +00:00
241 lines
7.2 KiB
JavaScript
241 lines
7.2 KiB
JavaScript
'use strict';
|
|
|
|
module.exports = async () => {
|
|
const cliArgs = new Set(process.argv.slice(2));
|
|
|
|
// Unconditionally favor "serverless" for version check
|
|
if (cliArgs.has('--version')) return 'serverless';
|
|
if (cliArgs.has('-v')) return 'serverless';
|
|
|
|
// Detect eventual component configuration
|
|
const fsp = require('fs').promises;
|
|
|
|
const isChinaUser = (() => {
|
|
if (process.env.SLS_GEO_LOCATION) return process.env.SLS_GEO_LOCATION === 'cn';
|
|
return new Intl.DateTimeFormat('en', { timeZoneName: 'long' })
|
|
.format()
|
|
.includes('China Standard Time');
|
|
})();
|
|
|
|
const resolvePlatformCli = () => {
|
|
// Support SERVERLESS_PLATFORM_VENDOR to be configured in .env files
|
|
const dotenv = require('dotenv');
|
|
dotenv.config({ path: require('path').resolve('.env') });
|
|
|
|
if (process.env.SERVERLESS_PLATFORM_VENDOR) {
|
|
return process.env.SERVERLESS_PLATFORM_VENDOR === 'tencent'
|
|
? 'serverless-tencent'
|
|
: '@serverless/components';
|
|
}
|
|
return isChinaUser ? 'serverless-tencent' : '@serverless/components';
|
|
};
|
|
|
|
if (
|
|
(
|
|
await Promise.all(
|
|
['yml', 'yaml', 'json'].map(async (extension) => {
|
|
try {
|
|
await fsp.access(`serverless.component.${extension}`);
|
|
return true;
|
|
} catch {
|
|
return false;
|
|
}
|
|
})
|
|
)
|
|
).some(Boolean)
|
|
) {
|
|
return resolvePlatformCli();
|
|
}
|
|
|
|
const isComposeIgnoredCommand = (() => {
|
|
const args = process.argv.slice(2);
|
|
// Simplified check - if arg starts with `-` then we consider it to be
|
|
// a param and everything before it to be a command
|
|
const firstParamIndex = args.findIndex((element) => element.startsWith('-'));
|
|
|
|
const commands = args.slice(0, firstParamIndex === -1 ? Infinity : firstParamIndex);
|
|
const command = commands.join(' ');
|
|
|
|
const composeIgnoredCommands = new Set([
|
|
'',
|
|
'config',
|
|
'config credentials',
|
|
'create',
|
|
'generate-event',
|
|
'install',
|
|
'login',
|
|
'logout',
|
|
'plugin list',
|
|
'plugin search',
|
|
'upgrade',
|
|
'uninstall',
|
|
]);
|
|
|
|
return composeIgnoredCommands.has(command);
|
|
})();
|
|
|
|
if (!isComposeIgnoredCommand) {
|
|
if (
|
|
(
|
|
await Promise.all(
|
|
['yml', 'yaml', 'json', 'js', 'ts'].map(async (extension) => {
|
|
try {
|
|
await fsp.access(`serverless-compose.${extension}`);
|
|
return true;
|
|
} catch {
|
|
return false;
|
|
}
|
|
})
|
|
)
|
|
).some(Boolean)
|
|
) {
|
|
return '@serverless/compose';
|
|
}
|
|
}
|
|
|
|
// Detect eventual service configuration
|
|
const configurationExtension =
|
|
(
|
|
await Promise.all(
|
|
['yml', 'yaml', 'json', 'js', 'ts'].map(async (extension) => {
|
|
try {
|
|
await fsp.access(`serverless.${extension}`);
|
|
return extension;
|
|
} catch {
|
|
return null;
|
|
}
|
|
})
|
|
)
|
|
).find(Boolean) || null;
|
|
|
|
if (configurationExtension) {
|
|
// Found top level service configuration, recognize CLI by content
|
|
const targetCliName = await (async () => {
|
|
const resolveByObjectConfiguration = (configuration) => {
|
|
if (configuration.provider) return 'serverless';
|
|
if (configuration.component) return resolvePlatformCli();
|
|
for (const value of Object.values(configuration)) {
|
|
if (value.component) return '@serverless/cli';
|
|
}
|
|
return null;
|
|
};
|
|
switch (configurationExtension) {
|
|
case 'yml':
|
|
case 'yaml': {
|
|
const content = await fsp.readFile(`serverless.${configurationExtension}`, 'utf8');
|
|
if (content.search(/(?:^|\n)provider\s*:/) !== -1) return 'serverless';
|
|
if (content.search(/(?:^|\n)component\s*:/) !== -1) return resolvePlatformCli();
|
|
if (content.search(/\n\s+component\s*:/) !== -1) return '@serverless/cli';
|
|
return null;
|
|
}
|
|
case 'json': {
|
|
const configuration = (() => {
|
|
try {
|
|
return require(`${process.cwd()}/serverless.json`);
|
|
} catch {
|
|
return null;
|
|
}
|
|
})();
|
|
if (!configuration) return 'serverless';
|
|
return resolveByObjectConfiguration(configuration);
|
|
}
|
|
case 'js': {
|
|
const configuration = (() => {
|
|
try {
|
|
return require(`${process.cwd()}/serverless.js`);
|
|
} catch {
|
|
return null;
|
|
}
|
|
})();
|
|
if (!configuration) return 'serverless';
|
|
if (typeof configuration === 'function') return '@serverless/cli';
|
|
return resolveByObjectConfiguration(configuration);
|
|
}
|
|
case 'ts':
|
|
return 'serverless';
|
|
default:
|
|
throw new Error(`Unrecognized extension "${configurationExtension}"`);
|
|
}
|
|
})();
|
|
if (targetCliName) return targetCliName;
|
|
}
|
|
|
|
// No top level service configuration
|
|
if (isChinaUser) return resolvePlatformCli();
|
|
|
|
// Detect eventual component template
|
|
const nestedTemplateKeywords = new Set([
|
|
'deploy',
|
|
'remove',
|
|
'info',
|
|
'help',
|
|
'--help',
|
|
'dev',
|
|
'logs',
|
|
'invoke',
|
|
'credentials',
|
|
]);
|
|
if (!nestedTemplateKeywords.has(process.argv[2])) return 'serverless';
|
|
|
|
const path = require('path');
|
|
const detectSubServiceType = async (subDirname) => {
|
|
const subConfigurationExtension =
|
|
(
|
|
await Promise.all(
|
|
['yml', 'yaml', 'json', 'js'].map(async (extension) => {
|
|
try {
|
|
await fsp.access(path.resolve(subDirname, `serverless.${extension}`));
|
|
return extension;
|
|
} catch {
|
|
return null;
|
|
}
|
|
})
|
|
)
|
|
).find(Boolean) || null;
|
|
if (!subConfigurationExtension) return null;
|
|
switch (subConfigurationExtension) {
|
|
case 'yml':
|
|
case 'yaml': {
|
|
const content = await fsp.readFile(
|
|
path.resolve(subDirname, `serverless.${subConfigurationExtension}`),
|
|
'utf8'
|
|
);
|
|
if (content.search(/(?:^|\n)component\s*:/) !== -1) return '@serverless/components';
|
|
return 'other';
|
|
}
|
|
case 'json': {
|
|
const configuration = (() => {
|
|
try {
|
|
return require(`${path.resolve(subDirname)}/serverless.json`);
|
|
} catch {
|
|
return null;
|
|
}
|
|
})();
|
|
return configuration && configuration.component ? '@serverless/components' : 'other';
|
|
}
|
|
case 'js': {
|
|
const configuration = (() => {
|
|
try {
|
|
return require(`${path.resolve(subDirname)}/serverless.js`);
|
|
} catch {
|
|
return null;
|
|
}
|
|
})();
|
|
return configuration && configuration.component ? '@serverless/components' : 'other';
|
|
}
|
|
default:
|
|
throw new Error(`Unrecognized extension "${subConfigurationExtension}"`);
|
|
}
|
|
};
|
|
let hasComponent = false;
|
|
for (const subDirname of await fsp.readdir('.')) {
|
|
const stats = await fsp.lstat(subDirname);
|
|
if (!stats.isDirectory()) continue;
|
|
const subServiceType = await detectSubServiceType(subDirname);
|
|
if (!subServiceType) continue;
|
|
if (subServiceType === '@serverless/components') hasComponent = true;
|
|
else return 'serverless';
|
|
}
|
|
return hasComponent ? resolvePlatformCli() : 'serverless';
|
|
};
|