or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

callback-api.mdindex.mdstream-api.mdsync-api.md

sync-api.mddocs/

0

# Synchronous API

1

2

Synchronous data transformation for immediate processing of data arrays. The sync API provides blocking execution with direct return values, ideal for small datasets where simplicity and immediate results are prioritized.

3

4

## Capabilities

5

6

### Synchronous Transform Function

7

8

Transform an array of records synchronously with immediate results.

9

10

```javascript { .api }

11

/**

12

* Transform records synchronously

13

* @param records - Array of data to transform

14

* @param handler - Synchronous function to transform each record

15

* @returns Array of transformed results

16

*/

17

function transform<T, U>(records: Array<T>, handler: Handler<T, U>): Array<U>;

18

19

/**

20

* Transform with options synchronously

21

* @param records - Array of data to transform

22

* @param options - Configuration options (limited subset)

23

* @param handler - Synchronous function to transform each record

24

* @returns Array of transformed results

25

*/

26

function transform<T, U>(

27

records: Array<T>,

28

options: Options,

29

handler: Handler<T, U>

30

): Array<U>;

31

32

/**

33

* Synchronous handler type - must return result directly

34

*/

35

type Handler<T = any, U = any> = (record: T, params?: any) => U;

36

```

37

38

**Module Import:**

39

40

```javascript

41

// Import from sync module

42

import { transform } from "stream-transform/sync";

43

44

// CommonJS

45

const { transform } = require("stream-transform/sync");

46

47

// Browser ESM

48

import { transform } from "stream-transform/browser/esm/sync";

49

```

50

51

**Usage Examples:**

52

53

```javascript

54

import { transform } from "stream-transform/sync";

55

56

// Basic synchronous transformation

57

const numbers = [1, 2, 3, 4, 5];

58

const doubled = transform(numbers, (num) => num * 2);

59

console.log(doubled); // [2, 4, 6, 8, 10]

60

61

// Object transformation

62

const users = [

63

{ name: " Alice ", age: "25" },

64

{ name: " Bob ", age: "30" }

65

];

66

67

const cleanUsers = transform(users, (user) => ({

68

name: user.name.trim(),

69

age: parseInt(user.age),

70

processed: true

71

}));

72

73

console.log(cleanUsers);

74

// [

75

// { name: "Alice", age: 25, processed: true },

76

// { name: "Bob", age: 30, processed: true }

77

// ]

78

79

// Array manipulation

80

const records = [

81

["a", "b", "c"],

82

["1", "2", "3"],

83

["x", "y", "z"]

84

];

85

86

const joined = transform(records, (record) => record.join("|"));

87

console.log(joined); // ["a|b|c", "1|2|3", "x|y|z"]

88

```

89

90

### Transform with Options

91

92

Enhanced synchronous transformation with configuration options.

93

94

```javascript { .api }

95

/**

96

* Transform with options synchronously

97

* @param records - Array of data to transform

98

* @param options - Configuration options

99

* @param handler - Synchronous transformation function

100

* @returns Array of transformed results

101

*/

102

function transform<T, U>(

103

records: Array<T>,

104

options: Options,

105

handler: Handler<T, U>

106

): Array<U>;

107

108

interface Options {

109

/** User-defined parameters passed to handler function */

110

params?: any;

111

}

112

```

113

114

**Usage Examples:**

115

116

```javascript

117

import { transform } from "stream-transform/sync";

118

119

// Using custom parameters

120

const data = [

121

{ value: 10, category: "A" },

122

{ value: 20, category: "B" },

123

{ value: 30, category: "A" }

124

];

125

126

const processed = transform(data, {

127

params: {

128

multiplier: 2,

129

prefix: "item_",

130

filter: "A"

131

}

132

}, (record, params) => {

133

if (record.category !== params.filter) {

134

return null; // Skip non-matching records

135

}

136

return {

137

id: params.prefix + record.value,

138

value: record.value * params.multiplier,

139

category: record.category

140

};

141

});

142

143

// Filter out null results

144

const filtered = processed.filter(item => item !== null);

145

console.log(filtered);

146

// [

147

// { id: "item_10", value: 20, category: "A" },

148

// { id: "item_30", value: 60, category: "A" }

149

// ]

150

151

// Configuration-driven transformation

152

const config = {

153

params: {

154

dateFormat: "YYYY-MM-DD",

155

timezone: "UTC",

156

includeMetadata: true

157

}

158

};

159

160

const events = [

161

{ timestamp: 1640995200000, event: "login" },

162

{ timestamp: 1640995260000, event: "logout" }

163

];

164

165

const formattedEvents = transform(events, config, (event, params) => {

166

const date = new Date(event.timestamp);

167

const formatted = {

168

event: event.event,

169

date: date.toISOString().split('T')[0], // Simple YYYY-MM-DD format

170

time: date.toISOString().split('T')[1].split('.')[0] // HH:MM:SS format

171

};

172

173

if (params.includeMetadata) {

174

formatted.metadata = {

175

timezone: params.timezone,

176

processed: new Date().toISOString()

177

};

178

}

179

180

return formatted;

181

});

182

```

183

184

### Handler Function Requirements

185

186

Synchronous API only supports synchronous handlers with specific signature requirements.

187

188

```javascript { .api }

189

/**

190

* Synchronous handler - returns result directly

191

* @param record - Individual record to transform

192

* @param params - Optional user-defined parameters

193

* @returns Transformed result

194

*/

195

type Handler<T, U> = (record: T, params?: any) => U;

196

197

// Handler must be synchronous - these patterns are NOT supported:

198

// ❌ (record, callback) => void // Async callback pattern

199

// ❌ (record) => Promise<result> // Promise-based pattern

200

// ❌ async (record) => result // Async function pattern

201

```

202

203

**Usage Examples:**

204

205

```javascript

206

import { transform } from "stream-transform/sync";

207

208

// ✅ Valid synchronous handlers

209

const result1 = transform([1, 2, 3], (num) => num * 2);

210

211

const result2 = transform(["a", "b"], (str) => str.toUpperCase());

212

213

const result3 = transform([{a: 1}, {a: 2}], (obj) => ({ ...obj, b: obj.a * 2 }));

214

215

// With parameters

216

const result4 = transform([1, 2, 3], { params: { factor: 10 } }, (num, params) => {

217

return num * params.factor;

218

});

219

220

// ❌ Invalid - async patterns will throw errors

221

try {

222

transform([1, 2, 3], (num, callback) => {

223

// This will throw: "Invalid Handler: only synchonous handlers are supported"

224

callback(null, num * 2);

225

});

226

} catch (err) {

227

console.error(err.message);

228

}

229

230

try {

231

transform([1, 2, 3], async (num) => {

232

// This will throw: "Invalid Handler: only synchonous handlers are supported"

233

return num * 2;

234

});

235

} catch (err) {

236

console.error(err.message);

237

}

238

```

239

240

### Record Manipulation Patterns

241

242

Various patterns for manipulating records in synchronous transformations.

243

244

```javascript { .api }

245

// Record transformation patterns:

246

// - Return transformed record: normal transformation

247

// - Return null/undefined/"": skip record (will be filtered out)

248

// - Return array: multiply record (each array element becomes separate result)

249

// - Throw error: halt processing with error

250

```

251

252

**Usage Examples:**

253

254

```javascript

255

import { transform } from "stream-transform/sync";

256

257

// Skip records by returning null/undefined/empty string

258

const numbers = [1, 2, 3, 4, 5, 6];

259

const evenOnly = transform(numbers, (num) => {

260

if (num % 2 !== 0) {

261

return null; // Skip odd numbers

262

}

263

return num * 2;

264

}).filter(result => result !== null); // Filter out nulls

265

console.log(evenOnly); // [4, 8, 12]

266

267

// Multiply records by returning arrays

268

const words = ["hello", "world"];

269

const letters = transform(words, (word) => {

270

return word.split(''); // Each word becomes array of letters

271

}).flat(); // Flatten the results

272

console.log(letters); // ['h','e','l','l','o','w','o','r','l','d']

273

274

// Error handling with synchronous throws

275

const data = [1, 2, "invalid", 4];

276

try {

277

const results = transform(data, (value) => {

278

if (typeof value !== "number") {

279

throw new Error(`Invalid value: ${value}`);

280

}

281

return value * 2;

282

});

283

} catch (err) {

284

console.error("Transformation failed:", err.message);

285

}

286

287

// Conditional transformation

288

const mixed = [1, "2", 3, "4", 5];

289

const processed = transform(mixed, (value) => {

290

if (typeof value === "string") {

291

return parseInt(value); // Convert strings to numbers

292

}

293

if (typeof value === "number") {

294

return value * 2; // Double numbers

295

}

296

return null; // Skip other types

297

}).filter(result => result !== null);

298

console.log(processed); // [2, 2, 6, 4, 10]

299

```

300

301

### Performance Characteristics

302

303

Understanding the performance profile of synchronous transformations.

304

305

```javascript { .api }

306

// Performance characteristics:

307

// - Blocking execution: entire process waits for completion

308

// - Memory efficient: processes one record at a time

309

// - CPU intensive: no I/O concurrency benefits

310

// - Best for: Small datasets, CPU-bound operations, simple transformations

311

// - Avoid for: Large datasets, I/O operations, long-running processes

312

```

313

314

**Usage Examples:**

315

316

```javascript

317

import { transform } from "stream-transform/sync";

318

319

// ✅ Good use cases for sync API

320

// Small datasets

321

const smallData = Array.from({ length: 100 }, (_, i) => i);

322

const processed = transform(smallData, (num) => num * num);

323

324

// Simple CPU operations

325

const texts = ["hello", "world", "sync", "api"];

326

const uppercased = transform(texts, (text) => text.toUpperCase());

327

328

// Data structure transformations

329

const objects = [{ a: 1, b: 2 }, { a: 3, b: 4 }];

330

const flattened = transform(objects, (obj) => [obj.a, obj.b]);

331

332

// ❌ Consider alternatives for these cases

333

// Large datasets - use stream API instead

334

const largeData = Array.from({ length: 1000000 }, (_, i) => i);

335

// const results = transform(largeData, processor); // May block for too long

336

337

// I/O operations - use async API instead

338

const urls = ["http://api1.com", "http://api2.com"];

339

// const responses = transform(urls, (url) => {

340

// return fetch(url); // Blocking I/O - not ideal

341

// });

342

343

// CPU-intensive operations - consider worker threads

344

const complexData = Array.from({ length: 10000 }, (_, i) => ({ data: i }));

345

// const computed = transform(complexData, (item) => {

346

// return heavyComputation(item); // May block UI/other operations

347

// });

348

349

// Better alternatives for problematic cases:

350

import { transform as asyncTransform } from "stream-transform";

351

352

// For large datasets - use streaming

353

const streamProcessor = asyncTransform((record) => processRecord(record));

354

355

// For I/O operations - use async handlers

356

asyncTransform(urls, async (url) => {

357

const response = await fetch(url);

358

return await response.json();

359

}, (err, results) => {

360

console.log("Async results:", results);

361

});

362

```

363

364

### Error Handling

365

366

Synchronous error handling with immediate exception throwing.

367

368

```javascript { .api }

369

// Errors are thrown synchronously and can be caught with try/catch

370

// Processing stops immediately when an error occurs

371

// No partial results are returned - either all succeed or all fail

372

```

373

374

**Usage Examples:**

375

376

```javascript

377

import { transform } from "stream-transform/sync";

378

379

// Basic error handling

380

const data = [1, 2, 3, "invalid", 5];

381

382

try {

383

const results = transform(data, (value) => {

384

if (typeof value !== "number") {

385

throw new Error(`Expected number, got ${typeof value}: ${value}`);

386

}

387

return value * 2;

388

});

389

console.log("All processed:", results);

390

} catch (err) {

391

console.error("Processing failed:", err.message);

392

// No partial results available

393

}

394

395

// Validation with detailed errors

396

const users = [

397

{ name: "Alice", email: "alice@example.com" },

398

{ name: "", email: "bob@example.com" }, // Invalid

399

{ name: "Charlie", email: "charlie@example.com" }

400

];

401

402

try {

403

const validatedUsers = transform(users, (user, index) => {

404

if (!user.name || user.name.trim() === "") {

405

throw new Error(`User at index ${index} has invalid name`);

406

}

407

if (!user.email || !user.email.includes("@")) {

408

throw new Error(`User at index ${index} has invalid email`);

409

}

410

return {

411

...user,

412

name: user.name.trim(),

413

email: user.email.toLowerCase(),

414

validated: true

415

};

416

});

417

console.log("All users validated:", validatedUsers);

418

} catch (err) {

419

console.error("Validation error:", err.message);

420

}

421

422

// Graceful error handling with recovery

423

function safeTransform(data, handler) {

424

const results = [];

425

const errors = [];

426

427

for (let i = 0; i < data.length; i++) {

428

try {

429

const result = handler(data[i], i);

430

results.push(result);

431

} catch (err) {

432

errors.push({ index: i, error: err.message, input: data[i] });

433

}

434

}

435

436

return { results, errors };

437

}

438

439

const mixed = [1, 2, "bad", 4, null, 6];

440

const { results, errors } = safeTransform(mixed, (value) => {

441

if (typeof value !== "number") {

442

throw new Error(`Invalid type: ${typeof value}`);

443

}

444

return value * 2;

445

});

446

447

console.log("Successful results:", results); // [2, 4, 8, 12]

448

console.log("Errors encountered:", errors);

449

// [

450

// { index: 2, error: "Invalid type: string", input: "bad" },

451

// { index: 4, error: "Invalid type: object", input: null }

452

// ]

453

```