kea-typegen 3.6.8 → 3.7.1
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/CHANGELOG.md +8 -0
- package/dist/package.json +1 -1
- package/dist/src/__tests__/watch.js +178 -0
- package/dist/src/__tests__/watch.js.map +1 -1
- package/dist/src/__tests__/write.js +44 -0
- package/dist/src/__tests__/write.js.map +1 -1
- package/dist/src/cli/typegen.js +10 -1
- package/dist/src/cli/typegen.js.map +1 -1
- package/dist/src/print/print.js +11 -3
- package/dist/src/print/print.js.map +1 -1
- package/dist/src/typegen.js +58 -10
- package/dist/src/typegen.js.map +1 -1
- package/dist/src/types.d.ts +1 -0
- package/dist/src/visit/visit.js +33 -11
- package/dist/src/visit/visit.js.map +1 -1
- package/dist/src/watch.d.ts +22 -0
- package/dist/src/watch.js +183 -0
- package/dist/src/watch.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/__tests__/watch.ts +259 -32
- package/src/__tests__/write.ts +56 -0
- package/src/cli/typegen.ts +10 -1
- package/src/print/print.ts +14 -5
- package/src/test-support/watch-mode-smoke.js +39 -4
- package/src/test-support/write-mode-smoke.js +6 -1
- package/src/typegen.ts +78 -15
- package/src/types.ts +2 -0
- package/src/visit/visit.ts +54 -13
- package/src/watch.ts +261 -0
package/src/__tests__/watch.ts
CHANGED
|
@@ -1,44 +1,271 @@
|
|
|
1
1
|
import { spawn } from 'child_process'
|
|
2
|
+
import * as fs from 'fs'
|
|
3
|
+
import * as os from 'os'
|
|
2
4
|
import * as path from 'path'
|
|
5
|
+
import * as ts from 'typescript'
|
|
6
|
+
import { planWatchTypegenPass } from '../watch'
|
|
3
7
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const scriptPath = path.join(repoRoot, 'src/test-support/watch-mode-smoke.js')
|
|
8
|
+
function writeFile(filePath: string, source: string): void {
|
|
9
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true })
|
|
10
|
+
fs.writeFileSync(filePath, source)
|
|
11
|
+
}
|
|
9
12
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
function createProgram(fileNames: string[]): ts.Program {
|
|
14
|
+
return ts.createProgram(fileNames, {
|
|
15
|
+
module: ts.ModuleKind.CommonJS,
|
|
16
|
+
moduleResolution: ts.ModuleResolutionKind.NodeJs,
|
|
17
|
+
target: ts.ScriptTarget.ES2020,
|
|
18
|
+
skipLibCheck: true,
|
|
19
|
+
})
|
|
20
|
+
}
|
|
16
21
|
|
|
17
|
-
|
|
18
|
-
|
|
22
|
+
test('watch mode does not overlap successive typegen passes', async () => {
|
|
23
|
+
const repoRoot = path.resolve(__dirname, '..', '..')
|
|
24
|
+
const scriptPath = path.join(repoRoot, 'src/test-support/watch-mode-smoke.js')
|
|
19
25
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
26
|
+
const result = await new Promise<{
|
|
27
|
+
code: number | null
|
|
28
|
+
signal: NodeJS.Signals | null
|
|
29
|
+
stdout: string
|
|
30
|
+
stderr: string
|
|
31
|
+
}>((resolve, reject) => {
|
|
32
|
+
const child = spawn(process.execPath, [scriptPath], {
|
|
33
|
+
cwd: repoRoot,
|
|
34
|
+
env: { ...process.env, FORCE_COLOR: '0' },
|
|
35
|
+
})
|
|
23
36
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
})
|
|
37
|
+
let stdout = ''
|
|
38
|
+
let stderr = ''
|
|
27
39
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
40
|
+
child.stdout.on('data', (chunk) => {
|
|
41
|
+
stdout += chunk.toString()
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
child.stderr.on('data', (chunk) => {
|
|
45
|
+
stderr += chunk.toString()
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
child.on('error', reject)
|
|
49
|
+
child.on('close', (code, signal) => resolve({ code, signal, stdout, stderr }))
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
expect(result.signal).toBeNull()
|
|
53
|
+
expect(result.code).toBe(0)
|
|
54
|
+
|
|
55
|
+
const payload = JSON.parse(result.stdout.trim())
|
|
56
|
+
|
|
57
|
+
expect(payload.started).toBeGreaterThan(1)
|
|
58
|
+
expect(payload.completed).toBeGreaterThan(0)
|
|
59
|
+
expect(payload.maxActive).toBe(1)
|
|
60
|
+
expect(payload.incrementalAfterEdit).toBe(true)
|
|
61
|
+
expect(payload.parsedLogicCountsAfterEdit).toContain(1)
|
|
62
|
+
expect(payload.sourceFilePathsAfterEdit.some(Boolean)).toBe(true)
|
|
63
|
+
expect(result.stderr).toBe('')
|
|
64
|
+
}, 30000)
|
|
65
|
+
|
|
66
|
+
test('watch planner limits a direct logic edit to the changed logic and dependent logics', () => {
|
|
67
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'kea-typegen-watch-direct-logic-'))
|
|
68
|
+
|
|
69
|
+
try {
|
|
70
|
+
const logicDir = path.join(tempDir, 'src')
|
|
71
|
+
const firstLogicPath = path.join(logicDir, 'firstLogic.ts')
|
|
72
|
+
const secondLogicPath = path.join(logicDir, 'secondLogic.ts')
|
|
73
|
+
const unrelatedLogicPath = path.join(logicDir, 'unrelatedLogic.ts')
|
|
74
|
+
const keaDtsPath = path.join(tempDir, 'node_modules', 'kea', 'index.d.ts')
|
|
75
|
+
|
|
76
|
+
writeFile(keaDtsPath, 'export function kea<T = any>(input: any): T\n')
|
|
77
|
+
writeFile(
|
|
78
|
+
firstLogicPath,
|
|
79
|
+
[
|
|
80
|
+
"import { kea } from 'kea'",
|
|
81
|
+
'',
|
|
82
|
+
'export const firstLogic = kea({',
|
|
83
|
+
' actions: () => ({ first: true }),',
|
|
84
|
+
'})',
|
|
85
|
+
'',
|
|
86
|
+
].join('\n'),
|
|
87
|
+
)
|
|
88
|
+
writeFile(
|
|
89
|
+
secondLogicPath,
|
|
90
|
+
[
|
|
91
|
+
"import { kea } from 'kea'",
|
|
92
|
+
"import { firstLogic } from './firstLogic'",
|
|
93
|
+
'',
|
|
94
|
+
'export const secondLogic = kea({',
|
|
95
|
+
' connect: { values: [firstLogic, ["first"]] },',
|
|
96
|
+
'})',
|
|
97
|
+
'',
|
|
98
|
+
].join('\n'),
|
|
99
|
+
)
|
|
100
|
+
writeFile(
|
|
101
|
+
unrelatedLogicPath,
|
|
102
|
+
[
|
|
103
|
+
"import { kea } from 'kea'",
|
|
104
|
+
'',
|
|
105
|
+
'export const unrelatedLogic = kea({',
|
|
106
|
+
' actions: () => ({ unrelated: true }),',
|
|
107
|
+
'})',
|
|
108
|
+
'',
|
|
109
|
+
].join('\n'),
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
const program = createProgram([firstLogicPath, secondLogicPath, unrelatedLogicPath])
|
|
113
|
+
const plan = planWatchTypegenPass(program, [
|
|
114
|
+
{ fileName: firstLogicPath, eventKind: ts.FileWatcherEventKind.Changed },
|
|
115
|
+
])
|
|
116
|
+
|
|
117
|
+
expect(plan).toEqual({
|
|
118
|
+
kind: 'files',
|
|
119
|
+
sourceFilePaths: [firstLogicPath, secondLogicPath].sort(),
|
|
120
|
+
reason: '2 affected Kea logic files',
|
|
121
|
+
})
|
|
122
|
+
} finally {
|
|
123
|
+
fs.rmSync(tempDir, { recursive: true, force: true })
|
|
124
|
+
}
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
test('watch planner regenerates logics affected by a helper type edit', () => {
|
|
128
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'kea-typegen-watch-helper-'))
|
|
129
|
+
|
|
130
|
+
try {
|
|
131
|
+
const logicDir = path.join(tempDir, 'src')
|
|
132
|
+
const helperPath = path.join(logicDir, 'helper.ts')
|
|
133
|
+
const logicPath = path.join(logicDir, 'logic.ts')
|
|
134
|
+
const unrelatedLogicPath = path.join(logicDir, 'unrelatedLogic.ts')
|
|
135
|
+
const keaDtsPath = path.join(tempDir, 'node_modules', 'kea', 'index.d.ts')
|
|
136
|
+
|
|
137
|
+
writeFile(keaDtsPath, 'export function kea<T = any>(input: any): T\n')
|
|
138
|
+
writeFile(helperPath, 'export interface HelperType { value: string }\n')
|
|
139
|
+
writeFile(
|
|
140
|
+
logicPath,
|
|
141
|
+
[
|
|
142
|
+
"import { kea } from 'kea'",
|
|
143
|
+
"import type { HelperType } from './helper'",
|
|
144
|
+
'',
|
|
145
|
+
'export const logic = kea({',
|
|
146
|
+
' actions: () => ({ setValue: (value: HelperType) => ({ value }) }),',
|
|
147
|
+
'})',
|
|
148
|
+
'',
|
|
149
|
+
].join('\n'),
|
|
150
|
+
)
|
|
151
|
+
writeFile(
|
|
152
|
+
unrelatedLogicPath,
|
|
153
|
+
[
|
|
154
|
+
"import { kea } from 'kea'",
|
|
155
|
+
'',
|
|
156
|
+
'export const unrelatedLogic = kea({',
|
|
157
|
+
' actions: () => ({ unrelated: true }),',
|
|
158
|
+
'})',
|
|
159
|
+
'',
|
|
160
|
+
].join('\n'),
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
const program = createProgram([helperPath, logicPath, unrelatedLogicPath])
|
|
164
|
+
const plan = planWatchTypegenPass(program, [
|
|
165
|
+
{ fileName: helperPath, eventKind: ts.FileWatcherEventKind.Changed },
|
|
166
|
+
])
|
|
167
|
+
|
|
168
|
+
expect(plan).toEqual({
|
|
169
|
+
kind: 'files',
|
|
170
|
+
sourceFilePaths: [logicPath],
|
|
171
|
+
reason: '1 affected Kea logic file',
|
|
172
|
+
})
|
|
173
|
+
} finally {
|
|
174
|
+
fs.rmSync(tempDir, { recursive: true, force: true })
|
|
175
|
+
}
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
test('watch planner maps generated type changes back to source logics and dependents', () => {
|
|
179
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'kea-typegen-watch-type-file-'))
|
|
180
|
+
|
|
181
|
+
try {
|
|
182
|
+
const logicDir = path.join(tempDir, 'src')
|
|
183
|
+
const firstLogicPath = path.join(logicDir, 'firstLogic.ts')
|
|
184
|
+
const firstLogicTypePath = path.join(logicDir, 'firstLogicType.ts')
|
|
185
|
+
const secondLogicPath = path.join(logicDir, 'secondLogic.ts')
|
|
186
|
+
const keaDtsPath = path.join(tempDir, 'node_modules', 'kea', 'index.d.ts')
|
|
187
|
+
|
|
188
|
+
writeFile(keaDtsPath, 'export function kea<T = any>(input: any): T\n')
|
|
189
|
+
writeFile(firstLogicTypePath, 'export interface firstLogicType {}\n')
|
|
190
|
+
writeFile(
|
|
191
|
+
firstLogicPath,
|
|
192
|
+
[
|
|
193
|
+
"import { kea } from 'kea'",
|
|
194
|
+
"import type { firstLogicType } from './firstLogicType'",
|
|
195
|
+
'',
|
|
196
|
+
'export const firstLogic = kea<firstLogicType>({',
|
|
197
|
+
' actions: () => ({ first: true }),',
|
|
198
|
+
'})',
|
|
199
|
+
'',
|
|
200
|
+
].join('\n'),
|
|
201
|
+
)
|
|
202
|
+
writeFile(
|
|
203
|
+
secondLogicPath,
|
|
204
|
+
[
|
|
205
|
+
"import { kea } from 'kea'",
|
|
206
|
+
"import { firstLogic } from './firstLogic'",
|
|
207
|
+
'',
|
|
208
|
+
'export const secondLogic = kea({',
|
|
209
|
+
' connect: { actions: [firstLogic, ["first"]] },',
|
|
210
|
+
'})',
|
|
211
|
+
'',
|
|
212
|
+
].join('\n'),
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
const program = createProgram([firstLogicPath, firstLogicTypePath, secondLogicPath])
|
|
216
|
+
const plan = planWatchTypegenPass(program, [
|
|
217
|
+
{ fileName: firstLogicTypePath, eventKind: ts.FileWatcherEventKind.Changed },
|
|
218
|
+
])
|
|
219
|
+
|
|
220
|
+
expect(plan).toEqual({
|
|
221
|
+
kind: 'files',
|
|
222
|
+
sourceFilePaths: [firstLogicPath, secondLogicPath].sort(),
|
|
223
|
+
reason: '2 affected Kea logic files',
|
|
224
|
+
})
|
|
225
|
+
} finally {
|
|
226
|
+
fs.rmSync(tempDir, { recursive: true, force: true })
|
|
227
|
+
}
|
|
228
|
+
})
|
|
229
|
+
|
|
230
|
+
test('watch planner falls back to a full pass for deleted files and resetContext changes', () => {
|
|
231
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'kea-typegen-watch-full-'))
|
|
232
|
+
|
|
233
|
+
try {
|
|
234
|
+
const logicDir = path.join(tempDir, 'src')
|
|
235
|
+
const logicPath = path.join(logicDir, 'logic.ts')
|
|
236
|
+
const contextPath = path.join(logicDir, 'context.ts')
|
|
237
|
+
const keaDtsPath = path.join(tempDir, 'node_modules', 'kea', 'index.d.ts')
|
|
238
|
+
|
|
239
|
+
writeFile(keaDtsPath, 'export function kea<T = any>(input: any): T\n')
|
|
240
|
+
writeFile(
|
|
241
|
+
logicPath,
|
|
242
|
+
[
|
|
243
|
+
"import { kea } from 'kea'",
|
|
244
|
+
'',
|
|
245
|
+
'export const logic = kea({',
|
|
246
|
+
' actions: () => ({ value: true }),',
|
|
247
|
+
'})',
|
|
248
|
+
'',
|
|
249
|
+
].join('\n'),
|
|
250
|
+
)
|
|
251
|
+
writeFile(
|
|
252
|
+
contextPath,
|
|
253
|
+
["import { resetContext } from 'kea'", '', 'resetContext({ plugins: [] })', ''].join('\n'),
|
|
31
254
|
)
|
|
32
255
|
|
|
33
|
-
|
|
34
|
-
expect(result.code).toBe(0)
|
|
256
|
+
const program = createProgram([logicPath, contextPath])
|
|
35
257
|
|
|
36
|
-
|
|
258
|
+
expect(
|
|
259
|
+
planWatchTypegenPass(program, [{ fileName: logicPath, eventKind: ts.FileWatcherEventKind.Deleted }]),
|
|
260
|
+
).toEqual({ kind: 'full', reason: 'deleted file detected' })
|
|
37
261
|
|
|
38
|
-
expect(
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
262
|
+
expect(
|
|
263
|
+
planWatchTypegenPass(program, [{ fileName: contextPath, eventKind: ts.FileWatcherEventKind.Changed }]),
|
|
264
|
+
).toEqual({
|
|
265
|
+
kind: 'full',
|
|
266
|
+
reason: `resetContext changed: ${path.relative(process.cwd(), contextPath)}`,
|
|
267
|
+
})
|
|
268
|
+
} finally {
|
|
269
|
+
fs.rmSync(tempDir, { recursive: true, force: true })
|
|
270
|
+
}
|
|
271
|
+
})
|
package/src/__tests__/write.ts
CHANGED
|
@@ -153,3 +153,59 @@ test('writeTypeImports replaces existing kea generic without leaving a trailing
|
|
|
153
153
|
fs.rmSync(tempDir, { recursive: true, force: true })
|
|
154
154
|
}
|
|
155
155
|
})
|
|
156
|
+
|
|
157
|
+
test('visitProgram limits project-aware single-file generation to the requested source file', () => {
|
|
158
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'kea-typegen-single-file-'))
|
|
159
|
+
|
|
160
|
+
try {
|
|
161
|
+
const logicDir = path.join(tempDir, 'src')
|
|
162
|
+
const firstLogicPath = path.join(logicDir, 'firstLogic.ts')
|
|
163
|
+
const secondLogicPath = path.join(logicDir, 'secondLogic.ts')
|
|
164
|
+
const keaDtsPath = path.join(tempDir, 'node_modules', 'kea', 'index.d.ts')
|
|
165
|
+
|
|
166
|
+
fs.mkdirSync(path.dirname(keaDtsPath), { recursive: true })
|
|
167
|
+
fs.mkdirSync(logicDir, { recursive: true })
|
|
168
|
+
|
|
169
|
+
fs.writeFileSync(keaDtsPath, 'export function kea<T = any>(input: any): T\n')
|
|
170
|
+
fs.writeFileSync(
|
|
171
|
+
firstLogicPath,
|
|
172
|
+
[
|
|
173
|
+
"import { kea } from 'kea'",
|
|
174
|
+
'',
|
|
175
|
+
'export const firstLogic = kea({',
|
|
176
|
+
' actions: () => ({ first: true }),',
|
|
177
|
+
'})',
|
|
178
|
+
'',
|
|
179
|
+
].join('\n'),
|
|
180
|
+
)
|
|
181
|
+
fs.writeFileSync(
|
|
182
|
+
secondLogicPath,
|
|
183
|
+
[
|
|
184
|
+
"import { kea } from 'kea'",
|
|
185
|
+
'',
|
|
186
|
+
'export const secondLogic = kea({',
|
|
187
|
+
' actions: () => ({ second: true }),',
|
|
188
|
+
'})',
|
|
189
|
+
'',
|
|
190
|
+
].join('\n'),
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
const program = ts.createProgram([firstLogicPath, secondLogicPath], {
|
|
194
|
+
module: ts.ModuleKind.CommonJS,
|
|
195
|
+
moduleResolution: ts.ModuleResolutionKind.NodeJs,
|
|
196
|
+
target: ts.ScriptTarget.ES2020,
|
|
197
|
+
skipLibCheck: true,
|
|
198
|
+
})
|
|
199
|
+
|
|
200
|
+
const parsedLogics = visitProgram(program, {
|
|
201
|
+
rootPath: logicDir,
|
|
202
|
+
typesPath: logicDir,
|
|
203
|
+
sourceFilePath: secondLogicPath,
|
|
204
|
+
log: () => {},
|
|
205
|
+
})
|
|
206
|
+
|
|
207
|
+
expect(parsedLogics.map((logic) => logic.logicName)).toEqual(['secondLogic'])
|
|
208
|
+
} finally {
|
|
209
|
+
fs.rmSync(tempDir, { recursive: true, force: true })
|
|
210
|
+
}
|
|
211
|
+
})
|
package/src/cli/typegen.ts
CHANGED
|
@@ -18,7 +18,11 @@ yargs
|
|
|
18
18
|
await runTypeGen({ ...includeKeaConfig(parsedToAppOptions(argv)), write: true, watch: true })
|
|
19
19
|
})
|
|
20
20
|
.option('config', { alias: 'c', describe: 'Path to tsconfig.json (otherwise auto-detected)', type: 'string' })
|
|
21
|
-
.option('file', {
|
|
21
|
+
.option('file', {
|
|
22
|
+
alias: 'f',
|
|
23
|
+
describe: 'Single file to evaluate. Uses --config/.kearc compiler options when available.',
|
|
24
|
+
type: 'string',
|
|
25
|
+
})
|
|
22
26
|
.option('root', {
|
|
23
27
|
alias: 'r',
|
|
24
28
|
describe: 'Root for logic paths. E.g: ./frontend/src',
|
|
@@ -51,6 +55,11 @@ yargs
|
|
|
51
55
|
describe: 'Cache generated logic files into .typegen, use them if generating a logic type for the first time',
|
|
52
56
|
type: 'boolean',
|
|
53
57
|
})
|
|
58
|
+
.option('prettier', {
|
|
59
|
+
describe: 'Format generated logic type declarations with Prettier (use --no-prettier to skip)',
|
|
60
|
+
type: 'boolean',
|
|
61
|
+
default: true,
|
|
62
|
+
})
|
|
54
63
|
.option('verbose', { describe: 'Slightly more verbose output log', type: 'boolean' })
|
|
55
64
|
.demandCommand()
|
|
56
65
|
.help()
|
package/src/print/print.ts
CHANGED
|
@@ -40,8 +40,16 @@ import { printInternalExtraInput } from './printInternalExtraInput'
|
|
|
40
40
|
import { convertToBuilders } from '../write/convertToBuilders'
|
|
41
41
|
import { cacheWrittenFile } from '../cache'
|
|
42
42
|
|
|
43
|
+
const prettierConfigCache = new Map<string, Promise<prettier.Options | null>>()
|
|
44
|
+
|
|
43
45
|
export async function runThroughPrettier(sourceText: string, filePath: string): Promise<string> {
|
|
44
|
-
|
|
46
|
+
let configPromise = prettierConfigCache.get(filePath)
|
|
47
|
+
if (!configPromise) {
|
|
48
|
+
configPromise = prettier.resolveConfig(filePath, { useCache: true })
|
|
49
|
+
prettierConfigCache.set(filePath, configPromise)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const options = await configPromise
|
|
45
53
|
if (options) {
|
|
46
54
|
try {
|
|
47
55
|
return await prettier.format(sourceText, { ...options, filepath: filePath })
|
|
@@ -107,11 +115,12 @@ export async function printToFiles(
|
|
|
107
115
|
const logicStrings = []
|
|
108
116
|
const requiredKeys = new Set(['Logic'])
|
|
109
117
|
for (const parsedLogic of parsedLogics) {
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
|
|
118
|
+
const logicTypeString = nodeToString(parsedLogic.interfaceDeclaration)
|
|
119
|
+
logicStrings.push(
|
|
120
|
+
appOptions.prettier === false
|
|
121
|
+
? logicTypeString
|
|
122
|
+
: await runThroughPrettier(logicTypeString, typeFileName),
|
|
113
123
|
)
|
|
114
|
-
logicStrings.push(logicTypeStirng)
|
|
115
124
|
for (const string of parsedLogic.importFromKeaInLogicType.values()) {
|
|
116
125
|
requiredKeys.add(string)
|
|
117
126
|
}
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
const fs = require('fs')
|
|
2
|
+
const os = require('os')
|
|
2
3
|
const path = require('path')
|
|
3
4
|
|
|
4
5
|
require('ts-node/register/transpile-only')
|
|
5
6
|
|
|
6
7
|
const repoRoot = path.resolve(__dirname, '..', '..')
|
|
7
|
-
const projectDir = fs.mkdtempSync(path.join(
|
|
8
|
+
const projectDir = fs.mkdtempSync(path.join(os.tmpdir(), 'kea-typegen-watch-smoke-'))
|
|
8
9
|
const tsconfigPath = path.join(projectDir, 'tsconfig.json')
|
|
10
|
+
const keaDtsPath = path.join(projectDir, 'node_modules', 'kea', 'index.d.ts')
|
|
9
11
|
const fileCount = 200
|
|
12
|
+
const logicPaths = []
|
|
10
13
|
|
|
11
14
|
const noop = () => {}
|
|
12
15
|
console.info = noop
|
|
@@ -18,6 +21,10 @@ let completed = 0
|
|
|
18
21
|
let settleTimer
|
|
19
22
|
let timeoutTimer
|
|
20
23
|
let finished = false
|
|
24
|
+
let editTriggered = false
|
|
25
|
+
let incrementalAfterEdit = false
|
|
26
|
+
const parsedLogicCountsAfterEdit = []
|
|
27
|
+
const sourceFilePathsAfterEdit = []
|
|
21
28
|
|
|
22
29
|
function cleanup() {
|
|
23
30
|
try {
|
|
@@ -41,16 +48,31 @@ function finish(code) {
|
|
|
41
48
|
completed,
|
|
42
49
|
active,
|
|
43
50
|
maxActive,
|
|
51
|
+
incrementalAfterEdit,
|
|
52
|
+
parsedLogicCountsAfterEdit,
|
|
53
|
+
sourceFilePathsAfterEdit,
|
|
44
54
|
}) + '\n',
|
|
45
55
|
)
|
|
46
56
|
process.exit(code)
|
|
47
57
|
}
|
|
48
58
|
|
|
49
59
|
function scheduleFinishIfSettled() {
|
|
50
|
-
if (
|
|
51
|
-
|
|
52
|
-
settleTimer = setTimeout(() => finish(0), 300)
|
|
60
|
+
if (active !== 0) {
|
|
61
|
+
return
|
|
53
62
|
}
|
|
63
|
+
|
|
64
|
+
clearTimeout(settleTimer)
|
|
65
|
+
settleTimer = setTimeout(() => {
|
|
66
|
+
if (!editTriggered && started > 1) {
|
|
67
|
+
editTriggered = true
|
|
68
|
+
fs.appendFileSync(logicPaths[0], '\n// trigger incremental watch pass\n')
|
|
69
|
+
return
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (editTriggered && incrementalAfterEdit) {
|
|
73
|
+
finish(0)
|
|
74
|
+
}
|
|
75
|
+
}, 300)
|
|
54
76
|
}
|
|
55
77
|
|
|
56
78
|
process.on('uncaughtException', (error) => {
|
|
@@ -82,9 +104,13 @@ fs.writeFileSync(
|
|
|
82
104
|
),
|
|
83
105
|
)
|
|
84
106
|
|
|
107
|
+
fs.mkdirSync(path.dirname(keaDtsPath), { recursive: true })
|
|
108
|
+
fs.writeFileSync(keaDtsPath, 'export function kea<T = any>(input: any): T\n')
|
|
109
|
+
|
|
85
110
|
for (let i = 0; i < fileCount; i++) {
|
|
86
111
|
const dir = path.join(projectDir, 'src', `group${String(i % 10).padStart(2, '0')}`)
|
|
87
112
|
const filePath = path.join(dir, `logic${i}.ts`)
|
|
113
|
+
logicPaths.push(filePath)
|
|
88
114
|
|
|
89
115
|
fs.mkdirSync(dir, { recursive: true })
|
|
90
116
|
fs.writeFileSync(
|
|
@@ -109,11 +135,20 @@ const printModule = require(path.join(repoRoot, 'src/print/print'))
|
|
|
109
135
|
const originalPrintToFiles = printModule.printToFiles
|
|
110
136
|
|
|
111
137
|
printModule.printToFiles = async function (...args) {
|
|
138
|
+
const appOptions = args[1]
|
|
139
|
+
const parsedLogics = args[2]
|
|
140
|
+
|
|
112
141
|
active += 1
|
|
113
142
|
started += 1
|
|
114
143
|
maxActive = Math.max(maxActive, active)
|
|
115
144
|
clearTimeout(settleTimer)
|
|
116
145
|
|
|
146
|
+
if (editTriggered) {
|
|
147
|
+
parsedLogicCountsAfterEdit.push(parsedLogics.length)
|
|
148
|
+
sourceFilePathsAfterEdit.push(appOptions.sourceFilePath || null)
|
|
149
|
+
incrementalAfterEdit = incrementalAfterEdit || (parsedLogics.length === 1 && !!appOptions.sourceFilePath)
|
|
150
|
+
}
|
|
151
|
+
|
|
117
152
|
await new Promise((resolve) => setTimeout(resolve, 25))
|
|
118
153
|
|
|
119
154
|
try {
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
const fs = require('fs')
|
|
2
2
|
const Module = require('module')
|
|
3
|
+
const os = require('os')
|
|
3
4
|
const path = require('path')
|
|
4
5
|
|
|
5
6
|
require('ts-node/register/transpile-only')
|
|
6
7
|
|
|
7
8
|
const repoRoot = path.resolve(__dirname, '..', '..')
|
|
8
|
-
const projectDir = fs.mkdtempSync(path.join(
|
|
9
|
+
const projectDir = fs.mkdtempSync(path.join(os.tmpdir(), 'kea-typegen-write-smoke-'))
|
|
9
10
|
const tsconfigPath = path.join(projectDir, 'tsconfig.json')
|
|
10
11
|
const logicFilePath = path.join(projectDir, 'src', 'logic.ts')
|
|
12
|
+
const keaDtsPath = path.join(projectDir, 'node_modules', 'kea', 'index.d.ts')
|
|
11
13
|
|
|
12
14
|
const noop = () => {}
|
|
13
15
|
|
|
@@ -83,6 +85,7 @@ process.on('unhandledRejection', (error) => {
|
|
|
83
85
|
})
|
|
84
86
|
|
|
85
87
|
fs.mkdirSync(path.dirname(logicFilePath), { recursive: true })
|
|
88
|
+
fs.mkdirSync(path.dirname(keaDtsPath), { recursive: true })
|
|
86
89
|
fs.writeFileSync(
|
|
87
90
|
tsconfigPath,
|
|
88
91
|
JSON.stringify(
|
|
@@ -102,6 +105,8 @@ fs.writeFileSync(
|
|
|
102
105
|
),
|
|
103
106
|
)
|
|
104
107
|
|
|
108
|
+
fs.writeFileSync(keaDtsPath, 'export function kea<T = any>(input: any): T\n')
|
|
109
|
+
|
|
105
110
|
fs.writeFileSync(
|
|
106
111
|
logicFilePath,
|
|
107
112
|
[
|