Edits history of script submission #22814 for ' Delete Record (netsuite)'

  • bunnative
    One script reply has been approved by the moderators
    Ap­pro­ved
    //native
    
    const percentEncode = (s: string) =>
      encodeURIComponent(s).replace(
        /[!'()*]/g,
        (c) => "%" + c.charCodeAt(0).toString(16).toUpperCase()
      )
    
    function restBase(auth: RT.Netsuite) {
      return `https://${auth.account_id.trim().toLowerCase()}.suitetalk.api.netsuite.com/services/rest`
    }
    
    // Bearer when an OAuth 2.0 token is set, otherwise TBA (OAuth 1.0a HMAC-SHA256).
    async function authHeader(auth: RT.Netsuite, method: string, url: URL) {
      if (auth.token !== undefined && auth.token !== "") {
        return `Bearer ${auth.token}`
      }
      // Re-serialize the query with %20 instead of '+' for spaces so the URL on
      // the wire matches the form the signature base string encodes
      url.search = [...url.searchParams.entries()]
        .map(([k, v]) => `${percentEncode(k)}=${percentEncode(v)}`)
        .join("&")
      const nonce = Array.from(crypto.getRandomValues(new Uint8Array(16)), (b) =>
        b.toString(16).padStart(2, "0")
      ).join("")
      const timestamp = Math.floor(Date.now() / 1000).toString()
      const oauthParams: [string, string][] = [
        ["oauth_consumer_key", auth.consumer_key ?? ""],
        ["oauth_nonce", nonce],
        ["oauth_signature_method", "HMAC-SHA256"],
        ["oauth_timestamp", timestamp],
        ["oauth_token", auth.token_id ?? ""],
        ["oauth_version", "1.0"],
      ]
      const sortedParams = [...url.searchParams.entries(), ...oauthParams]
        .map(([k, v]) => [percentEncode(k), percentEncode(v)])
        .sort(([ak, av], [bk, bv]) =>
          ak === bk ? (av < bv ? -1 : 1) : ak < bk ? -1 : 1
        )
        .map(([k, v]) => `${k}=${v}`)
        .join("&")
      const baseString = [
        method.toUpperCase(),
        percentEncode(`${url.protocol}//${url.host}${url.pathname}`),
        percentEncode(sortedParams),
      ].join("&")
      const key = await crypto.subtle.importKey(
        "raw",
        new TextEncoder().encode(
          `${percentEncode(auth.consumer_secret ?? "")}&${percentEncode(auth.token_secret ?? "")}`
        ),
        { name: "HMAC", hash: "SHA-256" },
        false,
        ["sign"]
      )
      const signature = btoa(
        String.fromCharCode(
          ...new Uint8Array(
            await crypto.subtle.sign(
              "HMAC",
              key,
              new TextEncoder().encode(baseString)
            )
          )
        )
      )
      const realm = auth.account_id.trim().toUpperCase().replace(/-/g, "_")
      return `OAuth realm="${realm}", oauth_consumer_key="${percentEncode(auth.consumer_key ?? "")}", oauth_token="${percentEncode(auth.token_id ?? "")}", oauth_signature_method="HMAC-SHA256", oauth_timestamp="${timestamp}", oauth_nonce="${nonce}", oauth_version="1.0", oauth_signature="${percentEncode(signature)}"`
    }
    
    export type DynSelect_record_type = string
    
    // Dropdown of the account's record types, from the REST metadata catalog.
    export async function record_type(auth: RT.Netsuite) {
      const url = new URL(`${restBase(auth)}/record/v1/metadata-catalog`)
      const response = await fetch(url, {
        headers: {
          Authorization: await authHeader(auth, "GET", url),
          Accept: "application/json",
        },
      })
      if (!response.ok) {
        throw new Error(`${response.status} ${await response.text()}`)
      }
      const { items } = (await response.json()) as { items: { name: string }[] }
      return items.map((i) => ({ value: i.name, label: i.name }))
    }
    
    /**
     * Delete Record
     * Delete a record by internal ID.
     */
    export async function main(
      auth: RT.Netsuite,
      record_type: DynSelect_record_type,
      id: string
    ) {
      const url = new URL(`${restBase(auth)}/record/v1/${record_type}/${id}`)
      const response = await fetch(url, {
        method: "DELETE",
        headers: {
          Authorization: await authHeader(auth, "DELETE", url),
          Accept: "application/json",
        },
      })
      if (!response.ok) {
        throw new Error(`${response.status} ${await response.text()}`)
      }
      if (response.status === 204) {
        return { success: true, id }
      }
      return await response.json()
    }
    

    Submitted by hugo989 5 hours ago