diff --git a/CHANGES.md b/CHANGES.md
index 1236c5b4d..84c547f89 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -57,6 +57,11 @@ To be released.
[[#206], [#797], [#798], [#799], [#803], [#806], [#812], [#923] by
ChanHaeng Lee]
+ - Fixed CommonJS distribution files that use Temporal so they no longer
+ require `@js-temporal/polyfill` at runtime. The CommonJS build now
+ bundles `temporal-polyfill`, while type declarations rely on the standard
+ `esnext.temporal` lib reference. [[#823], [#925]]
+
[FEP-8b32]: https://w3id.org/fep/8b32
[FEP-ef61]: https://w3id.org/fep/ef61
[Standard Schema]: https://standardschema.dev/
@@ -67,9 +72,11 @@ To be released.
[#803]: https://github.com/fedify-dev/fedify/pull/803
[#806]: https://github.com/fedify-dev/fedify/pull/806
[#812]: https://github.com/fedify-dev/fedify/pull/812
+[#823]: https://github.com/fedify-dev/fedify/issues/823
[#827]: https://github.com/fedify-dev/fedify/issues/827
[#915]: https://github.com/fedify-dev/fedify/pull/915
[#923]: https://github.com/fedify-dev/fedify/pull/923
+[#925]: https://github.com/fedify-dev/fedify/pull/925
### @fedify/vocab
@@ -84,6 +91,11 @@ To be released.
`FeatureAuthorization`, plus actor `featuredCollections` and
`InteractionPolicy.canFeature` properties. [[#810], [#914]]
+ - Fixed the CommonJS vocabulary build so it no longer requires
+ `@js-temporal/polyfill` at runtime. The build now bundles
+ `temporal-polyfill`, while type declarations rely on the standard
+ `esnext.temporal` lib reference. [[#823], [#925]]
+
[FEP-7aa9]: https://w3id.org/fep/7aa9
[#810]: https://github.com/fedify-dev/fedify/issues/810
[#826]: https://github.com/fedify-dev/fedify/issues/826
@@ -111,6 +123,60 @@ To be released.
[#912]: https://github.com/fedify-dev/fedify/issues/912
[#913]: https://github.com/fedify-dev/fedify/pull/913
+### @fedify/cli
+
+ - Switched the CLI's Temporal runtime dependency from
+ `@js-temporal/polyfill` to `temporal-polyfill`. [[#823], [#925]]
+
+### @fedify/debugger
+
+ - Fixed the CommonJS debugger build so it no longer requires
+ `@js-temporal/polyfill` at runtime. The build now bundles
+ `temporal-polyfill`, while type declarations rely on the standard
+ `esnext.temporal` lib reference. [[#823], [#925]]
+
+### @fedify/mysql
+
+ - Fixed the CommonJS MySQL adapter build so it no longer requires
+ `@js-temporal/polyfill` at runtime. The build now bundles
+ `temporal-polyfill`, while type declarations rely on the standard
+ `esnext.temporal` lib reference. [[#823], [#925]]
+
+### @fedify/postgres
+
+ - Fixed the CommonJS PostgreSQL adapter build so it no longer requires
+ `@js-temporal/polyfill` at runtime. The build now bundles
+ `temporal-polyfill`, while type declarations rely on the standard
+ `esnext.temporal` lib reference. [[#823], [#925]]
+
+### @fedify/redis
+
+ - Fixed the CommonJS Redis adapter build so it no longer requires
+ `@js-temporal/polyfill` at runtime. The build now bundles
+ `temporal-polyfill`, while type declarations rely on the standard
+ `esnext.temporal` lib reference. [[#823], [#925]]
+
+### @fedify/relay
+
+ - Fixed the CommonJS relay build so it no longer requires
+ `@js-temporal/polyfill` at runtime. The build now bundles
+ `temporal-polyfill`, while type declarations rely on the standard
+ `esnext.temporal` lib reference. [[#823], [#925]]
+
+### @fedify/sqlite
+
+ - Fixed the CommonJS SQLite adapter build so it no longer requires
+ `@js-temporal/polyfill` at runtime. The build now bundles
+ `temporal-polyfill`, while type declarations rely on the standard
+ `esnext.temporal` lib reference. [[#823], [#925]]
+
+### @fedify/testing
+
+ - Fixed the CommonJS testing utilities build so it no longer requires
+ `@js-temporal/polyfill` at runtime. The build now bundles
+ `temporal-polyfill`, while type declarations rely on the standard
+ `esnext.temporal` lib reference. [[#823], [#925]]
+
Version 2.3.1
-------------
diff --git a/deno.json b/deno.json
index 4755d4c7f..c72225a36 100644
--- a/deno.json
+++ b/deno.json
@@ -84,6 +84,7 @@
"mysql2/promise": "npm:mysql2@^3.22.3/promise",
"postgres": "npm:postgres@^3.4.7",
"preact": "npm:preact@10.19.6",
+ "temporal-polyfill": "npm:temporal-polyfill@^1.0.1",
"tsdown": "npm:tsdown@^0.22.0"
},
"unstable": [
diff --git a/deno.lock b/deno.lock
index 0f12de536..c47740704 100644
--- a/deno.lock
+++ b/deno.lock
@@ -169,6 +169,7 @@
"npm:smol-toml@^1.6.1": "1.6.1",
"npm:srvx@~0.8.7": "0.8.16",
"npm:structured-field-values@^2.0.4": "2.0.4",
+ "npm:temporal-polyfill@^1.0.1": "1.0.1",
"npm:tsdown@0.22": "0.22.0_tsx@4.21.0",
"npm:tsx@^4.21.0": "4.21.0",
"npm:uri-template-router@1": "1.0.0",
@@ -8474,6 +8475,19 @@
"streamx"
]
},
+ "temporal-polyfill@1.0.1": {
+ "integrity": "sha512-N2SoI9olnW7BUsU8RosDphZQl9s+WJ8O7PoJMFCr/e5/1rFkVI4GNOWaSeySG+UoP04foPYsnLWbJmbXOiShZg==",
+ "dependencies": [
+ "temporal-spec",
+ "temporal-utils"
+ ]
+ },
+ "temporal-spec@1.0.0": {
+ "integrity": "sha512-00Ahj1e1ifaERTMOIIGpOCdOo9IEk2m6GGSMedsn9a2SIsGLdOTbmME1Htv6IM82b6VHrzSUTIVc7YHy6hdhFQ=="
+ },
+ "temporal-utils@1.0.1": {
+ "integrity": "sha512-HAixuesxFQIUaQk3ptX2jhfO/FsOkgVkDDMawvp6n/fkB1q6BKfs3lURw9I+pK/2e2e/q/vrLrxmeqauBoyGMQ=="
+ },
"terracotta@1.1.0_solid-js@1.9.12": {
"integrity": "sha512-kfQciWUBUBgYkXu7gh3CK3FAJng/iqZslAaY08C+k1Hdx17aVEpcFFb/WPaysxAfcupNH3y53s/pc53xxZauww==",
"dependencies": [
@@ -9497,6 +9511,7 @@
"npm:mysql2@^3.22.3",
"npm:postgres@^3.4.7",
"npm:preact@10.19.6",
+ "npm:temporal-polyfill@^1.0.1",
"npm:tsdown@0.22"
],
"members": {
@@ -9640,7 +9655,6 @@
],
"packageJson": {
"dependencies": [
- "npm:@js-temporal/polyfill@~0.5.1",
"npm:@jsr/std__assert@0.226",
"npm:@types/node@^24.2.1",
"npm:devalue@^5.8.1",
@@ -9727,7 +9741,8 @@
"dependencies": [
"npm:fast-check@^3.22.0",
"npm:fetch-mock@^12.5.2",
- "npm:jsonld@9"
+ "npm:jsonld@9",
+ "npm:temporal-polyfill@^1.0.1"
],
"packageJson": {
"dependencies": [
diff --git a/docs/package.json b/docs/package.json
index 9fdd43087..45865af46 100644
--- a/docs/package.json
+++ b/docs/package.json
@@ -30,7 +30,6 @@
"@fontsource-variable/bricolage-grotesque": "^5.2.10",
"@hackmd/markdown-it-task-lists": "^2.1.4",
"@hono/node-server": "^1.13.7",
- "@js-temporal/polyfill": "catalog:",
"@logtape/file": "catalog:",
"@logtape/logtape": "catalog:",
"@lucide/vue": "^1.20.0",
@@ -67,6 +66,7 @@
"postgres": "catalog:",
"srvx": "^0.11.15",
"stringify-entities": "^4.0.4",
+ "temporal-polyfill": "catalog:",
"typescript": "catalog:",
"vitepress": "^2.0.0-alpha.17",
"vitepress-plugin-group-icons": "^1.7.5",
diff --git a/docs/tutorial/astro-blog.md b/docs/tutorial/astro-blog.md
index e99a1e88f..d83c560d8 100644
--- a/docs/tutorial/astro-blog.md
+++ b/docs/tutorial/astro-blog.md
@@ -1911,14 +1911,14 @@ as the HTML page URL since we'll share the path `/posts/{slug}` between Astro
and Fedify via content negotiation. `content_hash` is a SHA-256 digest of the
title and body, used to detect edits.
-### Adding `@js-temporal/polyfill`
+### Adding `temporal-polyfill`
The `Article` object uses `Temporal.Instant` from the [TC39 Temporal proposal]
polyfill. Although `@fedify/vocab` already depends on this package, you should
list it directly in your project so the version stays under your control:
~~~~ sh
-bun add @js-temporal/polyfill
+bun add temporal-polyfill
~~~~
[TC39 Temporal proposal]: https://tc39.es/proposal-temporal/
@@ -1967,7 +1967,7 @@ import {
Person,
Undo,
} from "@fedify/vocab";
-import { Temporal } from "@js-temporal/polyfill";
+import { Temporal } from "temporal-polyfill";
import { getLogger } from "@logtape/logtape";
import {
addFollower,
@@ -2114,7 +2114,7 @@ Create *src/lib/publish.ts*:
// @noErrors
import type { RequestContext } from "@fedify/fedify";
import { Article, Create, Delete, Update } from "@fedify/vocab";
-import { Temporal } from "@js-temporal/polyfill";
+import { Temporal } from "temporal-polyfill";
import { getCollection } from "astro:content";
import { BLOG_IDENTIFIER } from "../federation.ts";
import db from "./db.ts";
@@ -2519,7 +2519,7 @@ import {
Undo,
Update,
} from "@fedify/vocab";
-import { Temporal } from "@js-temporal/polyfill";
+import { Temporal } from "temporal-polyfill";
import { getLogger } from "@logtape/logtape";
import {
addComment,
diff --git a/docs/tutorial/content-sharing.md b/docs/tutorial/content-sharing.md
index eef00b083..e14700e33 100644
--- a/docs/tutorial/content-sharing.md
+++ b/docs/tutorial/content-sharing.md
@@ -3482,7 +3482,7 @@ import {
type Recipient,
Undo,
} from "@fedify/vocab";
-import { Temporal } from "@js-temporal/polyfill";
+import { Temporal } from "temporal-polyfill";
// ...
import { actorKeys, followers, posts, users } from "./db/schema";
~~~~
@@ -3490,7 +3490,7 @@ import { actorKeys, followers, posts, users } from "./db/schema";
We also need the polyfill itself in *package.json*:
~~~~ sh
-npm install @js-temporal/polyfill
+npm install temporal-polyfill
~~~~
Node.js 22 does not yet ship `Temporal` natively, and Fedify
@@ -6528,7 +6528,7 @@ import {
Note,
PUBLIC_COLLECTION,
} from "@fedify/vocab";
-import { Temporal } from "@js-temporal/polyfill";
+import { Temporal } from "temporal-polyfill";
import { and, eq } from "drizzle-orm";
import {
createError,
diff --git a/docs/tutorial/microblog.md b/docs/tutorial/microblog.md
index 85e7b9be7..6251a12ed 100644
--- a/docs/tutorial/microblog.md
+++ b/docs/tutorial/microblog.md
@@ -3137,16 +3137,16 @@ object.
Before implementation, we need to install a necessary library. Because
the [Temporal API] used by Fedify to represent time is not yet built into
-Node.js, we need the *[@js-temporal/polyfill]* package to polyfill it:
+Node.js, we need the *[temporal-polyfill]* package to polyfill it:
~~~~ sh
-npm add @js-temporal/polyfill
+npm add temporal-polyfill
~~~~
Open the *src/federation.ts* file and `import` the installed package:
~~~~ typescript [src/federation.ts]
-import { Temporal } from "@js-temporal/polyfill";
+import { Temporal } from "temporal-polyfill";
~~~~
Also `import` the `Post` type and the `PUBLIC_COLLECTION` constant provided by
@@ -3259,7 +3259,7 @@ temporary domain name) in the Mastodon search box again:
This time, our created post appears properly in the search results!
[Temporal API]: https://tc39.es/proposal-temporal/docs/
-[@js-temporal/polyfill]: https://github.com/js-temporal/temporal-polyfill
+[temporal-polyfill]: https://github.com/fullcalendar/temporal-polyfill
### Sending `Create(Note)` activity
diff --git a/mise.toml b/mise.toml
index 703bb6940..2d3760e05 100644
--- a/mise.toml
+++ b/mise.toml
@@ -268,7 +268,12 @@ run = "pnpm run --recursive --parallel --filter '!{docs}' --config.enable-pre-po
[tasks.test]
description = "Run the test suite across all environments (Deno, Node.js, Bun)"
-depends = ["check", "test:deno", "test:node", "test:bun"]
+depends = ["check", "test:deno", "test:node", "test:bun", "test:temporal-polyfill"]
+
+[tasks."test:temporal-polyfill"]
+description = "Check Temporal polyfill packaging"
+depends = ["build"]
+run = "deno run --allow-read --allow-write --allow-run scripts/check_temporal_polyfill.ts"
[tasks.test-each]
description = "Run tests for a specific package across all environments"
diff --git a/packages/cli/package.json b/packages/cli/package.json
index 676ceb97d..4de15ea4d 100644
--- a/packages/cli/package.json
+++ b/packages/cli/package.json
@@ -88,7 +88,6 @@
"@inquirer/prompts": "^7.8.4",
"@jimp/core": "^1.6.1",
"@jimp/wasm-webp": "^1.6.1",
- "@js-temporal/polyfill": "catalog:",
"@logtape/file": "catalog:",
"@logtape/logtape": "catalog:",
"@poppanator/http-constants": "^1.1.1",
@@ -109,6 +108,7 @@
"shiki": "^1.6.4",
"smol-toml": "^1.6.1",
"srvx": "^0.8.7",
+ "temporal-polyfill": "catalog:",
"valibot": "^1.4.0",
"yaml": "^2.9.0"
},
diff --git a/packages/cli/tsdown.config.ts b/packages/cli/tsdown.config.ts
index 541aa5413..7c488f6ba 100644
--- a/packages/cli/tsdown.config.ts
+++ b/packages/cli/tsdown.config.ts
@@ -1,4 +1,5 @@
import { defineConfig } from "tsdown";
+import { temporalPolyfillIntro } from "../../scripts/tsdown/temporal.mts";
export default defineConfig({
entry: [
@@ -24,9 +25,7 @@ export default defineConfig({
},
},
outputOptions(outputOptions) {
- outputOptions.intro = `
- import { Temporal } from "@js-temporal/polyfill";
- `;
+ outputOptions.intro = temporalPolyfillIntro;
return outputOptions;
},
});
diff --git a/packages/debugger/package.json b/packages/debugger/package.json
index 684d91acf..cea565924 100644
--- a/packages/debugger/package.json
+++ b/packages/debugger/package.json
@@ -32,13 +32,13 @@
"@fedify/fedify": "workspace:^"
},
"dependencies": {
- "@js-temporal/polyfill": "catalog:",
"@logtape/logtape": "catalog:",
"@opentelemetry/api": "catalog:",
"@opentelemetry/context-async-hooks": "catalog:",
"@opentelemetry/core": "catalog:",
"@opentelemetry/sdk-trace-base": "catalog:",
- "hono": "catalog:"
+ "hono": "catalog:",
+ "temporal-polyfill": "catalog:"
},
"devDependencies": {
"tsdown": "catalog:",
diff --git a/packages/debugger/tsdown.config.ts b/packages/debugger/tsdown.config.ts
index 9010f25ad..35286a6e9 100644
--- a/packages/debugger/tsdown.config.ts
+++ b/packages/debugger/tsdown.config.ts
@@ -1,9 +1,35 @@
import { defineConfig } from "tsdown";
+import {
+ temporalPolyfillCjsBanner,
+ temporalPolyfillCjsDeps,
+ temporalPolyfillEsmBanner,
+ temporalPolyfillImportPlugin,
+} from "../../scripts/tsdown/temporal.mts";
export default defineConfig({
entry: ["src/mod.tsx"],
dts: { compilerOptions: { isolatedDeclarations: true, declaration: true } },
- format: ["esm", "cjs"],
+ format: {
+ esm: {
+ banner: temporalPolyfillEsmBanner(),
+ },
+ cjs: {
+ deps: temporalPolyfillCjsDeps({
+ neverBundle: [
+ "@fedify/fedify",
+ "@fedify/fedify/federation",
+ "@fedify/fedify/otel",
+ "@logtape/logtape",
+ /^@logtape\//,
+ /^@opentelemetry\//,
+ "hono",
+ /^hono\//,
+ ],
+ }),
+ plugins: [temporalPolyfillImportPlugin],
+ banner: temporalPolyfillCjsBanner(),
+ },
+ },
platform: "node",
outExtensions({ format }) {
return {
@@ -23,13 +49,4 @@ export default defineConfig({
/^hono\//,
],
},
- banner({ format }) {
- const js = format === "cjs"
- ? `const { Temporal } = require("@js-temporal/polyfill");`
- : `import { Temporal } from "@js-temporal/polyfill";`;
- return {
- js,
- dts: `/// `,
- };
- },
});
diff --git a/packages/fedify/package.json b/packages/fedify/package.json
index 9549e3f68..c70e69a31 100644
--- a/packages/fedify/package.json
+++ b/packages/fedify/package.json
@@ -140,7 +140,6 @@
"@fedify/vocab": "workspace:*",
"@fedify/vocab-runtime": "workspace:*",
"@fedify/webfinger": "workspace:*",
- "@js-temporal/polyfill": "^0.5.1",
"@logtape/logtape": "catalog:",
"@opentelemetry/api": "catalog:",
"@opentelemetry/core": "catalog:",
@@ -154,6 +153,7 @@
"json-canon": "^1.0.1",
"jsonld": "^9.0.0",
"structured-field-values": "^2.0.4",
+ "temporal-polyfill": "catalog:",
"urlpattern-polyfill": "catalog:"
},
"devDependencies": {
diff --git a/packages/fedify/src/vocab/cjs.test.ts b/packages/fedify/src/vocab/cjs.test.ts
index 59b819cbf..c942d8cac 100644
--- a/packages/fedify/src/vocab/cjs.test.ts
+++ b/packages/fedify/src/vocab/cjs.test.ts
@@ -10,3 +10,20 @@ test("CommonJS vocab entry exports Object", {
strictEqual(typeof vocab.Object, "function");
strictEqual(typeof vocab.Update, "function");
});
+
+test("CommonJS entries load Temporal-backed modules", {
+ ignore: "Deno" in globalThis,
+}, () => {
+ const originalTemporal = globalThis.Temporal;
+ const require = createRequire(import.meta.url);
+ const fedify = require("../mod.cjs");
+ const federation = require("../federation/mod.cjs");
+ const sig = require("../sig/mod.cjs");
+ const utils = require("../utils/mod.cjs");
+
+ strictEqual(typeof fedify.createFederation, "function");
+ strictEqual(typeof federation.InProcessMessageQueue, "function");
+ strictEqual(typeof sig.signRequest, "function");
+ strictEqual(typeof utils.kvCache, "function");
+ strictEqual(globalThis.Temporal, originalTemporal);
+});
diff --git a/packages/fedify/tsdown.config.ts b/packages/fedify/tsdown.config.ts
index 428ab9ff4..5f0a90776 100644
--- a/packages/fedify/tsdown.config.ts
+++ b/packages/fedify/tsdown.config.ts
@@ -1,6 +1,13 @@
import { glob } from "node:fs/promises";
import { join, sep } from "node:path";
import { defineConfig } from "tsdown";
+import {
+ temporalPolyfillCjsBanner,
+ temporalPolyfillCjsDeps,
+ temporalPolyfillEsmBanner,
+ temporalPolyfillImportPlugin,
+ temporalPolyfillIntro,
+} from "../../scripts/tsdown/temporal.mts";
function isTestingHelperImporter(importer: string | undefined): boolean {
const normalized = importer?.replaceAll(sep, "/");
@@ -21,24 +28,24 @@ export default [
"./src/vocab/mod.ts",
],
dts: { compilerOptions: { isolatedDeclarations: true, declaration: true } },
- format: ["esm", "cjs"],
- platform: "neutral",
- deps: { neverBundle: [/^node:/] },
- banner({ format }) {
- const js = format === "cjs"
- ? [
- `const { Temporal } = require("@js-temporal/polyfill");`,
- `const { URLPattern } = require("urlpattern-polyfill");`,
- ].join("\n")
- : [
- `import { Temporal } from "@js-temporal/polyfill";`,
+ format: {
+ esm: {
+ banner: temporalPolyfillEsmBanner(
`import { URLPattern } from "urlpattern-polyfill";`,
- ].join("\n");
- return {
- js,
- dts: `/// `,
- };
+ ),
+ },
+ cjs: {
+ deps: temporalPolyfillCjsDeps({
+ neverBundle: [/^node:/],
+ }),
+ plugins: [temporalPolyfillImportPlugin],
+ banner: temporalPolyfillCjsBanner(
+ `const { URLPattern } = require("urlpattern-polyfill");`,
+ ),
+ },
},
+ platform: "neutral",
+ deps: { neverBundle: [/^node:/] },
}),
defineConfig({
entry: [
@@ -73,8 +80,7 @@ export default [
},
},
outputOptions: {
- intro: `
- import { Temporal } from "@js-temporal/polyfill";
+ intro: `${temporalPolyfillIntro}
import { URLPattern } from "urlpattern-polyfill";
globalThis.addEventListener = () => {};
`,
diff --git a/packages/mysql/package.json b/packages/mysql/package.json
index 137c8ab74..12edad69c 100644
--- a/packages/mysql/package.json
+++ b/packages/mysql/package.json
@@ -66,9 +66,9 @@
"README.md"
],
"dependencies": {
- "@js-temporal/polyfill": "catalog:",
"@logtape/logtape": "catalog:",
- "es-toolkit": "catalog:"
+ "es-toolkit": "catalog:",
+ "temporal-polyfill": "catalog:"
},
"peerDependencies": {
"@fedify/fedify": "workspace:^",
@@ -77,6 +77,7 @@
"devDependencies": {
"@fedify/fixture": "workspace:^",
"@fedify/testing": "workspace:^",
+ "@js-temporal/polyfill": "catalog:",
"tsdown": "catalog:",
"typescript": "catalog:"
},
diff --git a/packages/mysql/tsdown.config.ts b/packages/mysql/tsdown.config.ts
index 1dc5f83fb..2f59540f8 100644
--- a/packages/mysql/tsdown.config.ts
+++ b/packages/mysql/tsdown.config.ts
@@ -1,22 +1,28 @@
import { defineConfig } from "tsdown";
+import {
+ temporalPolyfillCjsBanner,
+ temporalPolyfillCjsDeps,
+ temporalPolyfillEsmBanner,
+ temporalPolyfillImportPlugin,
+} from "../../scripts/tsdown/temporal.mts";
export default defineConfig({
entry: ["src/mod.ts", "src/kv.ts", "src/mq.ts"],
dts: { compilerOptions: { isolatedDeclarations: true, declaration: true } },
unbundle: true,
- format: ["esm", "cjs"],
+ format: {
+ esm: {
+ banner: temporalPolyfillEsmBanner(),
+ },
+ cjs: {
+ deps: temporalPolyfillCjsDeps(),
+ plugins: [temporalPolyfillImportPlugin],
+ banner: temporalPolyfillCjsBanner(),
+ },
+ },
platform: "node",
outExtensions({ format }) {
if (format === "cjs") return { js: ".cjs", dts: ".d.cts" };
return { js: ".js", dts: ".d.ts" };
},
- banner({ format }) {
- const js = format === "cjs"
- ? `const { Temporal } = require("@js-temporal/polyfill");`
- : `import { Temporal } from "@js-temporal/polyfill";`;
- return {
- js,
- dts: `/// `,
- };
- },
});
diff --git a/packages/postgres/package.json b/packages/postgres/package.json
index 5114af06e..9506b8eb2 100644
--- a/packages/postgres/package.json
+++ b/packages/postgres/package.json
@@ -66,8 +66,8 @@
"README.md"
],
"dependencies": {
- "@js-temporal/polyfill": "catalog:",
- "@logtape/logtape": "catalog:"
+ "@logtape/logtape": "catalog:",
+ "temporal-polyfill": "catalog:"
},
"peerDependencies": {
"@fedify/fedify": "workspace:^",
@@ -76,6 +76,7 @@
"devDependencies": {
"@fedify/fixture": "workspace:^",
"@fedify/testing": "workspace:^",
+ "@js-temporal/polyfill": "catalog:",
"@std/async": "catalog:",
"tsdown": "catalog:",
"typescript": "catalog:"
diff --git a/packages/postgres/tsdown.config.ts b/packages/postgres/tsdown.config.ts
index fe377e44b..7d8a8e4b6 100644
--- a/packages/postgres/tsdown.config.ts
+++ b/packages/postgres/tsdown.config.ts
@@ -1,10 +1,25 @@
import { defineConfig } from "tsdown";
+import {
+ temporalPolyfillCjsBanner,
+ temporalPolyfillCjsDeps,
+ temporalPolyfillEsmBanner,
+ temporalPolyfillImportPlugin,
+} from "../../scripts/tsdown/temporal.mts";
export default defineConfig({
entry: ["src/mod.ts", "src/kv.ts", "src/mq.ts"],
dts: { compilerOptions: { isolatedDeclarations: true, declaration: true } },
unbundle: true,
- format: ["esm", "cjs"],
+ format: {
+ esm: {
+ banner: temporalPolyfillEsmBanner(),
+ },
+ cjs: {
+ deps: temporalPolyfillCjsDeps(),
+ plugins: [temporalPolyfillImportPlugin],
+ banner: temporalPolyfillCjsBanner(),
+ },
+ },
platform: "node",
outExtensions({ format }) {
return {
@@ -12,13 +27,4 @@ export default defineConfig({
dts: format === "cjs" ? ".d.cts" : ".d.ts",
};
},
- banner({ format }) {
- const js = format === "cjs"
- ? `const { Temporal } = require("@js-temporal/polyfill");`
- : `import { Temporal } from "@js-temporal/polyfill";`;
- return {
- js,
- dts: `/// `,
- };
- },
});
diff --git a/packages/redis/package.json b/packages/redis/package.json
index f8da72e49..795ea1c8b 100644
--- a/packages/redis/package.json
+++ b/packages/redis/package.json
@@ -74,8 +74,8 @@
"package.json"
],
"dependencies": {
- "@js-temporal/polyfill": "catalog:",
- "@logtape/logtape": "catalog:"
+ "@logtape/logtape": "catalog:",
+ "temporal-polyfill": "catalog:"
},
"peerDependencies": {
"@fedify/fedify": "workspace:^",
@@ -85,6 +85,7 @@
"@std/async": "catalog:",
"@fedify/fixture": "workspace:^",
"@fedify/testing": "workspace:^",
+ "@js-temporal/polyfill": "catalog:",
"@types/node": "catalog:",
"tsdown": "catalog:",
"typescript": "catalog:"
diff --git a/packages/redis/tsdown.config.ts b/packages/redis/tsdown.config.ts
index 0527386b5..291033dea 100644
--- a/packages/redis/tsdown.config.ts
+++ b/packages/redis/tsdown.config.ts
@@ -1,10 +1,25 @@
import { defineConfig } from "tsdown";
+import {
+ temporalPolyfillCjsBanner,
+ temporalPolyfillCjsDeps,
+ temporalPolyfillEsmBanner,
+ temporalPolyfillImportPlugin,
+} from "../../scripts/tsdown/temporal.mts";
export default defineConfig({
entry: ["src/mod.ts", "src/codec.ts", "src/kv.ts", "src/mq.ts"],
dts: { compilerOptions: { isolatedDeclarations: true, declaration: true } },
unbundle: true,
- format: ["esm", "cjs"],
+ format: {
+ esm: {
+ banner: temporalPolyfillEsmBanner(),
+ },
+ cjs: {
+ deps: temporalPolyfillCjsDeps(),
+ plugins: [temporalPolyfillImportPlugin],
+ banner: temporalPolyfillCjsBanner(),
+ },
+ },
platform: "node",
outExtensions({ format }) {
return {
@@ -12,13 +27,4 @@ export default defineConfig({
dts: format === "cjs" ? ".d.cts" : ".d.ts",
};
},
- banner({ format }) {
- const js = format === "cjs"
- ? `const { Temporal } = require("@js-temporal/polyfill");`
- : `import { Temporal } from "@js-temporal/polyfill";`;
- return {
- js,
- dts: `/// `,
- };
- },
});
diff --git a/packages/relay/package.json b/packages/relay/package.json
index 703200be6..8322d9b41 100644
--- a/packages/relay/package.json
+++ b/packages/relay/package.json
@@ -47,8 +47,8 @@
"dependencies": {
"@fedify/fedify": "workspace:^",
"@fedify/vocab": "workspace:*",
- "@js-temporal/polyfill": "catalog:",
- "@logtape/logtape": "catalog:"
+ "@logtape/logtape": "catalog:",
+ "temporal-polyfill": "catalog:"
},
"devDependencies": {
"@fedify/vocab-runtime": "workspace:^",
diff --git a/packages/relay/tsdown.config.ts b/packages/relay/tsdown.config.ts
index bdbaab38b..76fd38b99 100644
--- a/packages/relay/tsdown.config.ts
+++ b/packages/relay/tsdown.config.ts
@@ -1,12 +1,28 @@
import { glob } from "node:fs/promises";
import { sep } from "node:path";
import { defineConfig } from "tsdown";
+import {
+ temporalPolyfillCjsBanner,
+ temporalPolyfillCjsDeps,
+ temporalPolyfillEsmBanner,
+ temporalPolyfillImportPlugin,
+ temporalPolyfillIntro,
+} from "../../scripts/tsdown/temporal.mts";
export default [
defineConfig({
entry: ["src/mod.ts"],
dts: { compilerOptions: { isolatedDeclarations: true, declaration: true } },
- format: ["esm", "cjs"],
+ format: {
+ esm: {
+ banner: temporalPolyfillEsmBanner(),
+ },
+ cjs: {
+ deps: temporalPolyfillCjsDeps(),
+ plugins: [temporalPolyfillImportPlugin],
+ banner: temporalPolyfillCjsBanner(),
+ },
+ },
platform: "node",
outExtensions({ format }) {
return {
@@ -14,15 +30,6 @@ export default [
dts: format === "cjs" ? ".d.cts" : ".d.ts",
};
},
- banner({ format }) {
- const js = format === "cjs"
- ? `const { Temporal } = require("@js-temporal/polyfill");`
- : `import { Temporal } from "@js-temporal/polyfill";`;
- return {
- js,
- dts: `/// `,
- };
- },
}),
defineConfig({
entry: (await Array.fromAsync(glob(`src/**/*.test.ts`)))
@@ -35,8 +42,7 @@ export default [
},
deps: { neverBundle: [/^node:/] },
outputOptions: {
- intro: `
- import { Temporal } from "@js-temporal/polyfill";
+ intro: `${temporalPolyfillIntro}
import { URLPattern } from "urlpattern-polyfill";
globalThis.addEventListener = () => {};
`,
diff --git a/packages/sqlite/package.json b/packages/sqlite/package.json
index 40afd2176..ff49d4e26 100644
--- a/packages/sqlite/package.json
+++ b/packages/sqlite/package.json
@@ -64,15 +64,16 @@
}
},
"dependencies": {
- "@js-temporal/polyfill": "catalog:",
"@logtape/logtape": "catalog:",
- "es-toolkit": "^1.46.1"
+ "es-toolkit": "^1.46.1",
+ "temporal-polyfill": "catalog:"
},
"peerDependencies": {
"@fedify/fedify": "workspace:^"
},
"devDependencies": {
"@fedify/testing": "workspace:^",
+ "@js-temporal/polyfill": "catalog:",
"@std/async": "catalog:",
"tsdown": "catalog:",
"typescript": "catalog:"
diff --git a/packages/sqlite/tsdown.config.ts b/packages/sqlite/tsdown.config.ts
index 3dc353314..eb72ca332 100644
--- a/packages/sqlite/tsdown.config.ts
+++ b/packages/sqlite/tsdown.config.ts
@@ -1,4 +1,10 @@
import { defineConfig } from "tsdown";
+import {
+ temporalPolyfillCjsBanner,
+ temporalPolyfillCjsDeps,
+ temporalPolyfillEsmBanner,
+ temporalPolyfillImportPlugin,
+} from "../../scripts/tsdown/temporal.mts";
export default defineConfig({
entry: [
@@ -10,7 +16,16 @@ export default defineConfig({
],
dts: { compilerOptions: { isolatedDeclarations: true, declaration: true } },
unbundle: true,
- format: ["esm", "cjs"],
+ format: {
+ esm: {
+ banner: temporalPolyfillEsmBanner(),
+ },
+ cjs: {
+ deps: temporalPolyfillCjsDeps(),
+ plugins: [temporalPolyfillImportPlugin],
+ banner: temporalPolyfillCjsBanner(),
+ },
+ },
platform: "node",
outExtensions({ format }) {
return {
@@ -29,13 +44,4 @@ export default defineConfig({
defaultHandler(warning);
},
},
- banner({ format }) {
- const js = format === "cjs"
- ? `const { Temporal } = require("@js-temporal/polyfill");`
- : `import { Temporal } from "@js-temporal/polyfill";`;
- return {
- js,
- dts: `/// `,
- };
- },
});
diff --git a/packages/testing/package.json b/packages/testing/package.json
index 39efce142..0a4f17a51 100644
--- a/packages/testing/package.json
+++ b/packages/testing/package.json
@@ -50,11 +50,11 @@
"@fedify/fedify": "workspace:^"
},
"dependencies": {
- "es-toolkit": "catalog:"
+ "es-toolkit": "catalog:",
+ "temporal-polyfill": "catalog:"
},
"devDependencies": {
"@fedify/fixture": "workspace:^",
- "@js-temporal/polyfill": "catalog:",
"@standard-schema/spec": "catalog:",
"@std/assert": "catalog:",
"@std/async": "catalog:",
diff --git a/packages/testing/tsdown.config.ts b/packages/testing/tsdown.config.ts
index c7b2a22c2..54a75d6f3 100644
--- a/packages/testing/tsdown.config.ts
+++ b/packages/testing/tsdown.config.ts
@@ -1,9 +1,32 @@
import { defineConfig } from "tsdown";
+import {
+ temporalPolyfillCjsBanner,
+ temporalPolyfillCjsDeps,
+ temporalPolyfillEsmBanner,
+ temporalPolyfillImportPlugin,
+} from "../../scripts/tsdown/temporal.mts";
export default defineConfig({
entry: "src/mod.ts",
dts: { compilerOptions: { isolatedDeclarations: true, declaration: true } },
- format: ["esm", "cjs"],
+ format: {
+ esm: {
+ banner: temporalPolyfillEsmBanner(),
+ },
+ cjs: {
+ deps: temporalPolyfillCjsDeps({
+ neverBundle: [
+ "@fedify/fedify",
+ "@fedify/fedify/federation",
+ "@fedify/fixture",
+ "@fedify/vocab",
+ "@fedify/vocab-runtime",
+ ],
+ }),
+ plugins: [temporalPolyfillImportPlugin],
+ banner: temporalPolyfillCjsBanner(),
+ },
+ },
platform: "node",
outExtensions({ format }) {
return {
@@ -15,17 +38,9 @@ export default defineConfig({
neverBundle: [
"@fedify/fedify",
"@fedify/fedify/federation",
+ "@fedify/fixture",
"@fedify/vocab",
"@fedify/vocab-runtime",
],
},
- banner({ format }) {
- const js = format === "cjs"
- ? `const { Temporal } = require("@js-temporal/polyfill");`
- : `import { Temporal } from "@js-temporal/polyfill";`;
- return {
- js,
- dts: `/// `,
- };
- },
});
diff --git a/packages/vocab/deno.json b/packages/vocab/deno.json
index 90cb3d676..9a19a59df 100644
--- a/packages/vocab/deno.json
+++ b/packages/vocab/deno.json
@@ -14,7 +14,8 @@
"imports": {
"fast-check": "npm:fast-check@^3.22.0",
"fetch-mock": "npm:fetch-mock@^12.5.2",
- "jsonld": "npm:jsonld@^9.0.0"
+ "jsonld": "npm:jsonld@^9.0.0",
+ "temporal-polyfill": "npm:temporal-polyfill@^1.0.1"
},
"exclude": [
"dist/",
diff --git a/packages/vocab/package.json b/packages/vocab/package.json
index b0bf7dd88..4af7b7f07 100644
--- a/packages/vocab/package.json
+++ b/packages/vocab/package.json
@@ -37,7 +37,6 @@
"dependencies": {
"@fedify/vocab-tools": "workspace:*",
"@fedify/webfinger": "workspace:*",
- "@js-temporal/polyfill": "catalog:",
"@multiformats/base-x": "catalog:",
"@logtape/logtape": "catalog:",
"@opentelemetry/api": "catalog:",
@@ -45,7 +44,8 @@
"es-toolkit": "catalog:",
"@fedify/vocab-runtime": "workspace:*",
"jsonld": "^9.0.0",
- "pkijs": "catalog:"
+ "pkijs": "catalog:",
+ "temporal-polyfill": "catalog:"
},
"devDependencies": {
"@fedify/fixture": "workspace:*",
diff --git a/packages/vocab/src/cjs.test.ts b/packages/vocab/src/cjs.test.ts
new file mode 100644
index 000000000..9cdc2b3f6
--- /dev/null
+++ b/packages/vocab/src/cjs.test.ts
@@ -0,0 +1,31 @@
+import { ok, strictEqual, throws } from "node:assert";
+import { createRequire } from "node:module";
+import { mockDocumentLoader, test } from "@fedify/fixture";
+
+test("CommonJS entry bundles temporal-polyfill internally", {
+ ignore: "Deno" in globalThis,
+}, async () => {
+ const originalTemporal = globalThis.Temporal;
+
+ const require = createRequire(import.meta.url);
+ throws(
+ () => require("temporal-polyfill"),
+ (error: unknown) => {
+ if (error == null || typeof error !== "object") return false;
+ const { code } = error as { code?: unknown };
+ return code === "ERR_PACKAGE_PATH_NOT_EXPORTED" ||
+ code === "MODULE_NOT_FOUND";
+ },
+ );
+
+ const vocab = require("../dist/mod.cjs");
+ const obj = await vocab.Object.fromJsonLd({
+ "@context": "https://www.w3.org/ns/activitystreams",
+ type: "Object",
+ published: "2025-01-01T12:34:56Z",
+ }, { documentLoader: mockDocumentLoader, contextLoader: mockDocumentLoader });
+
+ ok(obj.published != null);
+ strictEqual(obj.published.toString(), "2025-01-01T12:34:56Z");
+ strictEqual(globalThis.Temporal, originalTemporal);
+});
diff --git a/packages/vocab/tsdown.config.ts b/packages/vocab/tsdown.config.ts
index fbb9d469b..761499881 100644
--- a/packages/vocab/tsdown.config.ts
+++ b/packages/vocab/tsdown.config.ts
@@ -1,6 +1,13 @@
import { glob, mkdir, readFile, writeFile } from "node:fs/promises";
import { dirname, join, sep } from "node:path";
import { defineConfig } from "tsdown";
+import {
+ temporalPolyfillCjsBanner,
+ temporalPolyfillCjsDeps,
+ temporalPolyfillEsmBanner,
+ temporalPolyfillImportPlugin,
+ temporalPolyfillIntro,
+} from "../../scripts/tsdown/temporal.mts";
async function copyFileSafely(
source: string,
@@ -16,17 +23,21 @@ export default [
"./src/mod.ts",
],
dts: { compilerOptions: { isolatedDeclarations: true, declaration: true } },
- format: ["esm", "cjs"],
+ format: {
+ esm: {
+ banner: temporalPolyfillEsmBanner(),
+ },
+ cjs: {
+ deps: temporalPolyfillCjsDeps({
+ neverBundle: [/^node:/],
+ }),
+ plugins: [temporalPolyfillImportPlugin],
+ banner: temporalPolyfillCjsBanner(),
+ },
+ },
platform: "neutral",
- deps: { neverBundle: [/^node:/] },
- banner({ format }) {
- const js = format === "cjs"
- ? `const { Temporal } = require("@js-temporal/polyfill");`
- : `import { Temporal } from "@js-temporal/polyfill";`;
- return {
- js,
- dts: `/// `,
- };
+ deps: {
+ neverBundle: [/^node:/],
},
}),
defineConfig({
@@ -49,8 +60,7 @@ export default [
},
},
outputOptions: {
- intro: `
- import { Temporal } from "@js-temporal/polyfill";
+ intro: `${temporalPolyfillIntro}
globalThis.addEventListener = () => {};
`,
},
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index fe81f5cef..acb0e15a5 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -174,6 +174,9 @@ catalogs:
postgres:
specifier: ^3.4.7
version: 3.4.7
+ temporal-polyfill:
+ specifier: ^1.0.1
+ version: 1.0.1
tsdown:
specifier: ^0.22.0
version: 0.22.0
@@ -280,9 +283,6 @@ importers:
'@hono/node-server':
specifier: ^1.13.7
version: 1.14.4(hono@4.8.3)
- '@js-temporal/polyfill':
- specifier: 'catalog:'
- version: 0.5.1
'@logtape/file':
specifier: 'catalog:'
version: 2.2.0(@logtape/logtape@2.2.0)
@@ -391,6 +391,9 @@ importers:
stringify-entities:
specifier: ^4.0.4
version: 4.0.4
+ temporal-polyfill:
+ specifier: 'catalog:'
+ version: 1.0.1
typescript:
specifier: 'catalog:'
version: 6.0.3
@@ -983,9 +986,6 @@ importers:
'@jimp/wasm-webp':
specifier: ^1.6.1
version: 1.6.1
- '@js-temporal/polyfill':
- specifier: 'catalog:'
- version: 0.5.1
'@logtape/file':
specifier: 'catalog:'
version: 2.2.0(@logtape/logtape@2.2.0)
@@ -1061,6 +1061,9 @@ importers:
srvx:
specifier: ^0.8.7
version: 0.8.16
+ temporal-polyfill:
+ specifier: 'catalog:'
+ version: 1.0.1
valibot:
specifier: ^1.4.0
version: 1.4.0(typescript@6.0.3)
@@ -1114,9 +1117,6 @@ importers:
'@fedify/fedify':
specifier: workspace:^
version: link:../fedify
- '@js-temporal/polyfill':
- specifier: 'catalog:'
- version: 0.5.1
'@logtape/logtape':
specifier: 'catalog:'
version: 2.2.0
@@ -1135,6 +1135,9 @@ importers:
hono:
specifier: 'catalog:'
version: 4.8.3
+ temporal-polyfill:
+ specifier: 'catalog:'
+ version: 1.0.1
devDependencies:
tsdown:
specifier: 'catalog:'
@@ -1220,9 +1223,6 @@ importers:
'@fedify/webfinger':
specifier: workspace:*
version: link:../webfinger
- '@js-temporal/polyfill':
- specifier: ^0.5.1
- version: 0.5.1
'@logtape/logtape':
specifier: 'catalog:'
version: 2.2.0
@@ -1262,6 +1262,9 @@ importers:
structured-field-values:
specifier: ^2.0.4
version: 2.0.4
+ temporal-polyfill:
+ specifier: 'catalog:'
+ version: 1.0.1
urlpattern-polyfill:
specifier: 'catalog:'
version: 10.1.0
@@ -1470,9 +1473,6 @@ importers:
'@fedify/fedify':
specifier: workspace:^
version: link:../fedify
- '@js-temporal/polyfill':
- specifier: 'catalog:'
- version: 0.5.1
'@logtape/logtape':
specifier: 'catalog:'
version: 2.2.0
@@ -1482,6 +1482,9 @@ importers:
mysql2:
specifier: 'catalog:'
version: 3.22.3(@types/node@24.3.0)
+ temporal-polyfill:
+ specifier: 'catalog:'
+ version: 1.0.1
devDependencies:
'@fedify/fixture':
specifier: workspace:^
@@ -1489,6 +1492,9 @@ importers:
'@fedify/testing':
specifier: workspace:^
version: link:../testing
+ '@js-temporal/polyfill':
+ specifier: 'catalog:'
+ version: 0.5.1
tsdown:
specifier: 'catalog:'
version: 0.22.0(tsx@4.21.0)(typescript@6.0.3)(unrun@0.2.34(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0))
@@ -1573,15 +1579,15 @@ importers:
'@fedify/fedify':
specifier: workspace:^
version: link:../fedify
- '@js-temporal/polyfill':
- specifier: 'catalog:'
- version: 0.5.1
'@logtape/logtape':
specifier: 'catalog:'
version: 2.2.0
postgres:
specifier: 'catalog:'
version: 3.4.7
+ temporal-polyfill:
+ specifier: 'catalog:'
+ version: 1.0.1
devDependencies:
'@fedify/fixture':
specifier: workspace:^
@@ -1589,6 +1595,9 @@ importers:
'@fedify/testing':
specifier: workspace:^
version: link:../testing
+ '@js-temporal/polyfill':
+ specifier: 'catalog:'
+ version: 0.5.1
'@std/async':
specifier: 'catalog:'
version: '@jsr/std__async@1.0.13'
@@ -1604,15 +1613,15 @@ importers:
'@fedify/fedify':
specifier: workspace:^
version: link:../fedify
- '@js-temporal/polyfill':
- specifier: 'catalog:'
- version: 0.5.1
'@logtape/logtape':
specifier: 'catalog:'
version: 2.2.0
ioredis:
specifier: 'catalog:'
version: 5.10.1
+ temporal-polyfill:
+ specifier: 'catalog:'
+ version: 1.0.1
devDependencies:
'@fedify/fixture':
specifier: workspace:^
@@ -1620,6 +1629,9 @@ importers:
'@fedify/testing':
specifier: workspace:^
version: link:../testing
+ '@js-temporal/polyfill':
+ specifier: 'catalog:'
+ version: 0.5.1
'@std/async':
specifier: 'catalog:'
version: '@jsr/std__async@1.0.13'
@@ -1641,12 +1653,12 @@ importers:
'@fedify/vocab':
specifier: workspace:*
version: link:../vocab
- '@js-temporal/polyfill':
- specifier: 'catalog:'
- version: 0.5.1
'@logtape/logtape':
specifier: 'catalog:'
version: 2.2.0
+ temporal-polyfill:
+ specifier: 'catalog:'
+ version: 1.0.1
devDependencies:
'@fedify/vocab-runtime':
specifier: workspace:^
@@ -1682,19 +1694,22 @@ importers:
'@fedify/fedify':
specifier: workspace:^
version: link:../fedify
- '@js-temporal/polyfill':
- specifier: 'catalog:'
- version: 0.5.1
'@logtape/logtape':
specifier: 'catalog:'
version: 2.2.0
es-toolkit:
specifier: ^1.46.1
version: 1.46.1
+ temporal-polyfill:
+ specifier: 'catalog:'
+ version: 1.0.1
devDependencies:
'@fedify/testing':
specifier: workspace:^
version: link:../testing
+ '@js-temporal/polyfill':
+ specifier: 'catalog:'
+ version: 0.5.1
'@std/async':
specifier: 'catalog:'
version: '@jsr/std__async@1.0.13'
@@ -1729,13 +1744,13 @@ importers:
es-toolkit:
specifier: 'catalog:'
version: 1.46.1
+ temporal-polyfill:
+ specifier: 'catalog:'
+ version: 1.0.1
devDependencies:
'@fedify/fixture':
specifier: workspace:^
version: link:../fixture
- '@js-temporal/polyfill':
- specifier: 'catalog:'
- version: 0.5.1
'@standard-schema/spec':
specifier: 'catalog:'
version: 1.1.0
@@ -1778,9 +1793,6 @@ importers:
'@fedify/webfinger':
specifier: workspace:*
version: link:../webfinger
- '@js-temporal/polyfill':
- specifier: 'catalog:'
- version: 0.5.1
'@logtape/logtape':
specifier: 'catalog:'
version: 2.2.0
@@ -1802,6 +1814,9 @@ importers:
pkijs:
specifier: 'catalog:'
version: 3.3.3
+ temporal-polyfill:
+ specifier: 'catalog:'
+ version: 1.0.1
devDependencies:
'@fedify/fixture':
specifier: workspace:*
@@ -11968,6 +11983,15 @@ packages:
teex@1.0.1:
resolution: {integrity: sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==}
+ temporal-polyfill@1.0.1:
+ resolution: {integrity: sha512-N2SoI9olnW7BUsU8RosDphZQl9s+WJ8O7PoJMFCr/e5/1rFkVI4GNOWaSeySG+UoP04foPYsnLWbJmbXOiShZg==}
+
+ temporal-spec@1.0.0:
+ resolution: {integrity: sha512-00Ahj1e1ifaERTMOIIGpOCdOo9IEk2m6GGSMedsn9a2SIsGLdOTbmME1Htv6IM82b6VHrzSUTIVc7YHy6hdhFQ==}
+
+ temporal-utils@1.0.1:
+ resolution: {integrity: sha512-HAixuesxFQIUaQk3ptX2jhfO/FsOkgVkDDMawvp6n/fkB1q6BKfs3lURw9I+pK/2e2e/q/vrLrxmeqauBoyGMQ==}
+
terracotta@1.1.0:
resolution: {integrity: sha512-kfQciWUBUBgYkXu7gh3CK3FAJng/iqZslAaY08C+k1Hdx17aVEpcFFb/WPaysxAfcupNH3y53s/pc53xxZauww==}
engines: {node: '>=10'}
@@ -24900,6 +24924,15 @@ snapshots:
- bare-abort-controller
- react-native-b4a
+ temporal-polyfill@1.0.1:
+ dependencies:
+ temporal-spec: 1.0.0
+ temporal-utils: 1.0.1
+
+ temporal-spec@1.0.0: {}
+
+ temporal-utils@1.0.1: {}
+
terracotta@1.1.0(solid-js@1.9.12):
dependencies:
solid-js: 1.9.12
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
index 267f7841e..e746f204e 100644
--- a/pnpm-workspace.yaml
+++ b/pnpm-workspace.yaml
@@ -112,6 +112,7 @@ catalog:
nuxt: ^4.4.2
oxlint: ^1.66.0
postgres: ^3.4.7
+ temporal-polyfill: ^1.0.1
tsdown: ^0.22.0
typescript: ^6.0.0
urlpattern-polyfill: "^10.1.0"
diff --git a/scripts/check_temporal_polyfill.ts b/scripts/check_temporal_polyfill.ts
new file mode 100644
index 000000000..23be2e7bc
--- /dev/null
+++ b/scripts/check_temporal_polyfill.ts
@@ -0,0 +1,287 @@
+// Regression check for Temporal packaging in published artifacts.
+//
+// The packages below publish files that use Temporal. Their CommonJS outputs
+// must be self-contained because temporal-polyfill cannot be required directly
+// from CJS consumers, and declaration files should expose only the standard
+// esnext.temporal library reference rather than polyfill-specific imports.
+// The final type-consumer checks make sure the generated declarations work
+// under the TypeScript module resolution modes used by modern app templates.
+
+import { join } from "node:path";
+
+const root = Deno.cwd();
+
+const packages = [
+ "cli",
+ "debugger",
+ "fedify",
+ "mysql",
+ "postgres",
+ "redis",
+ "relay",
+ "sqlite",
+ "testing",
+ "vocab",
+] as const;
+
+// @fedify/cli is still scanned above, but it does not expose a library type
+// surface for TypeScript consumers.
+const typeConsumerPackages = packages.filter((pkg) => pkg !== "cli");
+
+const forbiddenCjsRequires = [
+ `require("@js-temporal/polyfill")`,
+ `require('@js-temporal/polyfill')`,
+ `require("temporal-polyfill")`,
+ `require('temporal-polyfill')`,
+];
+
+const forbiddenDeclarationText = [
+ "@js-temporal/polyfill",
+ "temporal-polyfill",
+ "temporal-spec",
+];
+
+async function* walk(dir: string): AsyncGenerator {
+ try {
+ for await (const entry of Deno.readDir(dir)) {
+ const path = `${dir}/${entry.name}`;
+ if (entry.isDirectory) {
+ yield* walk(path);
+ } else if (entry.isFile) {
+ yield path;
+ }
+ }
+ } catch (error) {
+ if (error instanceof Deno.errors.NotFound) return;
+ throw error;
+ }
+}
+
+let failures = 0;
+
+async function findTypeScriptCompiler(): Promise {
+ const candidates = [
+ join(root, "node_modules", "typescript", "bin", "tsc"),
+ ];
+ for (const store of [".deno", ".pnpm"]) {
+ const storeDir = join(root, "node_modules", store);
+ try {
+ for await (const entry of Deno.readDir(storeDir)) {
+ if (!entry.isDirectory || !entry.name.startsWith("typescript@")) {
+ continue;
+ }
+ candidates.push(
+ join(
+ storeDir,
+ entry.name,
+ "node_modules",
+ "typescript",
+ "bin",
+ "tsc",
+ ),
+ );
+ }
+ } catch (error) {
+ if (!(error instanceof Deno.errors.NotFound)) throw error;
+ }
+ }
+ for (const candidate of candidates) {
+ try {
+ if ((await Deno.stat(candidate)).isFile) return candidate;
+ } catch (error) {
+ if (!(error instanceof Deno.errors.NotFound)) throw error;
+ }
+ }
+ throw new Error("Could not find the TypeScript compiler.");
+}
+
+for (const pkg of packages) {
+ const dist = `packages/${pkg}/dist`;
+ const files = [];
+ for await (const file of walk(dist)) files.push(file);
+ if (files.length < 1) {
+ console.error(`Missing build output: ${dist}`);
+ failures++;
+ continue;
+ }
+
+ for (const file of files) {
+ if (file.includes(".test.")) continue;
+ if (
+ !file.endsWith(".js") &&
+ !file.endsWith(".cjs") &&
+ !file.endsWith(".d.ts") &&
+ !file.endsWith(".d.cts")
+ ) {
+ continue;
+ }
+
+ const text = await Deno.readTextFile(file);
+ if (file.endsWith(".cjs")) {
+ for (const forbidden of forbiddenCjsRequires) {
+ if (text.includes(forbidden)) {
+ console.error(`${file} contains forbidden ${forbidden}`);
+ failures++;
+ }
+ }
+ } else if (file.endsWith(".d.ts") || file.endsWith(".d.cts")) {
+ for (const forbidden of forbiddenDeclarationText) {
+ if (text.includes(forbidden)) {
+ console.error(`${file} exposes ${forbidden}`);
+ failures++;
+ }
+ }
+ if (
+ /\bTemporal\b/.test(text) &&
+ !text.includes(`/// `)
+ ) {
+ console.error(`${file} is missing the Temporal lib reference`);
+ failures++;
+ }
+ }
+ }
+}
+
+async function prepareTypeConsumerProject(
+ name: string,
+ compilerOptions: Record,
+ sourceFile: string,
+): Promise {
+ await Deno.mkdir(join(root, "tmp"), { recursive: true });
+ const dir = await Deno.makeTempDir({
+ dir: join(root, "tmp"),
+ prefix: `temporal-polyfill-${name}-`,
+ });
+ await Deno.mkdir(join(dir, "node_modules", "@fedify"), { recursive: true });
+ for (const pkg of typeConsumerPackages) {
+ // Symlink the package root so package.json exports resolve to the dist
+ // artifacts produced by the earlier build check.
+ await Deno.symlink(
+ join(root, "packages", pkg),
+ join(dir, "node_modules", "@fedify", pkg),
+ { type: Deno.build.os === "windows" ? "junction" : "dir" },
+ );
+ }
+ await Deno.writeTextFile(
+ join(dir, "package.json"),
+ `${JSON.stringify({ type: "module", private: true }, null, 2)}\n`,
+ );
+ await Deno.writeTextFile(
+ join(dir, "tsconfig.json"),
+ `${
+ JSON.stringify(
+ {
+ compilerOptions: {
+ target: "ES2022",
+ strict: true,
+ noEmit: true,
+ skipLibCheck: false,
+ lib: ["ESNext", "ESNext.Temporal", "DOM"],
+ types: ["node"],
+ ...compilerOptions,
+ },
+ include: [sourceFile],
+ },
+ null,
+ 2,
+ )
+ }\n`,
+ );
+ await Deno.writeTextFile(
+ join(dir, sourceFile),
+ `
+ import { Object as ActivityObject } from "@fedify/vocab";
+
+ import type * as debuggerModule from "@fedify/debugger";
+ import type * as fedify from "@fedify/fedify";
+ import type * as mysql from "@fedify/mysql";
+ import type * as postgres from "@fedify/postgres";
+ import type * as redis from "@fedify/redis";
+ import type * as relay from "@fedify/relay";
+ import type * as sqlite from "@fedify/sqlite";
+ import type * as testing from "@fedify/testing";
+ import type * as vocab from "@fedify/vocab";
+
+ const instant: Temporal.Instant = Temporal.Instant.from(
+ "2025-01-01T00:00:00Z",
+ );
+ const object = new ActivityObject({ published: instant });
+
+ const modules: [
+ typeof debuggerModule | undefined,
+ typeof fedify | undefined,
+ typeof mysql | undefined,
+ typeof postgres | undefined,
+ typeof redis | undefined,
+ typeof relay | undefined,
+ typeof sqlite | undefined,
+ typeof testing | undefined,
+ typeof vocab | undefined,
+ ] = [
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ ];
+
+ void object;
+ void modules;
+ `,
+ );
+ return dir;
+}
+
+async function checkTypeConsumerProject(
+ name: string,
+ compilerOptions: Record,
+ sourceFile: string,
+): Promise {
+ const dir = await prepareTypeConsumerProject(
+ name,
+ compilerOptions,
+ sourceFile,
+ );
+ try {
+ const command = new Deno.Command(
+ "node",
+ {
+ args: [
+ await findTypeScriptCompiler(),
+ "-p",
+ "tsconfig.json",
+ ],
+ cwd: dir,
+ stdout: "piped",
+ stderr: "piped",
+ },
+ );
+ const result = await command.output();
+ if (!result.success) {
+ const decoder = new TextDecoder();
+ console.error(`TypeScript ${name} consumer check failed.`);
+ console.error(decoder.decode(result.stdout));
+ console.error(decoder.decode(result.stderr));
+ failures++;
+ }
+ } finally {
+ await Deno.remove(dir, { recursive: true });
+ }
+}
+
+await checkTypeConsumerProject(
+ "bundler",
+ { module: "ESNext", moduleResolution: "Bundler" },
+ "index.ts",
+);
+await checkTypeConsumerProject(
+ "nodenext",
+ { module: "NodeNext", moduleResolution: "NodeNext" },
+ "index.mts",
+);
+
+if (failures > 0) Deno.exit(1);
diff --git a/scripts/tsdown/temporal.mts b/scripts/tsdown/temporal.mts
new file mode 100644
index 000000000..0b7654b51
--- /dev/null
+++ b/scripts/tsdown/temporal.mts
@@ -0,0 +1,74 @@
+import { sep } from "node:path";
+import type { DepsConfig, ResolvedConfig } from "tsdown";
+
+// Shared tsdown helpers for packages that use Temporal in published output.
+//
+// ESM builds can import temporal-polyfill normally, but CommonJS builds cannot
+// require temporal-polyfill directly because its package exports are ESM-first.
+// For CJS, the build injects a local Temporal binding into source chunks and
+// bundles temporal-polyfill and temporal-utils so consumers do not need either
+// @js-temporal/polyfill or a global Temporal at runtime.
+
+export function isTemporalPolyfillDependency(id: string): boolean {
+ return /^temporal-polyfill(\/.*)?$/.test(id) ||
+ /^temporal-utils(\/.*)?$/.test(id);
+}
+
+export function temporalPolyfillCjsDeps(
+ deps: Omit = {},
+): ResolvedConfig["deps"] {
+ // tsdown's nested format type currently expects resolved deps, even though
+ // user config deps are accepted at runtime.
+ return ({
+ ...deps,
+ alwaysBundle: isTemporalPolyfillDependency,
+ } as unknown) as ResolvedConfig["deps"];
+}
+
+export const temporalPolyfillImportPlugin = {
+ name: "fedify-temporal-polyfill-import",
+ transform(code: string, id: string) {
+ if (!id.replaceAll(sep, "/").includes("/src/")) return null;
+ if (!/\.[cm]?[jt]sx?$/.test(id)) return null;
+ if (!/\bTemporal\./.test(code)) return null;
+ if (/from\s+["']temporal-polyfill["']/.test(code)) return null;
+ return {
+ code: [
+ `import { Temporal as __FedifyTemporal } from "temporal-polyfill";`,
+ `const Temporal: typeof globalThis.Temporal = __FedifyTemporal;`,
+ code,
+ ].join("\n"),
+ map: null,
+ };
+ },
+};
+
+export function temporalPolyfillEsmBanner(extraJs?: string): {
+ js: string;
+ dts: string;
+} {
+ return {
+ js: [
+ `import { Temporal } from "temporal-polyfill";`,
+ extraJs,
+ ].filter((line) => line != null && line !== "").join("\n"),
+ dts: `/// `,
+ };
+}
+
+export function temporalPolyfillCjsBanner(extraJs?: string): {
+ js?: string;
+ dts: string;
+} {
+ return {
+ js: extraJs,
+ dts: `/// `,
+ };
+}
+
+// ESM-only intro for configs that emit test or CLI artifacts without CJS.
+// CJS outputs must use temporalPolyfillCjsBanner() and
+// temporalPolyfillImportPlugin instead.
+export const temporalPolyfillIntro = `
+ import { Temporal } from "temporal-polyfill";
+ `;