Skip to content

Commit

Permalink
Merge pull request #2 from Sachindu-Nethmin/main
Browse files Browse the repository at this point in the history
Client generation with required sanitization
  • Loading branch information
aashikam authored Nov 1, 2024
2 parents 5ccc215 + 31c9cf0 commit 0251926
Show file tree
Hide file tree
Showing 8 changed files with 12,042 additions and 11 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@

## Overview

[//]: # (TODO: Add overview mentioning the purpose of the module, supported REST API versions, and other high-level details.)
[Spotify](https://www.spotify.com/) is a popular music streaming service that allows users to listen to millions of songs, podcasts, and other audio content from artists and creators worldwide. It offers personalized playlists, radio stations, and social features, enabling users to discover new music and share content with friends.

The `ballerinax/spotify` package provides APIs to connect and interact with Spotify Web API endpoints, which allow access to Spotify's catalog, user data, and playback features. This package enables developers to integrate Spotify functionalities, such as searching for tracks, managing playlists, and controlling playback, into their applications.

## Setup guide

Expand Down
2 changes: 1 addition & 1 deletion ballerina/Ballerina.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ version = "0.1.0"
license = ["Apache-2.0"]
authors = ["Ballerina"]
keywords = []
# icon = "icon.png" # TODO: update icon.png
icon = "icon.png"
repository = "https://github.com/ballerina-platform/module-ballerinax-spotify"

[build-options]
Expand Down
994 changes: 994 additions & 0 deletions ballerina/client.bal

Large diffs are not rendered by default.

Binary file added ballerina/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4,267 changes: 4,267 additions & 0 deletions ballerina/types.bal

Large diffs are not rendered by default.

217 changes: 217 additions & 0 deletions ballerina/utils.bal
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
// AUTO-GENERATED FILE. DO NOT MODIFY.
// This file is auto-generated by the Ballerina OpenAPI tool.

// Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com).
//
// WSO2 LLC. licenses this file to you under the Apache License,
// Version 2.0 (the "License"); you may not use this file except
// in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

import ballerina/url;

type SimpleBasicType string|boolean|int|float|decimal;

# Represents encoding mechanism details.
type Encoding record {
# Defines how multiple values are delimited
string style = FORM;
# Specifies whether arrays and objects should generate as separate fields
boolean explode = true;
# Specifies the custom content type
string contentType?;
# Specifies the custom headers
map<any> headers?;
};

enum EncodingStyle {
DEEPOBJECT, FORM, SPACEDELIMITED, PIPEDELIMITED
}

final Encoding & readonly defaultEncoding = {};

# Serialize the record according to the deepObject style.
#
# + parent - Parent record name
# + anyRecord - Record to be serialized
# + return - Serialized record as a string
isolated function getDeepObjectStyleRequest(string parent, record {} anyRecord) returns string {
string[] recordArray = [];
foreach [string, anydata] [key, value] in anyRecord.entries() {
if value is SimpleBasicType {
recordArray.push(parent + "[" + key + "]" + "=" + getEncodedUri(value.toString()));
} else if value is SimpleBasicType[] {
recordArray.push(getSerializedArray(parent + "[" + key + "]" + "[]", value, DEEPOBJECT, true));
} else if value is record {} {
string nextParent = parent + "[" + key + "]";
recordArray.push(getDeepObjectStyleRequest(nextParent, value));
} else if value is record {}[] {
string nextParent = parent + "[" + key + "]";
recordArray.push(getSerializedRecordArray(nextParent, value, DEEPOBJECT));
}
recordArray.push("&");
}
_ = recordArray.pop();
return string:'join("", ...recordArray);
}

# Serialize the record according to the form style.
#
# + parent - Parent record name
# + anyRecord - Record to be serialized
# + explode - Specifies whether arrays and objects should generate separate parameters
# + return - Serialized record as a string
isolated function getFormStyleRequest(string parent, record {} anyRecord, boolean explode = true) returns string {
string[] recordArray = [];
if explode {
foreach [string, anydata] [key, value] in anyRecord.entries() {
if value is SimpleBasicType {
recordArray.push(key, "=", getEncodedUri(value.toString()));
} else if value is SimpleBasicType[] {
recordArray.push(getSerializedArray(key, value, explode = explode));
} else if value is record {} {
recordArray.push(getFormStyleRequest(parent, value, explode));
}
recordArray.push("&");
}
_ = recordArray.pop();
} else {
foreach [string, anydata] [key, value] in anyRecord.entries() {
if value is SimpleBasicType {
recordArray.push(key, ",", getEncodedUri(value.toString()));
} else if value is SimpleBasicType[] {
recordArray.push(getSerializedArray(key, value, explode = false));
} else if value is record {} {
recordArray.push(getFormStyleRequest(parent, value, explode));
}
recordArray.push(",");
}
_ = recordArray.pop();
}
return string:'join("", ...recordArray);
}

# Serialize arrays.
#
# + arrayName - Name of the field with arrays
# + anyArray - Array to be serialized
# + style - Defines how multiple values are delimited
# + explode - Specifies whether arrays and objects should generate separate parameters
# + return - Serialized array as a string
isolated function getSerializedArray(string arrayName, anydata[] anyArray, string style = "form", boolean explode = true) returns string {
string key = arrayName;
string[] arrayValues = [];
if anyArray.length() > 0 {
if style == FORM && !explode {
arrayValues.push(key, "=");
foreach anydata i in anyArray {
arrayValues.push(getEncodedUri(i.toString()), ",");
}
} else if style == SPACEDELIMITED && !explode {
arrayValues.push(key, "=");
foreach anydata i in anyArray {
arrayValues.push(getEncodedUri(i.toString()), "%20");
}
} else if style == PIPEDELIMITED && !explode {
arrayValues.push(key, "=");
foreach anydata i in anyArray {
arrayValues.push(getEncodedUri(i.toString()), "|");
}
} else if style == DEEPOBJECT {
foreach anydata i in anyArray {
arrayValues.push(key, "[]", "=", getEncodedUri(i.toString()), "&");
}
} else {
foreach anydata i in anyArray {
arrayValues.push(key, "=", getEncodedUri(i.toString()), "&");
}
}
_ = arrayValues.pop();
}
return string:'join("", ...arrayValues);
}

# Serialize the array of records according to the form style.
#
# + parent - Parent record name
# + value - Array of records to be serialized
# + style - Defines how multiple values are delimited
# + explode - Specifies whether arrays and objects should generate separate parameters
# + return - Serialized record as a string
isolated function getSerializedRecordArray(string parent, record {}[] value, string style = FORM, boolean explode = true) returns string {
string[] serializedArray = [];
if style == DEEPOBJECT {
int arayIndex = 0;
foreach var recordItem in value {
serializedArray.push(getDeepObjectStyleRequest(parent + "[" + arayIndex.toString() + "]", recordItem), "&");
arayIndex = arayIndex + 1;
}
} else {
if !explode {
serializedArray.push(parent, "=");
}
foreach var recordItem in value {
serializedArray.push(getFormStyleRequest(parent, recordItem, explode), ",");
}
}
_ = serializedArray.pop();
return string:'join("", ...serializedArray);
}

# Get Encoded URI for a given value.
#
# + value - Value to be encoded
# + return - Encoded string
isolated function getEncodedUri(anydata value) returns string {
string|error encoded = url:encode(value.toString(), "UTF8");
if encoded is string {
return encoded;
} else {
return value.toString();
}
}

# Generate query path with query parameter.
#
# + queryParam - Query parameter map
# + encodingMap - Details on serialization mechanism
# + return - Returns generated Path or error at failure of client initialization
isolated function getPathForQueryParam(map<anydata> queryParam, map<Encoding> encodingMap = {}) returns string|error {
string[] param = [];
if queryParam.length() > 0 {
param.push("?");
foreach var [key, value] in queryParam.entries() {
if value is () {
_ = queryParam.remove(key);
continue;
}
Encoding encodingData = encodingMap.hasKey(key) ? encodingMap.get(key) : defaultEncoding;
if value is SimpleBasicType {
param.push(key, "=", getEncodedUri(value.toString()));
} else if value is SimpleBasicType[] {
param.push(getSerializedArray(key, value, encodingData.style, encodingData.explode));
} else if value is record {} {
if encodingData.style == DEEPOBJECT {
param.push(getDeepObjectStyleRequest(key, value));
} else {
param.push(getFormStyleRequest(key, value, encodingData.explode));
}
} else {
param.push(key, "=", value.toString());
}
param.push("&");
}
_ = param.pop();
}
string restOfPath = string:'join("", ...param);
return restOfPath;
}
Loading

0 comments on commit 0251926

Please sign in to comment.