From 45377876d802e97553c13e72ade0378503762ea0 Mon Sep 17 00:00:00 2001 From: Jason Yu Date: Mon, 14 Oct 2024 22:29:54 +0100 Subject: [PATCH 1/3] build: enable type checking for npm build --- README.md | 6 +-- scripts/build-npm.ts | 12 +++++- src/DnsUtils/ResolveDnsFunction.ts | 32 --------------- src/DnsUtils/_helpers.ts | 17 ++++++-- .../findAuthoritativeNameServerIps.ts | 6 +-- src/DnsUtils/mod.ts | 2 +- src/DnsUtils/pollDnsTxtRecord.ts | 39 ++++--------------- src/DnsUtils/resolveDns.deno.ts | 1 + src/DnsUtils/resolveDns.node.ts | 22 +++++++++++ src/DnsUtils/resolveDns.ts | 14 +++++++ 10 files changed, 73 insertions(+), 78 deletions(-) delete mode 100644 src/DnsUtils/ResolveDnsFunction.ts create mode 100644 src/DnsUtils/resolveDns.deno.ts create mode 100644 src/DnsUtils/resolveDns.node.ts create mode 100644 src/DnsUtils/resolveDns.ts diff --git a/README.md b/README.md index 59b1a46..414200d 100644 --- a/README.md +++ b/README.md @@ -34,11 +34,9 @@ application. This is built primarily for Deno. -But since this is built in 100% TypeScript with no dependencies, it should be +But since this is built in 100% TypeScript with no dependencies, it is compatible with all modern JavaScript platforms that support the [WebCrypto] and -[fetch]. (One exception being `DnsUtils.pollDnsTxtRecord()` which make use of -`Deno.resolveDns`, perhaps we can make this take in a `resolveDns` function -later to make this platform agnostic.) +[fetch]. ## Features diff --git a/scripts/build-npm.ts b/scripts/build-npm.ts index bcf663a..7f1cab4 100644 --- a/scripts/build-npm.ts +++ b/scripts/build-npm.ts @@ -26,8 +26,11 @@ await build({ })), outDir: OUT_DIR, test: false, - typeCheck: false, shims: {}, + compilerOptions: { + lib: ["ES2023", "DOM"], + target: "ES2022", + }, package: { name: DENO_JSON.name, version: DENO_JSON.version, @@ -43,6 +46,13 @@ await build({ }, keywords: ["acme"], homepage: "https://jsr.io/@fishballpkg/acme/doc", + devDependencies: { + "@types/node": "latest", + }, + }, + mappings: { + [`${PROJECT_ROOT}/src/DnsUtils/resolveDns.deno.ts`]: + `${PROJECT_ROOT}/src/DnsUtils/resolveDns.node.ts`, }, postBuild() { // steps to run after building and before running the tests diff --git a/src/DnsUtils/ResolveDnsFunction.ts b/src/DnsUtils/ResolveDnsFunction.ts deleted file mode 100644 index 7f9c43d..0000000 --- a/src/DnsUtils/ResolveDnsFunction.ts +++ /dev/null @@ -1,32 +0,0 @@ -/** - * A function that resolves DNS record. - * - * #### Deno - * - * `Deno.resolveDns` will be used by default and you may omit `resolveDns`. - * - * #### Node.js - * - * In Node.js, you can use the [`node:dns`](https://nodejs.org/api/dns.html#dnspromisesresolvetxthostname) - * to implement the `resolveDns` option. - * - * @example Example implementation for Node.js - * ```ts ignore - * const resolveDns = (domain, recordType, options) => { - * const resolver = new require('node:dns').promises.Resolver(); - * if (options?.nameServer?.ipAddr !== undefined) { - * resolver.setServers([options.nameServer.ipAddr]); - * } - * return resolver.resolve(domain, recordType); - * }; - * ``` - */ -export type ResolveDnsFunction = ( - query: string, - recordType: "A" | "AAAA" | "CNAME" | "NS", - options?: { - nameServer?: { - ipAddr: string; - }; - }, -) => Promise; diff --git a/src/DnsUtils/_helpers.ts b/src/DnsUtils/_helpers.ts index e8baa79..a41c829 100644 --- a/src/DnsUtils/_helpers.ts +++ b/src/DnsUtils/_helpers.ts @@ -1,3 +1,5 @@ +import { defaultResolveDns, type ResolveDnsFunction } from "./resolveDns.ts"; + type IpVersion = "ipv4" | "ipv6"; const QUAD9_DNS_IPS: Record = { @@ -12,10 +14,15 @@ const cache: Record | undefined> = { const isIpVersionSupported = async ( version: IpVersion, + { + resolveDns = defaultResolveDns, + }: { + resolveDns?: ResolveDnsFunction; + } = {}, ): Promise => { cache[version] ??= (async () => { try { - await Deno.resolveDns("example.com", "NS", { + await resolveDns("example.com", "NS", { nameServer: { ipAddr: QUAD9_DNS_IPS[version], }, @@ -29,12 +36,14 @@ const isIpVersionSupported = async ( return await cache[version]; }; -export const getSupportedIpVersions = async (): Promise< +export const getSupportedIpVersions = async ( + opts: { resolveDns?: ResolveDnsFunction } = {}, +): Promise< readonly IpVersion[] > => { const [ipv4Supported, ipv6Supported] = await Promise.all([ - isIpVersionSupported("ipv4"), - isIpVersionSupported("ipv6"), + isIpVersionSupported("ipv4", opts), + isIpVersionSupported("ipv6", opts), ]); if (ipv4Supported && ipv6Supported) { diff --git a/src/DnsUtils/findAuthoritativeNameServerIps.ts b/src/DnsUtils/findAuthoritativeNameServerIps.ts index f9349c3..e5a636a 100644 --- a/src/DnsUtils/findAuthoritativeNameServerIps.ts +++ b/src/DnsUtils/findAuthoritativeNameServerIps.ts @@ -1,4 +1,4 @@ -import type { ResolveDnsFunction } from "./ResolveDnsFunction.ts"; +import { defaultResolveDns, type ResolveDnsFunction } from "./resolveDns.ts"; export type FindAuthoritativeNameServerIpsConfig = { /** * A function to resolve DNS record. @@ -24,9 +24,7 @@ export const findAuthoritativeNameServerIps = async ( domain: string, config: FindAuthoritativeNameServerIpsConfig = {}, ): Promise => { - const resolveDns = - (config.resolveDns ?? Deno.resolveDns) as typeof Deno.resolveDns; - + const { resolveDns = defaultResolveDns } = config; while (domain.includes(".")) { // continue the loop if we haven't reached TLD const nameServers = await (async () => { try { diff --git a/src/DnsUtils/mod.ts b/src/DnsUtils/mod.ts index 873fd63..03a9acd 100644 --- a/src/DnsUtils/mod.ts +++ b/src/DnsUtils/mod.ts @@ -6,4 +6,4 @@ export * from "./findAuthoritativeNameServerIps.ts"; export * from "./pollDnsTxtRecord.ts"; -export * from "./ResolveDnsFunction.ts"; +export * from "./resolveDns.ts"; diff --git a/src/DnsUtils/pollDnsTxtRecord.ts b/src/DnsUtils/pollDnsTxtRecord.ts index 026254c..3ad8fbf 100644 --- a/src/DnsUtils/pollDnsTxtRecord.ts +++ b/src/DnsUtils/pollDnsTxtRecord.ts @@ -1,6 +1,6 @@ import { getIpVersion, getSupportedIpVersions } from "./_helpers.ts"; import { findAuthoritativeNameServerIps } from "./findAuthoritativeNameServerIps.ts"; -import type { ResolveDnsFunction } from "./ResolveDnsFunction.ts"; +import { defaultResolveDns, type ResolveDnsFunction } from "./resolveDns.ts"; /** * Config object for {@link pollDnsTxtRecord} @@ -24,36 +24,13 @@ export type PollDnsTxtRecordOptions = { onAfterFailAttempt?: (recordss: string[][]) => void; /** * A function to resolve DNS record. - * - * ### For Deno - * - * `Deno.resolveDns` will be used by default and you may omit `resolveDns`. - * - * ### For Other Platforms - * - * You should provide an implementation that resolves *at least* the `TXT` records. - * - * `pollDnsTxtRecord` performs lookup on the `TXT` record and it should return `Promise`, - * where each record is in chunks of strings. - * - * #### Node.js - * - * In Node.js, you can use the [`node:dns`](https://nodejs.org/api/dns.html#dnspromisesresolvetxthostname) to implement the `resolveDns` option. - * - * @example - * ```ts ignore - * const resolveDns = (domain, recordType, options) => { - * const resolver = new require('node:dns').promises.Resolver(); - * if (options?.nameServer?.ipAddr !== undefined) { - * resolver.setServers([options.nameServer.ipAddr]); - * } - * return resolver.resolve(domain, recordType); - * }; - * ``` */ resolveDns?: ResolveDnsFunction; /** - * A list of IPv4 or IPv6 addresses that will be used for DNS lookups. + * A list of IPv4 or IPv6 addresses that will be used for TXT lookups. + * + * If defined, {@link pollDnsTxtRecord} will not try to find the authoritative name server ips, + * but instead use the given list of ips for the lookups. * * If not defined, {@link pollDnsTxtRecord} will try to use the IP addresses of the * authoritative name servers of the given domain using {@link findAuthoritativeNameServerIps} @@ -120,6 +97,7 @@ export const pollDnsTxtRecord = async ( options: PollDnsTxtRecordOptions, ): Promise => { const { + resolveDns = defaultResolveDns, pollUntil, interval = 5000, onAfterFailAttempt, @@ -127,9 +105,6 @@ export const pollDnsTxtRecord = async ( timeout = 30_000, } = options; - const resolveDns = - (options.resolveDns ?? Deno.resolveDns) as typeof Deno.resolveDns; - const [ nameServerIps, supportedIpVersions, @@ -138,7 +113,7 @@ export const pollDnsTxtRecord = async ( findAuthoritativeNameServerIps(domain, { resolveDns, }), - getSupportedIpVersions(), + getSupportedIpVersions({ resolveDns }), ]); const supportedNameServerIps = nameServerIps.filter((ip) => diff --git a/src/DnsUtils/resolveDns.deno.ts b/src/DnsUtils/resolveDns.deno.ts new file mode 100644 index 0000000..cfbe60a --- /dev/null +++ b/src/DnsUtils/resolveDns.deno.ts @@ -0,0 +1 @@ +export const resolveDns = Deno.resolveDns; diff --git a/src/DnsUtils/resolveDns.node.ts b/src/DnsUtils/resolveDns.node.ts new file mode 100644 index 0000000..3c52785 --- /dev/null +++ b/src/DnsUtils/resolveDns.node.ts @@ -0,0 +1,22 @@ +/** + * Node.js implementation of `resolveDns`. + * + * This file will be used in Node.js. Thanks to DNT's build mapping. See more in `scripts/build-npm.ts`. + */ + +import { Resolver } from "node:dns/promises"; +import type { ResolveDnsFunction } from "./resolveDns.ts"; + +export const resolveDns: ResolveDnsFunction = async ( + domain, + recordType, + options, +) => { + const resolver = new Resolver(); + if (options?.nameServer?.ipAddr !== undefined) { + resolver.setServers([options.nameServer.ipAddr]); + } + + // deno-lint-ignore no-explicit-any -- typescript is hard + return (await resolver.resolve(domain, recordType)) as any; +}; diff --git a/src/DnsUtils/resolveDns.ts b/src/DnsUtils/resolveDns.ts new file mode 100644 index 0000000..19d06fc --- /dev/null +++ b/src/DnsUtils/resolveDns.ts @@ -0,0 +1,14 @@ +/** + * A function that resolves DNS record. + */ +export type ResolveDnsFunction = ( + query: string, + recordType: R, + options?: { + nameServer?: { + ipAddr: string; + }; + }, +) => Promise<"TXT" extends R ? string[][] : string[]>; + +export { resolveDns as defaultResolveDns } from "./resolveDns.deno.ts"; From d71885da48065da64cadb08e31ef39ba7b30bb31 Mon Sep 17 00:00:00 2001 From: Jason Yu Date: Mon, 14 Oct 2024 23:49:33 +0100 Subject: [PATCH 2/3] build: make npm build to run integration tests too --- e2e/create-certificate.test.ts | 2 +- e2e/workflows.test.ts | 2 +- ...{workflows.test.ts => 01workflows.test.ts} | 16 +++++++--------- integration/account.test.ts | 5 ++++- integration/order.test.ts | 5 ++++- integration/utils/PebbleChallTestSrv.ts | 2 +- integration/utils/resolveDns.ts | 19 +++++++++++++++++++ integration/utils/setupNode.ts | 6 ++++++ scripts/build-npm.ts | 10 +++++++--- src/DnsUtils/_helpers.ts | 3 ++- src/DnsUtils/resolveDns.node.ts | 11 ++++++++++- src/DnsUtils/resolveDns.ts | 1 + 12 files changed, 63 insertions(+), 19 deletions(-) rename integration/{workflows.test.ts => 01workflows.test.ts} (81%) create mode 100644 integration/utils/resolveDns.ts create mode 100644 integration/utils/setupNode.ts diff --git a/e2e/create-certificate.test.ts b/e2e/create-certificate.test.ts index c530e64..4971314 100644 --- a/e2e/create-certificate.test.ts +++ b/e2e/create-certificate.test.ts @@ -6,7 +6,7 @@ import { AcmeOrder, Dns01Challenge, DnsUtils, -} from "@fishballpkg/acme"; +} from "../src/mod.ts"; import { expect, it } from "../test_deps.ts"; import { CloudflareZone } from "./utils/cloudflare.ts"; import { expectToBeDefined } from "./utils/expectToBeDefined.ts"; diff --git a/e2e/workflows.test.ts b/e2e/workflows.test.ts index c6c07ef..f169511 100644 --- a/e2e/workflows.test.ts +++ b/e2e/workflows.test.ts @@ -3,7 +3,7 @@ import { AcmeClient, AcmeOrder, AcmeWorkflows, -} from "@fishballpkg/acme"; +} from "../src/mod.ts"; import { describe, expect, it } from "../test_deps.ts"; import { CloudflareZone } from "./utils/cloudflare.ts"; import { randomFishballTestingSubdomain } from "./utils/randomFishballTestingSubdomain.ts"; diff --git a/integration/workflows.test.ts b/integration/01workflows.test.ts similarity index 81% rename from integration/workflows.test.ts rename to integration/01workflows.test.ts index 969dbb4..28c5faa 100644 --- a/integration/workflows.test.ts +++ b/integration/01workflows.test.ts @@ -1,8 +1,13 @@ -import { AcmeClient, AcmeOrder, AcmeWorkflows } from "@fishballpkg/acme"; +// 01 prefix to this file because of https://github.com/denoland/dnt/issues/432 +import { AcmeClient, AcmeOrder, AcmeWorkflows } from "../src/mod.ts"; import { describe, expect, it } from "../test_deps.ts"; import { EMAIL, PEBBLE_DIRECTORY_URL } from "./CONSTANTS.ts"; import { generateRandomDomain } from "./utils/generateRandomDomain.ts"; import { PebbleChallTestSrv } from "./utils/PebbleChallTestSrv.ts"; +import { resolveDns } from "./utils/resolveDns.ts"; +import { setupNode } from "./utils/setupNode.ts"; + +setupNode(); const DOMAINS = [ generateRandomDomain(), @@ -27,14 +32,7 @@ describe("requestCertificates", () => { updateDnsRecords: async (dnsRecords) => { await pebbleChallTestSrv.createDnsRecords(dnsRecords); }, - resolveDns: async (query, recordType) => { - return await Deno.resolveDns(query, recordType, { - nameServer: { - ipAddr: "127.0.0.1", - port: 8053, - }, - }); - }, + resolveDns, }); expect(certKeyPair.privateKey).toBeInstanceOf(CryptoKey); diff --git a/integration/account.test.ts b/integration/account.test.ts index 8712e59..bd6daa1 100644 --- a/integration/account.test.ts +++ b/integration/account.test.ts @@ -1,6 +1,9 @@ -import { AcmeClient } from "@fishballpkg/acme"; +import { AcmeClient } from "../src/mod.ts"; import { expect, it } from "../test_deps.ts"; import { EMAIL, PEBBLE_DIRECTORY_URL } from "./CONSTANTS.ts"; +import { setupNode } from "./utils/setupNode.ts"; + +setupNode(); it("should create the account successfully and the key pair should allow login", async () => { const client = await AcmeClient.init(PEBBLE_DIRECTORY_URL); diff --git a/integration/order.test.ts b/integration/order.test.ts index 2711ff5..b9f74a7 100644 --- a/integration/order.test.ts +++ b/integration/order.test.ts @@ -1,7 +1,10 @@ -import { AcmeClient } from "@fishballpkg/acme"; +import { AcmeClient } from "../src/mod.ts"; import { expect, it } from "../test_deps.ts"; import { EMAIL, PEBBLE_DIRECTORY_URL } from "./CONSTANTS.ts"; import { generateRandomDomain } from "./utils/generateRandomDomain.ts"; +import { setupNode } from "./utils/setupNode.ts"; + +setupNode(); it("should place an order correctly and get the corresponding authorizations", async () => { const client = await AcmeClient.init(PEBBLE_DIRECTORY_URL); diff --git a/integration/utils/PebbleChallTestSrv.ts b/integration/utils/PebbleChallTestSrv.ts index b20eba7..fb8e3b9 100644 --- a/integration/utils/PebbleChallTestSrv.ts +++ b/integration/utils/PebbleChallTestSrv.ts @@ -1,4 +1,4 @@ -import type { DnsTxtRecord } from "@fishballpkg/acme"; +import type { DnsTxtRecord } from "../../src/mod.ts"; import { afterEach } from "../../test_deps.ts"; const PEBBLE_CHALLTESTSRV_URL = "http://localhost:8055"; diff --git a/integration/utils/resolveDns.ts b/integration/utils/resolveDns.ts new file mode 100644 index 0000000..b289d48 --- /dev/null +++ b/integration/utils/resolveDns.ts @@ -0,0 +1,19 @@ +import { + defaultResolveDns, + type ResolveDnsFunction, +} from "../../src/DnsUtils/resolveDns.ts"; + +/** + * A resolveDns function specifically for integration tests to allow TXT lookups to be done via pebble-testchallsrv + */ +export const resolveDns: ResolveDnsFunction = async (query, recordType) => { + return (await defaultResolveDns(query, recordType, { + nameServer: recordType === "TXT" + ? { + ipAddr: "127.0.0.1", + port: 8053, + } // only lookup via pebble-challtestsrv for txt records + : undefined, + // deno-lint-ignore no-explicit-any -- typescript is hard + })) as any; +}; diff --git a/integration/utils/setupNode.ts b/integration/utils/setupNode.ts new file mode 100644 index 0000000..17150fb --- /dev/null +++ b/integration/utils/setupNode.ts @@ -0,0 +1,6 @@ +export const setupNode = () => { + if ("process" in globalThis) { + // @ts-ignore: node specific + globalThis["process"]["env"]["NODE_TLS_REJECT_UNAUTHORIZED"] = 0; + } +}; diff --git a/scripts/build-npm.ts b/scripts/build-npm.ts index 7f1cab4..cf0b398 100644 --- a/scripts/build-npm.ts +++ b/scripts/build-npm.ts @@ -19,16 +19,20 @@ await emptyDir(OUT_DIR); const GITHUB_REPO = "https://github.com/fishballapp/acme"; await build({ + testPattern: "integration/**/*.test.ts", entryPoints: Object.entries(DENO_JSON.exports).map(([name, path]) => ({ kind: "export", name, path: join(PROJECT_ROOT, path), })), outDir: OUT_DIR, - test: false, - shims: {}, + test: true, + shims: { + deno: "dev", + undici: "dev", + }, compilerOptions: { - lib: ["ES2023", "DOM"], + lib: ["ESNext", "DOM"], target: "ES2022", }, package: { diff --git a/src/DnsUtils/_helpers.ts b/src/DnsUtils/_helpers.ts index a41c829..c2ec73f 100644 --- a/src/DnsUtils/_helpers.ts +++ b/src/DnsUtils/_helpers.ts @@ -28,7 +28,8 @@ const isIpVersionSupported = async ( }, }); return true; - } catch { + } catch (e) { + console.error(e); return false; } })(); diff --git a/src/DnsUtils/resolveDns.node.ts b/src/DnsUtils/resolveDns.node.ts index 3c52785..a51e2bb 100644 --- a/src/DnsUtils/resolveDns.node.ts +++ b/src/DnsUtils/resolveDns.node.ts @@ -5,6 +5,7 @@ */ import { Resolver } from "node:dns/promises"; +import { isIPv4, isIPv6 } from "node:net"; import type { ResolveDnsFunction } from "./resolveDns.ts"; export const resolveDns: ResolveDnsFunction = async ( @@ -14,9 +15,17 @@ export const resolveDns: ResolveDnsFunction = async ( ) => { const resolver = new Resolver(); if (options?.nameServer?.ipAddr !== undefined) { - resolver.setServers([options.nameServer.ipAddr]); + resolver.setServers([ + ipPort(options.nameServer.ipAddr, options.nameServer.port ?? 53), + ]); } // deno-lint-ignore no-explicit-any -- typescript is hard return (await resolver.resolve(domain, recordType)) as any; }; + +function ipPort(ip: string, port: number): string { + if (isIPv4(ip)) return `${ip}:${port}`; + if (isIPv6(ip)) return `[${ip}]:${port}`; + throw new Error("Invalid IP address"); +} diff --git a/src/DnsUtils/resolveDns.ts b/src/DnsUtils/resolveDns.ts index 19d06fc..83107ac 100644 --- a/src/DnsUtils/resolveDns.ts +++ b/src/DnsUtils/resolveDns.ts @@ -7,6 +7,7 @@ export type ResolveDnsFunction = ( options?: { nameServer?: { ipAddr: string; + port?: number; }; }, ) => Promise<"TXT" extends R ? string[][] : string[]>; From 11d8802a2c6f9763cd44fabf09b90e0000cfdebe Mon Sep 17 00:00:00 2001 From: Jason Yu Date: Mon, 14 Oct 2024 23:53:10 +0100 Subject: [PATCH 3/3] ci: run npm build in ci --- .github/workflows/npm-build.yaml | 46 ++++++++++++++++++++++++++++++++ .github/workflows/publish.yaml | 10 ++++--- deno.json | 3 ++- scripts/build-npm-integration.ts | 10 +++++++ scripts/build-npm.ts | 16 ++++++----- 5 files changed, 74 insertions(+), 11 deletions(-) create mode 100644 .github/workflows/npm-build.yaml create mode 100644 scripts/build-npm-integration.ts diff --git a/.github/workflows/npm-build.yaml b/.github/workflows/npm-build.yaml new file mode 100644 index 0000000..20b8b19 --- /dev/null +++ b/.github/workflows/npm-build.yaml @@ -0,0 +1,46 @@ +name: "Node: Build + Integration" + +on: + push: + branches: + - main + pull_request: + +jobs: + test: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - uses: denoland/setup-deno@v2 + with: + deno-version: v2.x # Run with latest stable Deno. + + - name: Start Pebble and pebble-challtestsrv + run: deno task pebble:start --detach + + - name: Wait for Pebble to be ready + run: | + echo "⏳ Waiting for Pebble... 🪨" + + # Loop until the port 14000 is open + until nc -zv localhost 14000 2>/dev/null; do + sleep 1 + done + + echo "✅ Pebble is running!" + - name: Wait for pebble-challtestsrv to be ready + run: | + echo "⏳ Waiting for pebble-challtestsrv... 🪨" + + until nc -zv localhost 8055 2>/dev/null; do + sleep 1 + done + + echo "✅ pebble-challtestsrv is running!" + + - run: deno task build:npm:integration + + - name: Stop Pebble + run: deno task pebble:stop diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index c35571d..b7dca57 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -1,11 +1,14 @@ name: Publish on: - push: - branches: - - main + workflow_run: + workflows: ["CI", "E2E", "Integration", "Node: Build + Integration"] + branches: [main] + types: + - completed jobs: publish-jsr: + if: ${{ github.event.workflow_run.conclusion == 'success' }} runs-on: ubuntu-latest permissions: @@ -19,6 +22,7 @@ jobs: run: npx jsr publish publish-npm: + if: ${{ github.event.workflow_run.conclusion == 'success' }} runs-on: ubuntu-latest permissions: diff --git a/deno.json b/deno.json index 84d406a..3dfbea2 100644 --- a/deno.json +++ b/deno.json @@ -13,7 +13,8 @@ "test:integration": "deno test --unsafely-ignore-certificate-errors=localhost -A integration", "pebble:start": "docker compose -f integration/docker-compose.yaml up", "pebble:stop": "docker compose -f integration/docker-compose.yaml down", - "build:npm": "deno run -A scripts/build-npm.ts" + "build:npm": "deno run -A scripts/build-npm.ts", + "build:npm:integration": "deno run -A scripts/build-npm-integration.ts" }, "compilerOptions": { "strict": true, diff --git a/scripts/build-npm-integration.ts b/scripts/build-npm-integration.ts new file mode 100644 index 0000000..207c550 --- /dev/null +++ b/scripts/build-npm-integration.ts @@ -0,0 +1,10 @@ +import { build, type BuildOptions } from "jsr:@deno/dnt"; +import { dntConfig } from "./build-npm.ts"; + +const config: BuildOptions = { + ...dntConfig, + testPattern: "integration/**/*.test.ts", + test: true, +}; + +await build(config); diff --git a/scripts/build-npm.ts b/scripts/build-npm.ts index cf0b398..ced1949 100644 --- a/scripts/build-npm.ts +++ b/scripts/build-npm.ts @@ -1,4 +1,4 @@ -import { build, emptyDir } from "jsr:@deno/dnt"; +import { build, type BuildOptions, emptyDir } from "jsr:@deno/dnt"; import { join } from "jsr:@std/path"; import DENO_JSON from "../deno.json" with { type: "json" }; @@ -14,19 +14,16 @@ const OUT_DIR = join( "./dist-npm", ); -await emptyDir(OUT_DIR); - const GITHUB_REPO = "https://github.com/fishballapp/acme"; -await build({ - testPattern: "integration/**/*.test.ts", +export const dntConfig: BuildOptions = { entryPoints: Object.entries(DENO_JSON.exports).map(([name, path]) => ({ kind: "export", name, path: join(PROJECT_ROOT, path), })), outDir: OUT_DIR, - test: true, + test: false, shims: { deno: "dev", undici: "dev", @@ -67,4 +64,9 @@ await build({ ); } }, -}); +}; + +if (import.meta.main) { + await emptyDir(OUT_DIR); + await build(dntConfig); +}