Skip to content

API payloads interface should use Record instead of Map #30

Description

@gagbo

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions