serverless-offline 9.1.7 → 9.2.2
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/package.json +4 -10
- package/src/ServerlessOffline.js +3 -3
- package/src/lambda/LambdaFunction.js +1 -4
- package/src/lambda/handler-runner/HandlerRunner.js +3 -11
- package/src/lambda/handler-runner/child-process-runner/ChildProcessRunner.js +9 -6
- package/src/lambda/handler-runner/child-process-runner/childProcessHelper.js +8 -5
- package/src/lambda/handler-runner/go-runner/GoRunner.js +3 -1
- package/src/lambda/handler-runner/in-process-runner/InProcessRunner.js +16 -34
- package/src/lambda/handler-runner/in-process-runner/aws-lambda-ric/UserFunction.js +359 -0
- package/src/lambda/{__tests__/fixtures → handler-runner/in-process-runner/aws-lambda-ric}/package.json +0 -0
- package/src/lambda/handler-runner/python-runner/PythonRunner.js +17 -19
- package/src/lambda/handler-runner/ruby-runner/RubyRunner.js +4 -1
- package/src/lambda/handler-runner/worker-thread-runner/WorkerThreadRunner.js +5 -6
- package/src/lambda/handler-runner/worker-thread-runner/workerThreadHelper.js +8 -5
- package/src/lambda/__tests__/LambdaContext.test.js +0 -30
- package/src/lambda/__tests__/LambdaFunction.test.js +0 -196
- package/src/lambda/__tests__/fixtures/Lambda/LambdaFunctionThatReturnsJSONObject.fixture.js +0 -47
- package/src/lambda/__tests__/fixtures/Lambda/LambdaFunctionThatReturnsNativeString.fixture.js +0 -46
- package/src/lambda/__tests__/fixtures/Lambda/package.json +0 -3
- package/src/lambda/__tests__/fixtures/lambdaFunction.fixture.js +0 -145
- package/src/lambda/__tests__/routes/invocations/InvocationsController.test.js +0 -42
- package/src/utils/__tests__/createUniqueId.test.js +0 -18
- package/src/utils/__tests__/formatToClfTime.test.js +0 -14
- package/src/utils/__tests__/generateHapiPath.test.js +0 -46
- package/src/utils/__tests__/lowerCaseKeys.test.js +0 -30
- package/src/utils/__tests__/parseHeaders.test.js +0 -13
- package/src/utils/__tests__/parseMultiValueHeaders.test.js +0 -24
- package/src/utils/__tests__/parseMultiValueQueryStringParameters.test.js +0 -159
- package/src/utils/__tests__/parseQueryStringParameters.test.js +0 -15
- package/src/utils/__tests__/splitHandlerPathAndName.test.js +0 -54
- package/src/utils/__tests__/unflatten.test.js +0 -32
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert'
|
|
2
|
-
import createUniqueId from '../createUniqueId.js'
|
|
3
|
-
|
|
4
|
-
describe('createUniqueId', () => {
|
|
5
|
-
it('should be unique', () => {
|
|
6
|
-
const items = 100000
|
|
7
|
-
const set = new Set(Array.from(Array(items)).map(createUniqueId))
|
|
8
|
-
|
|
9
|
-
assert.equal(set.size, items)
|
|
10
|
-
})
|
|
11
|
-
|
|
12
|
-
it('should be a 36 character string', () => {
|
|
13
|
-
const id = createUniqueId()
|
|
14
|
-
|
|
15
|
-
assert.equal(typeof id, 'string')
|
|
16
|
-
assert.equal(id.length, 36)
|
|
17
|
-
})
|
|
18
|
-
})
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert'
|
|
2
|
-
import formatToClfTime from '../formatToClfTime.js'
|
|
3
|
-
|
|
4
|
-
const { now } = Date
|
|
5
|
-
|
|
6
|
-
describe('formatToClfTime', () => {
|
|
7
|
-
it('should return "common log format" formatted time', () => {
|
|
8
|
-
const millis = now()
|
|
9
|
-
const result = formatToClfTime(millis)
|
|
10
|
-
|
|
11
|
-
// expected: 17/Dec/1995:03:24:00 -0500 (with varying offset)
|
|
12
|
-
assert.match(result, /([\w:/]+\s[+-]\d{4})/)
|
|
13
|
-
})
|
|
14
|
-
})
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert'
|
|
2
|
-
import generateHapiPath from '../generateHapiPath.js'
|
|
3
|
-
|
|
4
|
-
const serverless = {
|
|
5
|
-
service: {
|
|
6
|
-
provider: {
|
|
7
|
-
stage: 'dev',
|
|
8
|
-
},
|
|
9
|
-
},
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
describe('generateHapiPath', () => {
|
|
13
|
-
it('should generate url starting with a slash', () => {
|
|
14
|
-
const options = {}
|
|
15
|
-
const result = generateHapiPath('users', options, serverless)
|
|
16
|
-
assert.equal(result[0], '/')
|
|
17
|
-
})
|
|
18
|
-
|
|
19
|
-
it('should generate url with the stage prepended', () => {
|
|
20
|
-
const options = {}
|
|
21
|
-
const result = generateHapiPath('users', options, serverless)
|
|
22
|
-
assert.equal(result, '/dev/users')
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
describe('when a prefix option is set', () => {
|
|
26
|
-
it('the url should add the prefix', () => {
|
|
27
|
-
const options = { prefix: 'some-prefix' }
|
|
28
|
-
const result = generateHapiPath('users', options, serverless)
|
|
29
|
-
assert.equal(result, '/some-prefix/dev/users')
|
|
30
|
-
})
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
describe('when the noPrependStageInUrl option is set', () => {
|
|
34
|
-
it('the url should omit the stage', () => {
|
|
35
|
-
const options = { noPrependStageInUrl: true }
|
|
36
|
-
const result = generateHapiPath('users', options, serverless)
|
|
37
|
-
assert.equal(result, '/users')
|
|
38
|
-
})
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
it('the stage from options should override stage from serverless config', () => {
|
|
42
|
-
const options = { stage: 'prod' }
|
|
43
|
-
const result = generateHapiPath('users', options, serverless)
|
|
44
|
-
assert.equal(result, '/prod/users')
|
|
45
|
-
})
|
|
46
|
-
})
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert'
|
|
2
|
-
import lowerCaseKeys from '../lowerCaseKeys.js'
|
|
3
|
-
|
|
4
|
-
describe('lowerCaseKeys', () => {
|
|
5
|
-
it('should handle empty object', () => {
|
|
6
|
-
const result = lowerCaseKeys({})
|
|
7
|
-
assert.deepEqual(result, {})
|
|
8
|
-
})
|
|
9
|
-
|
|
10
|
-
it('should handle object with one key', () => {
|
|
11
|
-
const result = lowerCaseKeys({ 'Some-Key': 'value' })
|
|
12
|
-
assert.deepEqual(result, { 'some-key': 'value' })
|
|
13
|
-
})
|
|
14
|
-
|
|
15
|
-
it('should handle object with multiple keys', () => {
|
|
16
|
-
const result = lowerCaseKeys({
|
|
17
|
-
'already-lowercase': 'cool',
|
|
18
|
-
'Another-Key': 'anotherValue',
|
|
19
|
-
'lOts-OF-CAPitaLs': 'ButThisIsNotTouched',
|
|
20
|
-
'Some-Key': 'value',
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
assert.deepEqual(result, {
|
|
24
|
-
'already-lowercase': 'cool',
|
|
25
|
-
'another-key': 'anotherValue',
|
|
26
|
-
'lots-of-capitals': 'ButThisIsNotTouched',
|
|
27
|
-
'some-key': 'value',
|
|
28
|
-
})
|
|
29
|
-
})
|
|
30
|
-
})
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert'
|
|
2
|
-
// uses the same tests as parseMultiValueHeaders
|
|
3
|
-
import tests from './parseMultiValueHeaders.test.js'
|
|
4
|
-
import parseHeaders from '../parseHeaders.js'
|
|
5
|
-
|
|
6
|
-
describe('parseQueryStringParameters', () => {
|
|
7
|
-
tests.forEach(({ description, expected, param }) => {
|
|
8
|
-
it(`should return ${description}`, () => {
|
|
9
|
-
const result = parseHeaders(param)
|
|
10
|
-
assert.deepEqual(result, expected)
|
|
11
|
-
})
|
|
12
|
-
})
|
|
13
|
-
})
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert'
|
|
2
|
-
import parseMultiValueHeaders from '../parseMultiValueHeaders.js'
|
|
3
|
-
|
|
4
|
-
// TODO need more tests
|
|
5
|
-
const tests = [
|
|
6
|
-
{
|
|
7
|
-
description: 'no parameter (empty array)',
|
|
8
|
-
expected: null,
|
|
9
|
-
expectedMulti: null,
|
|
10
|
-
param: [],
|
|
11
|
-
},
|
|
12
|
-
]
|
|
13
|
-
|
|
14
|
-
describe('parseMultiValueHeaders', () => {
|
|
15
|
-
tests.forEach(({ description, expectedMulti, param }) => {
|
|
16
|
-
it(`should return ${description}`, () => {
|
|
17
|
-
const resultMulti = parseMultiValueHeaders(param)
|
|
18
|
-
assert.deepEqual(resultMulti, expectedMulti)
|
|
19
|
-
})
|
|
20
|
-
})
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
// export tests for parseHeaders
|
|
24
|
-
export default tests
|
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert'
|
|
2
|
-
import parseMultiValueQueryStringParameters from '../parseMultiValueQueryStringParameters.js'
|
|
3
|
-
|
|
4
|
-
const tests = [
|
|
5
|
-
{
|
|
6
|
-
description: 'no parameter (empty string)',
|
|
7
|
-
expected: null,
|
|
8
|
-
expectedMulti: null,
|
|
9
|
-
param: '',
|
|
10
|
-
},
|
|
11
|
-
|
|
12
|
-
{
|
|
13
|
-
description: 'string parameter',
|
|
14
|
-
expected: { foo: 'bar' },
|
|
15
|
-
expectedMulti: { foo: ['bar'] },
|
|
16
|
-
param: 'foo=bar',
|
|
17
|
-
},
|
|
18
|
-
|
|
19
|
-
{
|
|
20
|
-
description: 'number parameter (no type casting)',
|
|
21
|
-
expected: { foo: '1' },
|
|
22
|
-
expectedMulti: { foo: ['1'] },
|
|
23
|
-
param: 'foo=1',
|
|
24
|
-
},
|
|
25
|
-
|
|
26
|
-
{
|
|
27
|
-
description: 'boolean parameter (no type casting)',
|
|
28
|
-
expected: { foo: 'true' },
|
|
29
|
-
expectedMulti: { foo: ['true'] },
|
|
30
|
-
param: 'foo=true',
|
|
31
|
-
},
|
|
32
|
-
|
|
33
|
-
{
|
|
34
|
-
description: 'multiple parameters',
|
|
35
|
-
expected: { bar: 'test2', foo: 'test1' },
|
|
36
|
-
expectedMulti: { bar: ['test2'], foo: ['test1'] },
|
|
37
|
-
param: 'foo=test1&bar=test2',
|
|
38
|
-
},
|
|
39
|
-
|
|
40
|
-
{
|
|
41
|
-
description: 'multiple parameters, same keys',
|
|
42
|
-
expected: { foo: 'foobar' },
|
|
43
|
-
expectedMulti: { foo: ['test', 'foobar'] },
|
|
44
|
-
param: 'foo=test&foo=foobar',
|
|
45
|
-
},
|
|
46
|
-
|
|
47
|
-
{
|
|
48
|
-
description: 'multiple parameters, same keys, different casing',
|
|
49
|
-
expected: { foo: 'test', FOO: 'FOOBAR' },
|
|
50
|
-
expectedMulti: { foo: ['test'], FOO: ['FOOBAR'] },
|
|
51
|
-
param: 'foo=test&FOO=FOOBAR',
|
|
52
|
-
},
|
|
53
|
-
|
|
54
|
-
{
|
|
55
|
-
description: 'multiple parameters, same keys, same values',
|
|
56
|
-
expected: { foo: 'test' },
|
|
57
|
-
expectedMulti: { foo: ['test', 'test'] },
|
|
58
|
-
param: 'foo=test&foo=test',
|
|
59
|
-
},
|
|
60
|
-
|
|
61
|
-
{
|
|
62
|
-
description: 'no value',
|
|
63
|
-
expected: { foo: '' },
|
|
64
|
-
expectedMulti: { foo: [''] },
|
|
65
|
-
param: 'foo',
|
|
66
|
-
},
|
|
67
|
-
|
|
68
|
-
{
|
|
69
|
-
description: 'no value with =',
|
|
70
|
-
expected: { foo: '' },
|
|
71
|
-
expectedMulti: { foo: [''] },
|
|
72
|
-
param: 'foo=',
|
|
73
|
-
},
|
|
74
|
-
|
|
75
|
-
{
|
|
76
|
-
description: 'no value with &',
|
|
77
|
-
expected: { foo: '' },
|
|
78
|
-
expectedMulti: { foo: [''] },
|
|
79
|
-
param: 'foo&',
|
|
80
|
-
},
|
|
81
|
-
|
|
82
|
-
{
|
|
83
|
-
description: 'no value with = and &',
|
|
84
|
-
expected: { foo: '' },
|
|
85
|
-
expectedMulti: { foo: [''] },
|
|
86
|
-
param: 'foo=&',
|
|
87
|
-
},
|
|
88
|
-
|
|
89
|
-
{
|
|
90
|
-
description: 'value is whitespace',
|
|
91
|
-
expected: { foo: ' ' },
|
|
92
|
-
expectedMulti: { foo: [' '] },
|
|
93
|
-
param: 'foo=%20',
|
|
94
|
-
},
|
|
95
|
-
|
|
96
|
-
{
|
|
97
|
-
description: 'key and value have whitespace',
|
|
98
|
-
expected: { ' foo ': ' test ' },
|
|
99
|
-
expectedMulti: { ' foo ': [' test '] },
|
|
100
|
-
param: '%20foo%20=%20test%20',
|
|
101
|
-
},
|
|
102
|
-
|
|
103
|
-
{
|
|
104
|
-
description: 'unicode',
|
|
105
|
-
expected: { Σ: '😋' },
|
|
106
|
-
expectedMulti: { Σ: ['😋'] },
|
|
107
|
-
param: 'Σ=😋',
|
|
108
|
-
},
|
|
109
|
-
|
|
110
|
-
{
|
|
111
|
-
description: 'encoded', // encodeURIComponent
|
|
112
|
-
expected: { '?=/&:': '?=/&:' },
|
|
113
|
-
expectedMulti: { '?=/&:': ['?=/&:'] },
|
|
114
|
-
param: '%3F%3D%2F%26%3A=%3F%3D%2F%26%3A',
|
|
115
|
-
},
|
|
116
|
-
|
|
117
|
-
{
|
|
118
|
-
description: 'end of line',
|
|
119
|
-
expected: { '\n': '\n' },
|
|
120
|
-
expectedMulti: { '\n': ['\n'] },
|
|
121
|
-
param: '%0A=%0A',
|
|
122
|
-
},
|
|
123
|
-
|
|
124
|
-
// silly test section:
|
|
125
|
-
{
|
|
126
|
-
description: 'silly I.',
|
|
127
|
-
expected: { test: '?' },
|
|
128
|
-
expectedMulti: { test: ['?'] },
|
|
129
|
-
param: 'test=?',
|
|
130
|
-
},
|
|
131
|
-
|
|
132
|
-
{
|
|
133
|
-
description: 'silly II.',
|
|
134
|
-
expected: { test: '/' },
|
|
135
|
-
expectedMulti: { test: ['/'] },
|
|
136
|
-
param: 'test=/',
|
|
137
|
-
},
|
|
138
|
-
|
|
139
|
-
{
|
|
140
|
-
description: 'silly III.',
|
|
141
|
-
expected: { test: '=' },
|
|
142
|
-
expectedMulti: { test: ['='] },
|
|
143
|
-
param: 'test==',
|
|
144
|
-
},
|
|
145
|
-
]
|
|
146
|
-
|
|
147
|
-
describe('parseMultiValueQueryStringParameters', () => {
|
|
148
|
-
tests.forEach(({ description, expectedMulti, param }) => {
|
|
149
|
-
const url = `foo?${param}`
|
|
150
|
-
|
|
151
|
-
it(`should return ${description}`, () => {
|
|
152
|
-
const resultMulti = parseMultiValueQueryStringParameters(url)
|
|
153
|
-
assert.deepEqual(resultMulti, expectedMulti)
|
|
154
|
-
})
|
|
155
|
-
})
|
|
156
|
-
})
|
|
157
|
-
|
|
158
|
-
// export tests for parseQueryStringParameters
|
|
159
|
-
export default tests
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert'
|
|
2
|
-
// uses the same tests as parseMultiValueQueryStringParameters
|
|
3
|
-
import tests from './parseMultiValueQueryStringParameters.test.js'
|
|
4
|
-
import parseQueryStringParameters from '../parseQueryStringParameters.js'
|
|
5
|
-
|
|
6
|
-
describe('parseQueryStringParameters', () => {
|
|
7
|
-
tests.forEach(({ description, expected, param }) => {
|
|
8
|
-
const url = `/foo?${param}`
|
|
9
|
-
|
|
10
|
-
it(`should return ${description}`, () => {
|
|
11
|
-
const result = parseQueryStringParameters(url)
|
|
12
|
-
assert.deepEqual(result, expected)
|
|
13
|
-
})
|
|
14
|
-
})
|
|
15
|
-
})
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert'
|
|
2
|
-
import splitHandlerPathAndName from '../splitHandlerPathAndName.js'
|
|
3
|
-
|
|
4
|
-
const tests = [
|
|
5
|
-
{
|
|
6
|
-
description: 'ruby handler with namespace resolution operator ::',
|
|
7
|
-
expected: ['./src/somefolder/source', 'LambdaFunctions::Handler.process'],
|
|
8
|
-
handler: './src/somefolder/source.LambdaFunctions::Handler.process',
|
|
9
|
-
},
|
|
10
|
-
{
|
|
11
|
-
description: 'ruby handler with multiple namespace resolution operators ::',
|
|
12
|
-
expected: [
|
|
13
|
-
'./src/somefolder/source',
|
|
14
|
-
'Functions::LambdaFunctions::Handler.process',
|
|
15
|
-
],
|
|
16
|
-
handler:
|
|
17
|
-
'./src/somefolder/source.Functions::LambdaFunctions::Handler.process',
|
|
18
|
-
},
|
|
19
|
-
{
|
|
20
|
-
description: 'ruby handler with namespace resolution operator ::, unnested',
|
|
21
|
-
expected: ['source', 'LambdaFunctions::Handler.process'],
|
|
22
|
-
handler: 'source.LambdaFunctions::Handler.process',
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
description:
|
|
26
|
-
'ruby handler with multiple namespace resolution operators ::, unnested',
|
|
27
|
-
expected: ['./source', 'Functions::LambdaFunctions::Handler.process'],
|
|
28
|
-
handler: './source.Functions::LambdaFunctions::Handler.process',
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
description: 'ruby handler from kernel',
|
|
32
|
-
expected: ['./src/somefolder/function', 'handler'],
|
|
33
|
-
handler: './src/somefolder/function.handler',
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
description: 'generic handler',
|
|
37
|
-
expected: ['./src/somefolder/.handlers/handler', 'run'],
|
|
38
|
-
handler: './src/somefolder/.handlers/handler.run',
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
description: 'generic handler, unnested',
|
|
42
|
-
expected: ['handler', 'run'],
|
|
43
|
-
handler: 'handler.run',
|
|
44
|
-
},
|
|
45
|
-
]
|
|
46
|
-
|
|
47
|
-
describe('splitHandlerPathAndName', () => {
|
|
48
|
-
tests.forEach(({ description, expected, handler }) => {
|
|
49
|
-
it(`should split ${description}`, () => {
|
|
50
|
-
const result = splitHandlerPathAndName(handler)
|
|
51
|
-
assert.deepEqual(result, expected)
|
|
52
|
-
})
|
|
53
|
-
})
|
|
54
|
-
})
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert'
|
|
2
|
-
import unflatten from '../unflatten.js'
|
|
3
|
-
|
|
4
|
-
describe('unflatten', () => {
|
|
5
|
-
it('should work with empty array parameter', () => {
|
|
6
|
-
const value = []
|
|
7
|
-
const out = unflatten(value, 2)
|
|
8
|
-
const expected = []
|
|
9
|
-
|
|
10
|
-
assert.deepEqual(out, expected)
|
|
11
|
-
})
|
|
12
|
-
|
|
13
|
-
it('should work with single pair parameter', () => {
|
|
14
|
-
const value = ['a', 1]
|
|
15
|
-
const out = unflatten(value, 2)
|
|
16
|
-
const expected = [['a', 1]]
|
|
17
|
-
|
|
18
|
-
assert.deepEqual(out, expected)
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
it('should work with multiple pair parameters', () => {
|
|
22
|
-
const value = ['a', 1, 'b', 2, 'c', 3]
|
|
23
|
-
const out = unflatten(value, 2)
|
|
24
|
-
const expected = [
|
|
25
|
-
['a', 1],
|
|
26
|
-
['b', 2],
|
|
27
|
-
['c', 3],
|
|
28
|
-
]
|
|
29
|
-
|
|
30
|
-
assert.deepEqual(out, expected)
|
|
31
|
-
})
|
|
32
|
-
})
|