@vdhewei/xlsx-template-lib 1.6.6 → 1.6.10

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/README.md CHANGED
@@ -678,6 +678,8 @@ xlsx-cli render <xlsx-file> [options]
678
678
  - `-n, --sheet-name <string>` - Sheet name to render (default: first sheet)
679
679
  - `-s, --save <string>` - Save rendered file to specified directory (default: current directory)
680
680
  - `-d, --data <string>` - Render data source (JSON string, file path, or URL)
681
+ - `--header <string>` - HTTP headers for remote data fetch (can be specified multiple times, format: `Key:Value`)
682
+ - `--body <string>` - HTTP request body for POST requests
681
683
 
682
684
  **Examples:**
683
685
 
@@ -700,6 +702,15 @@ xlsx-cli render template.xlsx -c -d './data.json'
700
702
  # Render specific sheet
701
703
  xlsx-cli render template.xlsx -n Sheet1 -d './data.json'
702
704
 
705
+ # Render with custom HTTP headers
706
+ xlsx-cli render template.xlsx -d 'https://api.example.com/data.json' --header 'Authorization:Bearer token123' --header 'Content-Type:application/json'
707
+
708
+ # Render with POST request body
709
+ xlsx-cli render template.xlsx -d 'https://api.example.com/api/query' --body '{"query":"SELECT * FROM users"}' --header 'Content-Type:application/json'
710
+
711
+ # Render with POST method via header
712
+ xlsx-cli render template.xlsx -d 'https://api.example.com/api/create' --body '{"name":"Test"}' --header 'Content-Type:application/json' --header 'method:POST'
713
+
703
714
  # Full example
704
715
  xlsx-cli render template.xlsx -c -n Sheet1 -s ./output/ -d './data.json'
705
716
  ```
@@ -709,6 +720,70 @@ xlsx-cli render template.xlsx -c -n Sheet1 -s ./output/ -d './data.json'
709
720
  - **Local File**: Path to `.json` file (relative or absolute)
710
721
  - **Remote URL**: HTTP/HTTPS URL returning JSON
711
722
 
723
+ **HTTP Request Options (for Remote URL):**
724
+ - **Headers**: Use `--header` to add custom HTTP headers (can be specified multiple times)
725
+ - Format: `--header 'Key:Value'`
726
+ - Example: `--header 'Authorization:Bearer token123' --header 'Content-Type:application/json'`
727
+ - Special header: `method:POST` can set the HTTP method to POST
728
+ - **Body**: Use `--body` to send request body (typically for POST requests)
729
+ - Format: `--body '{"key":"value"}'`
730
+ - Automatically uses POST method when body is provided
731
+ - **Default Behavior**: GET request with no headers
732
+
733
+ **HTTP Request Examples:**
734
+
735
+ ```bash
736
+ # GET request with custom headers
737
+ xlsx-cli render template.xlsx \
738
+ -d 'https://api.example.com/data.json' \
739
+ --header 'Authorization:Bearer your-token' \
740
+ --header 'X-API-Key:api-key-123'
741
+
742
+ # POST request with JSON body
743
+ xlsx-cli render template.xlsx \
744
+ -d 'https://api.example.com/api/query' \
745
+ --body '{"query":"SELECT * FROM users LIMIT 10"}' \
746
+ --header 'Content-Type:application/json'
747
+
748
+ # POST request with method specified in header
749
+ xlsx-cli render template.xlsx \
750
+ -d 'https://api.example.com/api/create' \
751
+ --body '{"name":"New Record","value":100}' \
752
+ --header 'Content-Type:application/json' \
753
+ --header 'method:POST'
754
+
755
+ # Complex example with authentication and query body
756
+ xlsx-cli render template.xlsx \
757
+ -d 'https://api.example.com/v1/export' \
758
+ --header 'Authorization:Bearer eyJhbGc...' \
759
+ --header 'Content-Type:application/json' \
760
+ --body '{"format":"xlsx","filter":{"status":"active"}}' \
761
+ -c -n Sheet1 -s ./output/
762
+ ```
763
+
764
+ **HTTP Request Details:**
765
+
766
+ 1. **Method Determination**:
767
+ - Default: `GET`
768
+ - With `--body`: Automatically becomes `POST`
769
+ - With `method:POST` header: Explicitly set to `POST`
770
+ - With `method:GET` header: Explicitly set to `GET`
771
+
772
+ 2. **Header Format**:
773
+ - Headers are parsed as `Key:Value` pairs
774
+ - Multiple `--header` options can be used
775
+ - Example: `--header 'Accept:application/json' --header 'User-Agent:MyApp/1.0'`
776
+
777
+ 3. **Error Handling**:
778
+ - Non-200 status codes return `undefined` and display error message
779
+ - Network errors are caught and displayed in red
780
+ - Missing `node-fetch` (Node.js < 18) displays error message
781
+
782
+ 4. **Supported Data Formats**:
783
+ - JSON objects: `{"key":"value"}`
784
+ - JSON arrays: `[{"id":1},{"id":2}]`
785
+ - Nested structures: `{"user":{"name":"John","age":30}}`
786
+
712
787
  **Output:**
713
788
  - Rendered Excel file saved as `<filename>_<timestamp>.xlsx`
714
789
  - Validation checks for sheet existence
package/README.zh-CN.md CHANGED
@@ -676,6 +676,8 @@ xlsx-cli render <xlsx-文件> [选项]
676
676
  - `-n, --sheet-name <string>` - 要渲染的工作表名称(默认:第一个工作表)
677
677
  - `-s, --save <string>` - 将渲染后的文件保存到指定目录(默认:当前目录)
678
678
  - `-d, --data <string>` - 渲染数据源(JSON 字符串、文件路径或 URL)
679
+ - `--header <string>` - 远程数据获取的 HTTP 请求头(可指定多次,格式:`Key:Value`)
680
+ - `--body <string>` - POST 请求的 HTTP 请求体
679
681
 
680
682
  **示例:**
681
683
 
@@ -698,6 +700,15 @@ xlsx-cli render template.xlsx -c -d './data.json'
698
700
  # 渲染指定工作表
699
701
  xlsx-cli render template.xlsx -n Sheet1 -d './data.json'
700
702
 
703
+ # 使用自定义 HTTP 请求头渲染
704
+ xlsx-cli render template.xlsx -d 'https://api.example.com/data.json' --header 'Authorization:Bearer token123' --header 'Content-Type:application/json'
705
+
706
+ # 使用 POST 请求体渲染
707
+ xlsx-cli render template.xlsx -d 'https://api.example.com/api/query' --body '{"query":"SELECT * FROM users"}' --header 'Content-Type:application/json'
708
+
709
+ # 通过 header 指定 POST 方法
710
+ xlsx-cli render template.xlsx -d 'https://api.example.com/api/create' --body '{"name":"测试"}' --header 'Content-Type:application/json' --header 'method:POST'
711
+
701
712
  # 完整示例
702
713
  xlsx-cli render template.xlsx -c -n Sheet1 -s ./output/ -d './data.json'
703
714
  ```
@@ -707,6 +718,70 @@ xlsx-cli render template.xlsx -c -n Sheet1 -s ./output/ -d './data.json'
707
718
  - **本地文件**: `.json` 文件的路径(相对或绝对)
708
719
  - **远程 URL**: 返回 JSON 的 HTTP/HTTPS URL
709
720
 
721
+ **HTTP 请求选项(用于远程 URL):**
722
+ - **请求头**: 使用 `--header` 添加自定义 HTTP 请求头(可指定多次)
723
+ - 格式:`--header 'Key:Value'`
724
+ - 示例:`--header 'Authorization:Bearer token123' --header 'Content-Type:application/json'`
725
+ - 特殊请求头:`method:POST` 可设置 HTTP 方法为 POST
726
+ - **请求体**: 使用 `--body` 发送请求体(通常用于 POST 请求)
727
+ - 格式:`--body '{"key":"value"}'`
728
+ - 提供请求体时自动使用 POST 方法
729
+ - **默认行为**: 无请求头的 GET 请求
730
+
731
+ **HTTP 请求示例:**
732
+
733
+ ```bash
734
+ # 带自定义请求头的 GET 请求
735
+ xlsx-cli render template.xlsx \
736
+ -d 'https://api.example.com/data.json' \
737
+ --header 'Authorization:Bearer your-token' \
738
+ --header 'X-API-Key:api-key-123'
739
+
740
+ # 带 JSON 请求体的 POST 请求
741
+ xlsx-cli render template.xlsx \
742
+ -d 'https://api.example.com/api/query' \
743
+ --body '{"query":"SELECT * FROM users LIMIT 10"}' \
744
+ --header 'Content-Type:application/json'
745
+
746
+ # 通过 header 指定 POST 方法
747
+ xlsx-cli render template.xlsx \
748
+ -d 'https://api.example.com/api/create' \
749
+ --body '{"name":"新记录","value":100}' \
750
+ --header 'Content-Type:application/json' \
751
+ --header 'method:POST'
752
+
753
+ # 复杂示例:带认证和查询请求体
754
+ xlsx-cli render template.xlsx \
755
+ -d 'https://api.example.com/v1/export' \
756
+ --header 'Authorization:Bearer eyJhbGc...' \
757
+ --header 'Content-Type:application/json' \
758
+ --body '{"format":"xlsx","filter":{"status":"active"}}' \
759
+ -c -n Sheet1 -s ./output/
760
+ ```
761
+
762
+ **HTTP 请求详细说明:**
763
+
764
+ 1. **HTTP 方法确定**:
765
+ - 默认:`GET`
766
+ - 使用 `--body`:自动变为 `POST`
767
+ - 使用 `method:POST` 请求头:显式设置为 `POST`
768
+ - 使用 `method:GET` 请求头:显式设置为 `GET`
769
+
770
+ 2. **请求头格式**:
771
+ - 请求头按 `Key:Value` 格式解析
772
+ - 可以使用多个 `--header` 选项
773
+ - 示例:`--header 'Accept:application/json' --header 'User-Agent:MyApp/1.0'`
774
+
775
+ 3. **错误处理**:
776
+ - 非 200 状态码返回 `undefined` 并显示错误消息
777
+ - 网络错误会被捕获并以红色显示
778
+ - 缺少 `node-fetch`(Node.js < 18)会显示错误消息
779
+
780
+ 4. **支持的数据格式**:
781
+ - JSON 对象:`{"key":"value"}`
782
+ - JSON 数组:`[{"id":1},{"id":2}]`
783
+ - 嵌套结构:`{"user":{"name":"张三","age":30}}`
784
+
710
785
  **输出:**
711
786
  - 渲染后的 Excel 文件保存为 `<文件名>_<时间戳>.xlsx`
712
787
  - 检查工作表是否存在
package/dist/bin.js CHANGED
@@ -4289,11 +4289,9 @@ var XlsxRender = class _XlsxRender extends Workbook {
4289
4289
 
4290
4290
  // src/bin-helpers.ts
4291
4291
  var path2 = __toESM(require("path"));
4292
- var url = __toESM(require("url"));
4293
4292
  var import_node_fs = require("fs");
4294
4293
  var fs3 = __toESM(require("fs/promises"));
4295
4294
  var import_chalk = __toESM(require("chalk"));
4296
- var import_meta = {};
4297
4295
  function generateOutputFilename(inputFile) {
4298
4296
  const basename3 = path2.basename(inputFile, path2.extname(inputFile));
4299
4297
  const timestamp = Date.now();
@@ -4304,42 +4302,84 @@ async function resolveFilePath(filePath) {
4304
4302
  if ((0, import_node_fs.existsSync)(resolvedPath)) {
4305
4303
  return resolvedPath;
4306
4304
  }
4307
- const scriptDir = path2.dirname(url.fileURLToPath(import_meta.url));
4305
+ const scriptDir = path2.dirname(process.cwd());
4308
4306
  const relativePath = path2.resolve(scriptDir, filePath);
4309
4307
  if ((0, import_node_fs.existsSync)(relativePath)) {
4310
4308
  return relativePath;
4311
4309
  }
4312
4310
  throw new Error(`File not found: ${filePath}`);
4313
4311
  }
4314
- async function parseRenderData(dataOption) {
4312
+ function isValidJSON(str) {
4313
+ const trimmed = str.trim();
4314
+ if (!trimmed) return false;
4315
+ const firstChar = trimmed[0];
4316
+ const lastChar = trimmed.charAt(trimmed.length - 1);
4317
+ const validStartEndPairs = [
4318
+ ["{", "}"],
4319
+ ["[", "]"],
4320
+ ['"', '"']
4321
+ ];
4322
+ const hasValidFormat = validStartEndPairs.some(
4323
+ ([start, end]) => firstChar === start && lastChar === end
4324
+ );
4325
+ if (!hasValidFormat && !["true", "false", "null"].includes(trimmed) && !/^-?\d+(\.\d+)?([eE][+-]?\d+)?$/.test(trimmed)) {
4326
+ return false;
4327
+ }
4328
+ try {
4329
+ JSON.parse(str);
4330
+ return true;
4331
+ } catch {
4332
+ return false;
4333
+ }
4334
+ }
4335
+ async function parseRenderData(dataOption, httpHeaders, body) {
4315
4336
  if (!dataOption) {
4316
4337
  return {};
4317
4338
  }
4318
4339
  try {
4319
- return JSON.parse(dataOption);
4320
- } catch (e) {
4321
- try {
4322
- const filePath = await resolveFilePath(dataOption);
4323
- const fileContent = await fs3.readFile(filePath, "utf-8");
4324
- return JSON.parse(fileContent);
4325
- } catch (e2) {
4326
- if (dataOption.startsWith("http://") || dataOption.startsWith("https://")) {
4327
- let fetch;
4340
+ if (isValidJSON(dataOption)) {
4341
+ return JSON.parse(dataOption);
4342
+ }
4343
+ if (dataOption.startsWith("http://") || dataOption.startsWith("https://")) {
4344
+ let fetch;
4345
+ try {
4346
+ fetch = globalThis.fetch;
4347
+ } catch (e3) {
4328
4348
  try {
4329
- fetch = globalThis.fetch;
4330
- } catch (e3) {
4331
- try {
4332
- const nodeFetch = await import("node-fetch");
4333
- fetch = nodeFetch.default;
4334
- } catch (e4) {
4335
- throw new Error("Remote URLs require Node.js 18+ or node-fetch package");
4336
- }
4349
+ const nodeFetch = await import("node-fetch");
4350
+ fetch = nodeFetch.default;
4351
+ } catch (e4) {
4352
+ console.error(import_chalk.default.red("Remote URLs require Node.js 18+ or node-fetch package"));
4353
+ return void 0;
4337
4354
  }
4338
- const response = await fetch(dataOption);
4339
- return response.json();
4340
4355
  }
4341
- throw new Error(`Failed to parse render data from: ${dataOption}`);
4356
+ const headers = new Headers();
4357
+ httpHeaders?.forEach((header) => {
4358
+ const [key, value] = header.split(":");
4359
+ headers.append(key, value);
4360
+ });
4361
+ const reqOpts = {
4362
+ headers,
4363
+ method: headers.get(`method`) ? headers.get(`method`).toUpperCase() : "GET"
4364
+ };
4365
+ if (body !== void 0 && body !== "") {
4366
+ reqOpts.body = body;
4367
+ }
4368
+ console.log(import_chalk.default.gray(`Fetching data from: ${dataOption}`));
4369
+ console.log(import_chalk.default.gray(`request.init: ${JSON.stringify(reqOpts)}`));
4370
+ const response = await fetch(dataOption, reqOpts);
4371
+ if (response.status !== 200) {
4372
+ console.error(import_chalk.default.red(`Failed to fetch data from: ${dataOption}, status: ${response.status},${response.text()}`));
4373
+ return void 0;
4374
+ }
4375
+ return response.json();
4342
4376
  }
4377
+ const filePath = await resolveFilePath(dataOption);
4378
+ const fileContent = await fs3.readFile(filePath, "utf-8");
4379
+ return JSON.parse(fileContent);
4380
+ } catch (e) {
4381
+ console.error(import_chalk.default.red(`Failed to parse render data from: ${dataOption}`));
4382
+ return void 0;
4343
4383
  }
4344
4384
  }
4345
4385
  function checkSheetAndPlaceholders(xlsx, sheetName) {
@@ -4349,43 +4389,70 @@ function checkSheetAndPlaceholders(xlsx, sheetName) {
4349
4389
  throw new Error(`Sheet "${sheetName}" not found in Excel file`);
4350
4390
  }
4351
4391
  }
4352
- async function addRuleToSheet(xlsxBuffer, ruleType, ruleExpr, sheetName = "export_metadata.config") {
4353
- const workbook = await loadWorkbook(xlsxBuffer);
4392
+ async function addRuleToSheet(workbook, ruleType, ruleExpr, sheetName = "export_metadata.config") {
4354
4393
  let worksheet = workbook.getWorksheet(sheetName);
4355
4394
  if (!worksheet) {
4356
4395
  worksheet = workbook.addWorksheet(sheetName);
4357
4396
  console.log(import_chalk.default.gray(`Created new sheet: ${sheetName}`));
4358
4397
  }
4359
4398
  let startRow = 1;
4360
- let currentRow = 1;
4361
- let columnCount = 0;
4362
- worksheet.eachRow((row, rowNumber) => {
4363
- const cell = row.getCell(1);
4364
- const cellValue = cell.value?.toString().trim();
4365
- if (!cellValue) {
4366
- return;
4367
- }
4368
- if (cellValue.toLowerCase() === ruleType.toLowerCase()) {
4369
- let col = 2;
4370
- while (col <= 4) {
4371
- const ruleCell = row.getCell(col);
4372
- if (ruleCell.value) {
4373
- columnCount++;
4374
- }
4375
- col++;
4399
+ let currentRow = NaN;
4400
+ if (worksheet.rowCount > 0) {
4401
+ let stop = false;
4402
+ worksheet.eachRow((row, rowNumber) => {
4403
+ let columnCount = 0;
4404
+ const cell = row.getCell(1);
4405
+ const cellValue = cell.value;
4406
+ if (!cellValue || stop) {
4407
+ return;
4376
4408
  }
4377
- if (columnCount < 4) {
4378
- currentRow = rowNumber;
4379
- startRow = rowNumber;
4380
- } else {
4381
- currentRow = rowNumber + 1;
4409
+ const value = toCellValue(cellValue).trim();
4410
+ if (value.toLowerCase() === ruleType.toLowerCase()) {
4411
+ for (let col = 2; col < 5; col++) {
4412
+ const ruleCell2 = row.getCell(col);
4413
+ if (ruleCell2.value) {
4414
+ columnCount++;
4415
+ } else {
4416
+ break;
4417
+ }
4418
+ }
4419
+ if (columnCount < 3) {
4420
+ currentRow = rowNumber;
4421
+ startRow = rowNumber;
4422
+ } else {
4423
+ currentRow = rowNumber + 1;
4424
+ }
4425
+ const cell2 = worksheet.getRow(currentRow).getCell(1);
4426
+ if (cell2 === void 0 || cell2.value === null || cell2.value === void 0) {
4427
+ stop = true;
4428
+ return;
4429
+ }
4430
+ if (toCellValue(cell2.value).toLowerCase() !== ruleType.toLowerCase()) {
4431
+ worksheet.insertRow(currentRow, []);
4432
+ currentRow = currentRow + 1;
4433
+ stop = true;
4434
+ return;
4435
+ }
4436
+ if (toCellValue(cell2.value).toLowerCase() === ruleType.toLowerCase() && columnCount < 3) {
4437
+ stop = true;
4438
+ return;
4439
+ }
4382
4440
  }
4383
- }
4384
- });
4441
+ });
4442
+ }
4443
+ if (isNaN(currentRow)) {
4444
+ currentRow = worksheet.rowCount + 1;
4445
+ worksheet.insertRow(currentRow, []);
4446
+ }
4385
4447
  if (startRow === 1 && currentRow === 1 && worksheet.rowCount === 0) {
4386
4448
  currentRow = 1;
4387
4449
  }
4388
4450
  let targetRow = worksheet.getRow(currentRow);
4451
+ let lastCell = targetRow.getCell(4);
4452
+ if (lastCell !== void 0 && lastCell.value !== void 0 && lastCell.value !== null && lastCell.value !== "") {
4453
+ currentRow = worksheet.rowCount + 1;
4454
+ targetRow = worksheet.insertRow(currentRow, []);
4455
+ }
4389
4456
  if (!targetRow.getCell(1).value) {
4390
4457
  const typeCell = targetRow.getCell(1);
4391
4458
  typeCell.value = ruleType;
@@ -4395,23 +4462,21 @@ async function addRuleToSheet(xlsxBuffer, ruleType, ruleExpr, sheetName = "expor
4395
4462
  let ruleCol = 2;
4396
4463
  while (ruleCol <= 4) {
4397
4464
  const existingCell = targetRow.getCell(ruleCol);
4398
- if (!existingCell.value) {
4465
+ if (existingCell === void 0 || (existingCell.value === void 0 || existingCell.value === null || existingCell.value === "")) {
4399
4466
  break;
4400
4467
  }
4401
4468
  ruleCol++;
4402
4469
  }
4403
- if (ruleCol <= 4) {
4404
- const ruleCell = targetRow.getCell(ruleCol);
4405
- ruleCell.value = ruleExpr;
4406
- ruleCell.alignment = { vertical: "middle" };
4407
- const column = worksheet.getColumn(ruleCol);
4408
- column.width = Math.max(column.width || 10, ruleExpr.length + 2);
4409
- console.log(import_chalk.default.gray(`Added rule ${ruleType} at row ${currentRow}, column ${ruleCol}`));
4410
- } else {
4411
- throw new Error(`Cannot add more than 4 rules for type: ${ruleType}`);
4470
+ const ruleCell = targetRow.getCell(ruleCol);
4471
+ ruleCell.value = ruleExpr;
4472
+ ruleCell.alignment = { vertical: "middle", horizontal: "center" };
4473
+ const column = worksheet.getColumn(ruleCol);
4474
+ column.width = Math.max(column.width || 10, ruleExpr.length + 2);
4475
+ if (currentRow === 1 && ruleCol === 2) {
4476
+ const column2 = worksheet.getColumn(1);
4477
+ column2.width = Math.max(column2.width || 10, ruleExpr.length + 2);
4412
4478
  }
4413
- const buffer = await workbook.xlsx.writeBuffer();
4414
- return Buffer.from(buffer);
4479
+ return workbook;
4415
4480
  }
4416
4481
  async function parseRulesFromFile(filePath) {
4417
4482
  const resolvedPath = await resolveFilePath(filePath);
@@ -4430,8 +4495,17 @@ async function parseRulesFromFile(filePath) {
4430
4495
  console.log(import_chalk.default.yellow(`\u26A0 Line ${i + 1}: Invalid format. Expected "<type> ruleExpr"`));
4431
4496
  continue;
4432
4497
  }
4498
+ let items = [];
4433
4499
  const type = line.substring(0, spaceIndex).trim();
4434
- const items = line.substring(spaceIndex + 1).trim().split(" ");
4500
+ const values = line.substring(spaceIndex + 1).trim();
4501
+ if (values.indexOf(" ") >= 0) {
4502
+ items = values.split(" ");
4503
+ } else if (values.indexOf(" ") >= 0) {
4504
+ items = values.split(" ");
4505
+ } else {
4506
+ items = [values];
4507
+ }
4508
+ items = items.filter((item) => item.trim() !== "" && item.indexOf("=") > 0);
4435
4509
  if (!type) {
4436
4510
  console.log(import_chalk.default.yellow(`\u26A0 Line ${i + 1}: Invalid format. Expected "<type> ruleExpr"`));
4437
4511
  continue;
@@ -4445,6 +4519,9 @@ async function parseRulesFromFile(filePath) {
4445
4519
  }
4446
4520
  for (const rule of items) {
4447
4521
  let str = rule.trim();
4522
+ if (str === void 0 || str === null || str === "" || str === " ") {
4523
+ continue;
4524
+ }
4448
4525
  let key = `${type}:${str}`;
4449
4526
  if (validRulesSet.has(key)) {
4450
4527
  console.log(import_chalk.default.yellow(`\u26A0 Line ${i + 1}: Duplicate rule "${str}"`));
@@ -4460,30 +4537,38 @@ async function parseRulesFromFile(filePath) {
4460
4537
  return rules;
4461
4538
  }
4462
4539
  async function addMultipleRulesToSheet(xlsxBuffer, rules) {
4463
- let buffer = xlsxBuffer;
4540
+ let workbook = await loadWorkbook(xlsxBuffer);
4464
4541
  for (const { type, rule } of rules) {
4465
- console.log(import_chalk.default.gray(`Adding ${type} rule: ${rule}`));
4466
- buffer = await addRuleToSheet(buffer, type, rule);
4542
+ workbook = await addRuleToSheet(workbook, type, rule);
4467
4543
  }
4468
- return buffer;
4544
+ const buffer = await workbook.xlsx.writeBuffer();
4545
+ return Buffer.from(buffer);
4469
4546
  }
4470
4547
 
4471
4548
  // src/bin.ts
4472
4549
  async function main() {
4473
- let version = "1.0.0";
4550
+ let version;
4474
4551
  try {
4475
- const possiblePaths = [
4476
- path3.join(process.cwd(), "package.json"),
4477
- path3.join(process.cwd(), "..", "package.json")
4478
- ];
4479
- for (const packagePath of possiblePaths) {
4480
- if ((0, import_node_fs2.existsSync)(packagePath)) {
4481
- const packageJson = JSON.parse(await fs4.readFile(packagePath, "utf-8"));
4482
- version = packageJson.version;
4483
- break;
4484
- }
4552
+ version = __VERSION__;
4553
+ if (version.startsWith('"') && version.endsWith('"')) {
4554
+ version = version.slice(1, -1);
4485
4555
  }
4486
4556
  } catch (e) {
4557
+ version = "1.0.0";
4558
+ try {
4559
+ const possiblePaths = [
4560
+ path3.join(process.cwd(), "package.json"),
4561
+ path3.join(process.cwd(), "..", "package.json")
4562
+ ];
4563
+ for (const packagePath of possiblePaths) {
4564
+ if ((0, import_node_fs2.existsSync)(packagePath)) {
4565
+ const packageJson = JSON.parse(await fs4.readFile(packagePath, "utf-8"));
4566
+ version = packageJson.version;
4567
+ break;
4568
+ }
4569
+ }
4570
+ } catch (e2) {
4571
+ }
4487
4572
  }
4488
4573
  const envPath = path3.join(process.cwd(), ".env");
4489
4574
  if ((0, import_node_fs2.existsSync)(envPath)) {
@@ -4523,7 +4608,7 @@ async function main() {
4523
4608
  process.exit(1);
4524
4609
  }
4525
4610
  });
4526
- program.command("render").argument("<string>", "xlsx file path").option("-c,--compile", "auto compile flag", false).option("-n,--sheet-name <string>", "render xlsx sheet name when xlsx has multiple sheets").option("-s,--save <string>", "save render xlsx file to user dir").option("-d,--data <string>", "render xlsx file data from").action(async (xlsxFile, options) => {
4611
+ program.command("render").argument("<string>", "xlsx file path").option("-c,--compile", "auto compile flag", false).option("-n,--sheet-name <string>", "render xlsx sheet name when xlsx has multiple sheets").option("-s,--save <string>", "save render xlsx file to user dir").option("-d,--data <string>", "render xlsx file data from").option("--header <string>", "call remote http json data with header", []).option("--body <string>", "call remote http json request with body").action(async (xlsxFile, options) => {
4527
4612
  try {
4528
4613
  console.log(import_chalk2.default.green("\u{1F4C4} Rendering Excel template..."));
4529
4614
  const filePath = await resolveFilePath(xlsxFile);
@@ -4535,7 +4620,10 @@ async function main() {
4535
4620
  console.log(import_chalk2.default.gray(`Target sheet: ${sheetName}`));
4536
4621
  checkSheetAndPlaceholders(xlsx, sheetName);
4537
4622
  console.log(import_chalk2.default.gray("Sheet validation passed"));
4538
- const renderData = await parseRenderData(options.data);
4623
+ const renderData = await parseRenderData(options.data, options.header, options.body);
4624
+ if (renderData === void 0) {
4625
+ process.exit(1);
4626
+ }
4539
4627
  if (Object.keys(renderData).length > 0) {
4540
4628
  console.log(import_chalk2.default.gray(`Render data loaded with ${Object.keys(renderData).length} keys`));
4541
4629
  }