@verifyhash/uv-index 0.1.0 → 0.1.1

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.
Files changed (4) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +16 -2
  3. package/index.d.ts +110 -0
  4. package/package.json +4 -2
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2026 <OWNER-NAME PLACEHOLDER>
3
+ Copyright (c) 2026 verifyhash
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -11,6 +11,16 @@ a rough **burn-time** for fair skin.
11
11
  Everything runs locally with the Node standard library. No network calls, no npm
12
12
  dependencies, no API keys.
13
13
 
14
+ ## Install
15
+
16
+ ```bash
17
+ npm install @verifyhash/uv-index
18
+ ```
19
+
20
+ Published as [`@verifyhash/uv-index`](https://www.npmjs.com/package/@verifyhash/uv-index);
21
+ source lives in the [verifyhash/libs](https://github.com/verifyhash/libs) monorepo.
22
+ Zero runtime dependencies — you can also vendor the folder directly.
23
+
14
24
  ## Who it's for
15
25
 
16
26
  Developers building **sun-safety**, **weather**, or **outdoor-planning** features
@@ -59,7 +69,7 @@ console.log(r);
59
69
  this is an instantaneous estimate, not a daily one). To model a specific local
60
70
  clock time, convert it to UTC first.
61
71
 
62
- ### Other exports
72
+ ## API — all exports
63
73
 
64
74
  ```js
65
75
  const {
@@ -67,7 +77,11 @@ const {
67
77
  categoryFor, // (uvi) -> { category, min, max } — WHO band for a UVI value
68
78
  burnTimeMinutes, // (uvi, skinType='II') -> minutes to one MED, or null at UVI 0
69
79
  solarElevation, // (lat, lon, Date) -> sun elevation in degrees (vendored math)
70
- } = require('./uv-index');
80
+ MED_BY_SKIN_TYPE,// { I: 200, ..., VI: 1000 } minimal erythemal dose (J/m²)
81
+ // per Fitzpatrick skin type, the table burnTimeMinutes uses
82
+ REF_OZONE_DU, // 300 — the reference total-column ozone (Dobson Units)
83
+ // assumed when you don't pass ozoneDU
84
+ } = require('@verifyhash/uv-index');
71
85
  ```
72
86
 
73
87
  ## How the number is built
package/index.d.ts ADDED
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Type declarations for @verifyhash/uv-index — zero-dependency, network-free
3
+ * CLEAR-SKY UV-index estimator.
4
+ *
5
+ * It is a clear-sky MODEL: no clouds, no aerosols, no albedo boost; the ozone
6
+ * and elevation terms are simple approximations. Treat the number as a
7
+ * clear-sky ceiling, not a measurement. All functions are pure and throw
8
+ * TypeError on invalid input.
9
+ */
10
+
11
+ /** Fitzpatrick skin type, I (very fair, always burns) … VI (deeply pigmented). */
12
+ export type SkinType = 'I' | 'II' | 'III' | 'IV' | 'V' | 'VI';
13
+
14
+ /** WHO/WMO UV exposure category name. */
15
+ export type UVCategoryName =
16
+ | 'Low'
17
+ | 'Moderate'
18
+ | 'High'
19
+ | 'Very High'
20
+ | 'Extreme';
21
+
22
+ /** A WHO/WMO exposure band: its name and its (rounded-UVI) bounds. */
23
+ export interface UVCategoryBand {
24
+ /** 'Low' | 'Moderate' | 'High' | 'Very High' | 'Extreme'. */
25
+ category: UVCategoryName;
26
+ /** Lower bound of the band (rounded UVI), inclusive. */
27
+ min: number;
28
+ /** Upper bound of the band (rounded UVI), inclusive — null for the open-ended 'Extreme' band (11+). */
29
+ max: number | null;
30
+ }
31
+
32
+ /** Options for estimateUVIndex(). */
33
+ export interface EstimateUVIndexOptions {
34
+ /** Latitude in degrees, + North, within [-90, 90]. */
35
+ lat: number;
36
+ /** Longitude in degrees, + East, within [-180, 180]. */
37
+ lon: number;
38
+ /** A full JS Date instant (UTC-based) — date AND time both matter. */
39
+ date: Date;
40
+ /** Total-column ozone in Dobson Units (> 0). Default 300. */
41
+ ozoneDU?: number;
42
+ /** Site elevation above sea level in metres (>= 0). Default 0. */
43
+ elevationM?: number;
44
+ /** Fitzpatrick skin type used for the burn-time guidance. Default 'II'. */
45
+ skinType?: SkinType;
46
+ }
47
+
48
+ /** Result of estimateUVIndex(). */
49
+ export interface UVIndexEstimate {
50
+ /** Clear-sky erythemal UV index (unrounded, >= 0). */
51
+ uvi: number;
52
+ /** UVI rounded to the nearest whole number, as UVI is reported. */
53
+ uviRounded: number;
54
+ /** WHO exposure category for the estimated UVI. */
55
+ category: UVCategoryName;
56
+ /** Solar elevation above the horizon in degrees (negative when the sun is down). */
57
+ solarElevationDeg: number;
58
+ /** True when solar elevation > 0°. */
59
+ sunAboveHorizon: boolean;
60
+ /** Approximate minutes to one Minimal Erythemal Dose, or null when UVI is 0. */
61
+ burnTimeMinutes: number | null;
62
+ /** Echo of the resolved inputs (with defaults applied). */
63
+ inputs: {
64
+ lat: number;
65
+ lon: number;
66
+ ozoneDU: number;
67
+ elevationM: number;
68
+ skinType: SkinType;
69
+ };
70
+ }
71
+
72
+ /**
73
+ * Estimate the CLEAR-SKY UV index and derived guidance for a place and moment.
74
+ * Throws TypeError on a missing/invalid options object, invalid date,
75
+ * non-positive ozoneDU, or negative elevationM; lat/lon are validated by the
76
+ * vendored solar geometry.
77
+ */
78
+ export function estimateUVIndex(opts: EstimateUVIndexOptions): UVIndexEstimate;
79
+
80
+ /**
81
+ * Map a UV index to its WHO/WMO exposure category. Categorisation uses the
82
+ * value ROUNDED to the nearest whole number, exactly as UVI is reported:
83
+ * 0–2 Low · 3–5 Moderate · 6–7 High · 8–10 Very High · 11+ Extreme.
84
+ * Throws TypeError unless uvi is a finite number >= 0.
85
+ */
86
+ export function categoryFor(uvi: number): UVCategoryBand;
87
+
88
+ /**
89
+ * Approximate minutes of clear-sky exposure to one Minimal Erythemal Dose
90
+ * (visible sunburn onset) for a Fitzpatrick skin type (default 'II').
91
+ * Returns null when uvi is 0 (no meaningful burn risk). A physical
92
+ * order-of-magnitude figure, NOT medical advice.
93
+ */
94
+ export function burnTimeMinutes(uvi: number, skinType?: SkinType): number | null;
95
+
96
+ /**
97
+ * Solar elevation above the horizon in degrees for a lat/lon and UTC instant
98
+ * (vendored NOAA solar-position geometry; validates lat/lon and throws on
99
+ * out-of-range values).
100
+ */
101
+ export function solarElevation(lat: number, lon: number, date: Date): number;
102
+
103
+ /**
104
+ * Minimal Erythemal Dose (J/m² of erythemally-weighted UV) by Fitzpatrick
105
+ * skin type — exposed for advanced use / testing.
106
+ */
107
+ export const MED_BY_SKIN_TYPE: Record<SkinType, number>;
108
+
109
+ /** Reference total-column ozone (Dobson Units) the base coefficient is tuned to (300). */
110
+ export const REF_OZONE_DU: number;
package/package.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "@verifyhash/uv-index",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Zero-dependency, network-free clear-sky UV-index estimator: solar-elevation-driven UVI, WHO exposure category, and burn-time guidance from lat/lon/date/time (+ optional ozone and elevation).",
5
5
  "main": "index.js",
6
+ "types": "index.d.ts",
6
7
  "type": "commonjs",
7
8
  "scripts": {
8
9
  "test": "node test/index.test.js"
@@ -25,7 +26,8 @@
25
26
  "index.js",
26
27
  "lib/solar.js",
27
28
  "README.md",
28
- "LICENSE"
29
+ "LICENSE",
30
+ "index.d.ts"
29
31
  ],
30
32
  "publishConfig": {
31
33
  "access": "public"