// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
// This module is browser compatible.
import { stringify } from "./stringify.ts";

/** Options for {@linkcode CsvStringifyStream}. */
export interface CsvStringifyStreamOptions {
  /**
   * Delimiter used to separate values.
   *
   * @default {","}
   */
  readonly separator?: string;

  /**
   * A list of columns to be included in the output.
   *
   * If you want to stream objects, this option is required.
   */
  readonly columns?: Array<string>;
}

/**
 * Convert each chunk to a CSV record.
 *
 * @example Usage
 * ```ts no-assert
 * import { CsvStringifyStream } from "@std/csv/csv-stringify-stream";
 *
 * const path = await Deno.makeTempFile();
 *
 * const file = await Deno.open(path, { create: true, write: true });
 * const readable = ReadableStream.from([
 *   { id: 1, name: "one" },
 *   { id: 2, name: "two" },
 *   { id: 3, name: "three" },
 * ]);
 *
 * await readable
 *   .pipeThrough(new CsvStringifyStream({ columns: ["id", "name"] }))
 *   .pipeThrough(new TextEncoderStream())
 *   .pipeTo(file.writable);
 * ```
 *
 * @typeParam TOptions The type of options for the stream.
 */
export class CsvStringifyStream<TOptions extends CsvStringifyStreamOptions>
  extends TransformStream<
    TOptions["columns"] extends Array<string> ? Record<string, unknown>
      : Array<unknown>,
    string
  > {
  /**
   * Construct a new instance.
   *
   * @example Usage
   * ```ts no-assert
   * import { CsvStringifyStream } from "@std/csv/csv-stringify-stream";
   *
   * const path = await Deno.makeTempFile();
   *
   * const file = await Deno.open(path, { create: true, write: true });
   * const readable = ReadableStream.from([
   *   { id: 1, name: "one" },
   *   { id: 2, name: "two" },
   *   { id: 3, name: "three" },
   * ]);
   *
   * await readable
   *   .pipeThrough(new CsvStringifyStream({ columns: ["id", "name"] }))
   *   .pipeThrough(new TextEncoderStream())
   *   .pipeTo(file.writable);
   * ```
   *
   * @param options Options for the stream.
   */
  constructor(options?: TOptions) {
    const {
      separator,
      columns = [],
    } = options ?? {};

    super(
      {
        start(controller) {
          if (columns && columns.length > 0) {
            try {
              controller.enqueue(
                stringify([columns], { separator, headers: false }),
              );
            } catch (error) {
              controller.error(error);
            }
          }
        },
        transform(chunk, controller) {
          try {
            controller.enqueue(
              stringify([chunk], { separator, headers: false, columns }),
            );
          } catch (error) {
            controller.error(error);
          }
        },
      },
    );
  }
}

// denoCacheMetadata={"headers":{"x-content-type-options":"nosniff","cf-ray":"a223e656afb97db6-LAX","content-type":"text/typescript","x-robots-tag":"noindex","set-cookie":"__cf_bm=DqMXR.PnTv4nAP9yL4_P7oge35Pe9HTIoL1zvuvt4qM-1785241874.991578-1.0.1.1-pvJ4Ml7xQDHIn61w0Nmabu_YiBgU.8hzDBhTLwC7Slxy9EAxd1rLt82crRC05_473fsub05TVjCb6oh1W5gHyE3o8LYp4ANEu1WDso8YtafRpOgPzLzlzXaNW7YHFtmD; HttpOnly; SameSite=None; Secure; Path=/; Domain=jsr.io; Expires=Tue, 28 Jul 2026 13:01:15 GMT","report-to":"{\"group\":\"cf-nel\",\"max_age\":604800,\"endpoints\":[{\"url\":\"https://a.nel.cloudflare.com/report/v4?s=T4wuRo03WJA%2BmuwWd9nBadlYFsrQsPX3rDqM6%2FU8ArOjxsaM14S8I54FFyIRcILU431NF7wRyShpRyADKpZQoEqLtl063JN5ChQCBZkuIbNZtOl8q9tycEA%3D\"}]}","server":"cloudflare","cross-origin-resource-policy":"cross-origin","date":"Tue, 28 Jul 2026 12:31:15 GMT","content-security-policy":"default-src 'none'; script-src 'none'; style-src 'none'; img-src 'none'; font-src 'none'; connect-src 'none'; frame-src 'none'; object-src 'none'; frame-ancestors 'none'; sandbox; form-action 'none';","x-jsr-backend":"modules","access-control-allow-origin":"*","access-control-expose-headers":"*","vary":"Origin","nel":"{\"report_to\":\"cf-nel\",\"success_fraction\":0.0,\"max_age\":604800}","cache-control":"public, max-age=31536000, immutable","etag":"\"ca8500e5f9c9db7d40efd3fc498b1cb8\"","content-length":"2799","alt-svc":"h3=\":443\"; ma=86400"},"url":"https://jsr.io/@std/csv/0.224.3/csv_stringify_stream.ts","time":1785241875}