Skip to content

Commit

Permalink
fix: improve vscode extension handling of relative paths
Browse files Browse the repository at this point in the history
  • Loading branch information
rubenfiszel committed Sep 16, 2024
1 parent de78f6c commit 8ae6c32
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 43 deletions.
14 changes: 3 additions & 11 deletions frontend/src/lib/ata/edgeCases.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { isTypescriptRelativePath } from '$lib/relative_imports'

/** Converts some of the known global imports to node so that we grab the right info */
export const mapModuleNameToModule = (moduleSpecifier: string) => {
// in node repl:
Expand Down Expand Up @@ -61,7 +63,7 @@ export const mapModuleNameToModule = (moduleSpecifier: string) => {
return 'node'
}

if (isRelativePath(moduleSpecifier)) {
if (isTypescriptRelativePath(moduleSpecifier)) {
return moduleSpecifier
}
// strip module filepath e.g. lodash/identity => lodash
Expand All @@ -70,13 +72,3 @@ export const mapModuleNameToModule = (moduleSpecifier: string) => {

return moduleName
}

export function isRelativePath(d: string) {
return (
d.startsWith('./') ||
d.startsWith('../') ||
d.startsWith('/') ||
d.startsWith('.../') ||
d.startsWith('/')
)
}
7 changes: 4 additions & 3 deletions frontend/src/lib/ata/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isTypescriptRelativePath } from '$lib/relative_imports'
import {
getDTSFileForModuleWithVersion,
getFiletreeForModuleWithVersion,
Expand All @@ -8,7 +9,7 @@ import {
type NPMTreeMeta,
type ResLimit
} from './apis'
import { isRelativePath, mapModuleNameToModule } from './edgeCases'
import { mapModuleNameToModule } from './edgeCases'

export interface ATABootstrapConfig {
root: string
Expand Down Expand Up @@ -113,7 +114,7 @@ export const setupTypeAcquisition = (config: ATABootstrapConfig) => {
.filter((f) => !moduleMap.has(f.raw))

if (depth == 0) {
const relativeDeps = depsToGet.filter((f) => isRelativePath(f.raw))
const relativeDeps = depsToGet.filter((f) => isTypescriptRelativePath(f.raw))
relativeDeps.forEach(async (f) => {
let path = f.raw.startsWith('/')
? f.raw
Expand All @@ -129,7 +130,7 @@ export const setupTypeAcquisition = (config: ATABootstrapConfig) => {
}
depsToGet.forEach((dep) => moduleMap.set(dep.raw, { state: 'loading' }))

depsToGet = depsToGet.filter((f) => !isRelativePath(f.raw))
depsToGet = depsToGet.filter((f) => !isTypescriptRelativePath(f.raw))
if (depsToGet.length === 0) {
return []
}
Expand Down
94 changes: 78 additions & 16 deletions frontend/src/lib/components/Dev.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@
import type { FlowCopilotContext, FlowCopilotModule } from './copilot/flow'
import { pickScript } from './flows/flowStateUtils'
import type { Schedule } from './flows/scheduleUtils'
import {
approximateFindPythonRelativePath,
isTypescriptRelativePath,
parseTypescriptDeps
} from '$lib/relative_imports'
import Tooltip from './Tooltip.svelte'
$: token = $page.url.searchParams.get('wm_token') ?? undefined
$: workspace = $page.url.searchParams.get('workspace') ?? undefined
Expand All @@ -50,7 +56,8 @@
$: if (token) {
OpenAPI.WITH_CREDENTIALS = true
OpenAPI.TOKEN = $page.url.searchParams.get('wm_token')!
OpenAPI.TOKEN = token
loadUser()
}
let flowCopilotContext: FlowCopilotContext = {
Expand Down Expand Up @@ -184,7 +191,7 @@
let timeout: NodeJS.Timeout | undefined = undefined
let loadingCodebaseButton = false
let lastBundleCommandId = ''
let lastCommandId = ''
const el = (event) => {
// sendUserToast(`Received message from parent ${event.data.type}`, true)
Expand All @@ -195,10 +202,23 @@
mode = 'script'
replaceScript(event.data)
} else if (event.data.type == 'testBundle') {
if (event.data.id == lastBundleCommandId) {
if (event.data.id == lastCommandId) {
testBundle(event.data.file, event.data.isTar)
} else {
sendUserToast(`Bundle received ${lastBundleCommandId} was obsolete, ignoring`, true)
sendUserToast(`Bundle received ${lastCommandId} was obsolete, ignoring`, true)
}
} else if (event.data.type == 'testPreviewBundle') {
if (event.data.id == lastCommandId && currentScript) {
testJobLoader.runPreview(
currentScript.path,
event.data.file,
currentScript.language,
args,
currentScript.tag,
useLock ? currentScript.lock : undefined
)
} else {
sendUserToast(`Bundle received ${lastCommandId} was obsolete, ignoring`, true)
}
} else if (event.data.type == 'testBundleError') {
loadingCodebaseButton = false
Expand Down Expand Up @@ -330,25 +350,34 @@
}
}
let typescriptBundlePreviewMode = false
function runTest() {
if (mode == 'script') {
if (!currentScript) {
return
}
if (currentScript.isCodebase) {
loadingCodebaseButton = true
lastBundleCommandId = Math.random().toString(36).substring(7)
window.parent?.postMessage({ type: 'testBundle', id: lastBundleCommandId }, '*')
lastCommandId = Math.random().toString(36).substring(7)
window.parent?.postMessage({ type: 'testBundle', id: lastCommandId }, '*')
} else {
//@ts-ignore
testJobLoader.runPreview(
currentScript.path,
currentScript.content,
currentScript.language,
args,
currentScript.tag,
useLock ? currentScript.lock : undefined
)
if (relativePaths.length > 0 && typescriptBundlePreviewMode) {
lastCommandId = Math.random().toString(36).substring(7)
window.parent?.postMessage(
{ type: 'testPreviewBundle', external: ['!/*'], id: lastCommandId },
'*'
)
} else {
//@ts-ignore
testJobLoader.runPreview(
currentScript.path,
currentScript.content,
currentScript.language,
args,
currentScript.tag,
useLock ? currentScript.lock : undefined
)
}
}
} else {
flowPreviewButtons?.openPreview()
Expand Down Expand Up @@ -376,14 +405,21 @@
}
}
let relativePaths: any[] = []
let lastPath: string | undefined = undefined
async function replaceScript(lastEdit: LastEditScript) {
currentScript = lastEdit
if (lastPath !== lastEdit.path) {
schema = emptySchema()
relativePaths = []
}
try {
await inferArgs(lastEdit.language, lastEdit.content, schema)
if (lastEdit?.language == 'bun') {
relativePaths = await parseTypescriptDeps(lastEdit.content).filter(isTypescriptRelativePath)
} else if (lastEdit?.language == 'python3') {
relativePaths = approximateFindPythonRelativePath(lastEdit.content)
}
schema = schema
lastPath = lastEdit.path
validCode = true
Expand Down Expand Up @@ -521,7 +557,7 @@

<main class="h-screen w-full">
{#if mode == 'script'}
<div class="flex flex-col h-full">
<div class="flex flex-col min-h-full overflow-auto">
<div class="absolute top-0 left-2">
<DarkModeToggle bind:darkMode bind:this={darkModeToggle} forcedDarkMode={false} />
</div>
Expand Down Expand Up @@ -550,6 +586,32 @@
options={{ left: 'Infer lockfile', right: 'Use current lockfile' }}
/>
</div>
{#if (currentScript?.language == 'bun' || currentScript?.language == 'python3') && currentScript?.content != undefined}
{#if relativePaths.length > 0}
<div class="flex flex-row-reverse py-1">
{#if currentScript?.language == 'bun'}
<Toggle
size="xs"
bind:checked={typescriptBundlePreviewMode}
options={{
left: '',
right: 'bundle relative paths for preview',
rightTooltip:
'(Beta) Instead of only sending the current file for preview and rely on already deployed code for the common logic, bundle all code that is imported in relative paths'
}}
/>
{:else if currentScript?.language == 'python3'}
<div class="text-xs text-yellow-500"
>relative imports detected<Tooltip
>Beware that when using relative imports, the code used in preview for those is
the one that is already deployed. If you make update to the common logic, you will
need to `wmill sync push` to see it reflected in the preview runs.</Tooltip
></div
>
{/if}
</div>
{/if}
{/if}
<div class="flex justify-center pt-1">
{#if testIsLoading}
<Button on:click={testJobLoader?.cancelJob} btnClasses="w-full" color="red" size="xs">
Expand Down
5 changes: 3 additions & 2 deletions frontend/src/lib/components/Editor.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -167,9 +167,10 @@
SNOWFLAKE_TYPES
} from '$lib/consts'
import { setupTypeAcquisition } from '$lib/ata/index'
import { initWasmTs, parseDeps } from '$lib/infer'
import { initWasmTs } from '$lib/infer'
import { initVim } from './monaco_keybindings'
import { buildWorkerDefinition } from '$lib/monaco_workers/build_workers'
import { parseTypescriptDeps } from '$lib/relative_imports'
// import EditorTheme from './EditorTheme.svelte'
Expand Down Expand Up @@ -1220,7 +1221,7 @@
ata = setupTypeAcquisition({
projectName: 'Windmill',
depsParser: (c) => {
return parseDeps(c)
return parseTypescriptDeps(c)
},
root,
scriptPath: path,
Expand Down
12 changes: 1 addition & 11 deletions frontend/src/lib/infer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type { Schema, SupportedLanguage } from './common.js'
import { emptySchema, sortObject } from './utils.js'
import { tick } from 'svelte'

import initTsParser, { parse_deno, parse_outputs, parse_ts_imports } from 'windmill-parser-wasm-ts'
import initTsParser, { parse_deno, parse_outputs } from 'windmill-parser-wasm-ts'
import initRegexParsers, {
parse_sql,
parse_mysql,
Expand Down Expand Up @@ -55,16 +55,6 @@ async function initWasmGo() {
await initGoParser(wasmUrlGo)
}

export function parseDeps(code: string): string[] {
let r = JSON.parse(parse_ts_imports(code))
if (r.error) {
console.error(r.error)
return []
} else {
return r.imports
}
}

export async function inferArgs(
language: SupportedLanguage | 'bunnative' | undefined,
code: string,
Expand Down
30 changes: 30 additions & 0 deletions frontend/src/lib/relative_imports.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { parse_ts_imports } from 'windmill-parser-wasm-ts'

export function parseTypescriptDeps(code: string): string[] {
let r = JSON.parse(parse_ts_imports(code))
if (r.error) {
console.error(r.error)
return []
} else {
return r.imports
}
}

export function isTypescriptRelativePath(d: string) {
return (
d.startsWith('./') ||
d.startsWith('../') ||
d.startsWith('/') ||
d.startsWith('.../') ||
d.startsWith('/')
)
}

export function approximateFindPythonRelativePath(code: string) {
// Define the regular expression for finding relative imports
const regex = /^\s*from\s+(\.+)\w*\s+import\s+.+$/gm

// Use match to find all matches in the code
const matches = code.match(regex)
return [...(matches?.entries() ?? [])] || []
}

0 comments on commit 8ae6c32

Please sign in to comment.