@strapi/strapi 5.55.1 → 5.57.0
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/admin-styles.css +5 -0
- package/dist/cli/commands/build.d.ts.map +1 -1
- package/dist/cli/commands/content-types/rename-field.d.ts +13 -0
- package/dist/cli/commands/content-types/rename-field.d.ts.map +1 -0
- package/dist/cli/commands/develop.d.ts.map +1 -1
- package/dist/cli/commands/enterprise/index.d.ts +7 -0
- package/dist/cli/commands/enterprise/index.d.ts.map +1 -0
- package/dist/cli/commands/enterprise/install/action.d.ts +36 -0
- package/dist/cli/commands/enterprise/install/action.d.ts.map +1 -0
- package/dist/cli/commands/enterprise/install/checklist-prompt.d.ts +14 -0
- package/dist/cli/commands/enterprise/install/checklist-prompt.d.ts.map +1 -0
- package/dist/cli/commands/enterprise/install/constants.d.ts +7 -0
- package/dist/cli/commands/enterprise/install/constants.d.ts.map +1 -0
- package/dist/cli/commands/enterprise/install/directories.d.ts +3 -0
- package/dist/cli/commands/enterprise/install/directories.d.ts.map +1 -0
- package/dist/cli/commands/enterprise/install/discovery.d.ts +29 -0
- package/dist/cli/commands/enterprise/install/discovery.d.ts.map +1 -0
- package/dist/cli/commands/enterprise/install/errors.d.ts +11 -0
- package/dist/cli/commands/enterprise/install/errors.d.ts.map +1 -0
- package/dist/cli/commands/enterprise/install/install-packages.d.ts +11 -0
- package/dist/cli/commands/enterprise/install/install-packages.d.ts.map +1 -0
- package/dist/cli/commands/enterprise/install/license.d.ts +27 -0
- package/dist/cli/commands/enterprise/install/license.d.ts.map +1 -0
- package/dist/cli/commands/enterprise/install/package-manager.d.ts +17 -0
- package/dist/cli/commands/enterprise/install/package-manager.d.ts.map +1 -0
- package/dist/cli/commands/enterprise/install/plugin-status.d.ts +44 -0
- package/dist/cli/commands/enterprise/install/plugin-status.d.ts.map +1 -0
- package/dist/cli/commands/enterprise/install/registry-access.d.ts +55 -0
- package/dist/cli/commands/enterprise/install/registry-access.d.ts.map +1 -0
- package/dist/cli/commands/enterprise/install/registry.d.ts +54 -0
- package/dist/cli/commands/enterprise/install/registry.d.ts.map +1 -0
- package/dist/cli/commands/enterprise/install/selection.d.ts +62 -0
- package/dist/cli/commands/enterprise/install/selection.d.ts.map +1 -0
- package/dist/cli/commands/enterprise/install/setup-links.d.ts +16 -0
- package/dist/cli/commands/enterprise/install/setup-links.d.ts.map +1 -0
- package/dist/cli/commands/enterprise/install/versions.d.ts +42 -0
- package/dist/cli/commands/enterprise/install/versions.d.ts.map +1 -0
- package/dist/cli/commands/index.d.ts.map +1 -1
- package/dist/cli/utils/commander.d.ts.map +1 -1
- package/dist/cli/utils/helpers.d.ts +1 -1
- package/dist/cli/utils/helpers.d.ts.map +1 -1
- package/dist/node/core/admin-vite-aliases.d.ts +9 -0
- package/dist/node/core/admin-vite-aliases.d.ts.map +1 -1
- package/dist/node/core/aliases.d.ts +4 -1
- package/dist/node/core/aliases.d.ts.map +1 -1
- package/dist/node/core/scan-roots.d.ts +20 -0
- package/dist/node/core/scan-roots.d.ts.map +1 -0
- package/dist/node/create-build-context.d.ts +10 -1
- package/dist/node/create-build-context.d.ts.map +1 -1
- package/dist/node/develop.d.ts.map +1 -1
- package/dist/node/staticFiles.d.ts +3 -1
- package/dist/node/staticFiles.d.ts.map +1 -1
- package/dist/node/vite/config.d.ts.map +1 -1
- package/dist/node/vite/plugins.d.ts +2 -1
- package/dist/node/vite/plugins.d.ts.map +1 -1
- package/dist/node/vite/plugins.test.d.ts +2 -0
- package/dist/node/vite/plugins.test.d.ts.map +1 -0
- package/dist/package.json.js +1 -1
- package/dist/package.json.mjs +1 -1
- package/dist/src/cli/commands/build.js +4 -2
- package/dist/src/cli/commands/build.js.map +1 -1
- package/dist/src/cli/commands/build.mjs +4 -2
- package/dist/src/cli/commands/build.mjs.map +1 -1
- package/dist/src/cli/commands/content-types/rename-field.js +63 -0
- package/dist/src/cli/commands/content-types/rename-field.js.map +1 -0
- package/dist/src/cli/commands/content-types/rename-field.mjs +54 -0
- package/dist/src/cli/commands/content-types/rename-field.mjs.map +1 -0
- package/dist/src/cli/commands/develop.js +4 -2
- package/dist/src/cli/commands/develop.js.map +1 -1
- package/dist/src/cli/commands/develop.mjs +4 -2
- package/dist/src/cli/commands/develop.mjs.map +1 -1
- package/dist/src/cli/commands/enterprise/index.js +17 -0
- package/dist/src/cli/commands/enterprise/index.js.map +1 -0
- package/dist/src/cli/commands/enterprise/index.mjs +15 -0
- package/dist/src/cli/commands/enterprise/index.mjs.map +1 -0
- package/dist/src/cli/commands/enterprise/install/action.js +253 -0
- package/dist/src/cli/commands/enterprise/install/action.js.map +1 -0
- package/dist/src/cli/commands/enterprise/install/action.mjs +244 -0
- package/dist/src/cli/commands/enterprise/install/action.mjs.map +1 -0
- package/dist/src/cli/commands/enterprise/install/checklist-prompt.js +117 -0
- package/dist/src/cli/commands/enterprise/install/checklist-prompt.js.map +1 -0
- package/dist/src/cli/commands/enterprise/install/checklist-prompt.mjs +110 -0
- package/dist/src/cli/commands/enterprise/install/checklist-prompt.mjs.map +1 -0
- package/dist/src/cli/commands/enterprise/install/constants.js +16 -0
- package/dist/src/cli/commands/enterprise/install/constants.js.map +1 -0
- package/dist/src/cli/commands/enterprise/install/constants.mjs +9 -0
- package/dist/src/cli/commands/enterprise/install/constants.mjs.map +1 -0
- package/dist/src/cli/commands/enterprise/install/directories.js +23 -0
- package/dist/src/cli/commands/enterprise/install/directories.js.map +1 -0
- package/dist/src/cli/commands/enterprise/install/directories.mjs +17 -0
- package/dist/src/cli/commands/enterprise/install/directories.mjs.map +1 -0
- package/dist/src/cli/commands/enterprise/install/discovery.js +109 -0
- package/dist/src/cli/commands/enterprise/install/discovery.js.map +1 -0
- package/dist/src/cli/commands/enterprise/install/discovery.mjs +104 -0
- package/dist/src/cli/commands/enterprise/install/discovery.mjs.map +1 -0
- package/dist/src/cli/commands/enterprise/install/errors.js +26 -0
- package/dist/src/cli/commands/enterprise/install/errors.js.map +1 -0
- package/dist/src/cli/commands/enterprise/install/errors.mjs +22 -0
- package/dist/src/cli/commands/enterprise/install/errors.mjs.map +1 -0
- package/dist/src/cli/commands/enterprise/install/install-packages.js +39 -0
- package/dist/src/cli/commands/enterprise/install/install-packages.js.map +1 -0
- package/dist/src/cli/commands/enterprise/install/install-packages.mjs +32 -0
- package/dist/src/cli/commands/enterprise/install/install-packages.mjs.map +1 -0
- package/dist/src/cli/commands/enterprise/install/license.js +144 -0
- package/dist/src/cli/commands/enterprise/install/license.js.map +1 -0
- package/dist/src/cli/commands/enterprise/install/license.mjs +132 -0
- package/dist/src/cli/commands/enterprise/install/license.mjs.map +1 -0
- package/dist/src/cli/commands/enterprise/install/package-manager.js +72 -0
- package/dist/src/cli/commands/enterprise/install/package-manager.js.map +1 -0
- package/dist/src/cli/commands/enterprise/install/package-manager.mjs +62 -0
- package/dist/src/cli/commands/enterprise/install/package-manager.mjs.map +1 -0
- package/dist/src/cli/commands/enterprise/install/plugin-status.js +47 -0
- package/dist/src/cli/commands/enterprise/install/plugin-status.js.map +1 -0
- package/dist/src/cli/commands/enterprise/install/plugin-status.mjs +45 -0
- package/dist/src/cli/commands/enterprise/install/plugin-status.mjs.map +1 -0
- package/dist/src/cli/commands/enterprise/install/registry-access.js +293 -0
- package/dist/src/cli/commands/enterprise/install/registry-access.js.map +1 -0
- package/dist/src/cli/commands/enterprise/install/registry-access.mjs +277 -0
- package/dist/src/cli/commands/enterprise/install/registry-access.mjs.map +1 -0
- package/dist/src/cli/commands/enterprise/install/registry.js +98 -0
- package/dist/src/cli/commands/enterprise/install/registry.js.map +1 -0
- package/dist/src/cli/commands/enterprise/install/registry.mjs +95 -0
- package/dist/src/cli/commands/enterprise/install/registry.mjs.map +1 -0
- package/dist/src/cli/commands/enterprise/install/selection.js +148 -0
- package/dist/src/cli/commands/enterprise/install/selection.js.map +1 -0
- package/dist/src/cli/commands/enterprise/install/selection.mjs +141 -0
- package/dist/src/cli/commands/enterprise/install/selection.mjs.map +1 -0
- package/dist/src/cli/commands/enterprise/install/setup-links.js +34 -0
- package/dist/src/cli/commands/enterprise/install/setup-links.js.map +1 -0
- package/dist/src/cli/commands/enterprise/install/setup-links.mjs +31 -0
- package/dist/src/cli/commands/enterprise/install/setup-links.mjs.map +1 -0
- package/dist/src/cli/commands/enterprise/install/versions.js +127 -0
- package/dist/src/cli/commands/enterprise/install/versions.js.map +1 -0
- package/dist/src/cli/commands/enterprise/install/versions.mjs +107 -0
- package/dist/src/cli/commands/enterprise/install/versions.mjs.map +1 -0
- package/dist/src/cli/commands/export/action.js +4 -4
- package/dist/src/cli/commands/export/action.js.map +1 -1
- package/dist/src/cli/commands/export/action.mjs +2 -2
- package/dist/src/cli/commands/export/action.mjs.map +1 -1
- package/dist/src/cli/commands/import/action.js +2 -2
- package/dist/src/cli/commands/import/action.js.map +1 -1
- package/dist/src/cli/commands/import/action.mjs +1 -1
- package/dist/src/cli/commands/import/action.mjs.map +1 -1
- package/dist/src/cli/commands/index.js +4 -0
- package/dist/src/cli/commands/index.js.map +1 -1
- package/dist/src/cli/commands/index.mjs +24 -20
- package/dist/src/cli/commands/index.mjs.map +1 -1
- package/dist/src/cli/commands/routes/list.js +2 -2
- package/dist/src/cli/commands/routes/list.js.map +1 -1
- package/dist/src/cli/commands/routes/list.mjs +1 -1
- package/dist/src/cli/commands/routes/list.mjs.map +1 -1
- package/dist/src/cli/commands/transfer/action.js +2 -2
- package/dist/src/cli/commands/transfer/action.js.map +1 -1
- package/dist/src/cli/commands/transfer/action.mjs +1 -1
- package/dist/src/cli/commands/transfer/action.mjs.map +1 -1
- package/dist/src/cli/utils/commander.js +1 -2
- package/dist/src/cli/utils/commander.js.map +1 -1
- package/dist/src/cli/utils/commander.mjs +1 -2
- package/dist/src/cli/utils/commander.mjs.map +1 -1
- package/dist/src/cli/utils/data-transfer.js +2 -2
- package/dist/src/cli/utils/data-transfer.js.map +1 -1
- package/dist/src/cli/utils/data-transfer.mjs +2 -2
- package/dist/src/cli/utils/data-transfer.mjs.map +1 -1
- package/dist/src/cli/utils/helpers.js +6 -6
- package/dist/src/cli/utils/helpers.js.map +1 -1
- package/dist/src/cli/utils/helpers.mjs +4 -4
- package/dist/src/cli/utils/helpers.mjs.map +1 -1
- package/dist/src/node/core/admin-vite-aliases.js +51 -0
- package/dist/src/node/core/admin-vite-aliases.js.map +1 -1
- package/dist/src/node/core/admin-vite-aliases.mjs +46 -1
- package/dist/src/node/core/admin-vite-aliases.mjs.map +1 -1
- package/dist/src/node/core/aliases.js +6 -0
- package/dist/src/node/core/aliases.js.map +1 -1
- package/dist/src/node/core/aliases.mjs +6 -1
- package/dist/src/node/core/aliases.mjs.map +1 -1
- package/dist/src/node/core/scan-roots.js +87 -0
- package/dist/src/node/core/scan-roots.js.map +1 -0
- package/dist/src/node/core/scan-roots.mjs +79 -0
- package/dist/src/node/core/scan-roots.mjs.map +1 -0
- package/dist/src/node/create-build-context.js +40 -1
- package/dist/src/node/create-build-context.js.map +1 -1
- package/dist/src/node/create-build-context.mjs +40 -1
- package/dist/src/node/create-build-context.mjs.map +1 -1
- package/dist/src/node/develop.js +2 -1
- package/dist/src/node/develop.js.map +1 -1
- package/dist/src/node/develop.mjs +2 -1
- package/dist/src/node/develop.mjs.map +1 -1
- package/dist/src/node/staticFiles.js +43 -0
- package/dist/src/node/staticFiles.js.map +1 -1
- package/dist/src/node/staticFiles.mjs +42 -1
- package/dist/src/node/staticFiles.mjs.map +1 -1
- package/dist/src/node/vite/config.js +12 -2
- package/dist/src/node/vite/config.js.map +1 -1
- package/dist/src/node/vite/config.mjs +8 -2
- package/dist/src/node/vite/config.mjs.map +1 -1
- package/dist/src/node/vite/plugins.js +27 -1
- package/dist/src/node/vite/plugins.js.map +1 -1
- package/dist/src/node/vite/plugins.mjs +23 -1
- package/dist/src/node/vite/plugins.mjs.map +1 -1
- package/package.json +31 -26
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import fse from 'fs-extra';
|
|
3
|
+
import { ENTERPRISE_SCOPE, ENTERPRISE_REGISTRY_URL } from './constants.mjs';
|
|
4
|
+
import { EnterpriseInstallError } from './errors.mjs';
|
|
5
|
+
import { listAncestorDirectories } from './directories.mjs';
|
|
6
|
+
import { readsYarnrcYml } from './package-manager.mjs';
|
|
7
|
+
|
|
8
|
+
const SCOPE_REGISTRY_KEY = `${ENTERPRISE_SCOPE}:registry`;
|
|
9
|
+
const YARNRC_SCOPE_NAME = ENTERPRISE_SCOPE.slice(1);
|
|
10
|
+
const LICENSE_PLACEHOLDER = '<your license>';
|
|
11
|
+
// References the package manager expands when it reads the file, so the license stays off disk.
|
|
12
|
+
// Yarn 2+ fails every command on the machine when a referenced variable is unset, unless it has a
|
|
13
|
+
// default. `.npmrc` has no form that works everywhere: an unset variable breaks every Yarn 1
|
|
14
|
+
// command and makes pnpm warn on each one, and npm, pnpm and Yarn 1 share `~/.npmrc`.
|
|
15
|
+
/* eslint-disable no-template-curly-in-string */ const NPMRC_LICENSE_REFERENCE = '${STRAPI_LICENSE}';
|
|
16
|
+
const YARNRC_LICENSE_REFERENCE = '${STRAPI_LICENSE:-}';
|
|
17
|
+
/* eslint-enable no-template-curly-in-string */ const shouldReferenceLicense = (licenseSource, env)=>licenseSource === 'environment' && Boolean(env.CI) && env.CI !== 'false';
|
|
18
|
+
const describeRegistry = (registryUrl)=>{
|
|
19
|
+
const url = new URL(`${registryUrl.replace(/\/+$/, '')}/`);
|
|
20
|
+
return {
|
|
21
|
+
url: url.href,
|
|
22
|
+
host: url.host,
|
|
23
|
+
tokenKey: `//${url.host}${url.pathname}:_authToken`
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
const buildNpmrcConfiguration = (token, registry)=>[
|
|
27
|
+
`${SCOPE_REGISTRY_KEY}=${registry.url}`,
|
|
28
|
+
`${registry.tokenKey}=${token}`
|
|
29
|
+
].join('\n');
|
|
30
|
+
const buildYarnrcScopeConfiguration = (token, registry)=>[
|
|
31
|
+
` ${YARNRC_SCOPE_NAME}:`,
|
|
32
|
+
` npmRegistryServer: '${registry.url}'`,
|
|
33
|
+
' npmAlwaysAuth: true',
|
|
34
|
+
` npmAuthToken: '${token}'`
|
|
35
|
+
].join('\n');
|
|
36
|
+
const buildYarnrcConfiguration = (token, registry)=>[
|
|
37
|
+
'npmScopes:',
|
|
38
|
+
buildYarnrcScopeConfiguration(token, registry)
|
|
39
|
+
].join('\n');
|
|
40
|
+
const getUserNpmrcPath = (env, homeDir)=>env.NPM_CONFIG_USERCONFIG ?? env.npm_config_userconfig ?? path.join(homeDir, '.npmrc');
|
|
41
|
+
const getUserYarnrcPath = (homeDir)=>path.join(homeDir, '.yarnrc.yml');
|
|
42
|
+
const readFileIfExists = async (filePath)=>await fse.pathExists(filePath) ? fse.readFile(filePath, 'utf8') : '';
|
|
43
|
+
const appendToFile = async (filePath, text)=>{
|
|
44
|
+
const existingContent = await readFileIfExists(filePath);
|
|
45
|
+
const separator = existingContent.length > 0 && !existingContent.endsWith('\n') ? '\n' : '';
|
|
46
|
+
await fse.ensureDir(path.dirname(filePath));
|
|
47
|
+
await fse.appendFile(filePath, `${separator}${text}\n`);
|
|
48
|
+
// The file may now hold the license. A mode passed when writing only applies to a new file, so
|
|
49
|
+
// an existing one is restricted to its owner explicitly, as npm does when it saves this file.
|
|
50
|
+
await fse.chmod(filePath, 0o600);
|
|
51
|
+
};
|
|
52
|
+
const unquote = (value)=>value.replace(/^(['"])(.*)\1$/, '$2');
|
|
53
|
+
const parseNpmrc = (content)=>new Map(content.split(/\r?\n/).map((line)=>line.trim()).filter((line)=>line.length > 0 && !line.startsWith('#') && !line.startsWith(';')).map((line)=>{
|
|
54
|
+
const separatorIndex = line.indexOf('=');
|
|
55
|
+
return separatorIndex === -1 ? [
|
|
56
|
+
line,
|
|
57
|
+
''
|
|
58
|
+
] : [
|
|
59
|
+
line.slice(0, separatorIndex).trim(),
|
|
60
|
+
unquote(line.slice(separatorIndex + 1).trim())
|
|
61
|
+
];
|
|
62
|
+
}));
|
|
63
|
+
const withoutTrailingSlash = (url)=>url?.replace(/\/+$/, '');
|
|
64
|
+
const isEnvironmentVariableReference = (value)=>value?.startsWith('${') ?? false;
|
|
65
|
+
const inspectNpmrc = async (filePath, license, registry, writtenToken)=>{
|
|
66
|
+
const content = await readFileIfExists(filePath);
|
|
67
|
+
const entries = parseNpmrc(content);
|
|
68
|
+
const scopeRegistry = entries.get(SCOPE_REGISTRY_KEY);
|
|
69
|
+
const registryToken = entries.get(registry.tokenKey);
|
|
70
|
+
const outcome = (status)=>({
|
|
71
|
+
status,
|
|
72
|
+
filePath,
|
|
73
|
+
expectedConfiguration: buildNpmrcConfiguration(LICENSE_PLACEHOLDER, registry)
|
|
74
|
+
});
|
|
75
|
+
if (scopeRegistry === undefined && registryToken === undefined) {
|
|
76
|
+
return {
|
|
77
|
+
status: 'not-configured',
|
|
78
|
+
filePath,
|
|
79
|
+
expectedConfiguration: buildNpmrcConfiguration(LICENSE_PLACEHOLDER, registry),
|
|
80
|
+
linesToAdd: buildNpmrcConfiguration(writtenToken, registry)
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
const isScopeRegistryCorrect = withoutTrailingSlash(scopeRegistry) === withoutTrailingSlash(registry.url);
|
|
84
|
+
if (isEnvironmentVariableReference(registryToken)) {
|
|
85
|
+
return outcome(isScopeRegistryCorrect ? 'uses-environment-variable' : 'manual-edit-needed');
|
|
86
|
+
}
|
|
87
|
+
if (registryToken === license && isScopeRegistryCorrect) {
|
|
88
|
+
return outcome('already-configured');
|
|
89
|
+
}
|
|
90
|
+
if (registryToken !== undefined && registryToken !== license) {
|
|
91
|
+
return outcome('different-license');
|
|
92
|
+
}
|
|
93
|
+
return outcome('manual-edit-needed');
|
|
94
|
+
};
|
|
95
|
+
const indentationOf = (line)=>line.search(/\S/);
|
|
96
|
+
const isYarnrcContentLine = (line)=>line.trim() !== '' && !line.trim().startsWith('#');
|
|
97
|
+
const readYarnrcKey = (line)=>/^\s*(["']?)([^"':]+(?::\/\/[^"']+)?)\1\s*:/.exec(line)?.[2];
|
|
98
|
+
const readYarnrcEntry = (content, topLevelKey, isWantedEntry)=>{
|
|
99
|
+
const lines = content.split(/\r?\n/);
|
|
100
|
+
const topLevelIndex = lines.findIndex((line)=>new RegExp(`^${topLevelKey}\\s*:\\s*(#.*)?$`).test(line));
|
|
101
|
+
if (topLevelIndex === -1) {
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
let entryIndentation;
|
|
105
|
+
let settings;
|
|
106
|
+
for (const line of lines.slice(topLevelIndex + 1).filter(isYarnrcContentLine)){
|
|
107
|
+
const indentation = indentationOf(line);
|
|
108
|
+
if (indentation === 0) {
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
entryIndentation ?? (entryIndentation = indentation);
|
|
112
|
+
if (indentation <= entryIndentation) {
|
|
113
|
+
if (settings) {
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
const entryKey = readYarnrcKey(line);
|
|
117
|
+
settings = entryKey !== undefined && isWantedEntry(entryKey) ? new Map() : undefined;
|
|
118
|
+
} else if (settings) {
|
|
119
|
+
const settingMatch = /^\s*([A-Za-z]+)\s*:\s*(.*)$/.exec(line);
|
|
120
|
+
if (settingMatch) {
|
|
121
|
+
settings.set(settingMatch[1], unquote(settingMatch[2].trim()));
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return settings;
|
|
126
|
+
};
|
|
127
|
+
const readYarnrcScope = (content)=>readYarnrcEntry(content, 'npmScopes', (entryKey)=>entryKey === YARNRC_SCOPE_NAME);
|
|
128
|
+
const readYarnrcToken = (content, registry)=>{
|
|
129
|
+
const normalize = (url)=>withoutTrailingSlash(url.replace(/^https?:/, ''));
|
|
130
|
+
const registryEntry = readYarnrcEntry(content, 'npmRegistries', (entryKey)=>normalize(entryKey) === normalize(registry.url));
|
|
131
|
+
return readYarnrcScope(content)?.get('npmAuthToken') ?? registryEntry?.get('npmAuthToken');
|
|
132
|
+
};
|
|
133
|
+
const inspectYarnrc = async (filePath, license, registry, writtenToken)=>{
|
|
134
|
+
const content = await readFileIfExists(filePath);
|
|
135
|
+
const scope = readYarnrcScope(content);
|
|
136
|
+
const outcome = (status)=>({
|
|
137
|
+
status,
|
|
138
|
+
filePath,
|
|
139
|
+
expectedConfiguration: buildYarnrcScopeConfiguration(LICENSE_PLACEHOLDER, registry),
|
|
140
|
+
yarnrcScope: scope === undefined ? 'missing' : 'present'
|
|
141
|
+
});
|
|
142
|
+
if (!/^npmScopes\s*:/m.test(content)) {
|
|
143
|
+
return {
|
|
144
|
+
status: 'not-configured',
|
|
145
|
+
filePath,
|
|
146
|
+
expectedConfiguration: buildYarnrcConfiguration(LICENSE_PLACEHOLDER, registry),
|
|
147
|
+
linesToAdd: buildYarnrcConfiguration(writtenToken, registry)
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
if (scope === undefined) {
|
|
151
|
+
return outcome('manual-edit-needed');
|
|
152
|
+
}
|
|
153
|
+
const token = readYarnrcToken(content, registry);
|
|
154
|
+
const isScopeRegistryCorrect = withoutTrailingSlash(scope.get('npmRegistryServer')) === withoutTrailingSlash(registry.url);
|
|
155
|
+
if (isEnvironmentVariableReference(token)) {
|
|
156
|
+
// A reference only works once the scope points to the registry.
|
|
157
|
+
return outcome(isScopeRegistryCorrect ? 'uses-environment-variable' : 'manual-edit-needed');
|
|
158
|
+
}
|
|
159
|
+
if (token !== undefined && token !== license) {
|
|
160
|
+
return outcome('different-license');
|
|
161
|
+
}
|
|
162
|
+
// The license may be set for another registry, such as a local one used for testing.
|
|
163
|
+
return outcome(token === license && isScopeRegistryCorrect ? 'already-configured' : 'manual-edit-needed');
|
|
164
|
+
};
|
|
165
|
+
const describeManualEdit = (yarnrcScope)=>{
|
|
166
|
+
if (yarnrcScope === 'present') {
|
|
167
|
+
return `Replace its ${YARNRC_SCOPE_NAME} scope with this`;
|
|
168
|
+
}
|
|
169
|
+
return yarnrcScope === 'missing' ? 'Add this under its existing npmScopes key' : 'Add this to it';
|
|
170
|
+
};
|
|
171
|
+
const assertRegistryAccessUsable = ({ outcome: { status, filePath, expectedConfiguration, yarnrcScope }, overridingFiles, registryHost, userConfigPath })=>{
|
|
172
|
+
if (status === 'different-license') {
|
|
173
|
+
const replacedLines = yarnrcScope ? `its ${YARNRC_SCOPE_NAME} scope` : 'those lines';
|
|
174
|
+
throw new EnterpriseInstallError(`${filePath} already sets up ${registryHost} with another license, so installing would fail. Replace ${replacedLines} with:\n\n${expectedConfiguration}\n`);
|
|
175
|
+
}
|
|
176
|
+
if (status === 'manual-edit-needed') {
|
|
177
|
+
throw new EnterpriseInstallError(`${filePath} could not be updated automatically. ${describeManualEdit(yarnrcScope)}, then run the command again:\n\n${expectedConfiguration}\n`);
|
|
178
|
+
}
|
|
179
|
+
if (overridingFiles.length > 0) {
|
|
180
|
+
throw new EnterpriseInstallError([
|
|
181
|
+
...overridingFiles.map((filePath)=>`${filePath} sets another license for ${registryHost} and takes precedence over ${userConfigPath}.`),
|
|
182
|
+
'Update or remove that line, then run the command again.'
|
|
183
|
+
].join('\n'));
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
const isWorkspaceRoot = async (directory)=>{
|
|
187
|
+
if (await fse.pathExists(path.join(directory, 'pnpm-workspace.yaml'))) {
|
|
188
|
+
return true;
|
|
189
|
+
}
|
|
190
|
+
try {
|
|
191
|
+
const packageJson = await fse.readJson(path.join(directory, 'package.json'));
|
|
192
|
+
return packageJson?.workspaces !== undefined;
|
|
193
|
+
} catch {
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
const listProjectConfigDirectories = async (appDir, packageManager)=>{
|
|
198
|
+
const [appDirectory, ...parentDirectories] = listAncestorDirectories(appDir);
|
|
199
|
+
if (packageManager.name === 'yarn') {
|
|
200
|
+
return [
|
|
201
|
+
appDirectory,
|
|
202
|
+
...parentDirectories
|
|
203
|
+
];
|
|
204
|
+
}
|
|
205
|
+
for (const directory of parentDirectories){
|
|
206
|
+
if (await isWorkspaceRoot(directory)) {
|
|
207
|
+
return [
|
|
208
|
+
directory
|
|
209
|
+
];
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
return [
|
|
213
|
+
appDirectory
|
|
214
|
+
];
|
|
215
|
+
};
|
|
216
|
+
const findOverridingConfigFiles = async ({ appDir, packageManager, userConfigPaths, license, registry })=>{
|
|
217
|
+
const usesYarnrcYml = readsYarnrcYml(packageManager);
|
|
218
|
+
const fileName = usesYarnrcYml ? '.yarnrc.yml' : '.npmrc';
|
|
219
|
+
const skippedPaths = new Set(userConfigPaths.map((filePath)=>path.resolve(filePath)));
|
|
220
|
+
const overridingFiles = [];
|
|
221
|
+
for (const directory of (await listProjectConfigDirectories(appDir, packageManager))){
|
|
222
|
+
const filePath = path.join(directory, fileName);
|
|
223
|
+
if (skippedPaths.has(filePath)) {
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
const content = await readFileIfExists(filePath);
|
|
227
|
+
const token = usesYarnrcYml ? readYarnrcToken(content, registry) : parseNpmrc(content).get(registry.tokenKey);
|
|
228
|
+
if (token !== undefined && token !== license && !isEnvironmentVariableReference(token)) {
|
|
229
|
+
overridingFiles.push(filePath);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
return overridingFiles;
|
|
233
|
+
};
|
|
234
|
+
const prepareRegistryAccess = async ({ appDir, packageManager, license, licenseSource, logger, env, homeDir })=>{
|
|
235
|
+
const registry = describeRegistry(ENTERPRISE_REGISTRY_URL);
|
|
236
|
+
const usesYarnrcYml = readsYarnrcYml(packageManager);
|
|
237
|
+
const userConfigPath = usesYarnrcYml ? getUserYarnrcPath(homeDir) : getUserNpmrcPath(env, homeDir);
|
|
238
|
+
const referencesLicense = shouldReferenceLicense(licenseSource, env);
|
|
239
|
+
const licenseReference = usesYarnrcYml ? YARNRC_LICENSE_REFERENCE : NPMRC_LICENSE_REFERENCE;
|
|
240
|
+
const writtenToken = referencesLicense ? licenseReference : license;
|
|
241
|
+
const outcome = usesYarnrcYml ? await inspectYarnrc(userConfigPath, license, registry, writtenToken) : await inspectNpmrc(userConfigPath, license, registry, writtenToken);
|
|
242
|
+
const overridingFiles = await findOverridingConfigFiles({
|
|
243
|
+
appDir,
|
|
244
|
+
packageManager,
|
|
245
|
+
userConfigPaths: [
|
|
246
|
+
userConfigPath,
|
|
247
|
+
path.join(homeDir, usesYarnrcYml ? '.yarnrc.yml' : '.npmrc')
|
|
248
|
+
],
|
|
249
|
+
license,
|
|
250
|
+
registry
|
|
251
|
+
});
|
|
252
|
+
assertRegistryAccessUsable({
|
|
253
|
+
outcome,
|
|
254
|
+
overridingFiles,
|
|
255
|
+
registryHost: registry.host,
|
|
256
|
+
userConfigPath
|
|
257
|
+
});
|
|
258
|
+
if (outcome.status === 'already-configured') {
|
|
259
|
+
logger.info(`Access to ${registry.host} is already configured in ${userConfigPath}.`);
|
|
260
|
+
}
|
|
261
|
+
if (outcome.status === 'uses-environment-variable') {
|
|
262
|
+
logger.info(`${userConfigPath} reads the ${registry.host} token from an environment variable. Make sure it holds your Strapi license.`);
|
|
263
|
+
}
|
|
264
|
+
return {
|
|
265
|
+
outcome,
|
|
266
|
+
async apply () {
|
|
267
|
+
if (outcome.status !== 'not-configured') {
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
await appendToFile(userConfigPath, outcome.linesToAdd);
|
|
271
|
+
logger.success(referencesLicense ? `Configured access to ${registry.host} in ${userConfigPath}, reading the license from STRAPI_LICENSE.` : `Configured access to ${registry.host} in ${userConfigPath}.`);
|
|
272
|
+
}
|
|
273
|
+
};
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
export { buildNpmrcConfiguration, buildYarnrcConfiguration, describeRegistry, findOverridingConfigFiles, getUserNpmrcPath, getUserYarnrcPath, inspectNpmrc, inspectYarnrc, listProjectConfigDirectories, prepareRegistryAccess };
|
|
277
|
+
//# sourceMappingURL=registry-access.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry-access.mjs","sources":["../../../../../../src/cli/commands/enterprise/install/registry-access.ts"],"sourcesContent":["import path from 'node:path';\nimport fse from 'fs-extra';\n\nimport type { Logger } from '../../../utils/logger';\nimport { ENTERPRISE_REGISTRY_URL, ENTERPRISE_SCOPE } from './constants';\nimport { EnterpriseInstallError } from './errors';\nimport { listAncestorDirectories } from './directories';\nimport type { ResolvedLicense } from './license';\nimport { readsYarnrcYml, type DetectedPackageManager } from './package-manager';\n\nconst SCOPE_REGISTRY_KEY = `${ENTERPRISE_SCOPE}:registry`;\nconst YARNRC_SCOPE_NAME = ENTERPRISE_SCOPE.slice(1);\nconst LICENSE_PLACEHOLDER = '<your license>';\n\n// References the package manager expands when it reads the file, so the license stays off disk.\n// Yarn 2+ fails every command on the machine when a referenced variable is unset, unless it has a\n// default. `.npmrc` has no form that works everywhere: an unset variable breaks every Yarn 1\n// command and makes pnpm warn on each one, and npm, pnpm and Yarn 1 share `~/.npmrc`.\n/* eslint-disable no-template-curly-in-string */\nconst NPMRC_LICENSE_REFERENCE = '${STRAPI_LICENSE}';\nconst YARNRC_LICENSE_REFERENCE = '${STRAPI_LICENSE:-}';\n/* eslint-enable no-template-curly-in-string */\n\nconst shouldReferenceLicense = (\n licenseSource: ResolvedLicense['source'],\n env: NodeJS.ProcessEnv\n): boolean => licenseSource === 'environment' && Boolean(env.CI) && env.CI !== 'false';\n\ntype ConfiguredStatus =\n | 'already-configured'\n | 'uses-environment-variable'\n | 'different-license'\n | 'manual-edit-needed';\n\nexport type RegistryAccessOutcome = {\n filePath: string;\n /** The configuration the file should contain, with a placeholder instead of the license. */\n expectedConfiguration: string;\n yarnrcScope?: 'missing' | 'present';\n} & (\n | { status: ConfiguredStatus }\n /** `linesToAdd` holds the license, or a reference to it. */\n | { status: 'not-configured'; linesToAdd: string }\n);\n\nexport interface ConfiguredRegistry {\n /** Always ends with a slash, as npm expects for a scope registry. */\n url: string;\n host: string;\n /** The npm key holding the token for this registry, such as `//packages.strapi.io/:_authToken`. */\n tokenKey: string;\n}\n\nexport const describeRegistry = (registryUrl: string): ConfiguredRegistry => {\n const url = new URL(`${registryUrl.replace(/\\/+$/, '')}/`);\n\n return { url: url.href, host: url.host, tokenKey: `//${url.host}${url.pathname}:_authToken` };\n};\n\nexport const buildNpmrcConfiguration = (token: string, registry: ConfiguredRegistry): string =>\n [`${SCOPE_REGISTRY_KEY}=${registry.url}`, `${registry.tokenKey}=${token}`].join('\\n');\n\nconst buildYarnrcScopeConfiguration = (token: string, registry: ConfiguredRegistry): string =>\n [\n ` ${YARNRC_SCOPE_NAME}:`,\n ` npmRegistryServer: '${registry.url}'`,\n ' npmAlwaysAuth: true',\n ` npmAuthToken: '${token}'`,\n ].join('\\n');\n\nexport const buildYarnrcConfiguration = (token: string, registry: ConfiguredRegistry): string =>\n ['npmScopes:', buildYarnrcScopeConfiguration(token, registry)].join('\\n');\n\nexport const getUserNpmrcPath = (env: NodeJS.ProcessEnv, homeDir: string): string =>\n env.NPM_CONFIG_USERCONFIG ?? env.npm_config_userconfig ?? path.join(homeDir, '.npmrc');\n\nexport const getUserYarnrcPath = (homeDir: string): string => path.join(homeDir, '.yarnrc.yml');\n\nconst readFileIfExists = async (filePath: string): Promise<string> =>\n (await fse.pathExists(filePath)) ? fse.readFile(filePath, 'utf8') : '';\n\nconst appendToFile = async (filePath: string, text: string) => {\n const existingContent = await readFileIfExists(filePath);\n const separator = existingContent.length > 0 && !existingContent.endsWith('\\n') ? '\\n' : '';\n\n await fse.ensureDir(path.dirname(filePath));\n await fse.appendFile(filePath, `${separator}${text}\\n`);\n // The file may now hold the license. A mode passed when writing only applies to a new file, so\n // an existing one is restricted to its owner explicitly, as npm does when it saves this file.\n await fse.chmod(filePath, 0o600);\n};\n\nconst unquote = (value: string): string => value.replace(/^(['\"])(.*)\\1$/, '$2');\n\nconst parseNpmrc = (content: string): Map<string, string> =>\n new Map(\n content\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .filter((line) => line.length > 0 && !line.startsWith('#') && !line.startsWith(';'))\n .map((line): [string, string] => {\n const separatorIndex = line.indexOf('=');\n\n return separatorIndex === -1\n ? [line, '']\n : [line.slice(0, separatorIndex).trim(), unquote(line.slice(separatorIndex + 1).trim())];\n })\n );\n\nconst withoutTrailingSlash = (url: string | undefined) => url?.replace(/\\/+$/, '');\n\nconst isEnvironmentVariableReference = (value: string | undefined): boolean =>\n value?.startsWith('${') ?? false;\n\nexport const inspectNpmrc = async (\n filePath: string,\n license: string,\n registry: ConfiguredRegistry,\n writtenToken: string\n): Promise<RegistryAccessOutcome> => {\n const content = await readFileIfExists(filePath);\n const entries = parseNpmrc(content);\n const scopeRegistry = entries.get(SCOPE_REGISTRY_KEY);\n const registryToken = entries.get(registry.tokenKey);\n const outcome = (status: ConfiguredStatus): RegistryAccessOutcome => ({\n status,\n filePath,\n expectedConfiguration: buildNpmrcConfiguration(LICENSE_PLACEHOLDER, registry),\n });\n\n if (scopeRegistry === undefined && registryToken === undefined) {\n return {\n status: 'not-configured',\n filePath,\n expectedConfiguration: buildNpmrcConfiguration(LICENSE_PLACEHOLDER, registry),\n linesToAdd: buildNpmrcConfiguration(writtenToken, registry),\n };\n }\n\n const isScopeRegistryCorrect =\n withoutTrailingSlash(scopeRegistry) === withoutTrailingSlash(registry.url);\n\n if (isEnvironmentVariableReference(registryToken)) {\n return outcome(isScopeRegistryCorrect ? 'uses-environment-variable' : 'manual-edit-needed');\n }\n\n if (registryToken === license && isScopeRegistryCorrect) {\n return outcome('already-configured');\n }\n\n if (registryToken !== undefined && registryToken !== license) {\n return outcome('different-license');\n }\n\n return outcome('manual-edit-needed');\n};\n\nconst indentationOf = (line: string) => line.search(/\\S/);\n\nconst isYarnrcContentLine = (line: string) => line.trim() !== '' && !line.trim().startsWith('#');\n\nconst readYarnrcKey = (line: string): string | undefined =>\n /^\\s*([\"']?)([^\"':]+(?::\\/\\/[^\"']+)?)\\1\\s*:/.exec(line)?.[2];\n\nconst readYarnrcEntry = (\n content: string,\n topLevelKey: string,\n isWantedEntry: (entryKey: string) => boolean\n): Map<string, string> | undefined => {\n const lines = content.split(/\\r?\\n/);\n const topLevelIndex = lines.findIndex((line) =>\n new RegExp(`^${topLevelKey}\\\\s*:\\\\s*(#.*)?$`).test(line)\n );\n\n if (topLevelIndex === -1) {\n return undefined;\n }\n\n let entryIndentation: number | undefined;\n let settings: Map<string, string> | undefined;\n\n for (const line of lines.slice(topLevelIndex + 1).filter(isYarnrcContentLine)) {\n const indentation = indentationOf(line);\n\n if (indentation === 0) {\n break;\n }\n\n entryIndentation ??= indentation;\n\n if (indentation <= entryIndentation) {\n if (settings) {\n break;\n }\n\n const entryKey = readYarnrcKey(line);\n settings = entryKey !== undefined && isWantedEntry(entryKey) ? new Map() : undefined;\n } else if (settings) {\n const settingMatch = /^\\s*([A-Za-z]+)\\s*:\\s*(.*)$/.exec(line);\n\n if (settingMatch) {\n settings.set(settingMatch[1], unquote(settingMatch[2].trim()));\n }\n }\n }\n\n return settings;\n};\n\nconst readYarnrcScope = (content: string) =>\n readYarnrcEntry(content, 'npmScopes', (entryKey) => entryKey === YARNRC_SCOPE_NAME);\n\nconst readYarnrcToken = (content: string, registry: ConfiguredRegistry): string | undefined => {\n const normalize = (url: string) => withoutTrailingSlash(url.replace(/^https?:/, ''));\n const registryEntry = readYarnrcEntry(\n content,\n 'npmRegistries',\n (entryKey) => normalize(entryKey) === normalize(registry.url)\n );\n\n return readYarnrcScope(content)?.get('npmAuthToken') ?? registryEntry?.get('npmAuthToken');\n};\n\nexport const inspectYarnrc = async (\n filePath: string,\n license: string,\n registry: ConfiguredRegistry,\n writtenToken: string\n): Promise<RegistryAccessOutcome> => {\n const content = await readFileIfExists(filePath);\n const scope = readYarnrcScope(content);\n const outcome = (status: ConfiguredStatus): RegistryAccessOutcome => ({\n status,\n filePath,\n expectedConfiguration: buildYarnrcScopeConfiguration(LICENSE_PLACEHOLDER, registry),\n yarnrcScope: scope === undefined ? 'missing' : 'present',\n });\n\n if (!/^npmScopes\\s*:/m.test(content)) {\n return {\n status: 'not-configured',\n filePath,\n expectedConfiguration: buildYarnrcConfiguration(LICENSE_PLACEHOLDER, registry),\n linesToAdd: buildYarnrcConfiguration(writtenToken, registry),\n };\n }\n\n if (scope === undefined) {\n return outcome('manual-edit-needed');\n }\n\n const token = readYarnrcToken(content, registry);\n const isScopeRegistryCorrect =\n withoutTrailingSlash(scope.get('npmRegistryServer')) === withoutTrailingSlash(registry.url);\n\n if (isEnvironmentVariableReference(token)) {\n // A reference only works once the scope points to the registry.\n return outcome(isScopeRegistryCorrect ? 'uses-environment-variable' : 'manual-edit-needed');\n }\n\n if (token !== undefined && token !== license) {\n return outcome('different-license');\n }\n\n // The license may be set for another registry, such as a local one used for testing.\n return outcome(\n token === license && isScopeRegistryCorrect ? 'already-configured' : 'manual-edit-needed'\n );\n};\n\nconst describeManualEdit = (yarnrcScope: RegistryAccessOutcome['yarnrcScope']): string => {\n if (yarnrcScope === 'present') {\n return `Replace its ${YARNRC_SCOPE_NAME} scope with this`;\n }\n\n return yarnrcScope === 'missing' ? 'Add this under its existing npmScopes key' : 'Add this to it';\n};\n\nconst assertRegistryAccessUsable = ({\n outcome: { status, filePath, expectedConfiguration, yarnrcScope },\n overridingFiles,\n registryHost,\n userConfigPath,\n}: {\n outcome: RegistryAccessOutcome;\n overridingFiles: string[];\n registryHost: string;\n userConfigPath: string;\n}): void => {\n if (status === 'different-license') {\n const replacedLines = yarnrcScope ? `its ${YARNRC_SCOPE_NAME} scope` : 'those lines';\n\n throw new EnterpriseInstallError(\n `${filePath} already sets up ${registryHost} with another license, so installing would fail. Replace ${replacedLines} with:\\n\\n${expectedConfiguration}\\n`\n );\n }\n\n if (status === 'manual-edit-needed') {\n throw new EnterpriseInstallError(\n `${filePath} could not be updated automatically. ${describeManualEdit(yarnrcScope)}, then run the command again:\\n\\n${expectedConfiguration}\\n`\n );\n }\n\n if (overridingFiles.length > 0) {\n throw new EnterpriseInstallError(\n [\n ...overridingFiles.map(\n (filePath) =>\n `${filePath} sets another license for ${registryHost} and takes precedence over ${userConfigPath}.`\n ),\n 'Update or remove that line, then run the command again.',\n ].join('\\n')\n );\n }\n};\n\nconst isWorkspaceRoot = async (directory: string): Promise<boolean> => {\n if (await fse.pathExists(path.join(directory, 'pnpm-workspace.yaml'))) {\n return true;\n }\n\n try {\n const packageJson = await fse.readJson(path.join(directory, 'package.json'));\n return packageJson?.workspaces !== undefined;\n } catch {\n return false;\n }\n};\n\nexport const listProjectConfigDirectories = async (\n appDir: string,\n packageManager: DetectedPackageManager\n): Promise<string[]> => {\n const [appDirectory, ...parentDirectories] = listAncestorDirectories(appDir);\n\n if (packageManager.name === 'yarn') {\n return [appDirectory, ...parentDirectories];\n }\n\n for (const directory of parentDirectories) {\n if (await isWorkspaceRoot(directory)) {\n return [directory];\n }\n }\n\n return [appDirectory];\n};\n\nexport const findOverridingConfigFiles = async ({\n appDir,\n packageManager,\n userConfigPaths,\n license,\n registry,\n}: {\n appDir: string;\n packageManager: DetectedPackageManager;\n userConfigPaths: string[];\n license: string;\n registry: ConfiguredRegistry;\n}): Promise<string[]> => {\n const usesYarnrcYml = readsYarnrcYml(packageManager);\n const fileName = usesYarnrcYml ? '.yarnrc.yml' : '.npmrc';\n const skippedPaths = new Set(userConfigPaths.map((filePath) => path.resolve(filePath)));\n const overridingFiles: string[] = [];\n\n for (const directory of await listProjectConfigDirectories(appDir, packageManager)) {\n const filePath = path.join(directory, fileName);\n\n if (skippedPaths.has(filePath)) {\n continue;\n }\n\n const content = await readFileIfExists(filePath);\n const token = usesYarnrcYml\n ? readYarnrcToken(content, registry)\n : parseNpmrc(content).get(registry.tokenKey);\n\n if (token !== undefined && token !== license && !isEnvironmentVariableReference(token)) {\n overridingFiles.push(filePath);\n }\n }\n\n return overridingFiles;\n};\n\nexport interface RegistryAccess {\n outcome: RegistryAccessOutcome;\n /** Adds the setup when it is missing. Called once the registry has accepted the license. */\n apply: () => Promise<void>;\n}\n\nexport const prepareRegistryAccess = async ({\n appDir,\n packageManager,\n license,\n licenseSource,\n logger,\n env,\n homeDir,\n}: {\n appDir: string;\n packageManager: DetectedPackageManager;\n license: string;\n licenseSource: ResolvedLicense['source'];\n logger: Logger;\n env: NodeJS.ProcessEnv;\n homeDir: string;\n}): Promise<RegistryAccess> => {\n const registry = describeRegistry(ENTERPRISE_REGISTRY_URL);\n const usesYarnrcYml = readsYarnrcYml(packageManager);\n const userConfigPath = usesYarnrcYml\n ? getUserYarnrcPath(homeDir)\n : getUserNpmrcPath(env, homeDir);\n const referencesLicense = shouldReferenceLicense(licenseSource, env);\n const licenseReference = usesYarnrcYml ? YARNRC_LICENSE_REFERENCE : NPMRC_LICENSE_REFERENCE;\n const writtenToken = referencesLicense ? licenseReference : license;\n const outcome = usesYarnrcYml\n ? await inspectYarnrc(userConfigPath, license, registry, writtenToken)\n : await inspectNpmrc(userConfigPath, license, registry, writtenToken);\n const overridingFiles = await findOverridingConfigFiles({\n appDir,\n packageManager,\n userConfigPaths: [userConfigPath, path.join(homeDir, usesYarnrcYml ? '.yarnrc.yml' : '.npmrc')],\n license,\n registry,\n });\n\n assertRegistryAccessUsable({\n outcome,\n overridingFiles,\n registryHost: registry.host,\n userConfigPath,\n });\n\n if (outcome.status === 'already-configured') {\n logger.info(`Access to ${registry.host} is already configured in ${userConfigPath}.`);\n }\n\n if (outcome.status === 'uses-environment-variable') {\n logger.info(\n `${userConfigPath} reads the ${registry.host} token from an environment variable. Make sure it holds your Strapi license.`\n );\n }\n\n return {\n outcome,\n async apply() {\n if (outcome.status !== 'not-configured') {\n return;\n }\n\n await appendToFile(userConfigPath, outcome.linesToAdd);\n logger.success(\n referencesLicense\n ? `Configured access to ${registry.host} in ${userConfigPath}, reading the license from STRAPI_LICENSE.`\n : `Configured access to ${registry.host} in ${userConfigPath}.`\n );\n },\n };\n};\n"],"names":["SCOPE_REGISTRY_KEY","ENTERPRISE_SCOPE","YARNRC_SCOPE_NAME","slice","LICENSE_PLACEHOLDER","NPMRC_LICENSE_REFERENCE","YARNRC_LICENSE_REFERENCE","shouldReferenceLicense","licenseSource","env","Boolean","CI","describeRegistry","registryUrl","url","URL","replace","href","host","tokenKey","pathname","buildNpmrcConfiguration","token","registry","join","buildYarnrcScopeConfiguration","buildYarnrcConfiguration","getUserNpmrcPath","homeDir","NPM_CONFIG_USERCONFIG","npm_config_userconfig","path","getUserYarnrcPath","readFileIfExists","filePath","fse","pathExists","readFile","appendToFile","text","existingContent","separator","length","endsWith","ensureDir","dirname","appendFile","chmod","unquote","value","parseNpmrc","content","Map","split","map","line","trim","filter","startsWith","separatorIndex","indexOf","withoutTrailingSlash","isEnvironmentVariableReference","inspectNpmrc","license","writtenToken","entries","scopeRegistry","get","registryToken","outcome","status","expectedConfiguration","undefined","linesToAdd","isScopeRegistryCorrect","indentationOf","search","isYarnrcContentLine","readYarnrcKey","exec","readYarnrcEntry","topLevelKey","isWantedEntry","lines","topLevelIndex","findIndex","RegExp","test","entryIndentation","settings","indentation","entryKey","settingMatch","set","readYarnrcScope","readYarnrcToken","normalize","registryEntry","inspectYarnrc","scope","yarnrcScope","describeManualEdit","assertRegistryAccessUsable","overridingFiles","registryHost","userConfigPath","replacedLines","EnterpriseInstallError","isWorkspaceRoot","directory","packageJson","readJson","workspaces","listProjectConfigDirectories","appDir","packageManager","appDirectory","parentDirectories","listAncestorDirectories","name","findOverridingConfigFiles","userConfigPaths","usesYarnrcYml","readsYarnrcYml","fileName","skippedPaths","Set","resolve","has","push","prepareRegistryAccess","logger","ENTERPRISE_REGISTRY_URL","referencesLicense","licenseReference","info","apply","success"],"mappings":"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"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var constants = require('./constants.js');
|
|
4
|
+
|
|
5
|
+
const REQUEST_TIMEOUT_MS = 15 * 1000;
|
|
6
|
+
const SEARCH_PAGE_SIZE = 250;
|
|
7
|
+
const REGISTRY_URL = constants.ENTERPRISE_REGISTRY_URL.replace(/\/+$/, '');
|
|
8
|
+
const authorizationHeader = (license)=>({
|
|
9
|
+
Authorization: `Bearer ${license}`
|
|
10
|
+
});
|
|
11
|
+
const describeRejectedLicense = (registryUrl)=>`${registryUrl} rejected this Strapi license. Check it at ${constants.BILLING_URL}`;
|
|
12
|
+
const searchPackageNames = async ({ text, license, fetchImplementation })=>{
|
|
13
|
+
const registryUrl = REGISTRY_URL;
|
|
14
|
+
const searchUrl = `${registryUrl}/-/v1/search?text=${encodeURIComponent(text)}&size=${SEARCH_PAGE_SIZE}`;
|
|
15
|
+
try {
|
|
16
|
+
const response = await fetchImplementation(searchUrl, {
|
|
17
|
+
headers: authorizationHeader(license),
|
|
18
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
|
|
19
|
+
});
|
|
20
|
+
if (response.status === 401) {
|
|
21
|
+
return {
|
|
22
|
+
status: 'license-rejected',
|
|
23
|
+
message: describeRejectedLicense(registryUrl)
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
if (!response.ok) {
|
|
27
|
+
return {
|
|
28
|
+
status: 'unavailable'
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
const { objects } = await response.json();
|
|
32
|
+
const packageNames = (objects ?? []).map((searchResult)=>searchResult.package?.name).filter((packageName)=>typeof packageName === 'string');
|
|
33
|
+
return {
|
|
34
|
+
status: 'available',
|
|
35
|
+
packageNames
|
|
36
|
+
};
|
|
37
|
+
} catch {
|
|
38
|
+
return {
|
|
39
|
+
status: 'unavailable'
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
const fetchPackument = async ({ packageName, license, fetchImplementation })=>{
|
|
44
|
+
const registryUrl = REGISTRY_URL;
|
|
45
|
+
let response;
|
|
46
|
+
try {
|
|
47
|
+
// `@scope/name` as is: the Strapi registry redirects `@scope%2fname` to it.
|
|
48
|
+
response = await fetchImplementation(`${registryUrl}/${packageName}`, {
|
|
49
|
+
headers: {
|
|
50
|
+
...authorizationHeader(license),
|
|
51
|
+
Accept: 'application/json'
|
|
52
|
+
},
|
|
53
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
|
|
54
|
+
});
|
|
55
|
+
} catch {
|
|
56
|
+
return {
|
|
57
|
+
status: 'unavailable',
|
|
58
|
+
message: `Could not reach ${registryUrl}. Check your network connection and try again.`
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
if (response.status === 401) {
|
|
62
|
+
return {
|
|
63
|
+
status: 'license-rejected',
|
|
64
|
+
message: describeRejectedLicense(registryUrl)
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
if (response.status === 403) {
|
|
68
|
+
return {
|
|
69
|
+
status: 'not-licensed'
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
if (response.status === 404) {
|
|
73
|
+
return {
|
|
74
|
+
status: 'not-found'
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
if (!response.ok) {
|
|
78
|
+
return {
|
|
79
|
+
status: 'unavailable',
|
|
80
|
+
message: `${registryUrl} answered HTTP ${response.status} for ${packageName}. Try again later.`
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
const packument = await response.json().catch(()=>undefined);
|
|
84
|
+
if (typeof packument !== 'object' || packument === null) {
|
|
85
|
+
return {
|
|
86
|
+
status: 'unavailable',
|
|
87
|
+
message: `${registryUrl} answered with invalid data for ${packageName}. Try again later.`
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
status: 'available',
|
|
92
|
+
packument: packument
|
|
93
|
+
};
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
exports.fetchPackument = fetchPackument;
|
|
97
|
+
exports.searchPackageNames = searchPackageNames;
|
|
98
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sources":["../../../../../../src/cli/commands/enterprise/install/registry.ts"],"sourcesContent":["import { BILLING_URL, ENTERPRISE_REGISTRY_URL } from './constants';\n\nconst REQUEST_TIMEOUT_MS = 15 * 1000;\nconst SEARCH_PAGE_SIZE = 250;\n\nexport interface StrapiPackageMetadata {\n name?: string;\n displayName?: string;\n description?: string;\n kind?: string;\n}\n\nexport interface PackumentVersion {\n version: string;\n description?: string;\n deprecated?: string;\n peerDependencies?: Record<string, string>;\n strapi?: StrapiPackageMetadata;\n}\n\nexport interface Packument {\n name: string;\n 'dist-tags'?: Record<string, string>;\n versions?: Record<string, PackumentVersion>;\n}\n\nexport type PackumentLookup =\n | { status: 'available'; packument: Packument }\n | { status: 'license-rejected'; message: string }\n | { status: 'not-licensed' }\n | { status: 'not-found' }\n | { status: 'unavailable'; message: string };\n\nconst REGISTRY_URL = ENTERPRISE_REGISTRY_URL.replace(/\\/+$/, '');\n\nconst authorizationHeader = (license: string) => ({ Authorization: `Bearer ${license}` });\n\nconst describeRejectedLicense = (registryUrl: string) =>\n `${registryUrl} rejected this Strapi license. Check it at ${BILLING_URL}`;\n\nexport type SearchResult =\n | { status: 'available'; packageNames: string[] }\n | { status: 'license-rejected'; message: string }\n /** The search could not be reached, failed, or answered with invalid data. */\n | { status: 'unavailable' };\n\nexport const searchPackageNames = async ({\n text,\n license,\n fetchImplementation,\n}: {\n text: string;\n license: string;\n fetchImplementation: typeof fetch;\n}): Promise<SearchResult> => {\n const registryUrl = REGISTRY_URL;\n const searchUrl = `${registryUrl}/-/v1/search?text=${encodeURIComponent(text)}&size=${SEARCH_PAGE_SIZE}`;\n\n try {\n const response = await fetchImplementation(searchUrl, {\n headers: authorizationHeader(license),\n signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),\n });\n\n if (response.status === 401) {\n return { status: 'license-rejected', message: describeRejectedLicense(registryUrl) };\n }\n\n if (!response.ok) {\n return { status: 'unavailable' };\n }\n\n const { objects } = (await response.json()) as {\n objects?: Array<{ package?: { name?: unknown } }>;\n };\n\n const packageNames = (objects ?? [])\n .map((searchResult) => searchResult.package?.name)\n .filter((packageName): packageName is string => typeof packageName === 'string');\n\n return { status: 'available', packageNames };\n } catch {\n return { status: 'unavailable' };\n }\n};\n\nexport const fetchPackument = async ({\n packageName,\n license,\n fetchImplementation,\n}: {\n packageName: string;\n license: string;\n fetchImplementation: typeof fetch;\n}): Promise<PackumentLookup> => {\n const registryUrl = REGISTRY_URL;\n let response: Response;\n\n try {\n // `@scope/name` as is: the Strapi registry redirects `@scope%2fname` to it.\n response = await fetchImplementation(`${registryUrl}/${packageName}`, {\n headers: { ...authorizationHeader(license), Accept: 'application/json' },\n signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),\n });\n } catch {\n return {\n status: 'unavailable',\n message: `Could not reach ${registryUrl}. Check your network connection and try again.`,\n };\n }\n\n if (response.status === 401) {\n return {\n status: 'license-rejected',\n message: describeRejectedLicense(registryUrl),\n };\n }\n\n if (response.status === 403) {\n return { status: 'not-licensed' };\n }\n\n if (response.status === 404) {\n return { status: 'not-found' };\n }\n\n if (!response.ok) {\n return {\n status: 'unavailable',\n message: `${registryUrl} answered HTTP ${response.status} for ${packageName}. Try again later.`,\n };\n }\n\n const packument: unknown = await response.json().catch(() => undefined);\n\n if (typeof packument !== 'object' || packument === null) {\n return {\n status: 'unavailable',\n message: `${registryUrl} answered with invalid data for ${packageName}. Try again later.`,\n };\n }\n\n return { status: 'available', packument: packument as Packument };\n};\n"],"names":["REQUEST_TIMEOUT_MS","SEARCH_PAGE_SIZE","REGISTRY_URL","ENTERPRISE_REGISTRY_URL","replace","authorizationHeader","license","Authorization","describeRejectedLicense","registryUrl","BILLING_URL","searchPackageNames","text","fetchImplementation","searchUrl","encodeURIComponent","response","headers","signal","AbortSignal","timeout","status","message","ok","objects","json","packageNames","map","searchResult","package","name","filter","packageName","fetchPackument","Accept","packument","catch","undefined"],"mappings":"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"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { ENTERPRISE_REGISTRY_URL, BILLING_URL } from './constants.mjs';
|
|
2
|
+
|
|
3
|
+
const REQUEST_TIMEOUT_MS = 15 * 1000;
|
|
4
|
+
const SEARCH_PAGE_SIZE = 250;
|
|
5
|
+
const REGISTRY_URL = ENTERPRISE_REGISTRY_URL.replace(/\/+$/, '');
|
|
6
|
+
const authorizationHeader = (license)=>({
|
|
7
|
+
Authorization: `Bearer ${license}`
|
|
8
|
+
});
|
|
9
|
+
const describeRejectedLicense = (registryUrl)=>`${registryUrl} rejected this Strapi license. Check it at ${BILLING_URL}`;
|
|
10
|
+
const searchPackageNames = async ({ text, license, fetchImplementation })=>{
|
|
11
|
+
const registryUrl = REGISTRY_URL;
|
|
12
|
+
const searchUrl = `${registryUrl}/-/v1/search?text=${encodeURIComponent(text)}&size=${SEARCH_PAGE_SIZE}`;
|
|
13
|
+
try {
|
|
14
|
+
const response = await fetchImplementation(searchUrl, {
|
|
15
|
+
headers: authorizationHeader(license),
|
|
16
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
|
|
17
|
+
});
|
|
18
|
+
if (response.status === 401) {
|
|
19
|
+
return {
|
|
20
|
+
status: 'license-rejected',
|
|
21
|
+
message: describeRejectedLicense(registryUrl)
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
if (!response.ok) {
|
|
25
|
+
return {
|
|
26
|
+
status: 'unavailable'
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
const { objects } = await response.json();
|
|
30
|
+
const packageNames = (objects ?? []).map((searchResult)=>searchResult.package?.name).filter((packageName)=>typeof packageName === 'string');
|
|
31
|
+
return {
|
|
32
|
+
status: 'available',
|
|
33
|
+
packageNames
|
|
34
|
+
};
|
|
35
|
+
} catch {
|
|
36
|
+
return {
|
|
37
|
+
status: 'unavailable'
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
const fetchPackument = async ({ packageName, license, fetchImplementation })=>{
|
|
42
|
+
const registryUrl = REGISTRY_URL;
|
|
43
|
+
let response;
|
|
44
|
+
try {
|
|
45
|
+
// `@scope/name` as is: the Strapi registry redirects `@scope%2fname` to it.
|
|
46
|
+
response = await fetchImplementation(`${registryUrl}/${packageName}`, {
|
|
47
|
+
headers: {
|
|
48
|
+
...authorizationHeader(license),
|
|
49
|
+
Accept: 'application/json'
|
|
50
|
+
},
|
|
51
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
|
|
52
|
+
});
|
|
53
|
+
} catch {
|
|
54
|
+
return {
|
|
55
|
+
status: 'unavailable',
|
|
56
|
+
message: `Could not reach ${registryUrl}. Check your network connection and try again.`
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
if (response.status === 401) {
|
|
60
|
+
return {
|
|
61
|
+
status: 'license-rejected',
|
|
62
|
+
message: describeRejectedLicense(registryUrl)
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
if (response.status === 403) {
|
|
66
|
+
return {
|
|
67
|
+
status: 'not-licensed'
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
if (response.status === 404) {
|
|
71
|
+
return {
|
|
72
|
+
status: 'not-found'
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
if (!response.ok) {
|
|
76
|
+
return {
|
|
77
|
+
status: 'unavailable',
|
|
78
|
+
message: `${registryUrl} answered HTTP ${response.status} for ${packageName}. Try again later.`
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
const packument = await response.json().catch(()=>undefined);
|
|
82
|
+
if (typeof packument !== 'object' || packument === null) {
|
|
83
|
+
return {
|
|
84
|
+
status: 'unavailable',
|
|
85
|
+
message: `${registryUrl} answered with invalid data for ${packageName}. Try again later.`
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
status: 'available',
|
|
90
|
+
packument: packument
|
|
91
|
+
};
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
export { fetchPackument, searchPackageNames };
|
|
95
|
+
//# sourceMappingURL=registry.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.mjs","sources":["../../../../../../src/cli/commands/enterprise/install/registry.ts"],"sourcesContent":["import { BILLING_URL, ENTERPRISE_REGISTRY_URL } from './constants';\n\nconst REQUEST_TIMEOUT_MS = 15 * 1000;\nconst SEARCH_PAGE_SIZE = 250;\n\nexport interface StrapiPackageMetadata {\n name?: string;\n displayName?: string;\n description?: string;\n kind?: string;\n}\n\nexport interface PackumentVersion {\n version: string;\n description?: string;\n deprecated?: string;\n peerDependencies?: Record<string, string>;\n strapi?: StrapiPackageMetadata;\n}\n\nexport interface Packument {\n name: string;\n 'dist-tags'?: Record<string, string>;\n versions?: Record<string, PackumentVersion>;\n}\n\nexport type PackumentLookup =\n | { status: 'available'; packument: Packument }\n | { status: 'license-rejected'; message: string }\n | { status: 'not-licensed' }\n | { status: 'not-found' }\n | { status: 'unavailable'; message: string };\n\nconst REGISTRY_URL = ENTERPRISE_REGISTRY_URL.replace(/\\/+$/, '');\n\nconst authorizationHeader = (license: string) => ({ Authorization: `Bearer ${license}` });\n\nconst describeRejectedLicense = (registryUrl: string) =>\n `${registryUrl} rejected this Strapi license. Check it at ${BILLING_URL}`;\n\nexport type SearchResult =\n | { status: 'available'; packageNames: string[] }\n | { status: 'license-rejected'; message: string }\n /** The search could not be reached, failed, or answered with invalid data. */\n | { status: 'unavailable' };\n\nexport const searchPackageNames = async ({\n text,\n license,\n fetchImplementation,\n}: {\n text: string;\n license: string;\n fetchImplementation: typeof fetch;\n}): Promise<SearchResult> => {\n const registryUrl = REGISTRY_URL;\n const searchUrl = `${registryUrl}/-/v1/search?text=${encodeURIComponent(text)}&size=${SEARCH_PAGE_SIZE}`;\n\n try {\n const response = await fetchImplementation(searchUrl, {\n headers: authorizationHeader(license),\n signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),\n });\n\n if (response.status === 401) {\n return { status: 'license-rejected', message: describeRejectedLicense(registryUrl) };\n }\n\n if (!response.ok) {\n return { status: 'unavailable' };\n }\n\n const { objects } = (await response.json()) as {\n objects?: Array<{ package?: { name?: unknown } }>;\n };\n\n const packageNames = (objects ?? [])\n .map((searchResult) => searchResult.package?.name)\n .filter((packageName): packageName is string => typeof packageName === 'string');\n\n return { status: 'available', packageNames };\n } catch {\n return { status: 'unavailable' };\n }\n};\n\nexport const fetchPackument = async ({\n packageName,\n license,\n fetchImplementation,\n}: {\n packageName: string;\n license: string;\n fetchImplementation: typeof fetch;\n}): Promise<PackumentLookup> => {\n const registryUrl = REGISTRY_URL;\n let response: Response;\n\n try {\n // `@scope/name` as is: the Strapi registry redirects `@scope%2fname` to it.\n response = await fetchImplementation(`${registryUrl}/${packageName}`, {\n headers: { ...authorizationHeader(license), Accept: 'application/json' },\n signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),\n });\n } catch {\n return {\n status: 'unavailable',\n message: `Could not reach ${registryUrl}. Check your network connection and try again.`,\n };\n }\n\n if (response.status === 401) {\n return {\n status: 'license-rejected',\n message: describeRejectedLicense(registryUrl),\n };\n }\n\n if (response.status === 403) {\n return { status: 'not-licensed' };\n }\n\n if (response.status === 404) {\n return { status: 'not-found' };\n }\n\n if (!response.ok) {\n return {\n status: 'unavailable',\n message: `${registryUrl} answered HTTP ${response.status} for ${packageName}. Try again later.`,\n };\n }\n\n const packument: unknown = await response.json().catch(() => undefined);\n\n if (typeof packument !== 'object' || packument === null) {\n return {\n status: 'unavailable',\n message: `${registryUrl} answered with invalid data for ${packageName}. Try again later.`,\n };\n }\n\n return { status: 'available', packument: packument as Packument };\n};\n"],"names":["REQUEST_TIMEOUT_MS","SEARCH_PAGE_SIZE","REGISTRY_URL","ENTERPRISE_REGISTRY_URL","replace","authorizationHeader","license","Authorization","describeRejectedLicense","registryUrl","BILLING_URL","searchPackageNames","text","fetchImplementation","searchUrl","encodeURIComponent","response","headers","signal","AbortSignal","timeout","status","message","ok","objects","json","packageNames","map","searchResult","package","name","filter","packageName","fetchPackument","Accept","packument","catch","undefined"],"mappings":"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"}
|