@northguild/gmt-oxlint 1.2.0 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -121,11 +121,11 @@ Array form also supported:
121
121
 
122
122
  | Pattern | Rule | Suggestion |
123
123
  | -------------------------- | --------------------------- | --------------------------------------------------------------------------------------------------------------------- |
124
- | `Date` global reference | `no-date-global` | Use `getNow()`, `getUnixNow('milliseconds' or 'seconds')`, `getUtcNow()`, or `getZonedNow(timezone)` |
124
+ | `Date` global reference | `no-date-global` | Use `getNow()`, `getUnixNow({ epochUnit: 'milliseconds' or 'seconds' })`, `getUtcNow()`, or `getZonedNow(timezone)` |
125
125
  | `new Date(...)` | `no-new-date` | Use `getUtcNow()`, `getNow()`, or `getZonedNow(timezone)` |
126
- | `Date.now()` | `no-date-now` | Use `getUnixNow('milliseconds' or 'seconds')` or `getNow()` |
126
+ | `Date.now()` | `no-date-now` | Use `getUnixNow({ epochUnit: 'milliseconds' or 'seconds' })` or `getNow()` |
127
127
  | `Date.parse(...)` | `no-date-parse` | Use `convertZonedToUnix(value)` |
128
- | `Date.UTC(...)` | `no-date-utc` | Use `convertUtcDateTimeToUnix('YYYY-MM-DDTHH:mm:ss', 'milliseconds' or 'seconds')` |
128
+ | `Date.UTC(...)` | `no-date-utc` | Use `convertUtcToUnix('YYYY-MM-DDTHH:mm:ssZ', { epochUnit: 'milliseconds' or 'seconds' })` |
129
129
  | `date.getTimezoneOffset()` | `no-date-getTimezoneOffset` | Use `getZonedNow(timezone)`, other gmt zoned helpers such as `convertZonedToUnix(value)`, or `Temporal.ZonedDateTime` |
130
130
 
131
131
  > **`@js-joda/core` is deliberately allowed.** It has its own value types and touches
package/dist/index.js CHANGED
@@ -1,11 +1,25 @@
1
1
  // src/messages.ts
2
- var MSG_DATE_GLOBAL = "Avoid Date. Use @northguild/gmt getNow(), getUnixNow('milliseconds' | 'seconds'), getUtcNow(), or getZonedNow(timezone) instead.";
2
+ var MSG_DATE_GLOBAL = "Avoid Date. Use @northguild/gmt getNow(), getUnixNow({ epochUnit: 'milliseconds' | 'seconds' }), getUtcNow(), or getZonedNow(timezone) instead.";
3
3
  var MSG_NEW_DATE = "Avoid new Date(). Use @northguild/gmt getUtcNow(), getNow(), or getZonedNow(timezone) instead.";
4
- var MSG_DATE_NOW = "Avoid Date.now(). Use @northguild/gmt getUnixNow('milliseconds' | 'seconds') or getNow() instead.";
5
- var MSG_DATE_UTC = "Avoid Date.UTC(). Use @northguild/gmt convertUtcDateTimeToUnix('YYYY-MM-DDTHH:mm:ss', 'milliseconds' | 'seconds') instead.";
4
+ var MSG_DATE_NOW = "Avoid Date.now(). Use @northguild/gmt getUnixNow({ epochUnit: 'milliseconds' | 'seconds' }) or getNow() instead.";
5
+ var MSG_DATE_UTC = "Avoid Date.UTC(). Use @northguild/gmt convertUtcToUnix('YYYY-MM-DDTHH:mm:ssZ', { epochUnit: 'milliseconds' | 'seconds' }) instead.";
6
6
  var MSG_DATE_PARSE = "Avoid Date.parse(). Use @northguild/gmt convertZonedToUnix(value) instead.";
7
- var MSG_GET_TIMEZONE_OFFSET = "Avoid date.getTimezoneOffset(). Timezone offsets change throughout the year, so use @northguild/gmt zoned methods instead.";
8
- var MSG_DATE_LIBRARY_IMPORT = "Avoid date libraries that wrap native Date (moment, dayjs, luxon, date-fns, spacetime). Use @northguild/gmt instead.";
7
+ var MSG_GET_TIMEZONE_OFFSET = "Avoid date.getTimezoneOffset(). Timezone offsets change throughout the year, so use @northguild/gmt getTimeZoneOffset(timeZone, instant) instead.";
8
+ var MIGRATE_URL = "https://northguild.dev/gmt/migrate/";
9
+ var guideFor = (name, slug) => `${MIGRATE_URL}${slug}/ maps ${name} calls to their gmt replacements.`;
10
+ var MOMENT_GUIDE = guideFor("Moment.js", "moment");
11
+ var DATE_FNS_GUIDE = guideFor("date-fns", "date-fns");
12
+ var DATE_LIBRARY_GUIDES = {
13
+ moment: MOMENT_GUIDE,
14
+ "moment-timezone": MOMENT_GUIDE,
15
+ dayjs: guideFor("Day.js", "dayjs"),
16
+ luxon: guideFor("Luxon", "luxon"),
17
+ "date-fns": DATE_FNS_GUIDE,
18
+ "date-fns-tz": DATE_FNS_GUIDE,
19
+ "@date-fns/tz": DATE_FNS_GUIDE,
20
+ spacetime: `${MIGRATE_URL} lists the migration guides.`
21
+ };
22
+ var dateLibraryImportMessage = (lib) => `Avoid ${lib}: it wraps native Date. Use @northguild/gmt instead; ${DATE_LIBRARY_GUIDES[lib]}`;
9
23
 
10
24
  // src/utils/isChainExpression.ts
11
25
  function isChainExpression(node) {
@@ -45,7 +59,7 @@ function hasDateStaticMemberCall(node, memberName) {
45
59
  return isIdentifier(callee.object, "Date") && isIdentifier(callee.property, memberName);
46
60
  }
47
61
 
48
- // src/utils/isBannedDateLibrary.ts
62
+ // src/utils/bannedDateLibrary.ts
49
63
  var BANNED_DATE_LIBRARIES = [
50
64
  "moment",
51
65
  "moment-timezone",
@@ -53,13 +67,14 @@ var BANNED_DATE_LIBRARIES = [
53
67
  "luxon",
54
68
  "date-fns",
55
69
  "date-fns-tz",
70
+ "@date-fns/tz",
56
71
  "spacetime"
57
72
  ];
58
- var isBannedDateLibrary = (specifier) => {
73
+ var bannedDateLibraryOf = (specifier) => {
59
74
  if (typeof specifier !== "string") {
60
- return false;
75
+ return void 0;
61
76
  }
62
- return BANNED_DATE_LIBRARIES.some(
77
+ return BANNED_DATE_LIBRARIES.find(
63
78
  (lib) => specifier === lib || specifier.startsWith(`${lib}/`)
64
79
  );
65
80
  };
@@ -126,10 +141,11 @@ var noDateGlobalRule = {
126
141
 
127
142
  // src/rules/no-date-library-imports.ts
128
143
  var reportIfBanned = (context, source) => {
129
- if (!source || !isBannedDateLibrary(source.value)) {
144
+ const lib = bannedDateLibraryOf(source?.value);
145
+ if (!source || lib === void 0) {
130
146
  return;
131
147
  }
132
- context.report({ node: source, message: MSG_DATE_LIBRARY_IMPORT });
148
+ context.report({ node: source, message: dateLibraryImportMessage(lib) });
133
149
  };
134
150
  var noDateLibraryImportsRule = {
135
151
  meta: {
package/package.json CHANGED
@@ -1,12 +1,15 @@
1
1
  {
2
2
  "name": "@northguild/gmt-oxlint",
3
- "version": "1.2.0",
4
- "description": "Oxlint JS plugin for banning Date APIs in Temporal-first projects",
3
+ "version": "1.2.2",
4
+ "description": "Oxlint plugin that bans the JavaScript Date object and Date-based libraries, and names the Temporal-based @northguild/gmt function to use instead.",
5
5
  "keywords": [
6
6
  "date",
7
7
  "eslint-plugin",
8
+ "eslintplugin",
8
9
  "lint",
10
+ "no-date",
9
11
  "oxlint",
12
+ "oxlint-plugin",
10
13
  "tanstack-intent",
11
14
  "temporal"
12
15
  ],
@@ -55,7 +58,7 @@
55
58
  "registry": "https://registry.npmjs.org/"
56
59
  },
57
60
  "devDependencies": {
58
- "@tanstack/intent": "^0.3.8",
61
+ "@tanstack/intent": "^0.4.0",
59
62
  "oxlint": "^1.0.0",
60
63
  "tsup": "^8.5.0",
61
64
  "typescript": "^5.0.0"
@@ -5,7 +5,7 @@ description: >
5
5
  gmt-oxlint/* diagnostics, and policy alignment with ESLint/Biome where
6
6
  multiple linters are used.
7
7
  metadata:
8
- library_version: 1.1.2
8
+ library_version: 1.2.0
9
9
  ---
10
10
 
11
11
  # CI Enforcement
@@ -19,6 +19,9 @@ Use this skill when enabling Oxlint-based Date policy checks in CI.
19
19
 
20
20
  2. Stage adoption for large repos
21
21
  - Start with changed files or specific paths if baseline debt is high.
22
+ - `no-date-library-imports` usually carries the largest baseline (every `moment` / `dayjs` /
23
+ `luxon` / `date-fns` / `spacetime` import). It is safe to run it as `"warn"` for existing
24
+ paths while keeping it `"error"` for new ones, then tighten as imports are migrated.
22
25
  - Expand to full repository enforcement once baseline is controlled.
23
26
 
24
27
  3. Keep diagnostics actionable
@@ -5,7 +5,7 @@ description: >
5
5
  prefer oxlint.config.ts + recommendedConfig import, and verify gmt-oxlint
6
6
  diagnostics while preserving current repository lint behavior.
7
7
  metadata:
8
- library_version: 1.1.2
8
+ library_version: 1.2.0
9
9
  ---
10
10
 
11
11
  # First-Time Setup
@@ -30,6 +30,10 @@ Use this skill when a user wants to adopt `@northguild/gmt-oxlint`.
30
30
  3. Verify enforcement
31
31
  - Run Oxlint and confirm Date API bans are reported.
32
32
  - Confirm rule IDs are emitted as `@northguild/gmt-oxlint/*`.
33
+ - The recommended config also enables `no-date-library-imports`, which errors on `moment`,
34
+ `moment-timezone`, `dayjs`, `luxon`, `date-fns`, `date-fns-tz`, `@date-fns/tz` and `spacetime` imports.
35
+ In a codebase that still uses them, warn the user before enabling it, or stage it (see
36
+ the CI enforcement skill) instead of disabling it.
33
37
 
34
38
  4. Optional aliasing
35
39
  - If the user wants shorter rule IDs, use object-form `jsPlugins` with `name` alias and configure rules under that alias.
@@ -5,7 +5,7 @@ description: >
5
5
  helpers, preserving behavior, and guiding the Temporal custom-method path when
6
6
  gmt does not yet provide a needed helper.
7
7
  metadata:
8
- library_version: 1.1.2
8
+ library_version: 1.2.0
9
9
  ---
10
10
 
11
11
  # Migration Refactor
@@ -35,6 +35,14 @@ Use this skill when Oxlint reports Date API violations and the user asks for fix
35
35
  - `Date.parse(...)` -> gmt conversion helper where available.
36
36
  - `Date.UTC(...)` -> gmt UTC conversion helper where available.
37
37
  - `getTimezoneOffset()` usage -> timezone-aware gmt zoned helpers.
38
+ - `no-date-library-imports` (`moment`, `moment-timezone`, `dayjs`, `luxon`, `date-fns`,
39
+ `date-fns-tz`, `@date-fns/tz`, `spacetime`, including subpaths, `require()` and dynamic
40
+ `import()`) -> replace the call sites with gmt equivalents (the message links the migration guide
41
+ that maps the library's calls), then remove the import. Do not silence it by re-exporting through
42
+ a local module — `export … from` is flagged too. `@js-joda/core` is intentionally allowed.
43
+ - When porting library arithmetic, keep Temporal's semantics: a non-existent day clamps
44
+ (`2024-02-29` + 1 year → `2025-02-28`); date-fns `setYear` rolls to 1 March instead, so
45
+ flag that behaviour change to the user rather than copying it.
38
46
 
39
47
  ## Validation
40
48