Skip to content

Commit

Permalink
Add types to @solana/fast-stable-stringify (#2502)
Browse files Browse the repository at this point in the history
This thing returns a string always, unless you pass it `undefined` or a function.
  • Loading branch information
steveluscher committed Apr 17, 2024
1 parent f396267 commit 5ed19c6
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 12 deletions.
5 changes: 5 additions & 0 deletions .changeset/brave-chicken-own.md
@@ -0,0 +1,5 @@
---
"@solana/fast-stable-stringify": patch
---

Added TypeScript types to `@solana/fast-stable-stringify`
2 changes: 2 additions & 0 deletions packages/fast-stable-stringify/package.json
Expand Up @@ -37,6 +37,7 @@
],
"scripts": {
"compile:js": "tsup --config build-scripts/tsup.config.package.ts",
"compile:typedefs": "tsc -p ./tsconfig.declarations.json && node ../../node_modules/@solana/build-scripts/add-js-extension-to-types.mjs",
"dev": "jest -c ../../node_modules/@solana/test-config/jest-dev.config.ts --rootDir . --watch",
"prepublishOnly": "pnpm pkg delete devDependencies",
"publish-impl": "npm view $npm_package_name@$npm_package_version > /dev/null 2>&1 || pnpm publish --tag ${PUBLISH_TAG:-preview} --access public --no-git-checks",
Expand All @@ -47,6 +48,7 @@
"test:treeshakability:browser": "agadoo dist/index.browser.js",
"test:treeshakability:native": "agadoo dist/index.native.js",
"test:treeshakability:node": "agadoo dist/index.node.js",
"test:typecheck": "tsc --noEmit",
"test:unit:browser": "jest -c ../../node_modules/@solana/test-config/jest-unit.config.browser.ts --rootDir . --silent",
"test:unit:node": "jest -c ../../node_modules/@solana/test-config/jest-unit.config.node.ts --rootDir . --silent"
},
Expand Down
20 changes: 20 additions & 0 deletions packages/fast-stable-stringify/src/__typetests__/index-typetest.ts
@@ -0,0 +1,20 @@
import fastStableStringify from '../index';

fastStableStringify(undefined) satisfies undefined;
fastStableStringify(function () {}) satisfies undefined;
fastStableStringify(() => {}) satisfies undefined;
fastStableStringify(class Foo {}) satisfies undefined;

fastStableStringify({ UNDEFINED: undefined }) satisfies string;
fastStableStringify({ foo: 'bar' }) satisfies string;
fastStableStringify([1, 2, 3]) satisfies string;
fastStableStringify(1n) satisfies string;
fastStableStringify(BigInt(1)) satisfies string;
fastStableStringify(1) satisfies string;
fastStableStringify(5e-324) satisfies string;
fastStableStringify(0xdeadbeef) satisfies string;
fastStableStringify(true) satisfies string;
fastStableStringify(false) satisfies string;
fastStableStringify('string') satisfies string;
fastStableStringify(new Date()) satisfies string;
fastStableStringify(null) satisfies string;
22 changes: 14 additions & 8 deletions packages/fast-stable-stringify/src/index.ts
Expand Up @@ -9,7 +9,7 @@ const objKeys =
return keys;
};

function stringify(val, isArrayProp) {
function stringify(val: unknown, isArrayProp: boolean) {
let i, max, str, keys, key, propVal, toStr;
if (val === true) {
return 'true';
Expand All @@ -21,18 +21,18 @@ function stringify(val, isArrayProp) {
case 'object':
if (val === null) {
return null;
} else if (val.toJSON && typeof val.toJSON === 'function') {
} else if ('toJSON' in val && typeof val.toJSON === 'function') {
return stringify(val.toJSON(), isArrayProp);
} else {
toStr = objToString.call(val);
if (toStr === '[object Array]') {
str = '[';
max = val.length - 1;
max = (val as unknown[]).length - 1;
for (i = 0; i < max; i++) {
str += stringify(val[i], true) + ',';
str += stringify((val as unknown[])[i], true) + ',';
}
if (max > -1) {
str += stringify(val[i], true);
str += stringify((val as unknown[])[i], true);
}
return str + ']';
} else if (toStr === '[object Object]') {
Expand All @@ -43,7 +43,7 @@ function stringify(val, isArrayProp) {
i = 0;
while (i < max) {
key = keys[i];
propVal = stringify(val[key], false);
propVal = stringify((val as Record<typeof key, unknown>)[key], false);
if (propVal !== undefined) {
if (str) {
str += ',';
Expand All @@ -65,11 +65,17 @@ function stringify(val, isArrayProp) {
case 'string':
return JSON.stringify(val);
default:
return isFinite(val) ? val : null;
return isFinite(val as number) ? val : null;
}
}

export default function (val) {
export default function (
val:
| Function // eslint-disable-line @typescript-eslint/ban-types
| undefined,
): undefined;
export default function (val: unknown): string;
export default function (val: unknown): string | undefined {
const returnVal = stringify(val, false);
if (returnVal !== undefined) {
return '' + returnVal;
Expand Down
10 changes: 10 additions & 0 deletions packages/fast-stable-stringify/tsconfig.declarations.json
@@ -0,0 +1,10 @@
{
"compilerOptions": {
"declaration": true,
"declarationMap": true,
"emitDeclarationOnly": true,
"outDir": "./dist/types"
},
"extends": "./tsconfig.json",
"include": ["src/index.ts", "src/types"]
}
5 changes: 1 addition & 4 deletions packages/rpc-graphql/src/loaders/loader.ts
@@ -1,6 +1,4 @@
import type { Address } from '@solana/addresses';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import stringify from '@solana/fast-stable-stringify';
import type { Signature } from '@solana/keys';
import type { GetAccountInfoApi, GetBlockApi, GetProgramAccountsApi, GetTransactionApi } from '@solana/rpc';
Expand Down Expand Up @@ -67,5 +65,4 @@ export type RpcGraphQLLoaders = {
transaction: TransactionLoader;
};

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const cacheKeyFn = (obj: any) => stringify(obj);
export const cacheKeyFn = (obj: unknown) => stringify(obj) ?? '';

0 comments on commit 5ed19c6

Please sign in to comment.