Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

API payloads interface should use Record instead of Map #30

Open
gagbo opened this issue Dec 6, 2024 · 0 comments
Open

API payloads interface should use Record instead of Map #30

gagbo opened this issue Dec 6, 2024 · 0 comments

Comments

@gagbo
Copy link

gagbo commented Dec 6, 2024

Hello,

The payloads for e.g. the tunnel group backends enforces a Map<string, string>:

export interface TunnelGroupBackendCreate {
/** human-readable description of this backend. Optional */
description?: string;
/** arbitrary user-defined machine-readable data of this backend. Optional */
metadata?: string;
/** labels to watch for tunnels on, e.g. app->foo, dc->bar */
labels: Map<string, string>;
}

This is problematic because the function that serializes arguments for the underlying API calls iterates on Object.keys applied to the Map, and at least on the latest node LTS, this gives nothing

function objectKeysTo(obj, keyFunc) {
if (obj === null) {
return obj;
} else if (Array.isArray(obj)) {
return obj.map(item => objectKeysTo(item, keyFunc));
} else if (typeof obj === 'object') {
return Object.keys(obj).reduce((acc, k) => {
acc[keyFunc(k)] = objectKeysTo(obj[k], keyFunc);
return acc;
}, {});
} else {
return obj;
}
}

$ node -v
v22.11.0
$ node
> Object.keys(new Map([[ 1, 'one' ],[ 2, 'two' ]]))
[]

The association of these 2 facts mean that when we pass labels to ngrok-api generated type, we always lose all the values during serialization; in my example, that means I cannot set the labels to a tunnel group backend using the API*

All those Map<string, string> interfaces look like they could just be Record<string, string>, which would allow objects to be serialized as expected.

*Unless I use // @ts-ignore:

    // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
    const labels: Record<string, string> = Object.fromEntries(params.backend.labels ?? new Map())
    labels.edge = params.edge.id
    const request: TunnelGroupBackendUpdate = {
      id: params.backend.id,
      // @ts-expect-error ngrok-api wants a `Map`, but a `Map` serializes to nothing, so the tunnel backend group rule isn’t created. We
      // enforce an object to deal with this.
      labels,
    }

Cheers,
Gerry

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant