From 25824ab3c8c53d6b39e1c950da657f6ff36fb33d Mon Sep 17 00:00:00 2001 From: miichom Date: Fri, 26 Jun 2026 17:48:06 +0100 Subject: [PATCH 01/10] chore(biomejs): improve config and enable for vscode --- .vscode/settings.json | 6 ++++++ biome.json | 8 +++++++- package.json | 24 ++++++++++++------------ 3 files changed, 25 insertions(+), 13 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..330fff0 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "editor.codeActionsOnSave": { + "source.action.useSortedPackageJson.biome": "explicit", + "source.fixAll.biome": "explicit" + } +} diff --git a/biome.json b/biome.json index 88ba74f..5a0903b 100644 --- a/biome.json +++ b/biome.json @@ -47,6 +47,12 @@ }, "assist": { "enabled": true, - "actions": { "source": { "organizeImports": "on" } } + "actions": { + "source": { + "preset": "recommended", + "organizeImports": "on", + "useSortedPackageJson": "on" + } + } } } diff --git a/package.json b/package.json index 9a42a58..d68a917 100644 --- a/package.json +++ b/package.json @@ -2,18 +2,28 @@ "name": "@xivapi/js", "version": "1.0.5", "description": "A Node.JS wrapper for xivapi.com", + "keywords": ["xivapi", "ffxiv"], + "homepage": "https://github.com/xivapi/xivapi-js#readme", + "bugs": { + "url": "https://github.com/xivapi/xivapi-js/issues" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/xivapi/xivapi-js.git" + }, "license": "MIT", "author": "Kai (https://kai.moe/)", "type": "module", "main": "./dist/index.cjs", "module": "./dist/index.js", "types": "./dist/index.d.ts", + "files": ["dist"], "scripts": { "build": "tsdown", - "test": "vitest --coverage", + "format": "biome format --write", "lint": "biome check --write", "lint:check": "biome check", - "format": "biome format --write" + "test": "vitest --coverage" }, "devDependencies": { "@biomejs/biome": "2.5.1", @@ -32,16 +42,6 @@ "typescript-eslint": "^8.61.1", "vitest": "^4.1.9" }, - "homepage": "https://github.com/xivapi/xivapi-js#readme", - "bugs": { - "url": "https://github.com/xivapi/xivapi-js/issues" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/xivapi/xivapi-js.git" - }, - "keywords": ["xivapi", "ffxiv"], - "files": ["dist"], "engines": { "node": ">=20.0.0" } From 60ecd9fa8ab756e137794cbf12bf117608d347b0 Mon Sep 17 00:00:00 2001 From: miichom Date: Fri, 26 Jun 2026 19:10:08 +0100 Subject: [PATCH 02/10] chore(vscode): add organizeImports action to code actions on save --- .vscode/settings.json | 1 + 1 file changed, 1 insertion(+) diff --git a/.vscode/settings.json b/.vscode/settings.json index 330fff0..5154ce1 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,7 @@ { "editor.codeActionsOnSave": { "source.action.useSortedPackageJson.biome": "explicit", + "source.organizeImports.biome": "explicit", "source.fixAll.biome": "explicit" } } From 23d5c34acc31da04e039ddc9c52ec9867a789873 Mon Sep 17 00:00:00 2001 From: miichom Date: Fri, 26 Jun 2026 19:10:30 +0100 Subject: [PATCH 03/10] chore: add std-env dependency, update types, and improve request handling --- package-lock.json | 12 +++-- package.json | 7 ++- src/index.ts | 4 +- src/lib/assets.ts | 5 +- src/{models.ts => models.d.ts} | 0 src/utils.ts | 86 +++++++++++++++++++--------------- tests/lib/assets.test.ts | 20 ++++---- tsconfig.json | 6 +-- 8 files changed, 79 insertions(+), 61 deletions(-) rename src/{models.ts => models.d.ts} (100%) diff --git a/package-lock.json b/package-lock.json index cde0ca0..15eb83f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,11 +8,14 @@ "name": "@xivapi/js", "version": "1.0.5", "license": "MIT", + "dependencies": { + "std-env": "^4.1.0" + }, "devDependencies": { "@biomejs/biome": "2.5.1", "@eslint/js": "^10.0.1", "@tsconfig/node22": "^22.0.5", - "@types/node": "^26.0.0", + "@types/node": "^26.0.1", "@vitest/coverage-v8": "^4.1.9", "eslint": "^10.5.0", "eslint-config-prettier": "^10.1.8", @@ -1047,9 +1050,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "26.0.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-26.0.0.tgz", - "integrity": "sha512-vf2YFi1iY9lHGwNJMs01biZFbKJkrZR1T6/MlzjhJLPdntOHLhTrDSnSVcdtvjihi4VQNlrFRIxLsDBlQpAipA==", + "version": "26.0.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-26.0.1.tgz", + "integrity": "sha512-fc3KiUoBt6kie0N9bIW3E47vZsuaMf0PM2AaUpLCLT0s/LvX1nxAim6Fc049cNxODPpGm6qRAuUOB86SkRuPQw==", "dev": true, "license": "MIT", "dependencies": { @@ -3082,7 +3085,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.1.0.tgz", "integrity": "sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==", - "dev": true, "license": "MIT" }, "node_modules/supports-color": { diff --git a/package.json b/package.json index d68a917..1dad556 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "1.0.5", "description": "A Node.JS wrapper for xivapi.com", "keywords": ["xivapi", "ffxiv"], - "homepage": "https://github.com/xivapi/xivapi-js#readme", + "homepage": "https://github.com/xivapi/xivapi-js", "bugs": { "url": "https://github.com/xivapi/xivapi-js/issues" }, @@ -25,11 +25,14 @@ "lint:check": "biome check", "test": "vitest --coverage" }, + "dependencies": { + "std-env": "^4.1.0" + }, "devDependencies": { "@biomejs/biome": "2.5.1", "@eslint/js": "^10.0.1", "@tsconfig/node22": "^22.0.5", - "@types/node": "^26.0.0", + "@types/node": "^26.0.1", "@vitest/coverage-v8": "^4.1.9", "eslint": "^10.5.0", "eslint-config-prettier": "^10.1.8", diff --git a/src/index.ts b/src/index.ts index 821f38f..41af8d3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,7 +1,7 @@ import { Assets } from "./lib/assets.js"; import { Sheet, Sheets } from "./lib/sheets.js"; import { Versions } from "./lib/versions.js"; -import * as Models from "./models.js"; +import type * as Models from "./models.d.ts"; import { CustomError, request } from "./utils.js"; export default class XIVAPI { @@ -103,4 +103,4 @@ export type SearchParams = Models.SearchQuery & Models.VersionQuery & Models.RowReaderQuery & { verbose?: boolean }; -export { Models, XIVAPI }; +export { type Models, XIVAPI }; diff --git a/src/lib/assets.ts b/src/lib/assets.ts index 6c61ca3..05ac118 100644 --- a/src/lib/assets.ts +++ b/src/lib/assets.ts @@ -25,20 +25,19 @@ export class Assets { * Retrieve the specified map, composing it from split source files if necessary. * @param {string} territory Territory of the map to be retrieved. This typically takes the form of 4 characters, [letter][number][letter][number]. See Map's Id field for examples of possible combinations of `territory` and `index`. * @param {string} index Index of the map within the territory. This invariably takes the form of a two-digit zero-padded number. See Map's Id field for examples of possible combinations of `territory` and `index`. - * @param {Models.MapPath & Models.VersionQuery & Models.AssetQuery} params + * @param {Models.VersionQuery} [params] * @returns {Promise} An image of the map. * @see https://v2.xivapi.com/api/docs#tag/assets/get/asset/map/{territory}/{index} */ async map( territory: string, index: string, - params: Models.VersionQuery + params?: Models.VersionQuery ): Promise { const { data, errors } = await request({ path: `/asset/map/${territory}/${index}`, params: params as unknown as Record, }); - /* v8 ignore if -- @preserve */ if (errors) throw new CustomError(errors[0].message); return data as Buffer; } diff --git a/src/models.ts b/src/models.d.ts similarity index 100% rename from src/models.ts rename to src/models.d.ts diff --git a/src/utils.ts b/src/utils.ts index 9da9269..5d16ddb 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,3 +1,5 @@ +import { runtime } from "std-env"; +import pkg from "../package.json" with { type: "json" }; import type { XIVAPIOptions } from "./index.js"; import type * as Models from "./models.js"; @@ -20,67 +22,75 @@ export interface RequestPayload { options?: XIVAPIOptions; } -/* v8 ignore start -- @preserve */ export const request = async ( payload: RequestPayload ): Promise => { - const { path, params, options } = payload; + const { path, options } = payload; - if (options?.verbose && params?.verbose !== undefined) { - options.verbose = Boolean(params?.verbose); - delete params?.verbose; + const params: Record = { + ...(payload.params ?? {}), + language: payload.params?.language ?? options?.language ?? "en", + version: payload.params?.version ?? options?.version ?? "latest", + }; + + /* v8 ignore start -- @preserve */ + if (options?.verbose && "verbose" in params) { + options.verbose = Boolean(params.verbose); + delete params.verbose; } + /* v8 ignore stop -- @preserve */ const url = new URL( path instanceof URL ? path.toString() : path.replace(/^\/+/, ""), endpoint ); - if (params) { - const array: Record = { - query: " ", - fields: ",", - transient: ",", - }; - for (const key in array) { - if (Object.hasOwn(params, key) && Array.isArray(params[key])) { - params[key] = (params[key] as string[]).join(array[key]); - } - } - - url.search = new URLSearchParams( - params as Record - ).toString(); - - if (!params.language) { - if (options?.language) url.searchParams.set("language", options.language); - } - if (!params.version) { - if (options?.version) url.searchParams.set("version", options.version); + const joiners = { query: " ", fields: ",", transient: "," }; + for (const key in joiners) { + if (Array.isArray(params[key])) { + params[key] = params[key].join((joiners as Record)[key]); } } - const response = await fetch(url); - if (options?.verbose) + url.search = new URLSearchParams(params as Record).toString(); + + const response = await fetch(url, { + headers: { + "User-Agent": `${pkg.name}/${pkg.version} (${runtime}; +${pkg.homepage})`, + }, + }); + + if (options?.verbose) { console.debug(`Requesting ${path} with params:`, params); + } + /* v8 ignore if -- @preserve */ + const contentType = response.headers.get("Content-Type") ?? ""; if (response.ok) { - const contentType = response.headers.get("content-type"); - if (contentType?.includes("application/json")) { + if (contentType.includes("application/json")) { payload.data = await response.json(); } else { payload.data = Buffer.from(await response.arrayBuffer()); } + + if (options?.verbose) { + console.debug(`Success on ${path} with params:`, params); + } } else { - payload.errors = [(await response.json()) as Models.ErrorResponse]; - } + /* v8 ignore start -- @preserve */ + if (contentType.includes("application/json")) { + payload.errors = [(await response.json()) as Models.ErrorResponse]; + } else { + payload.errors = [ + { code: response.status, message: response.statusText }, + ]; + } - if (options?.verbose) - console.debug( - `${response.ok ? "Success" : "Error"} on ${path} with params:`, - params - ); + if (options?.verbose) { + console.debug(`Error on ${path} with params:`, params); + } + /* v8 ignore stop -- @preserve */ + } return payload; }; -/* v8 ignore stop -- @preserve */ diff --git a/tests/lib/assets.test.ts b/tests/lib/assets.test.ts index 4f03f01..6105094 100644 --- a/tests/lib/assets.test.ts +++ b/tests/lib/assets.test.ts @@ -18,14 +18,6 @@ describe("@xivapi/js", () => { expect(result.length).toBeGreaterThan(0); }); - it("should handle map requests correctly", async () => { - const result = await assets.map("s1d1", "00", { version: "latest" }); - - expect(result).toBeDefined(); - expect(Buffer.isBuffer(result)).toBe(true); - expect(result.length).toBeGreaterThan(0); - }); - it("should throw CustomError when asset fetch fails", async () => { await expect( assets.get({ @@ -34,5 +26,17 @@ describe("@xivapi/js", () => { }) ).rejects.toThrow(); }); + + it("should handle map requests correctly", async () => { + const result = await assets.map("s1d1", "00"); + + expect(result).toBeDefined(); + expect(Buffer.isBuffer(result)).toBe(true); + expect(result.length).toBeGreaterThan(0); + }); + + it("should throw CustomError when map fetch fails", async () => { + await expect(assets.map("invalid", "00")).rejects.toThrow(); + }); }); }); diff --git a/tsconfig.json b/tsconfig.json index c99404c..88c7e02 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,14 +1,14 @@ { "extends": "@tsconfig/node22/tsconfig.json", "compilerOptions": { - "module": "node20", "target": "esnext", + "moduleResolution": "nodenext", "types": ["node"], "declaration": true, "preserveConstEnums": true, + "resolveJsonModule": true, "outDir": "dist", - "rootDir": ".", - "ignoreDeprecations": "6.0" // 'baseUrl' is used in tsup, this is deprecated as of TS 7.0 + "rootDir": "." }, "include": ["src/**/*"], "exclude": ["**/*.spec.ts"] From c56523703caf7073388b971c3d82d0d6d09d2ee9 Mon Sep 17 00:00:00 2001 From: miichom Date: Fri, 26 Jun 2026 19:21:28 +0100 Subject: [PATCH 04/10] chore: refine request parameters handling and cleanup undefined values --- src/utils.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/utils.ts b/src/utils.ts index 5d16ddb..5a0c17d 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -29,8 +29,8 @@ export const request = async ( const params: Record = { ...(payload.params ?? {}), - language: payload.params?.language ?? options?.language ?? "en", - version: payload.params?.version ?? options?.version ?? "latest", + language: payload.params?.language ?? options?.language, + version: payload.params?.version ?? options?.version, }; /* v8 ignore start -- @preserve */ @@ -52,6 +52,9 @@ export const request = async ( } } + for (const key in params) { + if (params[key] === undefined) delete params[key]; + } url.search = new URLSearchParams(params as Record).toString(); const response = await fetch(url, { From 1507419bbb0842e99a5ec6cae2894fd020cdf9b4 Mon Sep 17 00:00:00 2001 From: miichom Date: Fri, 26 Jun 2026 19:25:05 +0100 Subject: [PATCH 05/10] chore: add actions and emotes sheets to XIVAPI and update tests for achievements --- src/index.ts | 13 +++--- tests/lib/xivapi.test.ts | 86 ++++++++++++++++++++++++++++++++++------ 2 files changed, 82 insertions(+), 17 deletions(-) diff --git a/src/index.ts b/src/index.ts index 41af8d3..195e695 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,12 +5,13 @@ import type * as Models from "./models.d.ts"; import { CustomError, request } from "./utils.js"; export default class XIVAPI { - public readonly options: XIVAPIOptions; - public readonly achievements: Sheet<"Achievement">; + public readonly actions: Sheet<"Action">; + public readonly emotes: Sheet<"Emote">; + public readonly items: Sheet<"Item">; public readonly minions: Sheet<"Companion">; public readonly mounts: Sheet<"Mount">; - public readonly items: Sheet<"Item">; + public readonly options: XIVAPIOptions; /** * Raw endpoints for the API. Please consider using the typed endpoints instead. @@ -54,10 +55,11 @@ export default class XIVAPI { } ) { this.achievements = new Sheet("Achievement", options); + this.actions = new Sheet("Action", options); + this.emotes = new Sheet("Emote", options); + this.items = new Sheet("Item", options); this.minions = new Sheet("Companion", options); this.mounts = new Sheet("Mount", options); - this.items = new Sheet("Item", options); - this.options = options; } @@ -72,6 +74,7 @@ export default class XIVAPI { const { data, errors } = await request({ path: "/search", params: params as Record, + options: this.options }); if (errors) throw new CustomError(errors[0].message); return data as Models.SearchResponse; diff --git a/tests/lib/xivapi.test.ts b/tests/lib/xivapi.test.ts index c29f651..45c6026 100644 --- a/tests/lib/xivapi.test.ts +++ b/tests/lib/xivapi.test.ts @@ -369,9 +369,9 @@ describe("@xivapi/js", () => { }); describe("typed sheet accessors", () => { - describe("items", () => { - it("can get a specific item by ID", async () => { - const result = await xiv.items.get(1, { + describe("achievements", () => { + it("can get a specific achievement by ID", async () => { + const result = await xiv.achievements.get(1, { fields: "Name", language: "en", }); @@ -382,11 +382,11 @@ describe("@xivapi/js", () => { expect(result.schema).toBeDefined(); expect(result.fields).toBeDefined(); expect(result.row_id).toBe(1); - expect(result.fields.Name).toBe("Gil"); + expect(result.fields.Name).toBe("To Crush Your Enemies I"); }); - it("can list items with parameters", async () => { - const result = await xiv.items.list({ limit: 3 }); + it("can list achievements with parameters", async () => { + const result = await xiv.achievements.list({ limit: 3 }); expect(result).toBeDefined(); expect(result.rows).toBeDefined(); @@ -403,9 +403,71 @@ describe("@xivapi/js", () => { }); }); - describe("achievements", () => { - it("can get a specific achievement by ID", async () => { - const result = await xiv.achievements.get(1, { + describe("actions", () => { + it("can get a specific action by ID", async () => { + const result = await xiv.actions.get(5); + + expect(result).toBeDefined(); + expect(result.row_id).toBeDefined(); + expect(typeof result.row_id).toBe("number"); + expect(result.schema).toBeDefined(); + expect(result.fields).toBeDefined(); + expect(result.row_id).toBe(5); + expect(result.fields.Name).toBe("Teleport"); + }); + + it("can list achievements with parameters", async () => { + const result = await xiv.actions.list({ limit: 3 }); + + expect(result).toBeDefined(); + expect(result.rows).toBeDefined(); + expect(Array.isArray(result.rows)).toBe(true); + expect(result.schema).toBeDefined(); + expect(result.rows.length).toBeLessThanOrEqual(3); + + result.rows.forEach((row) => { + expect(row.row_id).toBeDefined(); + expect(typeof row.row_id).toBe("number"); + expect(row.fields).toBeDefined(); + expect(typeof row.fields).toBe("object"); + }); + }); + }); + + describe("emotes", () => { + it("can get a specific action by ID", async () => { + const result = await xiv.emotes.get(11); + + expect(result).toBeDefined(); + expect(result.row_id).toBeDefined(); + expect(typeof result.row_id).toBe("number"); + expect(result.schema).toBeDefined(); + expect(result.fields).toBeDefined(); + expect(result.row_id).toBe(11); + expect(result.fields.Name).toBe("Dance"); + }); + + it("can list achievements with parameters", async () => { + const result = await xiv.emotes.list({ limit: 3 }); + + expect(result).toBeDefined(); + expect(result.rows).toBeDefined(); + expect(Array.isArray(result.rows)).toBe(true); + expect(result.schema).toBeDefined(); + expect(result.rows.length).toBeLessThanOrEqual(3); + + result.rows.forEach((row) => { + expect(row.row_id).toBeDefined(); + expect(typeof row.row_id).toBe("number"); + expect(row.fields).toBeDefined(); + expect(typeof row.fields).toBe("object"); + }); + }); + }); + + describe("items", () => { + it("can get a specific item by ID", async () => { + const result = await xiv.items.get(1, { fields: "Name", language: "en", }); @@ -416,11 +478,11 @@ describe("@xivapi/js", () => { expect(result.schema).toBeDefined(); expect(result.fields).toBeDefined(); expect(result.row_id).toBe(1); - expect(result.fields.Name).toBe("To Crush Your Enemies I"); + expect(result.fields.Name).toBe("Gil"); }); - it("can list achievements with parameters", async () => { - const result = await xiv.achievements.list({ limit: 3 }); + it("can list items with parameters", async () => { + const result = await xiv.items.list({ limit: 3 }); expect(result).toBeDefined(); expect(result.rows).toBeDefined(); From f3a2f17dd093398f397eaf69df7dd7836b085a7d Mon Sep 17 00:00:00 2001 From: miichom Date: Fri, 26 Jun 2026 19:30:29 +0100 Subject: [PATCH 06/10] chore: rename verify-publish job to publish in CI workflow --- .github/workflows/ci-verify.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-verify.yml b/.github/workflows/ci-verify.yml index c5bdc83..27f5a18 100644 --- a/.github/workflows/ci-verify.yml +++ b/.github/workflows/ci-verify.yml @@ -27,7 +27,7 @@ jobs: uses: davelosert/vitest-coverage-report-action@v2 with: threshold-icons: "{0: 'đź”´', 80: 'đźź ', 90: '🟢'}" - verify-publish: + publish: runs-on: ubuntu-latest needs: test permissions: From 923ceb07fa6e8c6a0ac3f5027f3fd15447791d18 Mon Sep 17 00:00:00 2001 From: miichom Date: Fri, 26 Jun 2026 19:37:22 +0100 Subject: [PATCH 07/10] chore: update README for clarity, improve usage examples, and enhance documentation --- README.md | 47 ++++++++++++----------------------------------- src/index.ts | 12 ++++++------ src/lib/assets.ts | 2 +- 3 files changed, 19 insertions(+), 42 deletions(-) diff --git a/README.md b/README.md index 42252cc..9710726 100644 --- a/README.md +++ b/README.md @@ -13,12 +13,12 @@ If you need help or run into any issues, please [open an issue](https://github.c ## Installation ```bash -npm install @xivapi/js@latest # or use yarn, pnpm, or bun +npm install @xivapi/js ``` -## Usage Examples +Supports Node, Bun, Deno, and modern bundlers. -#### 1. Importing and Initialization +## Quick Start ```js import xivapi from "@xivapi/js"; @@ -34,57 +34,34 @@ const xivCustom = new xivapi({ }); ``` -#### 2. Get an Item +## Examples + +#### 1. Get an Item ```js -// Fetch the Gil item (item ID 1) const item = await xiv.items.get(1); - -console.log(item.fields.Name); // "Gil" (or equivalent in your language) +console.log(item.fields.Name); // "Gil" ``` -#### 3. Search Example +#### 2. Search sheets ```js -// Find all items named "gil" -const params = { - query: 'Name~"gil"', - sheets: "Item", -}; - +const params = { query: 'Name~"gil"', sheets: "Item" }; const { results } = await xiv.search(params); console.log(results[0]); - -/* -Output example: -{ - "score": 1, - "sheet": "Item", - "row_id": 1, - "fields": { - "Icon": { - "id": 65002, - "path": "ui/icon/065000/065002.tex", - "path_hr1": "ui/icon/065000/065002_hr1.tex" - }, - "Name": "Gil", - "Singular": "gil" - } -} -*/ ``` -#### 4. Using Raw XIVAPI v2 Endpoints +#### 4. Using raw XIVAPI v2 endpoints ```js -// Fetch a raw asset file (e.g. icon image) +// Fetch an asset (e.g., icon) const assets = await xiv.data.assets(); const asset = await assets.get({ path: "ui/icon/051000/051474_hr1.tex", format: "png", // jpg or webp also supported }); -// List all quests +// List all rows from the "Quest" sheet const sheets = await xiv.data.sheets(); const quests = await sheets.list("Quest"); console.log(quests); diff --git a/src/index.ts b/src/index.ts index 195e695..8f7ab4f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -16,17 +16,17 @@ export default class XIVAPI { /** * Raw endpoints for the API. Please consider using the typed endpoints instead. * @see https://v2.xivapi.com/api/docs - * @since 0.5.0 + * @since 1.0.0 */ public readonly data = { /** * @see https://v2.xivapi.com/api/docs#tag/sheets - * @since 0.5.0 + * @since 1.0.0 */ sheets: () => new Sheets(this.options), /** * @see https://v2.xivapi.com/api/docs#tag/versions - * @since 0.5.0 + * @since 1.0.0 */ versions: () => new Versions() @@ -36,7 +36,7 @@ export default class XIVAPI { ), /** * @see https://v2.xivapi.com/api/docs#tag/assets - * @since 0.5.0 + * @since 1.0.0 */ assets: () => new Assets(), }; @@ -45,7 +45,7 @@ export default class XIVAPI { * A wrapper for the XIVAPI v2 API. * @param {XIVAPIOptions} [options] The client options to fetch with. * @see https://v2.xivapi.com/api/docs - * @since 0.5.0 + * @since 1.0.0 */ constructor( options: XIVAPIOptions = { @@ -68,7 +68,7 @@ export default class XIVAPI { * @param {SearchParams} params Query paramters accepted by the search endpoint. * @returns {Promise} Response structure for the search endpoint. * @see https://v2.xivapi.com/api/docs#tag/search/get/search - * @since 0.5.0 + * @since 1.0.0 */ public async search(params: SearchParams): Promise { const { data, errors } = await request({ diff --git a/src/lib/assets.ts b/src/lib/assets.ts index 05ac118..fae1935 100644 --- a/src/lib/assets.ts +++ b/src/lib/assets.ts @@ -32,7 +32,7 @@ export class Assets { async map( territory: string, index: string, - params?: Models.VersionQuery + params: Models.VersionQuery = {} ): Promise { const { data, errors } = await request({ path: `/asset/map/${territory}/${index}`, From 6e414056ad19ebff97869e1ef8913c3def238c0c Mon Sep 17 00:00:00 2001 From: miichom Date: Fri, 26 Jun 2026 19:38:24 +0100 Subject: [PATCH 08/10] chore: improve example section formatting in README --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9710726..0eb7997 100644 --- a/README.md +++ b/README.md @@ -36,14 +36,14 @@ const xivCustom = new xivapi({ ## Examples -#### 1. Get an Item +#### Get an Item ```js const item = await xiv.items.get(1); console.log(item.fields.Name); // "Gil" ``` -#### 2. Search sheets +#### Search sheets ```js const params = { query: 'Name~"gil"', sheets: "Item" }; @@ -51,7 +51,7 @@ const { results } = await xiv.search(params); console.log(results[0]); ``` -#### 4. Using raw XIVAPI v2 endpoints +#### Using raw XIVAPI v2 endpoints ```js // Fetch an asset (e.g., icon) From 3380fcf22782f721e7b61ae9e17803c54fefbdbc Mon Sep 17 00:00:00 2001 From: miichom Date: Fri, 26 Jun 2026 19:39:04 +0100 Subject: [PATCH 09/10] chore: add output example for search sheets in README --- README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/README.md b/README.md index 0eb7997..253a386 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,24 @@ console.log(item.fields.Name); // "Gil" const params = { query: 'Name~"gil"', sheets: "Item" }; const { results } = await xiv.search(params); console.log(results[0]); + +/* +Output: +{ + "score": 1, + "sheet": "Item", + "row_id": 1, + "fields": { + "Icon": { + "id": 65002, + "path": "ui/icon/065000/065002.tex", + "path_hr1": "ui/icon/065000/065002_hr1.tex" + }, + "Name": "Gil", + "Singular": "gil" + } +} +*/ ``` #### Using raw XIVAPI v2 endpoints From 9c3504d00b719c41289c456aea561e2e1a83776c Mon Sep 17 00:00:00 2001 From: miichom Date: Fri, 26 Jun 2026 19:43:34 +0100 Subject: [PATCH 10/10] chore: add Code of Conduct and contributing guidelines to improve community standards and documentation --- CODE_OF_CONDUCT.md | 34 ++++++++++++++++++++++++++++++++++ CONTRIBUTING | 44 ++++++++++++++++++++++++++++++++++++++++++++ README.md | 13 ++----------- 3 files changed, 80 insertions(+), 11 deletions(-) create mode 100644 CODE_OF_CONDUCT.md create mode 100644 CONTRIBUTING diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..316ecda --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,34 @@ +# Contributor Covenant Code of Conduct + +Our goal is to foster a respectful, welcoming, and collaborative space across every project in this monorepo. Everyone involved shares the responsibility of keeping participation positive and free from harassment. + +## Our Standards + +We encourage behaviors that help build a healthy and productive community: + +- Using welcoming and inclusive language +- Respecting differing viewpoints and experiences +- Offering and receiving constructive feedback gracefully +- Showing empathy and kindness toward others +- Collaborating in ways that support the long‑term health of the project + +## Unacceptable Behavior + +The following behaviors are not acceptable in any project within this monorepo: + +- Harassment, discrimination, or exclusion based on personal characteristics +- Personal attacks, insults, or trolling +- Public or private harassment of any kind +- Deliberate intimidation or threats +- Disruptive behavior that interferes with constructive collaboration + +## Enforcement + +If you observe or experience behavior that violates this Code of Conduct, please contact the maintainers through the repository’s issue tracker or by opening a private security advisory. + +All reports will be handled confidentially. +Maintainers are responsible for reviewing incidents, determining appropriate actions, and enforcing this Code of Conduct fairly and consistently across the monorepo. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org/) version 2.1. \ No newline at end of file diff --git a/CONTRIBUTING b/CONTRIBUTING new file mode 100644 index 0000000..47803ec --- /dev/null +++ b/CONTRIBUTING @@ -0,0 +1,44 @@ +# Contributing to xivapi-js + +Thanks for your interest in contributing! We welcome contributions of all kinds, including bug fixes, new features, documentation improvements, and — eventually — translations. + +## How to Contribute + +1. **Fork** the repository. +2. **Create a feature branch**, for example: + ```bash + git checkout -b feature/your-feature-name + ``` +3. Make your changes, following the style and structure of the project or package you are modifying. +4. Add tests or verify that your changes work as expected. +5. Commit your work using clear, descriptive commit messages. +6. Push your branch: + ```bash + git push origin feature/your-feature-name + ``` +7. Open a Pull Request. + In your PR description, include: + +- What you changed +- Why you changed it +- Any related issues or context + +## Reporting Issues + +Before opening a new issue: + +- Check existing issues to avoid duplicates. +- Provide a clear description of the problem or feature request. +- For bugs, include steps to reproduce, expected vs. actual behavior, and any relevant logs or screenshots. +- For feature requests, explain the problem the feature solves and any alternatives you’ve considered. + +## Code Style & Tests + +- Follow the existing coding conventions (formatting, naming, structure). +- Update or add tests when appropriate. +- Ensure all tests pass before submitting your PR (if a test suite is available). +- Keep changes focused—smaller, well‑scoped PRs are easier to review and merge. + +## Community Code of Conduct + +By contributing to this monorepo, you agree to follow our [Code of Conduct](./CODE_OF_CONDUCT.md). \ No newline at end of file diff --git a/README.md b/README.md index 253a386..d3fdedb 100644 --- a/README.md +++ b/README.md @@ -91,17 +91,8 @@ console.log(versions[0]); // e.g. "7.0" ## Contributing -We welcome all contributions! Whether you'd like to report a bug, suggest a feature, improve the documentation, or submit a pull request, your help is appreciated. - -To get started, clone the repository with: `git clone https://github.com/xivapi/xivapi-js.git` - -Before opening a pull request, please: - -- Make sure your code passes linting and all current tests (`npm run lint && npm test`). -- Clearly explain your changes and reference any relevant issues in your PR description. - -If you have questions, suggestions, or want to discuss changes before contributing, feel free to open an issue! +Contributions, bug reports, and feature requests are welcome! See [`CONTRIBUTING`](CONTRIBUTING) for guidelines on how to get started. ## License -MIT License - see [LICENSE](LICENSE) file for details. +This project is licensed under the MIT License. See [`LICENSE`](LICENSE) for details.