sandstone-cli 2.4.0 → 2.4.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sandstone-cli",
3
- "version": "2.4.0",
3
+ "version": "2.4.1",
4
4
  "description": "The CLI for Sandstone - the minecraft pack creation library.",
5
5
  "type": "module",
6
6
  "exports": "./lib/index.js",
@@ -70,7 +70,7 @@
70
70
  "@types/semver": "^7.5.3",
71
71
  "bun-types": "^1.3.9",
72
72
  "node-pty": "^1.1.0",
73
- "sandstone": "^1.0.0-beta.4",
73
+ "sandstone": "^1.0.0-beta.5",
74
74
  "typescript": "^5.2.2"
75
75
  },
76
76
  "trustedDependencies": [
@@ -515,7 +515,7 @@ export async function _buildCommand(
515
515
  const stackTrace = traceStart >= 0 ? stackLines.slice(traceStart).join('\n') : ''
516
516
 
517
517
  // Resolve source maps for better error locations
518
- const resolvedStackTrace = stackTrace ? await resolveStackTrace(stackTrace) : ''
518
+ const resolvedStackTrace = stackTrace ? resolveStackTrace(stackTrace) : ''
519
519
  const formattedError = resolvedStackTrace ? `${errorMessage}\n${resolvedStackTrace}` : errorMessage
520
520
  return {
521
521
  success: false,
@@ -559,7 +559,7 @@ export async function buildCommand(opts: BuildOptions, _folder?: string, silent
559
559
  const stackTrace = traceStart >= 0 ? stackLines.slice(traceStart).join('\n') : ''
560
560
 
561
561
  // Resolve source maps for better error locations
562
- const resolvedStackTrace = stackTrace ? await resolveStackTrace(stackTrace) : ''
562
+ const resolvedStackTrace = stackTrace ? resolveStackTrace(stackTrace) : ''
563
563
  const formattedError = resolvedStackTrace ? `${errorMessage}\n${resolvedStackTrace}` : errorMessage
564
564
  if (!silent) {
565
565
  log(chalk.bgRed.white('BuildError') + chalk.gray(':'), formattedError)
@@ -130,7 +130,7 @@ export async function createCommand(_project: string, opts: CreateOptions) {
130
130
 
131
131
  const sv = (v: string) => new SemVer(v)
132
132
 
133
- const versions = [[sv('1.0.0-beta.4'), sv(CLI_VERSION)], [sv('1.0.0-beta.3'), sv('2.3.2')]] as const
133
+ const versions = [[sv('1.0.0-beta.5'), sv(CLI_VERSION)]] as const
134
134
 
135
135
  const version = await select({
136
136
  message: 'Which version of Sandstone do you want to use? These are the only supported versions for new projects.',
@@ -9,6 +9,7 @@ import { WatchUI, getWatchUIAPI } from '../ui/WatchUI.js'
9
9
  import { initLogger, log, logInfo, logWarn, logError, logDebug, logTrace, setLiveLogCallback } from '../ui/logger.js'
10
10
  import type { TrackedChange, ChangeCategory } from '../ui/types.js'
11
11
  import { hot } from '@sandstone-mc/hot-hook'
12
+ import { resolveStackTrace } from '../utils/source-map.js'
12
13
  import fs from 'fs-extra'
13
14
  import { join, relative } from 'node:path'
14
15
 
@@ -33,7 +34,14 @@ function enableConsoleCapture() {
33
34
  .replace(/^Error\n/, '')
34
35
  .replace(/\?hot-hook=\d+/g, '')
35
36
  .replace(/file:\/\/\/?/g, '')
36
- logTrace(...args, '\n' + cleanedStack)
37
+
38
+ // Resolve source maps for stack frames
39
+ const stackLines = cleanedStack.split('\n')
40
+ const traceStart = stackLines.findIndex(line => line.trimStart().startsWith('at '))
41
+ const stackTrace = traceStart >= 0 ? stackLines.slice(traceStart).join('\n') : ''
42
+ const resolvedStack = stackTrace ? resolveStackTrace(stackTrace) : cleanedStack
43
+
44
+ logTrace(...args, '\n' + resolvedStack)
37
45
  }
38
46
  }
39
47
 
package/src/ui/logger.ts CHANGED
@@ -88,13 +88,14 @@ async function logWorkerMain(level: string | false, ...args: unknown[]) {
88
88
  const chunks: (string | Buffer | Uint8Array)[] = []
89
89
 
90
90
  // Timestamp and level prefix
91
- chunks.push(`[${new Date().toISOString()}]${level !== false ? ` [${level}]` : ''} `)
91
+ const prefix = `[${new Date().toISOString()}]${level !== false ? ` [${level}]` : ''} `
92
+ chunks.push(prefix)
92
93
 
93
94
  // Process each argument
94
95
  for (let i = 0; i < args.length; i++) {
95
96
  const arg = args[i]
96
97
  if (typeof arg === 'string') {
97
- chunks.push(stripVTControlCharacters(arg))
98
+ chunks.push(stripVTControlCharacters(arg).replaceAll('\n', `\n${' '.repeat(prefix.length)}`))
98
99
  } else if (Buffer.isBuffer(arg) || arg instanceof Uint8Array) {
99
100
  chunks.push(arg)
100
101
  } else if (arg instanceof ArrayBuffer) {
@@ -103,7 +104,7 @@ async function logWorkerMain(level: string | false, ...args: unknown[]) {
103
104
  chunks.push(new Uint8Array(await arg.arrayBuffer()))
104
105
  } else {
105
106
  // Use util.format for objects, numbers, etc.
106
- chunks.push(format('%O', arg))
107
+ chunks.push(stripVTControlCharacters(format('%O', arg)).replaceAll('\n', `\n${' '.repeat(prefix.length)}`))
107
108
  }
108
109
  // Add space between args (but not after last)
109
110
  if (i < args.length - 1) {
@@ -6,17 +6,17 @@
6
6
  */
7
7
 
8
8
  import { SourceMapConsumer, type RawSourceMap } from 'source-map-js'
9
- import { readFile } from 'fs/promises'
10
- import { dirname, join, resolve } from 'path'
9
+ import { readFileSync } from 'fs'
10
+ import { dirname, resolve } from 'path'
11
11
 
12
12
  // Cache for loaded source map consumers
13
13
  const sourceMapCache = new Map<string, SourceMapConsumer | null>()
14
14
 
15
15
  /**
16
- * Try to load a source map for a given JS file.
16
+ * Synchronously load a source map for a given JS file.
17
17
  * Returns null if no source map is found or it's invalid.
18
18
  */
19
- async function loadSourceMap(jsFilePath: string): Promise<SourceMapConsumer | null> {
19
+ function loadSourceMapSync(jsFilePath: string): SourceMapConsumer | null {
20
20
  // Check cache first
21
21
  if (sourceMapCache.has(jsFilePath)) {
22
22
  return sourceMapCache.get(jsFilePath) ?? null
@@ -24,7 +24,7 @@ async function loadSourceMap(jsFilePath: string): Promise<SourceMapConsumer | nu
24
24
 
25
25
  try {
26
26
  // Read the JS file to find the sourceMappingURL
27
- const jsContent = await readFile(jsFilePath, 'utf8')
27
+ const jsContent = readFileSync(jsFilePath, 'utf8')
28
28
 
29
29
  // Look for sourceMappingURL comment
30
30
  const match = jsContent.match(/\/\/[#@]\s*sourceMappingURL=(.+)$/m)
@@ -35,6 +35,7 @@ async function loadSourceMap(jsFilePath: string): Promise<SourceMapConsumer | nu
35
35
 
36
36
  const sourceMappingURL = match[1].trim()
37
37
  let mapPath: string
38
+ let mapContent: string
38
39
 
39
40
  if (sourceMappingURL.startsWith('data:')) {
40
41
  // Inline source map (base64 encoded)
@@ -43,17 +44,13 @@ async function loadSourceMap(jsFilePath: string): Promise<SourceMapConsumer | nu
43
44
  sourceMapCache.set(jsFilePath, null)
44
45
  return null
45
46
  }
46
- const mapContent = Buffer.from(base64Match[1], 'base64').toString('utf8')
47
- const rawMap: RawSourceMap = JSON.parse(mapContent)
48
- const consumer = new SourceMapConsumer(rawMap)
49
- sourceMapCache.set(jsFilePath, consumer)
50
- return consumer
47
+ mapContent = Buffer.from(base64Match[1], 'base64').toString('utf8')
51
48
  } else {
52
49
  // External source map file
53
50
  mapPath = resolve(dirname(jsFilePath), sourceMappingURL)
51
+ mapContent = readFileSync(mapPath, 'utf8')
54
52
  }
55
53
 
56
- const mapContent = await readFile(mapPath, 'utf8')
57
54
  const rawMap: RawSourceMap = JSON.parse(mapContent)
58
55
  const consumer = new SourceMapConsumer(rawMap)
59
56
  sourceMapCache.set(jsFilePath, consumer)
@@ -117,9 +114,9 @@ function parseStackLine(line: string): StackFrame {
117
114
  }
118
115
 
119
116
  /**
120
- * Resolve a stack frame using source maps.
117
+ * Resolve a stack frame using source maps (synchronous).
121
118
  */
122
- async function resolveStackFrame(frame: StackFrame): Promise<string> {
119
+ function resolveStackFrame(frame: StackFrame): string {
123
120
  if (!frame.filePath || !frame.line || !frame.column) {
124
121
  return frame.original
125
122
  }
@@ -130,7 +127,7 @@ async function resolveStackFrame(frame: StackFrame): Promise<string> {
130
127
  }
131
128
 
132
129
  try {
133
- const consumer = await loadSourceMap(frame.filePath)
130
+ const consumer = loadSourceMapSync(frame.filePath)
134
131
  if (!consumer) {
135
132
  return frame.original
136
133
  }
@@ -164,10 +161,10 @@ async function resolveStackFrame(frame: StackFrame): Promise<string> {
164
161
  }
165
162
 
166
163
  /**
167
- * Resolve source maps in a stack trace string.
164
+ * Resolve source maps in a stack trace string (synchronous).
168
165
  * Returns the stack trace with original source locations where possible.
169
166
  */
170
- export async function resolveStackTrace(stack: string): Promise<string> {
167
+ export function resolveStackTrace(stack: string): string {
171
168
  const lines = stack.split('\n')
172
169
  const resolvedLines: string[] = []
173
170
 
@@ -175,7 +172,7 @@ export async function resolveStackTrace(stack: string): Promise<string> {
175
172
  // Only process lines that look like stack frames
176
173
  if (line.trimStart().startsWith('at ')) {
177
174
  const frame = parseStackLine(line)
178
- const resolved = await resolveStackFrame(frame)
175
+ const resolved = resolveStackFrame(frame)
179
176
  resolvedLines.push(resolved)
180
177
  } else {
181
178
  resolvedLines.push(line)
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const CLI_VERSION = '2.4.0'
1
+ export const CLI_VERSION = '2.4.1'