// @ts-check
// Debian build config, derived from upstream scripts/rollup.config.mjs.
//
// Differences from upstream:
//   * TypeScript is transpiled with @babel/preset-typescript (type stripping
//     only) instead of @rollup/plugin-typescript. The source has a few
//     type-check errors that only surface with the older TypeScript currently
//     in Debian (upstream relies on the native NoInfer type from TS >= 5.4);
//     the emitted JavaScript is unaffected. Type declarations are produced
//     separately by tsc in debian/nodejs/build and only bundled here.
//   * preset-env's "loose" option is expressed as granular assumptions, and
//     "bugfixes" is dropped: Babel 8 removed both, and bugfix plugins are now
//     always enabled.
//   * rollup-plugin-delete (dist cleanup) and babel-plugin-annotate-pure-calls
//     (tree-shaking hints) are dropped: they are not packaged in Debian and are
//     not needed for a correct build.

import babel, { getBabelOutputPlugin } from '@rollup/plugin-babel'
import { nodeResolve } from '@rollup/plugin-node-resolve'
import { defineConfig } from 'rollup'
import { dts } from 'rollup-plugin-dts'

import pkg from '../package.json' with { type: 'json' }

const extensions = ['.ts', '.js', '.mjs', '.json']

// Babel 8 removed @babel/preset-env's "loose" option; these are the granular
// assumptions it used to enable. arrayLikeIsIterable is left out: Babel 8
// rejects it alongside iterableIsArray.
const looseAssumptions = {
    constantReexports: true,
    enumerableModuleMeta: true,
    ignoreFunctionLength: true,
    ignoreToPrimitiveHint: true,
    iterableIsArray: true,
    mutableTemplateObject: true,
    noClassCalls: true,
    noDocumentAll: true,
    noIncompleteNsImportDetection: true,
    noNewArrows: true,
    objectRestNoSymbols: true,
    privateFieldsAsProperties: true,
    pureGetters: true,
    setClassMethods: true,
    setComputedProperties: true,
    setPublicClassFields: true,
    setSpreadProperties: true,
    skipForOfIteratorClosing: true,
    superIsCallableConstructor: true,
}

/** Input plugins shared by every JavaScript bundle. */
const inputPlugins = () => [
    nodeResolve({ extensions }),
    babel({
        babelHelpers: 'bundled',
        extensions: ['.ts'],
        presets: ['@babel/preset-typescript'],
    }),
]

export default defineConfig([
    // Default entry point
    {
        input: pkg.source,
        output: [
            getOutputConfig({
                file: pkg.exports['.'].import,
                format: 'esm',
                targets: '> 0.5%, last 2 versions, Firefox ESR, not dead, maintained node versions',
            }),
            getOutputConfig({
                file: pkg.exports['.'].require,
                format: 'cjs',
                targets: '> 0.5%, last 2 versions, Firefox ESR, not dead, maintained node versions',
            }),
        ],
        external: /node_modules/,
        plugins: inputPlugins(),
    },

    // es5 entry point
    {
        input: pkg.source,
        output: [
            getOutputConfig({
                file: pkg.exports['./es5'].import,
                format: 'esm',
                targets: 'supports es5',
            }),
            getOutputConfig({
                file: pkg.exports['./es5'].require,
                format: 'cjs',
                targets: 'supports es5',
            }),
        ],
        external: /node_modules/,
        plugins: inputPlugins(),
    },

    // Type declarations of default and es5 entry points.
    // dist/index.d.ts is emitted beforehand by tsc (see debian/nodejs/build).
    {
        input: 'dist/index.d.ts',
        output: {
            file: pkg.exports['.'].types,
            format: 'esm',
        },
        plugins: [dts()],
    },
])

/**
 *
 * @param {object} param0
 * @param {string} param0.file
 * @param {'esm' | 'cjs'} param0.format
 * @param {string} param0.targets
 * @returns
 */
function getOutputConfig({ file, format, targets }) {
    /** @satisfies {import('rollup').OutputOptions} */
    const config = {
        file,
        format,
        sourcemap: true,
        freeze: false,
        generatedCode: 'es2015',
        plugins: [
            getBabelOutputPlugin({
                assumptions: looseAssumptions,
                presets: [
                    [
                        '@babel/preset-env',
                        {
                            modules: false,
                            targets,
                        },
                    ],
                ],
                plugins: [
                    ['babel-plugin-polyfill-regenerator', { method: 'usage-pure' }],
                ],
            }),
        ],
    }

    return config
}
