@netlify/zip-it-and-ship-it 14.6.0 → 14.7.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.
|
@@ -11,7 +11,7 @@ import { FunctionBundlingUserError } from '../../../utils/error.js';
|
|
|
11
11
|
import { getRoutes } from '../../../utils/routes.js';
|
|
12
12
|
import { RUNTIME } from '../../runtime.js';
|
|
13
13
|
import { createBindingsMethod } from '../parser/bindings.js';
|
|
14
|
-
import { traverseNodes } from '../parser/exports.js';
|
|
14
|
+
import { parseObject, traverseNodes } from '../parser/exports.js';
|
|
15
15
|
import { getImports } from '../parser/imports.js';
|
|
16
16
|
import { safelyParseSource, safelyReadSource } from '../parser/index.js';
|
|
17
17
|
import { eventHandlers } from '@netlify/serverless-functions-api';
|
|
@@ -59,20 +59,39 @@ export const inSourceConfig = functionConfigShape
|
|
|
59
59
|
path: ['vcpu'],
|
|
60
60
|
});
|
|
61
61
|
/**
|
|
62
|
-
*
|
|
63
|
-
*
|
|
62
|
+
* Resolves the default export expression to an ObjectExpression if possible,
|
|
63
|
+
* following identifier bindings when needed.
|
|
64
64
|
*/
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
65
|
+
const resolveObjectExpression = (expression, getAllBindings) => {
|
|
66
|
+
// Unwrap TS type assertions so `{...} satisfies T` and `{...} as T` are
|
|
67
|
+
// treated the same as the bare object literal.
|
|
68
|
+
const unwrapped = expression?.type === 'TSSatisfiesExpression' ||
|
|
69
|
+
expression?.type === 'TSAsExpression' ||
|
|
70
|
+
expression?.type === 'TSTypeAssertion'
|
|
71
|
+
? expression.expression
|
|
72
|
+
: expression;
|
|
73
|
+
if (unwrapped?.type === 'ObjectExpression') {
|
|
74
|
+
return unwrapped;
|
|
69
75
|
}
|
|
70
|
-
|
|
71
|
-
|
|
76
|
+
if (unwrapped?.type === 'Identifier') {
|
|
77
|
+
let binding = getAllBindings().get(unwrapped.name);
|
|
78
|
+
if (binding?.type === 'TSSatisfiesExpression' ||
|
|
79
|
+
binding?.type === 'TSAsExpression' ||
|
|
80
|
+
binding?.type === 'TSTypeAssertion') {
|
|
81
|
+
binding = binding.expression;
|
|
82
|
+
}
|
|
72
83
|
if (binding?.type === 'ObjectExpression') {
|
|
73
|
-
|
|
84
|
+
return binding;
|
|
74
85
|
}
|
|
75
86
|
}
|
|
87
|
+
return undefined;
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* Extracts event subscription slugs from the default export expression,
|
|
91
|
+
* if it's an object whose property names match known event handlers.
|
|
92
|
+
*/
|
|
93
|
+
const getEventSubscriptions = (expression, getAllBindings) => {
|
|
94
|
+
const objectExpression = resolveObjectExpression(expression, getAllBindings);
|
|
76
95
|
if (!objectExpression) {
|
|
77
96
|
return [];
|
|
78
97
|
}
|
|
@@ -89,6 +108,34 @@ const getEventSubscriptions = (expression, getAllBindings) => {
|
|
|
89
108
|
}
|
|
90
109
|
return events;
|
|
91
110
|
};
|
|
111
|
+
/**
|
|
112
|
+
* Extracts a `config` property from the default export object expression,
|
|
113
|
+
* returning it as a plain object. This supports patterns like:
|
|
114
|
+
*
|
|
115
|
+
* ```js
|
|
116
|
+
* export default {
|
|
117
|
+
* fetch() { ... },
|
|
118
|
+
* config: { path: "/hello" }
|
|
119
|
+
* }
|
|
120
|
+
* ```
|
|
121
|
+
*/
|
|
122
|
+
const getConfigFromDefaultExport = (expression, getAllBindings) => {
|
|
123
|
+
const objectExpression = resolveObjectExpression(expression, getAllBindings);
|
|
124
|
+
if (!objectExpression) {
|
|
125
|
+
return undefined;
|
|
126
|
+
}
|
|
127
|
+
for (const property of objectExpression.properties) {
|
|
128
|
+
if (property.type !== 'ObjectProperty' || property.value.type !== 'ObjectExpression') {
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
const isConfigKey = (property.key.type === 'Identifier' && property.key.name === 'config') ||
|
|
132
|
+
(property.key.type === 'StringLiteral' && property.key.value === 'config');
|
|
133
|
+
if (isConfigKey) {
|
|
134
|
+
return parseObject(property.value);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return undefined;
|
|
138
|
+
};
|
|
92
139
|
const validateScheduleFunction = (functionFound, scheduleFound, functionName) => {
|
|
93
140
|
if (!functionFound) {
|
|
94
141
|
throw new FunctionBundlingUserError("The `schedule` helper was imported but we couldn't find any usages. If you meant to schedule a function, please check that `schedule` is invoked and `handler` correctly exported.", { functionName, runtime: RUNTIME.JAVASCRIPT });
|
|
@@ -139,7 +186,12 @@ export const parseSource = (source, { functionName }) => {
|
|
|
139
186
|
if (eventSubscriptions.length > 0) {
|
|
140
187
|
result.eventSubscriptions = eventSubscriptions;
|
|
141
188
|
}
|
|
142
|
-
|
|
189
|
+
// A named `export const config` always wins (even if empty); we fall back
|
|
190
|
+
// to the `config` property of the default export object only when no
|
|
191
|
+
// named export exists.
|
|
192
|
+
const inlineConfig = getConfigFromDefaultExport(defaultExportExpression, getAllBindings);
|
|
193
|
+
const mergedConfigExport = configExport ?? inlineConfig ?? {};
|
|
194
|
+
const { data, error, success } = inSourceConfig.safeParse(mergedConfigExport);
|
|
143
195
|
if (success) {
|
|
144
196
|
result.config = data;
|
|
145
197
|
result.excludedRoutes = getRoutes(functionName, data.excludedPath);
|
|
@@ -104,13 +104,20 @@ const zipFunction = async function ({ archiveFormat, basePath, branch, cache, co
|
|
|
104
104
|
});
|
|
105
105
|
await cleanupFunction?.();
|
|
106
106
|
// Getting the invocation mode from ISC, in case the function is using the
|
|
107
|
-
// `stream` helper.
|
|
107
|
+
// `stream` helper or set `background: true` in the in-source config.
|
|
108
108
|
let { invocationMode } = staticAnalysisResult;
|
|
109
109
|
// If this is a background function (filename suffix), set the right
|
|
110
110
|
// `invocationMode` value.
|
|
111
111
|
if (name.endsWith('-background')) {
|
|
112
112
|
invocationMode = INVOCATION_MODE.Background;
|
|
113
113
|
}
|
|
114
|
+
// `background: true` in the merged config (e.g. via `[functions.<name>]` in
|
|
115
|
+
// `netlify.toml`) also marks the function as background. The in-source
|
|
116
|
+
// config has already been folded into `mergedConfig` by this point, so this
|
|
117
|
+
// check covers both TOML-only and in-source declarations.
|
|
118
|
+
if (mergedConfig?.background === true) {
|
|
119
|
+
invocationMode = INVOCATION_MODE.Background;
|
|
120
|
+
}
|
|
114
121
|
// V2 functions default to streamed invocation unless they were already
|
|
115
122
|
// marked as background (via filename suffix or `config.background: true`).
|
|
116
123
|
if (runtimeAPIVersion === 2 && invocationMode !== INVOCATION_MODE.Background) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Declaration, Expression, Statement } from '@babel/types';
|
|
1
|
+
import type { Declaration, Expression, ObjectExpression, Statement } from '@babel/types';
|
|
2
2
|
import type { ISCExport } from '../in_source_config/index.js';
|
|
3
3
|
import type { BindingMethod } from './bindings.js';
|
|
4
4
|
/**
|
|
@@ -11,9 +11,15 @@ import type { BindingMethod } from './bindings.js';
|
|
|
11
11
|
* declarations are found, this is ESM; if not, this is CJS
|
|
12
12
|
*/
|
|
13
13
|
export declare const traverseNodes: (nodes: Statement[], getAllBindings: BindingMethod) => {
|
|
14
|
-
configExport: Record<string, unknown
|
|
14
|
+
configExport: Record<string, unknown> | undefined;
|
|
15
15
|
handlerExports: ISCExport[];
|
|
16
16
|
hasDefaultExport: boolean;
|
|
17
17
|
defaultExportExpression: Expression | Declaration | undefined;
|
|
18
18
|
inputModuleFormat: "cjs";
|
|
19
19
|
};
|
|
20
|
+
/**
|
|
21
|
+
* Takes an object expression node and returns the object resulting from the
|
|
22
|
+
* subtree. Only values supported by the `parsePrimitive` method are returned,
|
|
23
|
+
* and any others will be ignored and excluded from the resulting object.
|
|
24
|
+
*/
|
|
25
|
+
export declare const parseObject: (node: ObjectExpression) => Record<string, unknown>;
|
|
@@ -11,7 +11,7 @@ import { isESMImportExport, isModuleExports } from './helpers.js';
|
|
|
11
11
|
*/
|
|
12
12
|
export const traverseNodes = (nodes, getAllBindings) => {
|
|
13
13
|
const handlerExports = [];
|
|
14
|
-
let configExport
|
|
14
|
+
let configExport;
|
|
15
15
|
let hasDefaultExport = false;
|
|
16
16
|
let defaultExportExpression;
|
|
17
17
|
let inputModuleFormat = MODULE_FORMAT.COMMONJS;
|
|
@@ -142,7 +142,7 @@ const parseConfigESMExport = (node) => {
|
|
|
142
142
|
* subtree. Only values supported by the `parsePrimitive` method are returned,
|
|
143
143
|
* and any others will be ignored and excluded from the resulting object.
|
|
144
144
|
*/
|
|
145
|
-
const parseObject = (node) => node.properties.reduce((acc, property) => {
|
|
145
|
+
export const parseObject = (node) => node.properties.reduce((acc, property) => {
|
|
146
146
|
if (property.type === 'ObjectProperty' && property.key.type === 'Identifier') {
|
|
147
147
|
return {
|
|
148
148
|
...acc,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@netlify/zip-it-and-ship-it",
|
|
3
|
-
"version": "14.
|
|
3
|
+
"version": "14.7.0",
|
|
4
4
|
"description": "Zip it and ship it",
|
|
5
5
|
"main": "./dist/main.js",
|
|
6
6
|
"type": "module",
|
|
@@ -100,5 +100,5 @@
|
|
|
100
100
|
"engines": {
|
|
101
101
|
"node": ">=18.14.0"
|
|
102
102
|
},
|
|
103
|
-
"gitHead": "
|
|
103
|
+
"gitHead": "0e2b212c4ffae1e07159374df9991584e5b4bb0b"
|
|
104
104
|
}
|