Sign In

specshot

Package Overview
Dependencies
Maintainers
1
Versions
19
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

specshot - npm Package Compare versions

Comparing version
3.0.3
to
3.0.4
+51
templates/presets/class/templates/api/provider/currency.hbs
{{!-- ---
behavior: scaffold
target: {{outDir}}/plugins
filter:
{{#each pluginNames}}
- {{this}}.hbs
{{/each}}
--- --}}
import type { ApiClient } from "{{#if importAlias}}{{importAlias}}/core/api-client{{else}}{{relPath (concat outDir "/plugins") coreOut}}/api-client{{/if}}";
import type { ApiPlugin } from "{{#if importAlias}}{{importAlias}}/core{{else}}{{relPath (concat outDir "/plugins") coreOut}}{{/if}}/types";
export class CurrencyManager {
private currency: string | null = null;
public setCurrency(currency: string | null) {
this.currency = currency;
}
public getCurrency(): string | null {
return this.currency;
}
}
declare module "{{#if importAlias}}{{importAlias}}/core/types{{else}}{{relPath (concat outDir "/plugins") coreOut}}/types{{/if}}" {
interface PluginRegistry {
currency: CurrencyManager;
}
}
export function installCurrency(client: ApiClient) {
const manager = new CurrencyManager();
const plugin: ApiPlugin = {
name: "currency",
onInit: (c) => {
c.use("currency", manager);
},
onRequest: async (config) => {
const headers = new Headers(config.headers);
const currency = manager.getCurrency();
if (currency && !headers.has("X-Currency")) {
headers.set("X-Currency", currency);
}
return { ...config, headers };
}
};
client.use(plugin);
}
{{!-- ---
behavior: scaffold
target: {{outDir}}/plugins
filter:
{{#each pluginNames}}
- {{this}}.hbs
{{/each}}
--- --}}
import type { ApiClient } from "{{#if importAlias}}{{importAlias}}/core/api-client{{else}}{{relPath (concat outDir "/plugins") coreOut}}/api-client{{/if}}";
import type { ApiPlugin } from "{{#if importAlias}}{{importAlias}}/core{{else}}{{relPath (concat outDir "/plugins") coreOut}}{{/if}}/types";
export class LocaleManager {
private locale: string | null = null;
public setLocale(locale: string | null) {
this.locale = locale;
}
public getLocale(): string | null {
return this.locale;
}
}
declare module "{{#if importAlias}}{{importAlias}}/core/types{{else}}{{relPath (concat outDir "/plugins") coreOut}}/types{{/if}}" {
interface PluginRegistry {
locale: LocaleManager;
}
}
export function installLocale(client: ApiClient) {
const manager = new LocaleManager();
if (typeof window !== "undefined" && typeof navigator !== "undefined") {
manager.setLocale(navigator.language);
}
const plugin: ApiPlugin = {
name: "locale",
onInit: (c) => {
c.use("locale", manager);
},
onRequest: async (config) => {
const headers = new Headers(config.headers);
const locale = manager.getLocale();
if (locale && !headers.has("Accept-Language")) {
headers.set("Accept-Language", locale);
}
return { ...config, headers };
}
};
client.use(plugin);
}
{{!-- ---
behavior: scaffold
target: {{outDir}}/plugins
filter:
{{#each pluginNames}}
- {{this}}.hbs
{{/each}}
--- --}}
import type { ApiClient } from "{{#if importAlias}}{{importAlias}}/core/api-client{{else}}{{relPath (concat outDir "/plugins") coreOut}}/api-client{{/if}}";
import type { ApiPlugin } from "{{#if importAlias}}{{importAlias}}/core{{else}}{{relPath (concat outDir "/plugins") coreOut}}{{/if}}/types";
export function installTimezone(client: ApiClient) {
const timezonePlugin: ApiPlugin = {
name: "timezone",
onRequest: async (config) => {
const headers = new Headers(config.headers);
if (!headers.has("X-Timezone")) {
try {
const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
if (tz) {
headers.set("X-Timezone", tz);
}
} catch (e) {
// Fallback if Intl is not supported
}
}
return { ...config, headers };
}
};
client.use(timezonePlugin);
}
+8
-4
{
"name": "specshot",
"version": "3.0.3",
"version": "3.0.4",
"description": "Fire an OpenAPI spec, get strictly-typed TypeScript code and a robust API mock server — zero-dependency, Zod-validated, and highly customizable.",

@@ -32,3 +32,4 @@ "type": "module",

"test:coverage": "vitest run --coverage",
"lint": "npm run lint:types && npm run lint:format",
"lint": "npm run lint:types && npm run lint:js && npm run lint:format",
"lint:js": "eslint 'src/**/*.ts'",
"lint:types": "tsc --noEmit",

@@ -82,8 +83,11 @@ "lint:format": "prettier --check .",

"@types/node": "^25.9.2",
"@typescript-eslint/parser": "^5.0.1",
"eslint": "^8.52.0",
"husky": "^9.1.7",
"prettier": "^3.9.4",
"prettier": "^3.1.0",
"prettier-eslint": "^16.1.2",
"tsup": "^8.5.1",
"typescript": "^6.0.3",
"typescript": "^5.6.3",
"vitest": "^1.6.0"
}
}

@@ -78,2 +78,5 @@ # Class Preset for Specshot

- **`"circuit-breaker"`**: Scaffolds circuit breaker logic to temporarily stop calling endpoints if they fail repeatedly.
- **`"timezone"`**: Automatically attaches an `X-Timezone` header based on the user's local timezone.
- **`"locale"`**: Manages and injects the `Accept-Language` header automatically.
- **`"currency"`**: Manages and injects the `X-Currency` header automatically.

@@ -175,4 +178,20 @@ #### `toastLibrary`

### 4. The Global Toast Plugin
### 4. Locale and Currency Plugins
If you enable the `"locale"` or `"currency"` plugins, they automatically inject `Accept-Language` and `X-Currency` headers into your requests. You can globally set them using their respective managers.
```typescript
import { api } from "@/lib/api";
const currencyManager = api.plugin("currency");
currencyManager.setCurrency("THB");
// Next request will include `X-Currency: THB`
const localeManager = api.plugin("locale");
localeManager.setLocale("th-TH");
// Next request will include `Accept-Language: th-TH`
```
### 5. The Global Toast Plugin
If you selected a Toast library, the client will automatically trigger a UI toast whenever an API request fails. The message displayed will be the one extracted by your `setErrorExtractor`.

@@ -190,3 +209,3 @@

### 5. API Request Cancellation
### 6. API Request Cancellation

@@ -224,3 +243,3 @@ Every request made by the client returns a `CancelablePromise`. This means you can easily abort an in-flight request by calling `.cancel()` on the returned promise.

### 6. Writing Custom Plugins
### 7. Writing Custom Plugins

@@ -254,3 +273,3 @@ You can easily extend the client by writing your own interceptors.

### 6. Using React Hooks (SWR / React Query)
### 8. Using React Hooks (SWR / React Query)

@@ -257,0 +276,0 @@ If hook generation is enabled, Specshot generates ready-to-use hooks for all `GET` endpoints. These hooks handle caching, deduplication, and loading states automatically.

@@ -11,3 +11,11 @@ {

"type": "string",
"enum": ["bearer", "logger", "request-id", "circuit-breaker"]
"enum": [
"bearer",
"logger",
"request-id",
"circuit-breaker",
"timezone",
"locale",
"currency"
]
},

@@ -14,0 +22,0 @@ "default": [],

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display