Skip to content

Commit

Permalink
Split date adapters into sub packages to help with peerDependencies r…
Browse files Browse the repository at this point in the history
…esolution

```diff
- import { AdapterDateFns } from "@salt-ds/date-adapters";
- import { AdapterDayjs } from "@salt-ds/date-adapters";
- import { AdapterLuxon } from "@salt-ds/date-adapters";
- import { AdapterMoment } from "@salt-ds/date-adapters";
+ import { AdapterDateFns } from "@salt-ds/date-adapters/date-fns";
+ import { AdapterDayjs } from "@salt-ds/date-adapters/dayjs";
+ import { AdapterLuxon } from "@salt-ds/date-adapters/luxon";
+ import { AdapterMoment } from "@salt-ds/date-adapters/moment";
```
  • Loading branch information
mark-tate committed Dec 26, 2024
1 parent 47e2f12 commit a5b7e20
Show file tree
Hide file tree
Showing 39 changed files with 401 additions and 153 deletions.
50 changes: 50 additions & 0 deletions .changeset/giant-cycles-clap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
"@salt-ds/date-adapters": patch
"@salt-ds/lab": patch
---

Refine peer dependency management for DatePicker adapters by splitting them into sub-packages. You now import only the specific date framework adapter you need, simplifying dependency handling.

- **For `date-fns`:**

```diff
- import { AdapterDateFns } from "@salt-ds/date-adapters";
+ import { AdapterDateFns } from "@salt-ds/date-adapters/date-fns";
```

- **For `dayjs`:**

```diff
- import { AdapterDayjs } from "@salt-ds/date-adapters";
+ import { AdapterDayjs } from "@salt-ds/date-adapters/dayjs";
```

- **For `luxon`:**

```diff
- import { AdapterLuxon } from "@salt-ds/date-adapters";
+ import { AdapterLuxon } from "@salt-ds/date-adapters/luxon";
```

- **For `moment`:**

```diff
- import { AdapterMoment } from "@salt-ds/date-adapters";
+ import { AdapterMoment } from "@salt-ds/date-adapters/moment";
```

### Instructions

1. Modify your import statements to use the specific sub-package for the date adapter you require.

2. Ensure your `package.json` includes the necessary date framework as a dependency. For example, if using `date-fns`:

```json
{
"dependencies": {
"date-fns": "^x.x.x"
}
}
```

This change helps streamline the integration of date frameworks with the DatePicker component by ensuring only the necessary adapters and dependencies are included.
5 changes: 0 additions & 5 deletions cypress.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,6 @@ async function getViteConfig(config: UserConfig) {
__dirname,
"./dist/salt-ds-countries",
),
"@salt-ds/date-adapters": path.resolve(
__dirname,
"./dist/salt-ds-date-adapters",
),
"@salt-ds/data-grid": path.resolve(
__dirname,
"./dist/salt-ds-data-grid",
Expand All @@ -73,7 +69,6 @@ async function getViteConfig(config: UserConfig) {
optimizeDeps: {
include: [
"@salt-ds/core",
"@salt-ds/data-adapters",
"@salt-ds/data-grid",
"@salt-ds/lab",
"@salt-ds/icons",
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@
"get-tsconfig": "^4.7.5",
"rollup": "^4.24.2",
"rollup-plugin-esbuild": "^6.1.1",
"rollup-plugin-postcss": "^4.0.2"
"rollup-plugin-postcss": "^4.0.2",
"vite-tsconfig-paths": "^4.2.0"
}
}
2 changes: 1 addition & 1 deletion packages/date-adapters/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,6 @@
"provenance": true
},
"scripts": {
"build": "yarn node ../../scripts/build.mjs"
"build": "yarn node ./scripts/build.mjs"
}
}
164 changes: 164 additions & 0 deletions packages/date-adapters/scripts/build.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
import path from "node:path";
import commonjs from "@rollup/plugin-commonjs";
import json from "@rollup/plugin-json";
import { nodeResolve } from "@rollup/plugin-node-resolve";
import browserslistToEsbuild from "browserslist-to-esbuild";
import fs from "fs-extra";
import { rollup } from "rollup";
import esbuild from "rollup-plugin-esbuild";
import { makeTypings } from "./../../../scripts/makeTypings.mjs";
import { transformWorkspaceDeps } from "./../../../scripts/transformWorkspaceDeps.mjs";
import { distinct } from "./../../../scripts/utils.mjs";

const cwd = process.cwd();

const packageJson = (
await import(path.join("file://", cwd, "package.json"), {
with: { type: "json" },
})
).default;

const FILES_TO_COPY = ["README.md", "LICENSE", "CHANGELOG.md"].concat(
packageJson.files ?? [],
);

const packageName = packageJson.name;
const outputDir = path.join(packageJson.publishConfig.directory);

console.log(`Building ${packageName}`);

await fs.mkdirp(outputDir);
await fs.emptyDir(outputDir);

// Define entry points for each adapter
const entryPoints = {
types: path.join(cwd, "src/types/index.ts"),
moment: path.join(cwd, "src/moment-adapter/index.ts"),
luxon: path.join(cwd, "src/luxon-adapter/index.ts"),
dayjs: path.join(cwd, "src/dayjs-adapter/index.ts"),
"date-fns": path.join(cwd, "src/date-fns-adapter/index.ts"),
};

for (const [adapterName, inputPath] of Object.entries(entryPoints)) {
const entryFolder = path.basename(path.dirname(inputPath));

await makeTypings(outputDir, path.dirname(inputPath));

const bundle = await rollup({
input: inputPath,
external: (id) => {
if (id === "babel-plugin-transform-async-to-promises/helpers") {
return false;
}
return !id.startsWith(".") && !path.isAbsolute(id);
},
treeshake: {
propertyReadSideEffects: false,
},
plugins: [
nodeResolve({
extensions: [".ts", ".tsx", ".js", ".jsx"],
browser: true,
mainFields: ["module", "main", "browser"],
}),
commonjs({ include: /\/node_modules\// }),
esbuild({
target: browserslistToEsbuild(),
minify: false,
sourceMap: true,
}),
json(),
],
});

const transformSourceMap = (relativeSourcePath, sourceMapPath) => {
const absoluteSourcepath = path.resolve(
path.dirname(sourceMapPath),
relativeSourcePath,
);
const packageRelativeSourcePath = path.relative(cwd, absoluteSourcepath);

return `../${packageRelativeSourcePath}`;
};

await bundle.write({
freeze: false,
sourcemap: true,
preserveModules: false,
dir: path.join(outputDir, `dist-cjs/${adapterName}`),
format: "cjs",
exports: "named",
sourcemapPathTransform: transformSourceMap,
});

await bundle.write({
freeze: false,
sourcemap: true,
preserveModules: false,
dir: path.join(outputDir, `dist-es/${adapterName}`),
format: "es",
exports: "named",
sourcemapPathTransform: transformSourceMap,
});

await bundle.close();
}

await fs.writeJSON(
path.join(outputDir, "package.json"),
{
...packageJson,
dependencies: await transformWorkspaceDeps(packageJson.dependencies),
main: "dist-cjs/index.js",
module: "dist-es/index.js",
typings: "dist-types/types/index.d.ts",
exports: {
".": {
import: "./dist-es/types/index.js",
require: "./dist-cjs/types/index.js",
types: "./dist-types/types/index.d.ts",
},
"./date-fns": {
import: "./dist-es/date-fns/index.js",
require: "./dist-cjs/date-fns/index.js",
types: "./dist-types/date-fns-adapter/index.d.ts",
},
"./dayjs": {
import: "./dist-es/dayjs/index.js",
require: "./dist-cjs/dayjs/index.js",
types: "./dist-types/dayjs-adapter/index.d.ts",
},
"./luxon": {
import: "./dist-es/luxon/index.js",
require: "./dist-cjs/luxon/index.js",
types: "./dist-types/luxon-adapter/index.d.ts",
},
"./moment": {
import: "./dist-es/moment/index.js",
require: "./dist-cjs/moment/index.js",
types: "./dist-types/moment-adapter/index.d.ts",
},
},
files: distinct([
...(packageJson.files ?? []),
"dist-cjs",
"dist-es",
"dist-types",
"CHANGELOG.md",
]),
},
{ spaces: 2 },
);

for (const file of FILES_TO_COPY) {
const filePath = path.join(cwd, file);
try {
await fs.copy(filePath, path.join(outputDir, file));
} catch (error) {
if (error.code !== "ENOENT") {
throw error;
}
}
}

console.log(`Built ${packageName} into ${outputDir}`);
4 changes: 2 additions & 2 deletions packages/date-adapters/src/__tests__/date-fns.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { isValid } from "date-fns";
import { enUS } from "date-fns/locale";
import { describe, expect, it } from "vitest";
import { AdapterDateFns, DateDetailErrorEnum } from "../index";
import { AdapterDateFns, DateDetailError } from "../index";

describe("GIVEN a AdapterDateFns", () => {
const adapter = new AdapterDateFns({ locale: enUS });
Expand Down Expand Up @@ -34,7 +34,7 @@ describe("GIVEN a AdapterDateFns", () => {
expect(result.errors).toEqual([
{
message: "not a valid date",
type: DateDetailErrorEnum.INVALID_DATE,
type: DateDetailError.INVALID_DATE,
},
]);
});
Expand Down
4 changes: 2 additions & 2 deletions packages/date-adapters/src/__tests__/dayjs.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import customParseFormat from "dayjs/plugin/customParseFormat";
import timezone from "dayjs/plugin/timezone";
import utc from "dayjs/plugin/utc";
import { describe, expect, it } from "vitest";
import { AdapterDayjs, DateDetailErrorEnum } from "../index";
import { AdapterDayjs, DateDetailError } from "../index";

// Extend dayjs with necessary plugins
dayjs.extend(utc);
Expand Down Expand Up @@ -70,7 +70,7 @@ describe("GIVEN a AdapterDayjs", () => {
expect(result.errors).toEqual([
{
message: "not a valid date",
type: DateDetailErrorEnum.INVALID_DATE,
type: DateDetailError.INVALID_DATE,
},
]);
});
Expand Down
4 changes: 2 additions & 2 deletions packages/date-adapters/src/__tests__/luxon.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { DateTime } from "luxon";
import { describe, expect, it } from "vitest";
import { AdapterLuxon, DateDetailErrorEnum } from "../index";
import { AdapterLuxon, DateDetailError } from "../index";

describe("GIVEN a AdapterLuxon", () => {
const adapter = new AdapterLuxon({ locale: "en-US" });
Expand Down Expand Up @@ -62,7 +62,7 @@ describe("GIVEN a AdapterLuxon", () => {
expect(result.errors).toEqual([
{
message: "not a valid date",
type: DateDetailErrorEnum.INVALID_DATE,
type: DateDetailError.INVALID_DATE,
},
]);
});
Expand Down
4 changes: 2 additions & 2 deletions packages/date-adapters/src/__tests__/moment.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import moment from "moment";
import { describe, expect, it } from "vitest";
import "moment-timezone";
import { AdapterMoment, DateDetailErrorEnum } from "../index";
import { AdapterMoment, DateDetailError } from "../index";

describe("GIVEN a AdapterMoment", () => {
const adapter = new AdapterMoment({ locale: "en" });
Expand Down Expand Up @@ -63,7 +63,7 @@ describe("GIVEN a AdapterMoment", () => {
expect(result.errors).toEqual([
{
message: "not a valid date",
type: DateDetailErrorEnum.INVALID_DATE,
type: DateDetailError.INVALID_DATE,
},
]);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,15 @@ import {
import { enUS } from "date-fns/locale";
import {
type AdapterOptions,
DateDetailErrorEnum,
DateDetailError,
type ParserResult,
type RecommendedFormats,
type SaltDateAdapter,
type TimeFields,
type Timezone,
} from "../types";

declare module "../types" {
declare module "@salt-ds/date-adapters" {
interface DateFrameworkTypeMap {
"date-fns": Date;
}
Expand Down Expand Up @@ -213,8 +213,8 @@ export class AdapterDateFns implements SaltDateAdapter<Date, Locale> {
{
message: isDateDefined ? "not a valid date" : "no date defined",
type: isDateDefined
? DateDetailErrorEnum.INVALID_DATE
: DateDetailErrorEnum.UNSET,
? DateDetailError.INVALID_DATE
: DateDetailError.UNSET,
},
],
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import utc from "dayjs/plugin/utc";
import weekday from "dayjs/plugin/weekday";
import {
type AdapterOptions,
DateDetailErrorEnum,
DateDetailError,
type ParserResult,
type RecommendedFormats,
type SaltDateAdapter,
Expand All @@ -20,7 +20,7 @@ type Constructor = {
utc?: (value?: Parameters<typeof defaultDayjs>[0]) => Dayjs;
};

declare module "../types" {
declare module "@salt-ds/date-adapters" {
interface DateFrameworkTypeMap {
dayjs: Dayjs;
}
Expand Down Expand Up @@ -223,8 +223,8 @@ export class AdapterDayjs implements SaltDateAdapter<Dayjs, string> {
{
message: isDateDefined ? "not a valid date" : "no date defined",
type: isDateDefined
? DateDetailErrorEnum.INVALID_DATE
: DateDetailErrorEnum.UNSET,
? DateDetailError.INVALID_DATE
: DateDetailError.UNSET,
},
],
};
Expand Down
Loading

0 comments on commit a5b7e20

Please sign in to comment.