Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@tekir/cli

Package Overview
Dependencies
Maintainers
1
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@tekir/cli - npm Package Compare versions

Comparing version
0.1.4
to
0.1.5
+68
-10
bin/tekir.mjs

@@ -51,3 +51,3 @@ #!/usr/bin/env bun

import { spawn, spawnSync } from 'node:child_process'
import { isAbsolute, resolve } from 'node:path'
import { isAbsolute, join, resolve } from 'node:path'
import { pathToFileURL } from 'node:url'

@@ -318,16 +318,74 @@

if (command === 'build') {
// Tell library code that this process exists for bundling, not for
// serving traffic. Eager side-effect modules (Redis subscribers,
// queue workers, fs watchers, scheduler ticks) read `TEKIR_RUNNER`
// and short-circuit when it equals `'build'`, the same way they do
// for `'test'`. Use `??=` so an outer caller can pin the value first
// (e.g. CI scripts wrapping `tekir build` with their own marker).
process.env.TEKIR_RUNNER ??= 'build'
ensureBunOrReexec()
// From here on we are guaranteed to be running under Bun.
//
// Run the entry through `runEntry` (same path as `serve`) so the
// user's `tekir({...})` instance gets to register `onBuild` hooks
// before we bundle. Inside `tekir()` core, `argv[2] === 'build'` is
// detected and triggers `server.build()` (which fires the hooks,
// e.g. `@tekir/vite` builds the frontend into `dist/client/`)
// followed by the actual `Bun.build` for the backend bundle. Calling
// `runBuild` directly from this bin, as we did before, skipped the
// entry entirely and silently dropped any frontend build.
// The `tekir build` entry is parsed by `@tekir/core`'s build-entry
// preparer, which extracts the top-level `await tekir({...})` call
// and emits a temporary source containing only the imports and
// declarations reachable from the call's argument expression. That
// temp file is what gets imported here; `process.argv[1]` keeps the
// original entry path so the in-app build dispatch bundles the real
// file (the temp file is throwaway). Everything else in the user
// entry — registerDir, route handlers, app.start callbacks, eager
// service constructors, scheduler ticks, fs watchers — is dropped
// for the duration of the build, so a hostile remote dependency
// (Redis with no listener, queue server, ...) never blocks the
// bundle. Entries we cannot parse statically (no literal `tekir()`
// call, multiple calls, parse error) return `null` from
// `generateBuildEntry`; in that case the cli falls through to a
// plain full-entry import as a last resort.
const entry = await findEntry(entryFlag, tekirCfg)
const rest = argv.slice(1)
await runEntry(entry, command, rest)
const absEntry = isAbsolute(entry) ? entry : resolve(process.cwd(), entry)
let result = null
try {
const { generateBuildEntry } = await import('@tekir/core')
result = await generateBuildEntry(absEntry)
} catch {
// @tekir/core not installed locally; fall through.
}
if (result && result.source) {
const { writeFileSync, unlinkSync } = await import('fs')
const { dirname } = await import('node:path')
// Write the build-entry alongside the original file (not into
// `os.tmpdir()`) so relative imports the user wrote (`import
// './types'`, `import '../config/env'`, ...) resolve from the
// expected directory. Bun resolves bare `./` specifiers relative
// to the importing file; if the temp file lives elsewhere those
// imports throw `Cannot find module './...'` even though the
// dependency is right next to the original entry. The leading dot
// in the filename hides it from most editors, and the
// `${pid}-${timestamp}` suffix keeps parallel builds from racing
// on the same path. Cleanup runs in a `finally` block; an orphan
// would survive a hard crash but the pattern is easy to spot and
// safe to delete by hand.
const buildEntryPath = join(dirname(absEntry), `.tekir-build-entry-${process.pid}-${Date.now()}.ts`)
writeFileSync(buildEntryPath, result.source)
// The in-app build dispatcher calls `process.exit(0)` once
// `Bun.build` resolves, which short-circuits any `try/finally`
// unlink we'd schedule below. `process.on('exit')` runs
// synchronously at the very end of the exit sequence and is
// allowed to do filesystem work, so the temp file goes away on
// every successful build. The handler also covers a non-zero exit
// (build failure) since `process.exit(N)` fires the same event.
process.on('exit', () => { try { unlinkSync(buildEntryPath) } catch {} })
// `process.argv[1]` MUST stay on the original entry so the in-app
// build dispatcher bundles the real file. We import the temp file
// only to fire the `tekir({...})` call.
process.argv = [process.argv[0], absEntry, command, ...rest]
try {
await import(pathToFileURL(buildEntryPath).href)
} finally {
try { unlinkSync(buildEntryPath) } catch {}
}
} else {
await runEntry(entry, command, rest)
}
}

@@ -334,0 +392,0 @@

+2
-9
{
"name": "@tekir/cli",
"version": "0.1.4",
"version": "0.1.5",
"description": "tekir command-line tool: serve, build, generate-key, and provider-registered commands.",

@@ -33,12 +33,5 @@ "author": "dev@tekir.io",

"dependencies": {
"@tekir/core": "^0.1.28"
},
"peerDependencies": {
"@tekir/core": "^0.1.29",
"oxc-parser": ">=0.30.0"
},
"peerDependenciesMeta": {
"oxc-parser": {
"optional": true
}
},
"engines": {

@@ -45,0 +38,0 @@ "node": ">=18.0.0"