netlify 27.8.1 → 27.10.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/dist/commands/blobs/blobs-delete.js +1 -0
- package/dist/commands/blobs/blobs-get.d.ts +2 -0
- package/dist/commands/blobs/blobs-get.js +1 -0
- package/dist/commands/blobs/blobs-list.d.ts +2 -0
- package/dist/commands/blobs/blobs-list.js +1 -0
- package/dist/commands/blobs/blobs-set.d.ts +2 -0
- package/dist/commands/blobs/blobs-set.js +1 -0
- package/dist/commands/blobs/blobs.js +5 -0
- package/dist/commands/deploy/deploy.js +5 -1
- package/dist/utils/deploy/deploy-site.d.ts +4 -1
- package/dist/utils/deploy/deploy-site.js +9 -4
- package/dist/utils/deploy/hash-fns.d.ts +10 -1
- package/dist/utils/deploy/hash-fns.js +73 -19
- package/dist/utils/deploy/upload-files.d.ts +6 -2
- package/dist/utils/deploy/upload-files.js +13 -0
- package/dist/utils/functions/functions.d.ts +4 -0
- package/dist/utils/functions/functions.js +5 -0
- package/package.json +4 -4
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import { type GetStoreOptions } from '@netlify/blobs';
|
|
1
2
|
import { OptionValues } from 'commander';
|
|
2
3
|
import BaseCommand from '../base-command.js';
|
|
3
4
|
interface Options extends OptionValues {
|
|
4
5
|
output?: string;
|
|
6
|
+
region?: GetStoreOptions['region'];
|
|
5
7
|
}
|
|
6
8
|
export declare const blobsGet: (storeName: string, key: string, options: Options, command: BaseCommand) => Promise<undefined>;
|
|
7
9
|
export {};
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import { type GetStoreOptions } from '@netlify/blobs';
|
|
1
2
|
import { OptionValues } from 'commander';
|
|
2
3
|
import BaseCommand from '../base-command.js';
|
|
3
4
|
interface Options extends OptionValues {
|
|
4
5
|
directories?: boolean;
|
|
5
6
|
json?: boolean;
|
|
6
7
|
prefix?: string;
|
|
8
|
+
region?: GetStoreOptions['region'];
|
|
7
9
|
}
|
|
8
10
|
export declare const blobsList: (storeName: string, options: Options, command: BaseCommand) => Promise<undefined>;
|
|
9
11
|
export {};
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { type GetStoreOptions } from '@netlify/blobs';
|
|
1
2
|
import { OptionValues } from 'commander';
|
|
2
3
|
import BaseCommand from '../base-command.js';
|
|
3
4
|
interface Options extends OptionValues {
|
|
4
5
|
input?: string;
|
|
5
6
|
force?: string | boolean;
|
|
7
|
+
region?: GetStoreOptions['region'];
|
|
6
8
|
}
|
|
7
9
|
export declare const blobsSet: (storeName: string, key: string, valueParts: string[], options: Options, command: BaseCommand) => Promise<undefined>;
|
|
8
10
|
export {};
|
|
@@ -15,6 +15,7 @@ export const createBlobsCommand = (program) => {
|
|
|
15
15
|
.description(`Deletes an object with a given key, if it exists, from a Netlify Blobs store`)
|
|
16
16
|
.argument('<store>', 'Name of the store')
|
|
17
17
|
.argument('<key>', 'Object key')
|
|
18
|
+
.option('--region <region>', "The region where the store data is held, such as 'eu-central-1'; when omitted, the default region is used")
|
|
18
19
|
.alias('blob:delete')
|
|
19
20
|
.hook('preAction', requiresSiteInfo)
|
|
20
21
|
.action(async (storeName, key, _options, command) => {
|
|
@@ -27,6 +28,7 @@ export const createBlobsCommand = (program) => {
|
|
|
27
28
|
.argument('<store>', 'Name of the store')
|
|
28
29
|
.argument('<key>', 'Object key')
|
|
29
30
|
.option('-O, --output <path>', 'Defines the filesystem path where the blob data should be persisted')
|
|
31
|
+
.option('--region <region>', "The region where the store data is held, such as 'eu-central-1'; when omitted, the default region is used")
|
|
30
32
|
.alias('blob:get')
|
|
31
33
|
.hook('preAction', requiresSiteInfo)
|
|
32
34
|
.action(async (storeName, key, options, command) => {
|
|
@@ -40,6 +42,7 @@ export const createBlobsCommand = (program) => {
|
|
|
40
42
|
.option('-d, --directories', `Indicates that keys with the '/' character should be treated as directories, returning a list of sub-directories at a given level rather than all the keys inside them`)
|
|
41
43
|
.option('-p, --prefix <prefix>', `A string for filtering down the entries; when specified, only the entries whose key starts with that prefix are returned`)
|
|
42
44
|
.option('--json', 'Output list contents as JSON')
|
|
45
|
+
.option('--region <region>', "The region where the store data is held, such as 'eu-central-1'; when omitted, the default region is used")
|
|
43
46
|
.alias('blob:list')
|
|
44
47
|
.hook('preAction', requiresSiteInfo)
|
|
45
48
|
.action(async (storeName, options, command) => {
|
|
@@ -53,6 +56,7 @@ export const createBlobsCommand = (program) => {
|
|
|
53
56
|
.argument('<key>', 'Object key')
|
|
54
57
|
.argument('[value...]', 'Object value')
|
|
55
58
|
.option('-i, --input <path>', 'Defines the filesystem path where the blob data should be read from')
|
|
59
|
+
.option('--region <region>', "The region where the store data is held, such as 'eu-central-1'; when omitted, the default region is used")
|
|
56
60
|
.alias('blob:set')
|
|
57
61
|
.hook('preAction', requiresSiteInfo)
|
|
58
62
|
.action(async (storeName, key, valueParts, options, command) => {
|
|
@@ -76,6 +80,7 @@ For more information about Netlify Blobs, see ${terminalLink(docsUrl, docsUrl, {
|
|
|
76
80
|
'netlify blobs:delete my-store my-key',
|
|
77
81
|
'netlify blobs:list my-store',
|
|
78
82
|
'netlify blobs:list my-store --json',
|
|
83
|
+
'netlify blobs:list my-store --region eu-central-1',
|
|
79
84
|
])
|
|
80
85
|
.action(blobs);
|
|
81
86
|
};
|
|
@@ -22,7 +22,7 @@ import { getDeploySourceFields } from '../../utils/deploy/deploy-source.js';
|
|
|
22
22
|
import { uploadSourceZip } from '../../utils/deploy/upload-source-zip.js';
|
|
23
23
|
import { getEnvelopeEnv } from '../../utils/env/index.js';
|
|
24
24
|
import { mergeDeployEnvVars } from '../../utils/env/deploy-env-vars.js';
|
|
25
|
-
import { getFunctionsManifestPath, getInternalFunctionsDir } from '../../utils/functions/index.js';
|
|
25
|
+
import { getFunctionsManifestPath, getInternalFunctionsDir, getServerManifestPath, } from '../../utils/functions/index.js';
|
|
26
26
|
import { isEmpty } from '../../utils/object-utilities.js';
|
|
27
27
|
import openBrowser from '../../utils/open-browser.js';
|
|
28
28
|
import { isInteractive } from '../../utils/scripted-commands.js';
|
|
@@ -458,6 +458,7 @@ title, deployId: existingDeployId, }) => {
|
|
|
458
458
|
functionsFolder,
|
|
459
459
|
].filter((folder) => Boolean(folder));
|
|
460
460
|
const manifestPath = skipFunctionsCache ? null : await getFunctionsManifestPath({ base: site.root, packagePath });
|
|
461
|
+
const serverManifestPath = await getServerManifestPath({ base: site.root, packagePath });
|
|
461
462
|
const redirectsPath = `${deployFolder}/_redirects`;
|
|
462
463
|
const headersPath = `${deployFolder}/_headers`;
|
|
463
464
|
const { redirects } = await parseAllRedirects({
|
|
@@ -493,6 +494,9 @@ title, deployId: existingDeployId, }) => {
|
|
|
493
494
|
filter: getDeployFilesFilter({ site, deployFolder }),
|
|
494
495
|
workingDir: command.workingDir,
|
|
495
496
|
manifestPath,
|
|
497
|
+
packagePath,
|
|
498
|
+
serverEnabled: Boolean(siteData?.feature_flags?.netlify_build_server_standalone),
|
|
499
|
+
serverManifestPath: serverManifestPath ?? undefined,
|
|
496
500
|
skipFunctionsCache,
|
|
497
501
|
siteRoot: site.root,
|
|
498
502
|
environment: mergeDeployEnvVars(options.env, options.secretEnv),
|
|
@@ -3,13 +3,16 @@ import { type $TSFixMe } from '../../commands/types.js';
|
|
|
3
3
|
import type { DeployEvent } from './status-cb.js';
|
|
4
4
|
import type { DeployEnvironmentVariable } from '../env/deploy-env-vars.js';
|
|
5
5
|
export type { DeployEvent };
|
|
6
|
-
export declare const deploySite: (command: BaseCommand, api: $TSFixMe, siteId: any, dir: any, { assetType, branch, concurrentHash, concurrentUpload, config, deployId, deployTimeout, draft, environment, filter, fnDir, functionsConfig, hashAlgorithm, manifestPath, maxRetry, siteRoot, skipFunctionsCache, statusCb, syncFileLimit, tmpDir, workingDir, }: {
|
|
6
|
+
export declare const deploySite: (command: BaseCommand, api: $TSFixMe, siteId: any, dir: any, { assetType, branch, concurrentHash, concurrentUpload, config, deployId, deployTimeout, draft, environment, filter, fnDir, functionsConfig, hashAlgorithm, manifestPath, maxRetry, packagePath, serverEnabled, serverManifestPath, siteRoot, skipFunctionsCache, statusCb, syncFileLimit, tmpDir, workingDir, }: {
|
|
7
7
|
concurrentHash?: number;
|
|
8
8
|
concurrentUpload?: number;
|
|
9
9
|
deployTimeout?: number;
|
|
10
10
|
draft?: boolean;
|
|
11
11
|
environment?: DeployEnvironmentVariable[];
|
|
12
12
|
maxRetry?: number;
|
|
13
|
+
packagePath?: string;
|
|
14
|
+
serverEnabled?: boolean;
|
|
15
|
+
serverManifestPath?: string;
|
|
13
16
|
statusCb?: (status: DeployEvent) => void;
|
|
14
17
|
syncFileLimit?: number;
|
|
15
18
|
tmpDir?: string;
|
|
@@ -36,7 +36,7 @@ functionsConfig,
|
|
|
36
36
|
// @ts-expect-error TS(2525) FIXME: Initializer provides no value for this binding ele... Remove this comment to see the full error message
|
|
37
37
|
hashAlgorithm,
|
|
38
38
|
// @ts-expect-error TS(2525) FIXME: Initializer provides no value for this binding ele... Remove this comment to see the full error message
|
|
39
|
-
manifestPath, maxRetry = DEFAULT_MAX_RETRY,
|
|
39
|
+
manifestPath, maxRetry = DEFAULT_MAX_RETRY, packagePath, serverEnabled, serverManifestPath,
|
|
40
40
|
// @ts-expect-error TS(2525) FIXME: Initializer provides no value for this binding ele... Remove this comment to see the full error message
|
|
41
41
|
siteRoot,
|
|
42
42
|
// @ts-expect-error TS(2525) FIXME: Initializer provides no value for this binding ele... Remove this comment to see the full error message
|
|
@@ -51,7 +51,7 @@ skipFunctionsCache, statusCb = () => {
|
|
|
51
51
|
const edgeFunctionsDistPath = await getEdgeFunctionsDistPathIfExists(workingDir);
|
|
52
52
|
const deployConfigPath = await getDeployConfigPathIfExists(workingDir);
|
|
53
53
|
const dbMigrationsDistPath = await getDbMigrationsDistPathIfExists(workingDir);
|
|
54
|
-
const [{ files: staticFiles, filesShaMap: staticShaMap }, { fnConfig, fnShaMap, functionSchedules, functions, functionsWithNativeModules }, configFile, { edgeFunctions, edgeFnShaMap },] = await Promise.all([
|
|
54
|
+
const [{ files: staticFiles, filesShaMap: staticShaMap }, { fnConfig, fnShaMap, functionSchedules, functions, functionsWithNativeModules, server, serverShaMap }, configFile, { edgeFunctions, edgeFnShaMap },] = await Promise.all([
|
|
55
55
|
hashFiles({
|
|
56
56
|
assetType,
|
|
57
57
|
concurrentHash,
|
|
@@ -68,6 +68,9 @@ skipFunctionsCache, statusCb = () => {
|
|
|
68
68
|
hashAlgorithm,
|
|
69
69
|
statusCb,
|
|
70
70
|
manifestPath,
|
|
71
|
+
packagePath,
|
|
72
|
+
serverEnabled,
|
|
73
|
+
serverManifestPath,
|
|
71
74
|
skipFunctionsCache,
|
|
72
75
|
rootDir: siteRoot,
|
|
73
76
|
}),
|
|
@@ -122,6 +125,7 @@ For more information, visit https://ntl.fyi/cli-native-modules.`);
|
|
|
122
125
|
files,
|
|
123
126
|
functions,
|
|
124
127
|
edge_functions: edgeFunctions,
|
|
128
|
+
server,
|
|
125
129
|
function_schedules: functionSchedules,
|
|
126
130
|
functions_config: fnConfig,
|
|
127
131
|
async: Object.keys(files).length > syncFileLimit,
|
|
@@ -141,7 +145,7 @@ For more information, visit https://ntl.fyi/cli-native-modules.`);
|
|
|
141
145
|
let deploy = await api.updateSiteDeploy(deployParams);
|
|
142
146
|
if (deployParams.body.async)
|
|
143
147
|
deploy = await waitForDiff(api, deploy.id, siteId, deployTimeout);
|
|
144
|
-
const { required: requiredFiles, required_functions: requiredFns, required_edge_functions: requiredEdgeFns } = deploy;
|
|
148
|
+
const { required: requiredFiles, required_functions: requiredFns, required_edge_functions: requiredEdgeFns, required_server: requiredServer, } = deploy;
|
|
145
149
|
statusCb({
|
|
146
150
|
type: 'create-deploy',
|
|
147
151
|
msg: `CDN requesting ${requiredFiles.length} files${Array.isArray(requiredFns) ? ` and ${requiredFns.length} functions` : ''}${Array.isArray(requiredEdgeFns) ? ` and ${requiredEdgeFns.length} edge functions` : ''}`,
|
|
@@ -150,7 +154,8 @@ For more information, visit https://ntl.fyi/cli-native-modules.`);
|
|
|
150
154
|
const filesUploadList = getUploadList(requiredFiles, filesShaMap);
|
|
151
155
|
const functionsUploadList = getUploadList(requiredFns, fnShaMap);
|
|
152
156
|
const edgeFunctionsUploadList = getUploadList(requiredEdgeFns, edgeFnShaMap);
|
|
153
|
-
const
|
|
157
|
+
const serverUploadList = getUploadList(requiredServer, serverShaMap);
|
|
158
|
+
const uploadList = [...filesUploadList, ...functionsUploadList, ...edgeFunctionsUploadList, ...serverUploadList];
|
|
154
159
|
await uploadFiles(api, deployId, uploadList, { concurrentUpload, statusCb, maxRetry });
|
|
155
160
|
statusCb({
|
|
156
161
|
type: 'wait-for-deploy',
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import BaseCommand from '../../commands/base-command.js';
|
|
2
2
|
import { $TSFixMe } from '../../commands/types.js';
|
|
3
|
-
|
|
3
|
+
import type { ServerUploadFile } from './upload-files.js';
|
|
4
|
+
declare const hashFns: (command: BaseCommand, directories: string[], { concurrentHash, functionsConfig, hashAlgorithm, manifestPath, packagePath, rootDir, serverEnabled, serverManifestPath, skipFunctionsCache, statusCb, tmpDir, }: {
|
|
4
5
|
concurrentHash?: number;
|
|
5
6
|
functionsConfig?: $TSFixMe;
|
|
6
7
|
hashAlgorithm?: string | undefined;
|
|
7
8
|
manifestPath?: string | undefined;
|
|
9
|
+
packagePath?: string | undefined;
|
|
8
10
|
rootDir?: string | undefined;
|
|
11
|
+
serverEnabled?: boolean | undefined;
|
|
12
|
+
serverManifestPath?: string | undefined;
|
|
9
13
|
skipFunctionsCache?: boolean | undefined;
|
|
10
14
|
statusCb: $TSFixMe;
|
|
11
15
|
tmpDir: $TSFixMe;
|
|
@@ -19,6 +23,11 @@ declare const hashFns: (command: BaseCommand, directories: string[], { concurren
|
|
|
19
23
|
shaMap?: Record<string, $TSFixMe> | undefined;
|
|
20
24
|
fnShaMap?: Record<string, $TSFixMe[]> | undefined;
|
|
21
25
|
fnConfig?: Record<string, $TSFixMe> | undefined;
|
|
26
|
+
server?: {
|
|
27
|
+
sha: string;
|
|
28
|
+
region?: string;
|
|
29
|
+
} | undefined;
|
|
30
|
+
serverShaMap?: Record<string, ServerUploadFile[]> | undefined;
|
|
22
31
|
}>;
|
|
23
32
|
export default hashFns;
|
|
24
33
|
//# sourceMappingURL=hash-fns.d.ts.map
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { readFile } from 'fs/promises';
|
|
2
|
-
import path from 'path';
|
|
2
|
+
import path, { join } from 'path';
|
|
3
3
|
import { pipeline } from 'stream/promises';
|
|
4
4
|
import { Readable } from 'stream';
|
|
5
|
-
import {
|
|
5
|
+
import { SERVER_DIRECTORY } from '@netlify/build';
|
|
6
|
+
import { findServerEntry, zipFunctions, zipServer, } from '@netlify/zip-it-and-ship-it';
|
|
6
7
|
import { INTERNAL_FUNCTIONS_FOLDER } from '../functions/functions.js';
|
|
7
8
|
import { hasherCtor, manifestCollectorCtor } from './hasher-segments.js';
|
|
8
9
|
// Maximum age of functions manifest (2 minutes).
|
|
@@ -15,9 +16,7 @@ const getFunctionZips = async ({ command, directories, functionsConfig, manifest
|
|
|
15
16
|
});
|
|
16
17
|
if (manifestPath) {
|
|
17
18
|
try {
|
|
18
|
-
|
|
19
|
-
// @ts-expect-error TS(2345) FIXME: Argument of type 'Buffer' is not assignable to par... Remove this comment to see the full error message
|
|
20
|
-
const { functions, timestamp } = JSON.parse(await readFile(manifestPath));
|
|
19
|
+
const { functions, timestamp } = JSON.parse(await readFile(manifestPath, 'utf-8'));
|
|
21
20
|
const manifestAge = Date.now() - timestamp;
|
|
22
21
|
if (manifestAge > MANIFEST_FILE_TTL) {
|
|
23
22
|
throw new Error('Manifest expired');
|
|
@@ -53,6 +52,28 @@ const getFunctionZips = async ({ command, directories, functionsConfig, manifest
|
|
|
53
52
|
config: functionsConfig,
|
|
54
53
|
});
|
|
55
54
|
};
|
|
55
|
+
const getServerBundle = async ({ packagePath, rootDir, serverEnabled, serverManifestPath, tmpDir, }) => {
|
|
56
|
+
if (!serverEnabled) {
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
if (serverManifestPath) {
|
|
60
|
+
try {
|
|
61
|
+
const { server, timestamp } = JSON.parse(await readFile(serverManifestPath, 'utf-8'));
|
|
62
|
+
if (server && Date.now() - timestamp <= MANIFEST_FILE_TTL) {
|
|
63
|
+
return server;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
// An unusable manifest is no different from not having one: the server is
|
|
68
|
+
// rebuilt below.
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
const entryPath = rootDir ? await findServerEntry(join(rootDir, packagePath ?? '', SERVER_DIRECTORY)) : undefined;
|
|
72
|
+
if (entryPath === undefined) {
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
return await zipServer(entryPath, join(tmpDir, 'server'), { basePath: rootDir });
|
|
76
|
+
};
|
|
56
77
|
const trafficRulesConfig = (trafficRules) => {
|
|
57
78
|
if (!trafficRules) {
|
|
58
79
|
return;
|
|
@@ -72,24 +93,30 @@ const trafficRulesConfig = (trafficRules) => {
|
|
|
72
93
|
},
|
|
73
94
|
};
|
|
74
95
|
};
|
|
75
|
-
const hashFns = async (command, directories, { concurrentHash, functionsConfig, hashAlgorithm = 'sha256', manifestPath, rootDir, skipFunctionsCache, statusCb, tmpDir, }) => {
|
|
76
|
-
// Exit early if
|
|
77
|
-
|
|
96
|
+
const hashFns = async (command, directories, { concurrentHash, functionsConfig, hashAlgorithm = 'sha256', manifestPath, packagePath, rootDir, serverEnabled, serverManifestPath, skipFunctionsCache, statusCb, tmpDir, }) => {
|
|
97
|
+
// Exit early if there is nothing to bundle. A site can have a server without
|
|
98
|
+
// any functions directory.
|
|
99
|
+
if (directories.length === 0 && !serverEnabled) {
|
|
78
100
|
return { functions: {}, functionsWithNativeModules: [], shaMap: {} };
|
|
79
101
|
}
|
|
80
102
|
if (!tmpDir) {
|
|
81
103
|
throw new Error('Missing tmpDir directory for zipping files');
|
|
82
104
|
}
|
|
83
|
-
const functionZips = await
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
105
|
+
const [functionZips, serverBundle] = await Promise.all([
|
|
106
|
+
directories.length === 0
|
|
107
|
+
? []
|
|
108
|
+
: getFunctionZips({
|
|
109
|
+
command,
|
|
110
|
+
directories,
|
|
111
|
+
functionsConfig,
|
|
112
|
+
manifestPath,
|
|
113
|
+
rootDir,
|
|
114
|
+
skipFunctionsCache,
|
|
115
|
+
statusCb,
|
|
116
|
+
tmpDir,
|
|
117
|
+
}),
|
|
118
|
+
getServerBundle({ packagePath, rootDir, serverEnabled, serverManifestPath, tmpDir }),
|
|
119
|
+
]);
|
|
93
120
|
// ZISI's in-memory FunctionResult only nests bootstrap/runtime version into
|
|
94
121
|
// buildData when writing the manifest cache. Reconstruct it for direct-zip paths.
|
|
95
122
|
for (const func of functionZips) {
|
|
@@ -156,7 +183,34 @@ const hashFns = async (command, directories, { concurrentHash, functionsConfig,
|
|
|
156
183
|
const fnShaMap = {};
|
|
157
184
|
const manifestCollector = manifestCollectorCtor(functions, fnShaMap, { statusCb });
|
|
158
185
|
await pipeline([functionStream, hasher, manifestCollector]);
|
|
159
|
-
|
|
186
|
+
const { server, serverShaMap } = await hashServer(serverBundle, { concurrentHash, hashAlgorithm, statusCb, tmpDir });
|
|
187
|
+
return { functionSchedules, functions, functionsWithNativeModules, fnShaMap, fnConfig, server, serverShaMap };
|
|
188
|
+
};
|
|
189
|
+
// A deploy has at most one server, so it is declared on its own rather than in a
|
|
190
|
+
// map keyed by name. It still goes through the same hashing pipeline, so the
|
|
191
|
+
// upload flow can treat it like any other artifact.
|
|
192
|
+
const hashServer = async (serverBundle, { concurrentHash, hashAlgorithm, statusCb, tmpDir, }) => {
|
|
193
|
+
if (!serverBundle) {
|
|
194
|
+
return {};
|
|
195
|
+
}
|
|
196
|
+
const fileObj = {
|
|
197
|
+
filepath: serverBundle.path,
|
|
198
|
+
root: tmpDir,
|
|
199
|
+
relname: path.relative(tmpDir, serverBundle.path),
|
|
200
|
+
basename: path.basename(serverBundle.path),
|
|
201
|
+
extname: path.extname(serverBundle.path),
|
|
202
|
+
type: 'file',
|
|
203
|
+
assetType: 'server',
|
|
204
|
+
normalizedPath: path.basename(serverBundle.path, path.extname(serverBundle.path)),
|
|
205
|
+
};
|
|
206
|
+
const servers = {};
|
|
207
|
+
const serverShaMap = {};
|
|
208
|
+
await pipeline([
|
|
209
|
+
Readable.from([fileObj]),
|
|
210
|
+
hasherCtor({ concurrentHash, hashAlgorithm }),
|
|
211
|
+
manifestCollectorCtor(servers, serverShaMap, { statusCb }),
|
|
212
|
+
]);
|
|
213
|
+
return { server: { sha: Object.values(servers)[0], region: serverBundle.region }, serverShaMap };
|
|
160
214
|
};
|
|
161
215
|
export default hashFns;
|
|
162
216
|
//# sourceMappingURL=hash-fns.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import type { NetlifyAPI } from '@netlify/api';
|
|
3
3
|
import type { StatusCallback } from './status-cb.js';
|
|
4
|
-
export type UploadApi = Pick<NetlifyAPI, 'uploadDeployFile' | 'uploadDeployFunction' | 'uploadDeployEdgeFunction'>;
|
|
4
|
+
export type UploadApi = Pick<NetlifyAPI, 'uploadDeployFile' | 'uploadDeployFunction' | 'uploadDeployEdgeFunction' | 'uploadDeployServer'>;
|
|
5
5
|
interface UploadFileBase {
|
|
6
6
|
filepath: string;
|
|
7
7
|
normalizedPath: string;
|
|
@@ -20,7 +20,11 @@ export interface EdgeFunctionUploadFile extends UploadFileBase {
|
|
|
20
20
|
assetType: 'edge-function';
|
|
21
21
|
hash: string;
|
|
22
22
|
}
|
|
23
|
-
export
|
|
23
|
+
export interface ServerUploadFile extends UploadFileBase {
|
|
24
|
+
assetType: 'server';
|
|
25
|
+
hash: string;
|
|
26
|
+
}
|
|
27
|
+
export type UploadFile = StaticUploadFile | FunctionUploadFile | EdgeFunctionUploadFile | ServerUploadFile;
|
|
24
28
|
interface UploadFilesOptions {
|
|
25
29
|
concurrentUpload: number;
|
|
26
30
|
maxRetry: number;
|
|
@@ -63,6 +63,19 @@ const uploadFiles = async (api, deployId, uploadList, { concurrentUpload, maxRet
|
|
|
63
63
|
return api.uploadDeployEdgeFunction(params);
|
|
64
64
|
}, maxRetry);
|
|
65
65
|
}
|
|
66
|
+
case 'server': {
|
|
67
|
+
return await retryUpload((retryCount) => {
|
|
68
|
+
const params = {
|
|
69
|
+
body: readStreamCtor,
|
|
70
|
+
deployId,
|
|
71
|
+
codeSha: fileObj.hash,
|
|
72
|
+
};
|
|
73
|
+
if (retryCount > 0) {
|
|
74
|
+
params.xNfRetryCount = retryCount;
|
|
75
|
+
}
|
|
76
|
+
return api.uploadDeployServer(params);
|
|
77
|
+
}, maxRetry);
|
|
78
|
+
}
|
|
66
79
|
default: {
|
|
67
80
|
throw new MissingAssetTypeError(fileObj);
|
|
68
81
|
}
|
|
@@ -13,6 +13,10 @@ export declare const getFunctionsManifestPath: ({ base, packagePath }: {
|
|
|
13
13
|
base: string;
|
|
14
14
|
packagePath?: string;
|
|
15
15
|
}) => Promise<string | null>;
|
|
16
|
+
export declare const getServerManifestPath: ({ base, packagePath }: {
|
|
17
|
+
base: string;
|
|
18
|
+
packagePath?: string;
|
|
19
|
+
}) => Promise<string | null>;
|
|
16
20
|
export declare const getFunctionsDistPath: ({ base, packagePath, }: {
|
|
17
21
|
base?: undefined | string;
|
|
18
22
|
packagePath?: string;
|
|
@@ -17,6 +17,11 @@ export const getFunctionsManifestPath = async ({ base, packagePath = '' }) => {
|
|
|
17
17
|
const isFile = await isFileAsync(path);
|
|
18
18
|
return isFile ? path : null;
|
|
19
19
|
};
|
|
20
|
+
export const getServerManifestPath = async ({ base, packagePath = '' }) => {
|
|
21
|
+
const path = resolve(base, packagePath, getPathInProject(['server', 'manifest.json']));
|
|
22
|
+
const isFile = await isFileAsync(path);
|
|
23
|
+
return isFile ? path : null;
|
|
24
|
+
};
|
|
20
25
|
export const getFunctionsDistPath = async ({ base, packagePath = '', }) => {
|
|
21
26
|
const path = resolve(base ?? '', packagePath, getPathInProject(['functions']));
|
|
22
27
|
const isDirectory = await isDirectoryAsync(path);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "netlify",
|
|
3
|
-
"version": "27.
|
|
3
|
+
"version": "27.10.0",
|
|
4
4
|
"description": "Netlify command line tool",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"api",
|
|
@@ -55,12 +55,12 @@
|
|
|
55
55
|
"@netlify/ai": "^1.0.1",
|
|
56
56
|
"@netlify/api": "^15.1.2",
|
|
57
57
|
"@netlify/blobs": "^11.1.0",
|
|
58
|
-
"@netlify/build": "^37.
|
|
58
|
+
"@netlify/build": "^37.3.0",
|
|
59
59
|
"@netlify/build-info": "^11.3.0",
|
|
60
60
|
"@netlify/config": "^25.2.5",
|
|
61
61
|
"@netlify/dev": "^5.1.2",
|
|
62
62
|
"@netlify/dev-utils": "^6.0.1",
|
|
63
|
-
"@netlify/edge-bundler": "^16.0
|
|
63
|
+
"@netlify/edge-bundler": "^16.1.0",
|
|
64
64
|
"@netlify/edge-functions": "^4.0.0",
|
|
65
65
|
"@netlify/edge-functions-bootstrap": "^3.2.0",
|
|
66
66
|
"@netlify/headers-parser": "^10.1.1",
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"@netlify/local-functions-proxy": "^2.0.3",
|
|
69
69
|
"@netlify/redirect-parser": "^16.1.1",
|
|
70
70
|
"@netlify/server-dev": "^0.1.1",
|
|
71
|
-
"@netlify/zip-it-and-ship-it": "^16.
|
|
71
|
+
"@netlify/zip-it-and-ship-it": "^16.2.0",
|
|
72
72
|
"@octokit/rest": "^22.0.0",
|
|
73
73
|
"@opentelemetry/api": "~1.9.0",
|
|
74
74
|
"@pnpm/tabtab": "^0.5.4",
|