velocious 1.0.40 → 1.0.41
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/README.md +1 -1
- package/package.json +2 -1
- package/peak_flow.yml +8 -4
- package/spec/cli/commands/db/create-spec.js +1 -0
- package/spec/cli/commands/db/migrate-spec.js +28 -11
- package/spec/cli/commands/test/test-files-finder-spec.js +5 -4
- package/spec/database/record/create-spec.js +6 -0
- package/spec/database/record/destroy-spec.js +6 -3
- package/spec/database/record/find-spec.js +3 -1
- package/spec/database/record/query-spec.js +7 -3
- package/spec/database/record/translation-fallbacks-spec.js +1 -1
- package/spec/database/record/update-spec.js +2 -1
- package/spec/database/record/validations-spec.js +10 -6
- package/spec/database/transactions-spec.js +7 -5
- package/spec/dummy/index.js +18 -29
- package/spec/dummy/src/config/configuration.example.js +3 -2
- package/spec/dummy/src/config/configuration.peakflow.mariadb.js +3 -7
- package/spec/dummy/src/config/configuration.peakflow.mssql.js +3 -2
- package/spec/dummy/src/config/configuration.peakflow.pgsql.js +3 -7
- package/spec/dummy/src/config/configuration.peakflow.sqlite.js +3 -7
- package/spec/dummy/src/config/testing.js +62 -0
- package/spec/dummy/src/database/migrations/20250912183605-create-users.js +15 -0
- package/spec/dummy/src/database/migrations/20250912183606-create-authentication-tokens.js +15 -0
- package/spec/dummy/src/models/authentication-token.js +8 -0
- package/spec/dummy/src/models/task.js +2 -2
- package/spec/dummy/src/models/user.js +15 -0
- package/spec/dummy/src/routes/projects/controller.js +7 -1
- package/spec/http-server/client-spec.js +1 -1
- package/spec/http-server/get-spec.js +1 -1
- package/spec/http-server/post-spec.js +21 -8
- package/spec/http-server/root-get-spec.js +1 -1
- package/src/cli/commands/db/create.js +11 -8
- package/src/cli/commands/db/drop.js +19 -0
- package/src/cli/commands/db/migrate.js +1 -1
- package/src/cli/commands/db/reset.js +7 -1
- package/src/cli/commands/test.js +10 -4
- package/src/configuration.js +26 -3
- package/src/database/drivers/base-column.js +22 -0
- package/src/database/drivers/base-columns-index.js +34 -0
- package/src/database/drivers/base-table.js +43 -0
- package/src/database/drivers/base.js +12 -16
- package/src/database/drivers/mssql/column.js +43 -2
- package/src/database/drivers/mssql/columns-index.js +9 -0
- package/src/database/drivers/mssql/index.js +26 -14
- package/src/database/drivers/mssql/table.js +16 -1
- package/src/database/drivers/mysql/column.js +47 -2
- package/src/database/drivers/mysql/columns-index.js +10 -0
- package/src/database/drivers/mysql/index.js +5 -8
- package/src/database/drivers/mysql/table.js +3 -1
- package/src/database/drivers/pgsql/column.js +37 -2
- package/src/database/drivers/pgsql/columns-index.js +4 -0
- package/src/database/drivers/pgsql/index.js +6 -5
- package/src/database/drivers/pgsql/table.js +3 -1
- package/src/database/drivers/sqlite/base.js +6 -4
- package/src/database/drivers/sqlite/column.js +46 -2
- package/src/database/drivers/sqlite/columns-index.js +22 -0
- package/src/database/drivers/sqlite/connection-sql-js.js +1 -1
- package/src/database/drivers/sqlite/table.js +3 -1
- package/src/database/migrator.js +27 -7
- package/src/database/query/create-index-base.js +10 -1
- package/src/database/query/create-table-base.js +56 -2
- package/src/database/query/drop-table-base.js +8 -2
- package/src/database/table-data/index.js +2 -1
- package/src/database/use-database.js +1 -1
- package/src/routes/resolver.js +1 -1
- package/src/templates/configuration.js +1 -1
- package/src/testing/test-runner.js +86 -26
- package/src/testing/test.js +155 -7
- package/src/utils/with-tracked-stack.js +5 -3
|
@@ -3,7 +3,7 @@ import restArgsError from "../../utils/rest-args-error.js"
|
|
|
3
3
|
class TableColumn {
|
|
4
4
|
constructor(name, args) {
|
|
5
5
|
if (args) {
|
|
6
|
-
const {autoIncrement, default: columnDefault, foreignKey, maxLength, name, null: argsNull, primaryKey, type, ...restArgs} = args
|
|
6
|
+
const {autoIncrement, default: columnDefault, foreignKey, index, maxLength, name, null: argsNull, primaryKey, type, ...restArgs} = args
|
|
7
7
|
|
|
8
8
|
restArgsError(restArgs)
|
|
9
9
|
}
|
|
@@ -15,6 +15,7 @@ class TableColumn {
|
|
|
15
15
|
getAutoIncrement = () => this.args?.autoIncrement
|
|
16
16
|
getDefault = () => this.args?.default
|
|
17
17
|
getForeignKey = () => this.args?.foreignKey
|
|
18
|
+
getIndex = () => this.args?.index
|
|
18
19
|
getMaxLength = () => this.args?.maxLength
|
|
19
20
|
getName = () => this.name
|
|
20
21
|
getNull = () => this.args?.null
|
|
@@ -14,7 +14,7 @@ const loadMigrations = function loadMigrations({migrationsRequireContext, ...res
|
|
|
14
14
|
instance.running = true
|
|
15
15
|
|
|
16
16
|
try {
|
|
17
|
-
await Configuration.current().
|
|
17
|
+
await Configuration.current().ensureConnections(async () => {
|
|
18
18
|
const migrator = new Migrator({configuration: Configuration.current()})
|
|
19
19
|
|
|
20
20
|
await migrator.prepare()
|
package/src/routes/resolver.js
CHANGED
|
@@ -59,7 +59,7 @@ export default class VelociousRoutesResolver {
|
|
|
59
59
|
throw new Error(`Missing action on controller: ${controller}#${action}`)
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
await this.configuration.
|
|
62
|
+
await this.configuration.ensureConnections(async () => {
|
|
63
63
|
await controllerInstance._runBeforeCallbacks()
|
|
64
64
|
await controllerInstance[action]()
|
|
65
65
|
})
|
|
@@ -43,7 +43,7 @@ export default new Configuration({
|
|
|
43
43
|
const requireContextModels = requireContext(modelsPath, true, /^(.+)\.js$/)
|
|
44
44
|
const initializerFromRequireContext = new InitializerFromRequireContext({requireContext: requireContextModels})
|
|
45
45
|
|
|
46
|
-
await configuration.
|
|
46
|
+
await configuration.ensureConnections(async () => {
|
|
47
47
|
await initializerFromRequireContext.initialize({configuration})
|
|
48
48
|
})
|
|
49
49
|
},
|
|
@@ -45,45 +45,87 @@ export default class TestRunner {
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
isFailed() {
|
|
48
|
-
return this.
|
|
48
|
+
return this._failedTests > 0
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
this.
|
|
53
|
-
|
|
51
|
+
getFailedTests() {
|
|
52
|
+
return this._failedTests
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
getSuccessfulTests() {
|
|
56
|
+
return this._successfulTests
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
getTestsCount() {
|
|
60
|
+
return this._testsCount
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async prepare() {
|
|
64
|
+
this._failedTests = 0
|
|
65
|
+
this._successfulTests = 0
|
|
66
|
+
this._testsCount = 0
|
|
54
67
|
await this.importTestFiles()
|
|
55
|
-
|
|
56
|
-
|
|
68
|
+
await this.analyzeTests(tests)
|
|
69
|
+
this._onlyFocussed = this.anyTestsFocussed
|
|
70
|
+
|
|
71
|
+
const testingConfigPath = this.configuration.getTesting()
|
|
72
|
+
|
|
73
|
+
if (testingConfigPath) {
|
|
74
|
+
await import(testingConfigPath)
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async run() {
|
|
79
|
+
await this.configuration.ensureConnections(async () => {
|
|
80
|
+
await this.runTests({
|
|
81
|
+
afterEaches: [],
|
|
82
|
+
beforeEaches: [],
|
|
83
|
+
tests,
|
|
84
|
+
descriptions: [],
|
|
85
|
+
indentLevel: 0
|
|
86
|
+
})
|
|
87
|
+
})
|
|
57
88
|
}
|
|
58
89
|
|
|
59
|
-
|
|
90
|
+
analyzeTests(tests) {
|
|
91
|
+
let anyTestsFocussedFound = false
|
|
92
|
+
|
|
60
93
|
for (const testDescription in tests.tests) {
|
|
61
94
|
const testData = tests.tests[testDescription]
|
|
62
95
|
const testArgs = Object.assign({}, testData.args)
|
|
63
96
|
|
|
97
|
+
this._testsCount++
|
|
98
|
+
|
|
64
99
|
if (testArgs.focus) {
|
|
65
|
-
|
|
100
|
+
anyTestsFocussedFound = true
|
|
101
|
+
this.anyTestsFocussed = true
|
|
66
102
|
}
|
|
67
103
|
}
|
|
68
104
|
|
|
69
105
|
for (const subDescription in tests.subs) {
|
|
70
106
|
const subTest = tests.subs[subDescription]
|
|
71
|
-
const
|
|
107
|
+
const {anyTestsFocussed} = this.analyzeTests(subTest)
|
|
108
|
+
|
|
109
|
+
if (anyTestsFocussed) {
|
|
110
|
+
anyTestsFocussedFound = true
|
|
111
|
+
}
|
|
72
112
|
|
|
73
|
-
|
|
113
|
+
subTest.anyTestsFocussed = anyTestsFocussed
|
|
74
114
|
}
|
|
75
115
|
|
|
76
|
-
return
|
|
116
|
+
return {anyTestsFocussed: anyTestsFocussedFound}
|
|
77
117
|
}
|
|
78
118
|
|
|
79
|
-
async runTests(tests, descriptions, indentLevel) {
|
|
119
|
+
async runTests({afterEaches, beforeEaches, tests, descriptions, indentLevel}) {
|
|
80
120
|
const leftPadding = " ".repeat(indentLevel * 2)
|
|
121
|
+
const newAfterEaches = [...afterEaches, ...tests.afterEaches]
|
|
122
|
+
const newBeforeEaches = [...beforeEaches, ...tests.beforeEaches]
|
|
81
123
|
|
|
82
124
|
for (const testDescription in tests.tests) {
|
|
83
125
|
const testData = tests.tests[testDescription]
|
|
84
126
|
const testArgs = Object.assign({}, testData.args)
|
|
85
127
|
|
|
86
|
-
if (this.
|
|
128
|
+
if (this._onlyFocussed && !testArgs.focus) continue
|
|
87
129
|
|
|
88
130
|
if (testArgs.type == "request") {
|
|
89
131
|
testArgs.application = await this.application()
|
|
@@ -93,26 +135,44 @@ export default class TestRunner {
|
|
|
93
135
|
console.log(`${leftPadding}it ${testDescription}`)
|
|
94
136
|
|
|
95
137
|
try {
|
|
138
|
+
for (const beforeEachData of newBeforeEaches) {
|
|
139
|
+
await beforeEachData.callback({testArgs, testData})
|
|
140
|
+
}
|
|
141
|
+
|
|
96
142
|
await testData.function(testArgs)
|
|
97
|
-
this.
|
|
143
|
+
this._successfulTests++
|
|
98
144
|
} catch (error) {
|
|
99
|
-
this.
|
|
145
|
+
this._failedTests++
|
|
100
146
|
|
|
101
147
|
// console.error(`${leftPadding} Test failed: ${error.message}`)
|
|
102
|
-
|
|
103
|
-
}
|
|
104
|
-
}
|
|
148
|
+
addTrackedStackToError(error)
|
|
105
149
|
|
|
106
|
-
|
|
107
|
-
for (const subDescription in tests.subs) {
|
|
108
|
-
const subTest = tests.subs[subDescription]
|
|
109
|
-
const newDecriptions = descriptions.concat([subDescription])
|
|
150
|
+
const stackLines = error.stack.split("\n")
|
|
110
151
|
|
|
111
|
-
|
|
112
|
-
console.
|
|
113
|
-
|
|
152
|
+
for (const stackLine of stackLines) {
|
|
153
|
+
console.error(`${leftPadding} ${stackLine}`)
|
|
154
|
+
}
|
|
155
|
+
} finally {
|
|
156
|
+
for (const afterEachData of newAfterEaches) {
|
|
157
|
+
await afterEachData.callback({testArgs, testData})
|
|
114
158
|
}
|
|
115
159
|
}
|
|
116
|
-
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
for (const subDescription in tests.subs) {
|
|
163
|
+
const subTest = tests.subs[subDescription]
|
|
164
|
+
const newDecriptions = descriptions.concat([subDescription])
|
|
165
|
+
|
|
166
|
+
if (!this._onlyFocussed || subTest.anyTestsFocussed) {
|
|
167
|
+
console.log(`${leftPadding}${subDescription}`)
|
|
168
|
+
await this.runTests({
|
|
169
|
+
afterEaches: newAfterEaches,
|
|
170
|
+
beforeEaches: newBeforeEaches,
|
|
171
|
+
tests: subTest,
|
|
172
|
+
descriptions: newDecriptions,
|
|
173
|
+
indentLevel: indentLevel + 1
|
|
174
|
+
})
|
|
175
|
+
}
|
|
176
|
+
}
|
|
117
177
|
}
|
|
118
178
|
}
|
package/src/testing/test.js
CHANGED
|
@@ -1,13 +1,28 @@
|
|
|
1
|
+
import {anythingDifferent} from "set-state-compare/src/diff-utils.js"
|
|
1
2
|
import restArgsError from "../utils/rest-args-error.js"
|
|
2
3
|
|
|
3
4
|
const tests = {
|
|
5
|
+
afterEaches: [],
|
|
4
6
|
args: {},
|
|
7
|
+
beforeEaches: [],
|
|
5
8
|
subs: {},
|
|
6
9
|
tests: {}
|
|
7
10
|
}
|
|
8
11
|
|
|
9
12
|
let currentPath = [tests]
|
|
10
13
|
|
|
14
|
+
function beforeEach(callback) {
|
|
15
|
+
const currentTest = currentPath[currentPath.length - 1]
|
|
16
|
+
|
|
17
|
+
currentTest.beforeEaches.push({callback})
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function afterEach(callback) {
|
|
21
|
+
const currentTest = currentPath[currentPath.length - 1]
|
|
22
|
+
|
|
23
|
+
currentTest.afterEaches.push({callback})
|
|
24
|
+
}
|
|
25
|
+
|
|
11
26
|
class ExpectToChange {
|
|
12
27
|
constructor({changeCallback, expect, ...restArgs}) {
|
|
13
28
|
restArgsError(restArgs)
|
|
@@ -45,7 +60,61 @@ class Expect {
|
|
|
45
60
|
this.expectations = []
|
|
46
61
|
}
|
|
47
62
|
|
|
63
|
+
andChange(...args) {
|
|
64
|
+
return this.toChange(...args)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
get not() {
|
|
68
|
+
this._not = true
|
|
69
|
+
|
|
70
|
+
return this
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
toBe(result) {
|
|
74
|
+
if (this._not) {
|
|
75
|
+
if (this._object === result) {
|
|
76
|
+
throw new Error(`${this._object} was unexpected not to be ${result}`)
|
|
77
|
+
}
|
|
78
|
+
} else {
|
|
79
|
+
if (this._object !== result) {
|
|
80
|
+
throw new Error(`${this._object} wasn't expected be ${result}`)
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
toBeDefined() {
|
|
86
|
+
if (this._not) {
|
|
87
|
+
if (this._object !== undefined) {
|
|
88
|
+
throw new Error(`${this._object} wasn´t expected to be defined`)
|
|
89
|
+
}
|
|
90
|
+
} else {
|
|
91
|
+
if (this._object === undefined) {
|
|
92
|
+
throw new Error(`${this._object} wasn't expected be undefined`)
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
toBeInstanceOf(klass) {
|
|
98
|
+
if (!(this._object instanceof klass)) {
|
|
99
|
+
throw new Error(`Expected ${this._object?.constructor?.name || "null"} to be a ${klass.name} but it wasn't`)
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
toBeFalse() {
|
|
104
|
+
this.toBe(false)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
toBeUndefined() {
|
|
108
|
+
this.toBe(undefined)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
toBeTrue() {
|
|
112
|
+
this.toBe(true)
|
|
113
|
+
}
|
|
114
|
+
|
|
48
115
|
toChange(changeCallback) {
|
|
116
|
+
if (this._not) throw new Error("not stub")
|
|
117
|
+
|
|
49
118
|
const expectToChange = new ExpectToChange({changeCallback, expect: this})
|
|
50
119
|
|
|
51
120
|
this.expectations.push(expectToChange)
|
|
@@ -53,13 +122,81 @@ class Expect {
|
|
|
53
122
|
return expectToChange
|
|
54
123
|
}
|
|
55
124
|
|
|
56
|
-
|
|
57
|
-
|
|
125
|
+
toContain(valueToContain) {
|
|
126
|
+
if (this._not) throw new Error("not stub")
|
|
127
|
+
|
|
128
|
+
if (!this._object.includes(valueToContain)) {
|
|
129
|
+
throw new Error(`${this._object} doesn't contain ${valueToContain}`)
|
|
130
|
+
}
|
|
58
131
|
}
|
|
59
132
|
|
|
60
133
|
toEqual(result) {
|
|
61
|
-
if (this.
|
|
62
|
-
|
|
134
|
+
if (this._not) {
|
|
135
|
+
if (typeof this._object == "object" && typeof result == "object") {
|
|
136
|
+
if (!anythingDifferent(this._object, result)) {
|
|
137
|
+
throw new Error(`${this._object} was unexpected equal to ${result}`)
|
|
138
|
+
}
|
|
139
|
+
} else {
|
|
140
|
+
if (this._object == result) {
|
|
141
|
+
throw new Error(`${this._object} was unexpected equal to ${result}`)
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
} else {
|
|
145
|
+
if (typeof this._object == "object" && typeof result == "object") {
|
|
146
|
+
if (anythingDifferent(this._object, result)) {
|
|
147
|
+
throw new Error(`${JSON.stringify(this._object)} wasn't equal to ${JSON.stringify(result)}`)
|
|
148
|
+
}
|
|
149
|
+
} else {
|
|
150
|
+
if (this._object != result) {
|
|
151
|
+
throw new Error(`${this._object} wasn't equal to ${result}`)
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
toMatch(regex) {
|
|
158
|
+
const match = this._object.match(regex)
|
|
159
|
+
|
|
160
|
+
if (this._not) {
|
|
161
|
+
if (match) {
|
|
162
|
+
throw new Error(`${this._object} shouldn't match ${regex}`)
|
|
163
|
+
}
|
|
164
|
+
} else {
|
|
165
|
+
if (!match) {
|
|
166
|
+
throw new Error(`${this._object} didn't match ${regex}`)
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
async toThrowError(expectedError) {
|
|
172
|
+
if (this._not) throw new Error("not stub")
|
|
173
|
+
|
|
174
|
+
let failedError
|
|
175
|
+
|
|
176
|
+
try {
|
|
177
|
+
await this._object()
|
|
178
|
+
} catch (error) {
|
|
179
|
+
failedError = error
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (!failedError) throw new Error("Expected to fail but didn't")
|
|
183
|
+
|
|
184
|
+
let expectedErrorMessage, failedErrorMessage
|
|
185
|
+
|
|
186
|
+
if (typeof failedError == "string") {
|
|
187
|
+
failedErrorMessage = failedError
|
|
188
|
+
} else {
|
|
189
|
+
failedErrorMessage = failedError.message
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (typeof expectedError == "string") {
|
|
193
|
+
expectedErrorMessage = expectedError
|
|
194
|
+
} else {
|
|
195
|
+
expectedErrorMessage = expectedError.message
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (failedErrorMessage != expectedErrorMessage) {
|
|
199
|
+
throw new Error(`Expected to fail with '${expectedErrorMessage}' but failed with '${failedErrorMessage}'`)
|
|
63
200
|
}
|
|
64
201
|
}
|
|
65
202
|
|
|
@@ -82,6 +219,8 @@ class Expect {
|
|
|
82
219
|
}
|
|
83
220
|
|
|
84
221
|
toHaveAttributes(result) {
|
|
222
|
+
if (this._not) throw new Error("not stub")
|
|
223
|
+
|
|
85
224
|
const differences = {}
|
|
86
225
|
|
|
87
226
|
for (const key in result) {
|
|
@@ -93,8 +232,9 @@ class Expect {
|
|
|
93
232
|
}
|
|
94
233
|
}
|
|
95
234
|
|
|
96
|
-
if (Object.keys(differences).length > 0)
|
|
97
|
-
|
|
235
|
+
if (Object.keys(differences).length > 0) {
|
|
236
|
+
throw new Error(`Object had differet values: ${JSON.stringify(differences)}`)
|
|
237
|
+
}
|
|
98
238
|
}
|
|
99
239
|
}
|
|
100
240
|
|
|
@@ -118,7 +258,7 @@ async function describe(description, arg1, arg2) {
|
|
|
118
258
|
throw new Error(`Duplicate test description: ${description}`)
|
|
119
259
|
}
|
|
120
260
|
|
|
121
|
-
const newTestData = {args: newTestArgs, subs: {}, tests: {}}
|
|
261
|
+
const newTestData = {afterEaches: [], args: newTestArgs, beforeEaches: [], subs: {}, tests: {}}
|
|
122
262
|
|
|
123
263
|
currentTest.subs[description] = newTestData
|
|
124
264
|
currentPath.push(newTestData)
|
|
@@ -169,4 +309,12 @@ function fit(description, arg1, arg2) {
|
|
|
169
309
|
return it(description, testArgs, testFunction)
|
|
170
310
|
}
|
|
171
311
|
|
|
312
|
+
// Make the methods global so they can be used in test files
|
|
313
|
+
globalThis.afterEach = afterEach
|
|
314
|
+
globalThis.beforeEach = beforeEach
|
|
315
|
+
globalThis.describe = describe
|
|
316
|
+
globalThis.expect = expect
|
|
317
|
+
globalThis.it = it
|
|
318
|
+
globalThis.fit = fit
|
|
319
|
+
|
|
172
320
|
export {describe, expect, fit, it, tests}
|
|
@@ -38,16 +38,18 @@ async function withTrackedStack(arg1, arg2) {
|
|
|
38
38
|
if (!asyncLocalStorage) return await callback()
|
|
39
39
|
|
|
40
40
|
const parentStacks = asyncLocalStorage.getStore() || []
|
|
41
|
-
const additionalStackLines = [
|
|
41
|
+
const additionalStackLines = []
|
|
42
42
|
const currentStackLines = stack.split("\n")
|
|
43
43
|
|
|
44
|
+
currentStackLines[0] = " [WITH TRACKED STACK]"
|
|
45
|
+
|
|
44
46
|
for (let i = currentStackLines.length; i >= 0; i--) {
|
|
45
47
|
const stackLine = currentStackLines[i]
|
|
46
48
|
|
|
49
|
+
additionalStackLines.unshift(stackLine)
|
|
50
|
+
|
|
47
51
|
if (stackLine == " [WITH TRACKED STACK]") {
|
|
48
52
|
break
|
|
49
|
-
} else {
|
|
50
|
-
additionalStackLines.unshift(stackLine)
|
|
51
53
|
}
|
|
52
54
|
}
|
|
53
55
|
|