diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
index 2399ba9..c7dc716 100644
--- a/.github/copilot-instructions.md
+++ b/.github/copilot-instructions.md
@@ -1,4 +1,4 @@
-# Copilot Instructions for Kiota Abstractions Ruby
+# Copilot Instructions for Kiota Ruby
## Commit Messages
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index fcdf0dc..b9ba800 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -12,7 +12,28 @@ updates:
cooldown:
default-days: 7
- package-ecosystem: bundler
- directory: /
+ directory: /components/abstractions
+ schedule:
+ interval: daily
+ open-pull-requests-limit: 10
+ cooldown:
+ default-days: 7
+- package-ecosystem: bundler
+ directory: /components/serialization/json
+ schedule:
+ interval: daily
+ open-pull-requests-limit: 10
+ cooldown:
+ default-days: 7
+- package-ecosystem: bundler
+ directory: /components/http
+ schedule:
+ interval: daily
+ open-pull-requests-limit: 10
+ cooldown:
+ default-days: 7
+- package-ecosystem: bundler
+ directory: /components/authentication/oauth
schedule:
interval: daily
open-pull-requests-limit: 10
diff --git a/.github/policies/kiota-abstractions-ruby-branch-protection.yml b/.github/policies/kiota-ruby-branch-protection.yml
similarity index 93%
rename from .github/policies/kiota-abstractions-ruby-branch-protection.yml
rename to .github/policies/kiota-ruby-branch-protection.yml
index 5b217a2..aa1df5c 100644
--- a/.github/policies/kiota-abstractions-ruby-branch-protection.yml
+++ b/.github/policies/kiota-ruby-branch-protection.yml
@@ -1,8 +1,8 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
-name: kiota-abstractions-ruby-branch-protection
-description: Branch protection policy for the kiota-abstractions-ruby repository
+name: kiota-ruby-branch-protection
+description: Branch protection policy for the kiota-ruby repository
resource: repository
configuration:
branchProtectionRules:
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 0bde8a6..e54f050 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -9,7 +9,7 @@ permissions:
contents: read
jobs:
- deploy_prod:
+ publish-abstractions:
environment:
name: production_feeds
runs-on: ubuntu-latest
@@ -23,8 +23,50 @@ jobs:
bundler-cache: true
bundler: 'latest'
cache-version: 1
- - run: bundle exec rake
- - name: Publish to RubyGems
+ working-directory: components/abstractions
+ - name: Run tests
+ working-directory: components/abstractions
+ run: bundle exec rake
+ - name: Publish microsoft_kiota_abstractions to RubyGems
+ working-directory: components/abstractions
+ run: |
+ mkdir -p $HOME/.gem
+ touch $HOME/.gem/credentials
+ chmod 0600 $HOME/.gem/credentials
+ printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
+ gem build *.gemspec
+ gem push *.gem
+ env:
+ GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_AUTH_TOKEN}}"
+
+ publish-downstream:
+ needs: publish-abstractions
+ environment:
+ name: production_feeds
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ component:
+ - { name: serialization-json, dir: components/serialization/json }
+ - { name: http, dir: components/http }
+ - { name: authentication-oauth, dir: components/authentication/oauth }
+ steps:
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+ with:
+ ref: ${{ github.ref }}
+ - uses: ruby/setup-ruby@95ef2b042f9d7a56d8268cba8559e2842e2ad01b # v1.321.0
+ with:
+ ruby-version: '3.4'
+ bundler-cache: true
+ bundler: 'latest'
+ cache-version: 1
+ working-directory: ${{ matrix.component.dir }}
+ - name: Run tests
+ working-directory: ${{ matrix.component.dir }}
+ run: bundle exec rake
+ - name: Publish ${{ matrix.component.name }} to RubyGems
+ working-directory: ${{ matrix.component.dir }}
run: |
mkdir -p $HOME/.gem
touch $HOME/.gem/credentials
diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml
index 86459b6..ade4cd7 100644
--- a/.github/workflows/ruby.yml
+++ b/.github/workflows/ruby.yml
@@ -7,37 +7,48 @@ on:
pull_request:
jobs:
+ lint:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+ - uses: ruby/setup-ruby@95ef2b042f9d7a56d8268cba8559e2842e2ad01b # v1.321.0
+ with:
+ ruby-version: '3.4'
+ bundler-cache: true
+ bundler: 'latest'
+ - name: Run rubocop
+ run: bundle exec rubocop
+
build:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
ruby-version: ['3.3', '3.4', '4.0', head, jruby, jruby-head, truffleruby, truffleruby-head]
+ component:
+ - { name: abstractions, dir: components/abstractions }
+ - { name: serialization-json, dir: components/serialization/json }
+ - { name: http, dir: components/http }
+ - { name: authentication-oauth, dir: components/authentication/oauth }
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: ruby/setup-ruby@95ef2b042f9d7a56d8268cba8559e2842e2ad01b # v1.321.0
with:
ruby-version: ${{ matrix.ruby-version }}
- bundler-cache: true # runs 'bundle install' and caches installed gems automatically
+ bundler-cache: true
bundler: 'latest'
cache-version: 2
- - name: Run tests
+ working-directory: ${{ matrix.component.dir }}
+ - name: Run tests for ${{ matrix.component.name }}
+ working-directory: ${{ matrix.component.dir }}
run: bundle exec rake
- - name: Upload artifacts for ruby version 3 and ubuntu
- if: ${{ matrix.os == 'ubuntu-latest' && matrix.ruby-version == '3.4'}}
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
- with:
- name: drop
- path: |
- ./Gemfile.lock
- ./README.md
# The check-ruby-version-matrix returns success if all matrix jobs in build are successful; otherwise, it returns a failure.
# Use this as a PR status check for GitHub Policy Service instead of individual matrix entry checks.
check-ruby-version-matrix:
runs-on: ubuntu-latest
- needs: [build]
+ needs: [lint, build]
if: always()
steps:
- name: All build matrix options are successful
diff --git a/.gitignore b/.gitignore
index 57ba118..1f25878 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,14 +1,14 @@
*.gem
*.rbc
-/.config
-/coverage/
-/InstalledFiles
-/pkg/
-/spec/reports/
-/spec/examples.txt
-/test/tmp/
-/test/version_tmp/
-/tmp/
+.config
+coverage/
+InstalledFiles
+pkg/
+spec/reports/
+spec/examples.txt
+test/tmp/
+test/version_tmp/
+tmp/
# Used by dotenv library to load environment variables.
# .env
@@ -33,15 +33,15 @@ build-iPhoneSimulator/
# vendor/Pods/
## Documentation cache and generated files:
-/.yardoc/
-/_yardoc/
-/doc/
-/rdoc/
+.yardoc/
+_yardoc/
+doc/
+rdoc/
## Environment normalization:
-/.bundle/
-/vendor/bundle
-/lib/bundler/man/
+.bundle/
+vendor/bundle
+lib/bundler/man/
# for a library or gem, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index bc7e4aa..7b51ca0 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.16.0"
+ ".": "0.17.0"
}
diff --git a/.rubocop.yml b/.rubocop.yml
new file mode 100644
index 0000000..50d9f8e
--- /dev/null
+++ b/.rubocop.yml
@@ -0,0 +1,12 @@
+inherit_from: .rubocop_todo.yml
+
+AllCops:
+ TargetRubyVersion: 3.3
+ NewCops: enable
+ SuggestExtensions: false
+
+Style/StringLiterals:
+ EnforcedStyle: single_quotes
+
+Style/FrozenStringLiteralComment:
+ Enabled: true
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
new file mode 100644
index 0000000..02f7e2b
--- /dev/null
+++ b/.rubocop_todo.yml
@@ -0,0 +1,189 @@
+# This configuration was generated by
+# `rubocop --auto-gen-config`
+# on 2026-08-21 15:03:46 UTC using RuboCop version 1.89.0.
+# The point is for the user to remove these configuration records
+# one by one as the offenses are removed from the code base.
+# Note that changes in the inspected code, or installation of new
+# versions of RuboCop, may require this file to be generated again.
+
+# Offense count: 12
+# Configuration parameters: EnforcedStyle, AllowedGems.
+# SupportedStyles: Gemfile, gems.rb, gemspec
+Gemspec/DevelopmentDependencies:
+ Exclude:
+ - 'components/abstractions/microsoft_kiota_abstractions.gemspec'
+ - 'components/authentication/oauth/microsoft_kiota_authentication_oauth.gemspec'
+ - 'components/http/microsoft_kiota_faraday.gemspec'
+ - 'components/serialization/json/microsoft_kiota_serialization_json.gemspec'
+
+# Offense count: 3
+# Configuration parameters: IgnoreLiteralBranches, IgnoreConstantBranches, IgnoreDuplicateElseBranch.
+Lint/DuplicateBranch:
+ Exclude:
+ - 'components/serialization/json/lib/microsoft_kiota_serialization_json/json_parse_node.rb'
+
+# Offense count: 2
+# Configuration parameters: DelegatingMethods.
+# DelegatingMethods: delegate
+Lint/DuplicateMethods:
+ Exclude:
+ - 'components/abstractions/lib/microsoft_kiota_abstractions/serialization/parse_node_factory_registry.rb'
+ - 'components/abstractions/lib/microsoft_kiota_abstractions/serialization/serialization_writer_factory_registry.rb'
+
+# Offense count: 2
+# Configuration parameters: AllowComments, AllowEmptyLambdas.
+Lint/EmptyBlock:
+ Exclude:
+ - 'components/abstractions/lib/microsoft_kiota_abstractions/authentication/anonymous_authentication_provider.rb'
+ - 'components/abstractions/lib/microsoft_kiota_abstractions/authentication/base_bearer_token_authentication_provider.rb'
+
+# Offense count: 3
+# Configuration parameters: AllowedParentClasses.
+Lint/MissingSuper:
+ Exclude:
+ - 'components/authentication/oauth/lib/microsoft_kiota_authentication_oauth/contexts/authorization_code_context.rb'
+ - 'components/authentication/oauth/lib/microsoft_kiota_authentication_oauth/contexts/client_credential_context.rb'
+ - 'components/authentication/oauth/lib/microsoft_kiota_authentication_oauth/contexts/on_behalf_of_context.rb'
+
+# Offense count: 1
+Lint/SharedMutableDefault:
+ Exclude:
+ - 'components/serialization/json/lib/microsoft_kiota_serialization_json/json_parse_node.rb'
+
+# Offense count: 17
+# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes.
+Metrics/AbcSize:
+ Max: 83
+
+# Offense count: 17
+# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
+# AllowedMethods: refine
+Metrics/BlockLength:
+ Max: 152
+
+# Offense count: 5
+# Configuration parameters: CountComments, CountAsOne.
+Metrics/ClassLength:
+ Max: 175
+
+# Offense count: 17
+# Configuration parameters: AllowedMethods, AllowedPatterns.
+Metrics/CyclomaticComplexity:
+ Max: 20
+
+# Offense count: 23
+# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
+Metrics/MethodLength:
+ Max: 61
+
+# Offense count: 11
+# Configuration parameters: AllowedMethods, AllowedPatterns.
+Metrics/PerceivedComplexity:
+ Max: 18
+
+# Offense count: 60
+Naming/AccessorMethodName:
+ Enabled: false
+
+# Offense count: 1
+Naming/ConstantName:
+ Exclude:
+ - 'components/serialization/json/spec/files/body_type.rb'
+
+# Offense count: 2
+# Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames.
+# AllowedNames: as, at, by, cc, db, id, if, in, io, ip, of, on, os, pp, to
+Naming/MethodParameterName:
+ Exclude:
+ - 'components/abstractions/lib/microsoft_kiota_abstractions/request_information.rb'
+
+# Offense count: 1
+# Configuration parameters: Mode, AllowedMethods, AllowedPatterns, AllowBangMethods, WaywardPredicates.
+# AllowedMethods: call
+# WaywardPredicates: infinite?, nonzero?
+Naming/PredicateMethod:
+ Exclude:
+ - 'components/abstractions/lib/microsoft_kiota_abstractions/request_headers.rb'
+
+# Offense count: 1
+Security/Eval:
+ Exclude:
+ - 'components/abstractions/lib/microsoft_kiota_abstractions/request_information.rb'
+
+# Offense count: 6
+Style/ClassVars:
+ Exclude:
+ - 'components/abstractions/lib/microsoft_kiota_abstractions/request_information.rb'
+ - 'components/http/lib/microsoft_kiota_faraday/middleware/parameters_name_decoding_handler.rb'
+ - 'components/http/lib/microsoft_kiota_faraday/middleware/user_agent_handler.rb'
+
+# Offense count: 1
+Style/DocumentDynamicEvalDefinition:
+ Exclude:
+ - 'components/abstractions/lib/microsoft_kiota_abstractions/request_information.rb'
+
+# Offense count: 53
+# Configuration parameters: AllowedConstants.
+Style/Documentation:
+ Enabled: false
+
+# Offense count: 1
+# This cop supports safe autocorrection (--autocorrect).
+Style/EvalWithLocation:
+ Exclude:
+ - 'components/abstractions/lib/microsoft_kiota_abstractions/request_information.rb'
+
+# Offense count: 2
+Style/FileOpen:
+ Exclude:
+ - 'components/serialization/json/spec/microsoft_kiota_serialization_json_spec.rb'
+
+# Offense count: 3
+# This cop supports safe autocorrection (--autocorrect).
+# Configuration parameters: MinBodyLength, AllowConsecutiveConditionals.
+Style/GuardClause:
+ Exclude:
+ - 'components/authentication/oauth/lib/microsoft_kiota_authentication_oauth/contexts/authorization_code_context.rb'
+ - 'components/authentication/oauth/lib/microsoft_kiota_authentication_oauth/contexts/client_credential_context.rb'
+ - 'components/authentication/oauth/lib/microsoft_kiota_authentication_oauth/contexts/on_behalf_of_context.rb'
+
+# Offense count: 15
+# This cop supports safe autocorrection (--autocorrect).
+Style/IfUnlessModifier:
+ Exclude:
+ - 'components/abstractions/lib/microsoft_kiota_abstractions/request_headers.rb'
+ - 'components/abstractions/lib/microsoft_kiota_abstractions/request_information.rb'
+ - 'components/authentication/oauth/lib/microsoft_kiota_authentication_oauth/contexts/authorization_code_context.rb'
+ - 'components/authentication/oauth/lib/microsoft_kiota_authentication_oauth/contexts/client_credential_context.rb'
+ - 'components/authentication/oauth/lib/microsoft_kiota_authentication_oauth/contexts/on_behalf_of_context.rb'
+ - 'components/http/lib/microsoft_kiota_faraday/faraday_request_adapter.rb'
+ - 'components/http/lib/microsoft_kiota_faraday/kiota_client_factory.rb'
+ - 'components/http/lib/microsoft_kiota_faraday/middleware/parameters_name_decoding_handler.rb'
+ - 'components/http/lib/microsoft_kiota_faraday/middleware/user_agent_handler.rb'
+
+# Offense count: 1
+# Configuration parameters: AllowedClasses.
+Style/OneClassPerFile:
+ Exclude:
+ - 'spec/**/*'
+ - 'test/**/*'
+ - 'components/authentication/oauth/lib/microsoft_kiota_authentication_oauth/extensions/oauth2_ext.rb'
+
+# Offense count: 1
+Style/OptionalArguments:
+ Exclude:
+ - 'components/abstractions/lib/microsoft_kiota_abstractions/request_information.rb'
+
+# Offense count: 1
+# Configuration parameters: AllowedMethods.
+# AllowedMethods: respond_to_missing?
+Style/OptionalBooleanParameter:
+ Exclude:
+ - 'components/http/lib/microsoft_kiota_faraday/middleware/parameters_name_decoding_option.rb'
+
+# Offense count: 55
+# This cop supports safe autocorrection (--autocorrect).
+# Configuration parameters: AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, AllowRBSInlineAnnotation, AllowCopDirectives, AllowedPatterns, SplitStrings.
+# URISchemes: http, https
+Layout/LineLength:
+ Max: 373
diff --git a/Gemfile b/Gemfile
index c6f618d..aa8a008 100644
--- a/Gemfile
+++ b/Gemfile
@@ -2,5 +2,11 @@
source 'https://rubygems.org'
-# Specify your gem's dependencies in microsoft_kiota_abstractions.gemspec
-gemspec
+gem 'microsoft_kiota_abstractions', path: 'components/abstractions'
+gem 'microsoft_kiota_authentication_oauth', path: 'components/authentication/oauth'
+gem 'microsoft_kiota_faraday', path: 'components/http'
+gem 'microsoft_kiota_serialization_json', path: 'components/serialization/json'
+
+gem 'rake', '~> 13.0'
+gem 'rspec', '~> 3.0'
+gem 'rubocop'
diff --git a/README.md b/README.md
index 53a906e..1810538 100644
--- a/README.md
+++ b/README.md
@@ -1,32 +1,53 @@
-# Kiota Abstractions Library for Ruby
+# Kiota SDK for Ruby
-
+
-The Kiota abstractions Library for go is the go library defining the basic constructs Kiota projects need once an SDK has been generated from an OpenAPI definition.
+This repository contains the Ruby libraries for [Kiota](https://github.com/microsoft/kiota)-generated API clients.
-A [Kiota](https://github.com/microsoft/kiota) generated project will need a reference to the abstraction package to build and run.
+## Components
-Read more about Kiota [here](https://github.com/microsoft/kiota/blob/main/README.md).
+| Gem | Description | RubyGems |
+|-----|-------------|----------|
+| [microsoft_kiota_abstractions](components/abstractions/) | Core abstractions for Kiota-generated clients | [](https://rubygems.org/gems/microsoft_kiota_abstractions) |
+| [microsoft_kiota_serialization_json](components/serialization/json/) | JSON serialization implementation | [](https://rubygems.org/gems/microsoft_kiota_serialization_json) |
+| [microsoft_kiota_faraday](components/http/) | HTTP client implementation with Faraday | [](https://rubygems.org/gems/microsoft_kiota_faraday) |
+| [microsoft_kiota_authentication_oauth](components/authentication/oauth/) | OAuth authentication provider | [](https://rubygems.org/gems/microsoft_kiota_authentication_oauth) |
-## Using the abstractions library
+## Installation
-Add this line to your application's Gemfile:
+Add the gems you need to your application's Gemfile:
```ruby
-gem "microsoft_kiota_abstractions", "0.12.0"
+gem 'microsoft_kiota_abstractions'
+gem 'microsoft_kiota_serialization_json'
+gem 'microsoft_kiota_faraday'
+gem 'microsoft_kiota_authentication_oauth'
```
-And then execute:
+## Development
```shell
+git clone https://github.com/microsoft/kiota-ruby.git
+cd kiota-ruby
bundle install
+rake spec # run all tests
+rake rubocop # run linter
```
-Or install it yourself as:
+To run tests for a specific component:
- ```shell
-gem install microsoft_kiota_abstractions --version "0.12.0"
- ```
+```shell
+rake abstractions:spec
+rake serialization-json:spec
+rake http:spec
+rake authentication-oauth:spec
+```
+
+To auto-fix formatting issues:
+
+```shell
+bundle exec rubocop -a
+```
## Contributing
@@ -44,8 +65,8 @@ contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additio
## Trademarks
-This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft
-trademarks or logos is subject to and must follow
+This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft
+trademarks or logos is subject to and must follow
[Microsoft's Trademark & Brand Guidelines](https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks/usage/general).
Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship.
Any use of third-party trademarks or logos are subject to those third-party's policies.
diff --git a/Rakefile b/Rakefile
index b6ae734..1f2c3f9 100644
--- a/Rakefile
+++ b/Rakefile
@@ -1,8 +1,51 @@
# frozen_string_literal: true
-require "bundler/gem_tasks"
-require "rspec/core/rake_task"
+COMPONENTS = {
+ 'abstractions' => 'components/abstractions',
+ 'serialization-json' => 'components/serialization/json',
+ 'http' => 'components/http',
+ 'authentication-oauth' => 'components/authentication/oauth'
+}.freeze
-RSpec::Core::RakeTask.new(:spec)
+def run_in_component(dir, command)
+ Dir.chdir(dir) do
+ sh 'bundle install --quiet' unless ENV['CI']
+ sh command
+ end
+end
+
+COMPONENTS.each do |name, path|
+ namespace name do
+ desc "Run specs for #{name}"
+ task :spec do
+ run_in_component(path, 'bundle exec rake spec')
+ end
+
+ desc "Build gem for #{name}"
+ task :build do
+ run_in_component(path, 'bundle exec rake build')
+ end
+ end
+end
+
+desc 'Run all component specs'
+task :spec do
+ COMPONENTS.each do |name, path|
+ puts "\n=== Running specs for #{name} ==="
+ run_in_component(path, 'bundle exec rake spec')
+ end
+end
+
+desc 'Build all gems'
+task :build do
+ COMPONENTS.each do |name, path|
+ puts "\n=== Building #{name} ==="
+ run_in_component(path, 'bundle exec rake build')
+ end
+end
+
+require 'rubocop/rake_task'
+
+RuboCop::RakeTask.new(:rubocop)
task default: :spec
diff --git a/components/abstractions/Gemfile b/components/abstractions/Gemfile
new file mode 100644
index 0000000..c6f618d
--- /dev/null
+++ b/components/abstractions/Gemfile
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+
+source 'https://rubygems.org'
+
+# Specify your gem's dependencies in microsoft_kiota_abstractions.gemspec
+gemspec
diff --git a/components/abstractions/Rakefile b/components/abstractions/Rakefile
new file mode 100644
index 0000000..82bb534
--- /dev/null
+++ b/components/abstractions/Rakefile
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+require 'bundler/gem_tasks'
+require 'rspec/core/rake_task'
+
+RSpec::Core::RakeTask.new(:spec)
+
+task default: :spec
diff --git a/components/abstractions/lib/microsoft_kiota_abstractions.rb b/components/abstractions/lib/microsoft_kiota_abstractions.rb
new file mode 100644
index 0000000..d7147e6
--- /dev/null
+++ b/components/abstractions/lib/microsoft_kiota_abstractions.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+require_relative 'microsoft_kiota_abstractions/authentication/authentication_provider'
+require_relative 'microsoft_kiota_abstractions/authentication/base_bearer_token_authentication_provider'
+require_relative 'microsoft_kiota_abstractions/authentication/anonymous_authentication_provider'
+require_relative 'microsoft_kiota_abstractions/api_error'
+require_relative 'microsoft_kiota_abstractions/http_method'
+require_relative 'microsoft_kiota_abstractions/base_request_builder'
+require_relative 'microsoft_kiota_abstractions/api_client_builder'
+require_relative 'microsoft_kiota_abstractions/request_adapter'
+require_relative 'microsoft_kiota_abstractions/request_configuration'
+require_relative 'microsoft_kiota_abstractions/request_option'
+require_relative 'microsoft_kiota_abstractions/request_headers'
+require_relative 'microsoft_kiota_abstractions/request_information'
+require_relative 'microsoft_kiota_abstractions/version'
+require_relative 'microsoft_kiota_abstractions/serialization/parsable'
+require_relative 'microsoft_kiota_abstractions/serialization/iso_duration'
+require_relative 'microsoft_kiota_abstractions/serialization/additional_data_holder'
+require_relative 'microsoft_kiota_abstractions/serialization/parse_node'
+require_relative 'microsoft_kiota_abstractions/serialization/parse_node_factory'
+require_relative 'microsoft_kiota_abstractions/serialization/parse_node_factory_registry'
+require_relative 'microsoft_kiota_abstractions/serialization/serialization_writer'
+require_relative 'microsoft_kiota_abstractions/serialization/serialization_writer_factory'
+require_relative 'microsoft_kiota_abstractions/serialization/serialization_writer_factory_registry'
+require_relative 'microsoft_kiota_abstractions/serialization/composed_type_wrapper'
+require_relative 'microsoft_kiota_abstractions/serialization/parse_node_helper'
+
+module MicrosoftKiotaAbstractions
+end
diff --git a/lib/microsoft_kiota_abstractions/api_client_builder.rb b/components/abstractions/lib/microsoft_kiota_abstractions/api_client_builder.rb
similarity index 52%
rename from lib/microsoft_kiota_abstractions/api_client_builder.rb
rename to components/abstractions/lib/microsoft_kiota_abstractions/api_client_builder.rb
index 7cd6079..21d08e1 100644
--- a/lib/microsoft_kiota_abstractions/api_client_builder.rb
+++ b/components/abstractions/lib/microsoft_kiota_abstractions/api_client_builder.rb
@@ -1,19 +1,22 @@
-require_relative "serialization/parse_node_factory"
-require_relative "serialization/parse_node_factory_registry"
-require_relative "serialization/serialization_writer_factory"
-require_relative "serialization/serialization_writer_factory_registry"
+# frozen_string_literal: true
+
+require_relative 'serialization/parse_node_factory'
+require_relative 'serialization/parse_node_factory_registry'
+require_relative 'serialization/serialization_writer_factory'
+require_relative 'serialization/serialization_writer_factory_registry'
module MicrosoftKiotaAbstractions
class ApiClientBuilder
def self.register_default_serializer(factory_class)
- factory = factory_class.new()
- MicrosoftKiotaAbstractions::SerializationWriterFactoryRegistry.default_instance.content_type_associated_factories[factory.get_valid_content_type()] = factory
+ factory = factory_class.new
+ MicrosoftKiotaAbstractions::SerializationWriterFactoryRegistry.default_instance.content_type_associated_factories[factory.get_valid_content_type] =
+ factory
end
def self.register_default_deserializer(factory_class)
- factory = factory_class.new()
- MicrosoftKiotaAbstractions::ParseNodeFactoryRegistry.default_instance.content_type_associated_factories[factory.get_valid_content_type()] = factory
+ factory = factory_class.new
+ MicrosoftKiotaAbstractions::ParseNodeFactoryRegistry.default_instance.content_type_associated_factories[factory.get_valid_content_type] =
+ factory
end
end
end
-
diff --git a/components/abstractions/lib/microsoft_kiota_abstractions/api_error.rb b/components/abstractions/lib/microsoft_kiota_abstractions/api_error.rb
new file mode 100644
index 0000000..ebc5a69
--- /dev/null
+++ b/components/abstractions/lib/microsoft_kiota_abstractions/api_error.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require_relative 'serialization/parsable'
+module MicrosoftKiotaAbstractions
+ class ApiError < StandardError
+ include MicrosoftKiotaAbstractions::Parsable
+
+ ##
+ ## The deserialization information for the current model
+ ## @return a i_dictionary
+ ##
+ def get_field_deserializers
+ {}
+ end
+
+ ##
+ ## Serializes information the current object
+ ## @param writer Serialization writer to use to serialize this model
+ ## @return a void
+ ##
+ def serialize(writer)
+ raise StandardError, 'writer cannot be null' if writer.nil?
+ end
+ end
+end
diff --git a/lib/microsoft_kiota_abstractions/authentication/access_token_provider.rb b/components/abstractions/lib/microsoft_kiota_abstractions/authentication/access_token_provider.rb
similarity index 76%
rename from lib/microsoft_kiota_abstractions/authentication/access_token_provider.rb
rename to components/abstractions/lib/microsoft_kiota_abstractions/authentication/access_token_provider.rb
index ad3df83..aa356f1 100644
--- a/lib/microsoft_kiota_abstractions/authentication/access_token_provider.rb
+++ b/components/abstractions/lib/microsoft_kiota_abstractions/authentication/access_token_provider.rb
@@ -7,14 +7,13 @@ module MicrosoftKiotaAbstractions
module AccessTokenProvider
# This function obtains the authorization token.
# :params
- # uri: a string containing the uri
+ # uri: a string containing the uri
# additional_params: hash of symbols to string values, ie { response_mode: 'fragment', prompt: 'login' }
# default is empty hash
- def get_authorization_token(uri, additional_properties = {})
- raise NotImplementedError.new
+ def get_authorization_token(_uri, _additional_properties = {})
+ raise NotImplementedError
end
attr_accessor :scopes, :host_validator
-
end
end
diff --git a/lib/microsoft_kiota_abstractions/authentication/allowed_hosts_validator.rb b/components/abstractions/lib/microsoft_kiota_abstractions/authentication/allowed_hosts_validator.rb
similarity index 99%
rename from lib/microsoft_kiota_abstractions/authentication/allowed_hosts_validator.rb
rename to components/abstractions/lib/microsoft_kiota_abstractions/authentication/allowed_hosts_validator.rb
index 72379ea..f912e51 100644
--- a/lib/microsoft_kiota_abstractions/authentication/allowed_hosts_validator.rb
+++ b/components/abstractions/lib/microsoft_kiota_abstractions/authentication/allowed_hosts_validator.rb
@@ -24,11 +24,10 @@ def url_host_valid?(url)
parsed_url = URI(url)
return false if parsed_url.host.nil?
-
+
return false unless parsed_url.is_a?(URI::HTTPS)
@allowed_hosts.key? parsed_url.host.downcase
-
rescue URI::InvalidURIError
false
end
diff --git a/lib/microsoft_kiota_abstractions/authentication/anonymous_authentication_provider.rb b/components/abstractions/lib/microsoft_kiota_abstractions/authentication/anonymous_authentication_provider.rb
similarity index 74%
rename from lib/microsoft_kiota_abstractions/authentication/anonymous_authentication_provider.rb
rename to components/abstractions/lib/microsoft_kiota_abstractions/authentication/anonymous_authentication_provider.rb
index 8c0747a..208a304 100644
--- a/lib/microsoft_kiota_abstractions/authentication/anonymous_authentication_provider.rb
+++ b/components/abstractions/lib/microsoft_kiota_abstractions/authentication/anonymous_authentication_provider.rb
@@ -1,10 +1,13 @@
+# frozen_string_literal: true
+
module MicrosoftKiotaAbstractions
class AnonymousAuthenticationProvider
include MicrosoftKiotaAbstractions::AuthenticationProvider
- def authenticate_request(request, additional_properties = {})
+
+ def authenticate_request(_request, _additional_properties = {})
# return an empty Fiber - all other authentication providers do the same, and the FaradayRequestAdapter requires it.
Fiber.new do
end
end
end
-end
\ No newline at end of file
+end
diff --git a/components/abstractions/lib/microsoft_kiota_abstractions/authentication/authentication_provider.rb b/components/abstractions/lib/microsoft_kiota_abstractions/authentication/authentication_provider.rb
new file mode 100644
index 0000000..2c79499
--- /dev/null
+++ b/components/abstractions/lib/microsoft_kiota_abstractions/authentication/authentication_provider.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+module MicrosoftKiotaAbstractions
+ module AuthenticationProvider
+ def authenticate_request(_request, _additional_properties = {})
+ raise NotImplementedError
+ end
+ end
+end
diff --git a/lib/microsoft_kiota_abstractions/authentication/base_bearer_token_authentication_provider.rb b/components/abstractions/lib/microsoft_kiota_abstractions/authentication/base_bearer_token_authentication_provider.rb
similarity index 92%
rename from lib/microsoft_kiota_abstractions/authentication/base_bearer_token_authentication_provider.rb
rename to components/abstractions/lib/microsoft_kiota_abstractions/authentication/base_bearer_token_authentication_provider.rb
index e03fe92..6d476d0 100644
--- a/lib/microsoft_kiota_abstractions/authentication/base_bearer_token_authentication_provider.rb
+++ b/components/abstractions/lib/microsoft_kiota_abstractions/authentication/base_bearer_token_authentication_provider.rb
@@ -1,17 +1,18 @@
# frozen_string_literal: true
-require_relative './authentication_provider'
-require_relative './access_token_provider'
+require_relative 'authentication_provider'
+require_relative 'access_token_provider'
module MicrosoftKiotaAbstractions
# Provides a base class for implementing AuthenticationProvider for Bearer token scheme
class BaseBearerTokenAuthenticationProvider
include MicrosoftKiotaAbstractions::AuthenticationProvider
+
def initialize(access_token_provider)
raise StandardError, 'access_token_provider parameter cannot be nil' if access_token_provider.nil?
@access_token_provider = access_token_provider
- end
+ end
AUTHORIZATION_HEADER_KEY = 'Authorization'
def authenticate_request(request, additional_properties = {})
diff --git a/components/abstractions/lib/microsoft_kiota_abstractions/base_request_builder.rb b/components/abstractions/lib/microsoft_kiota_abstractions/base_request_builder.rb
new file mode 100644
index 0000000..46a8b54
--- /dev/null
+++ b/components/abstractions/lib/microsoft_kiota_abstractions/base_request_builder.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module MicrosoftKiotaAbstractions
+ ##
+ # Base class for request builders. Performs basic validation and defines common properties.
+ class BaseRequestBuilder
+ ##
+ # Path parameters for the request
+ ##
+ # The request adapter to use to execute the requests.
+ ##
+ # Url template to use to build the URL for the current request builder
+ ##
+ ## Instantiates a new BaseRequestBuilder and sets the default values.
+ ## @param path_parameters Path parameters for the request
+ ## @param request_adapter The request adapter to use to execute the requests.
+ ## @param url_template Url template to use to build the URL for the current request builder
+ ## @return a void
+ ##
+ def initialize(path_parameters, request_adapter, url_template)
+ raise StandardError, 'request_adapter cannot be null' if request_adapter.nil?
+ raise StandardError, 'url_template cannot be null' if url_template.nil? || url_template.empty?
+
+ @request_adapter = request_adapter
+ unless path_parameters.nil?
+ if path_parameters.is_a? Hash
+ @path_parameters = path_parameters.clone
+ elsif path_parameters.is_a? String
+ @path_parameters = { 'request-raw-url' => path_parameters }
+ end
+ end
+ @path_parameters = {} if path_parameters.nil?
+ @url_template = url_template
+ end
+ end
+end
diff --git a/lib/microsoft_kiota_abstractions/http_method.rb b/components/abstractions/lib/microsoft_kiota_abstractions/http_method.rb
similarity index 85%
rename from lib/microsoft_kiota_abstractions/http_method.rb
rename to components/abstractions/lib/microsoft_kiota_abstractions/http_method.rb
index ed7b913..9b1a95d 100644
--- a/lib/microsoft_kiota_abstractions/http_method.rb
+++ b/components/abstractions/lib/microsoft_kiota_abstractions/http_method.rb
@@ -1,6 +1,7 @@
+# frozen_string_literal: true
+
module MicrosoftKiotaAbstractions
module HttpMethod
-
HTTP_METHOD = {
GET: :GET,
POST: :POST,
@@ -11,7 +12,6 @@ module HttpMethod
PUT: :PUT,
TRACE: :TRACE,
HEAD: :HEAD
- }
-
- end
+ }.freeze
end
+end
diff --git a/components/abstractions/lib/microsoft_kiota_abstractions/request_adapter.rb b/components/abstractions/lib/microsoft_kiota_abstractions/request_adapter.rb
new file mode 100644
index 0000000..0888674
--- /dev/null
+++ b/components/abstractions/lib/microsoft_kiota_abstractions/request_adapter.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+require_relative 'request_information'
+
+module MicrosoftKiotaAbstractions
+ module RequestAdapter
+ def send_async(_request_info, _factory, _errors_mapping)
+ raise NotImplementedError
+ end
+
+ # TODO: we're most likley missing something for enums and collections or at least at the implemenation level
+
+ def get_serialization_writer_factory
+ raise NotImplementedError
+ end
+
+ def set_base_url(_base_url)
+ raise NotImplementedError
+ end
+
+ def get_base_url
+ raise NotImplementedError
+ end
+
+ # Converts the given RequestInformation into a native HTTP request.
+ def convert_to_native_request_async(_request_info)
+ raise NotImplementedError
+ end
+ end
+end
diff --git a/components/abstractions/lib/microsoft_kiota_abstractions/request_configuration.rb b/components/abstractions/lib/microsoft_kiota_abstractions/request_configuration.rb
new file mode 100644
index 0000000..f8f44ee
--- /dev/null
+++ b/components/abstractions/lib/microsoft_kiota_abstractions/request_configuration.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+require_relative 'request_headers'
+
+module MicrosoftKiotaAbstractions
+ ##
+ # Configuration for the request such as headers, query parameters, and middleware options.
+ class RequestConfiguration
+ ##
+ # Request headers
+ attr_accessor :headers
+ ##
+ # Request options
+ attr_accessor :options
+ ##
+ # Request query parameters
+ attr_accessor :query_parameters
+
+ def initialize
+ @headers = RequestHeaders.new
+ @options = []
+ end
+ end
+end
diff --git a/components/abstractions/lib/microsoft_kiota_abstractions/request_headers.rb b/components/abstractions/lib/microsoft_kiota_abstractions/request_headers.rb
new file mode 100644
index 0000000..c417215
--- /dev/null
+++ b/components/abstractions/lib/microsoft_kiota_abstractions/request_headers.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+module MicrosoftKiotaAbstractions
+ class RequestHeaders
+ def initialize
+ @headers = {}
+ end
+
+ def add(key, value)
+ if key.nil? || key.empty? || value.nil? || value.empty?
+ raise ArgumentError, 'key and value cannot be nil or empty'
+ end
+
+ existing_value = @headers[key]
+ if existing_value.nil?
+ @headers[key] = if value.is_a?(Array)
+ value
+ else
+ [value.to_s]
+ end
+ elsif value.is_a?(Array)
+ @headers[key] = existing_value | value
+ else
+ existing_value << value.to_s
+ end
+ end
+
+ def try_add(key, value)
+ if key.nil? || key.empty? || value.nil? || value.empty?
+ raise ArgumentError, 'key and value cannot be nil or empty'
+ end
+
+ existing_value = @headers[key]
+ return false unless existing_value.nil? || existing_value.empty?
+
+ @headers[key] = [value.to_s]
+ true
+ end
+
+ def get(key)
+ raise ArgumentError, 'key cannot be nil or empty' if key.nil? || key.empty?
+
+ @headers[key]
+ end
+
+ def remove(key)
+ raise ArgumentError, 'key cannot be nil or empty' if key.nil? || key.empty?
+
+ @headers.delete(key)
+ end
+
+ def clear
+ @headers.clear
+ end
+
+ def get_all
+ @headers
+ end
+ end
+end
diff --git a/components/abstractions/lib/microsoft_kiota_abstractions/request_information.rb b/components/abstractions/lib/microsoft_kiota_abstractions/request_information.rb
new file mode 100644
index 0000000..8ef6d40
--- /dev/null
+++ b/components/abstractions/lib/microsoft_kiota_abstractions/request_information.rb
@@ -0,0 +1,120 @@
+# frozen_string_literal: true
+
+require 'uri'
+require 'stduritemplate'
+require_relative 'http_method'
+require_relative 'request_headers'
+
+module MicrosoftKiotaAbstractions
+ class RequestInformation
+ attr_reader :content, :http_method, :headers
+ attr_accessor :url_template, :path_parameters, :query_parameters
+
+ @@binary_content_type = 'application/octet-stream'
+ @@content_type_header = 'Content-Type'
+ @@raw_url_key = 'request-raw-url'
+
+ def initialize
+ @headers = RequestHeaders.new
+ @query_parameters = {}
+ @path_parameters = {}
+ end
+
+ def uri=(arg)
+ raise ArgumentError, 'arg cannot be nil or empty' if arg.nil? || arg.empty?
+
+ path_parameters.clear
+ query_parameters.clear
+ @uri = URI(arg)
+ end
+
+ def uri
+ return @uri unless @uri.nil?
+
+ if path_parameters[@@raw_url_key].nil?
+ return URI(StdUriTemplate.expand(@url_template, path_parameters.merge(query_parameters)))
+ end
+
+ self.uri = path_parameters[@@raw_url_key]
+ @uri
+ end
+
+ def add_request_options(request_options_to_add)
+ return if request_options_to_add.nil?
+
+ @request_options ||= {}
+ request_options_to_add = [request_options_to_add] unless request_options_to_add.is_a?(Array)
+ request_options_to_add.each do |request_option|
+ key = request_option.get_key
+ @request_options[key] = request_option
+ end
+ end
+
+ def get_request_options
+ return [] if @request_options.nil?
+
+ @request_options.values
+ end
+
+ def get_request_option(key)
+ return nil if @request_options.nil? || key.nil? || key.empty?
+
+ @request_options[key]
+ end
+
+ def remove_request_options(keys)
+ return if keys.nil? || @request_options.nil?
+
+ keys = [keys] unless keys.is_a?(Array)
+ keys.each do |key|
+ @request_options.delete(key)
+ end
+ end
+
+ def http_method=(method)
+ @http_method = HttpMethod::HTTP_METHOD[method]
+ end
+
+ def set_stream_content(value = $stdin, content_type)
+ @content = value
+ content_type = @@binary_content_type if content_type.nil? || content_type.empty?
+ @headers.try_add(@@content_type_header, content_type)
+ end
+
+ def set_content_from_parsable(request_adapter, content_type, values)
+ writer = request_adapter.get_serialization_writer_factory.get_serialization_writer(content_type)
+ @headers.try_add(@@content_type_header, content_type)
+ if !values.nil? && values.is_a?(Array)
+ writer.write_collection_of_object_values(nil, values)
+ else
+ writer.write_object_value(nil, values)
+ end
+ @content = writer.get_serialized_content
+ rescue StandardError
+ raise StandardError, 'could not serialize payload'
+ end
+
+ def add_headers_from_raw_object(h)
+ h&.get_all&.select { |x, y| @headers.add(x.to_s, y) }
+ end
+
+ def set_query_string_parameters_from_raw_object(q)
+ return if !q || q.is_a?(Hash) || q.is_a?(Array)
+
+ q.class.instance_methods(false).select do |x|
+ method_name = x.to_s
+ if method_name == 'compare_by_identity' || method_name == 'get_query_parameter' || method_name.end_with?('=') || method_name.end_with?('?') || method_name.end_with?('!')
+ next
+ end
+
+ begin
+ key = q.get_query_parameter(method_name)
+ rescue StandardError
+ key = method_name
+ end
+ value = eval("q.#{method_name}")
+ query_parameters[key] = value unless value.nil?
+ end
+ end
+ end
+end
diff --git a/components/abstractions/lib/microsoft_kiota_abstractions/request_option.rb b/components/abstractions/lib/microsoft_kiota_abstractions/request_option.rb
new file mode 100644
index 0000000..43284da
--- /dev/null
+++ b/components/abstractions/lib/microsoft_kiota_abstractions/request_option.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+module MicrosoftKiotaAbstractions
+ module RequestOption
+ def get_key
+ raise NotImplementedError
+ end
+ end
+end
diff --git a/components/abstractions/lib/microsoft_kiota_abstractions/serialization/additional_data_holder.rb b/components/abstractions/lib/microsoft_kiota_abstractions/serialization/additional_data_holder.rb
new file mode 100644
index 0000000..7f819cb
--- /dev/null
+++ b/components/abstractions/lib/microsoft_kiota_abstractions/serialization/additional_data_holder.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+module MicrosoftKiotaAbstractions
+ module AdditionalDataHolder
+ def additional_data
+ @additional_data ||= {}
+ end
+ end
+end
diff --git a/lib/microsoft_kiota_abstractions/serialization/composed_type_wrapper.rb b/components/abstractions/lib/microsoft_kiota_abstractions/serialization/composed_type_wrapper.rb
similarity index 70%
rename from lib/microsoft_kiota_abstractions/serialization/composed_type_wrapper.rb
rename to components/abstractions/lib/microsoft_kiota_abstractions/serialization/composed_type_wrapper.rb
index 278b8c0..6880ba9 100644
--- a/lib/microsoft_kiota_abstractions/serialization/composed_type_wrapper.rb
+++ b/components/abstractions/lib/microsoft_kiota_abstractions/serialization/composed_type_wrapper.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module MicrosoftKiotaAbstractions
module ComposedTypeWrapper
end
diff --git a/components/abstractions/lib/microsoft_kiota_abstractions/serialization/iso_duration.rb b/components/abstractions/lib/microsoft_kiota_abstractions/serialization/iso_duration.rb
new file mode 100644
index 0000000..d2a840a
--- /dev/null
+++ b/components/abstractions/lib/microsoft_kiota_abstractions/serialization/iso_duration.rb
@@ -0,0 +1,210 @@
+# frozen_string_literal: true
+
+require 'iso8601'
+
+module MicrosoftKiotaAbstractions
+ # Wrapper Class for ISO8601::Duration
+ # Integer support for :years, :months, :weeks, :days, :hours, :minutes, :seconds
+ # Initialize with a hash of symbols to integers eg { :years => 3, :days => 4, seconds: => 2}
+ # or with an ISO8601 formated string eg "PT3H12M5S".
+ class ISODuration
+ attr_reader :years, :months, :weeks, :days, :hours, :minutes, :seconds
+
+ UNITS = { years: 'Y',
+ months: 'M',
+ weeks: 'W',
+ days: 'D',
+ hours: 'H',
+ minutes: 'M',
+ seconds: 'S' }.freeze
+
+ CONVERSIONS = {
+ ms_to_s: 1000,
+ s_to_m: 60,
+ m_to_h: 60,
+ h_to_d: 24,
+ d_to_w: 7,
+ m_to_y: 12
+ }.freeze
+ def initialize(input)
+ if input.is_a? String
+ @duration_obj = ISO8601::Duration.new(input)
+ elsif input.is_a? Hash
+ @duration_obj = parse_hash(input)
+ else
+ raise StandardError, 'Must provide initialize ISODuration by providing a hash or an ISO8601-formatted string.'
+ end
+ update_member_variables
+ normalize
+ end
+
+ def string
+ input = { seconds: @seconds, minutes: @minutes, hours: @hours,
+ days: @days, weeks: @weeks, months: @months,
+ years: @years }
+ iso_str = 'P'
+ UNITS.each do |unit, abrev|
+ iso_str += input[unit].to_s + abrev unless input[unit].zero?
+ iso_str += 'T' if unit == :days
+ end
+ iso_str = iso_str.strip
+ iso_str = iso_str.chomp('T') if iso_str[-1].eql? 'T'
+ iso_str
+ end
+
+ def normalize
+ if @seconds >= CONVERSIONS[:s_to_m]
+ @minutes += (@seconds / CONVERSIONS[:s_to_m]).floor
+ @seconds %= CONVERSIONS[:s_to_m]
+ end
+ if @minutes >= CONVERSIONS[:m_to_h]
+ @hours += (@minutes / CONVERSIONS[:m_to_h]).floor
+ @minutes %= CONVERSIONS[:m_to_h]
+ end
+ if @hours >= CONVERSIONS[:h_to_d]
+ @days += (@hours / CONVERSIONS[:h_to_d]).floor
+ @hours %= CONVERSIONS[:h_to_d]
+ end
+ if @days >= CONVERSIONS[:d_to_w] && @months.zero? && @years.zero?
+ @weeks += (@days / CONVERSIONS[:d_to_w]).floor
+ @days %= CONVERSIONS[:d_to_w]
+ end
+ return unless @months > CONVERSIONS[:m_to_y]
+
+ @years += (@months / CONVERSIONS[:m_to_y]).floor
+ @months %= CONVERSIONS[:m_to_y]
+ end
+
+ def seconds=(value)
+ input = { seconds: value, minutes: @minutes, hours: @hours,
+ days: @days, weeks: @weeks, months: @months,
+ years: @years }
+ @duration_obj = parse_hash(input)
+ @seconds = value
+ normalize
+ end
+
+ def minutes=(value)
+ input = { seconds: @seconds, minutes: value, hours: @hours,
+ days: @days, weeks: @weeks, months: @months,
+ years: @years }
+ @duration_obj = parse_hash(input)
+ @minutes = value
+ normalize
+ end
+
+ def hours=(value)
+ input = { seconds: @seconds, minutes: @minutes, hours: value,
+ days: @days, weeks: @weeks, months: @months,
+ years: @years }
+ @duration_obj = parse_hash(input)
+ @hours = value
+ normalize
+ end
+
+ def days=(value)
+ input = { seconds: @seconds, minutes: @minutes, hours: @hours,
+ days: value, weeks: @weeks, months: @months,
+ years: @years }
+ @duration_obj = parse_hash(input)
+ @days = value
+ normalize
+ end
+
+ def weeks=(value)
+ input = { seconds: @seconds, minutes: @minutes, hours: @hours,
+ days: @days, weeks: value, months: @months,
+ years: @years }
+ @duration_obj = parse_hash(input)
+ @weeks = value
+ normalize
+ end
+
+ def months=(value)
+ input = { seconds: @seconds, minutes: @minutes, hours: @hours,
+ days: @days, weeks: @weeks, months: value,
+ years: @years }
+ @duration_obj = parse_hash(input)
+ @months = value
+ normalize
+ end
+
+ def years=(value)
+ input = { seconds: @seconds, minutes: @minutes, hours: @hours,
+ days: @days, weeks: @weeks, months: @months,
+ years: value }
+ @duration_obj = parse_hash(input)
+ @years = value
+ normalize
+ end
+
+ def abs
+ @duration_obj = @duration_obj.abs
+ update_member_variables
+ self
+ end
+
+ def +(other)
+ new_obj = duration_obj + other.duration_obj
+ MicrosoftKiotaAbstractions::ISODuration.new(dur_obj_to_hash(new_obj))
+ end
+
+ def -(other)
+ new_obj = duration_obj - other.duration_obj
+ MicrosoftKiotaAbstractions::ISODuration.new(dur_obj_to_hash(new_obj))
+ end
+
+ def ==(other)
+ @duration_obj == other.duration_obj
+ end
+
+ def -@
+ @duration_obj = -@duration_obj
+ update_member_variables
+ end
+
+ def eql?(other)
+ @duration_obj == other.duration_obj
+ end
+
+ protected
+
+ attr_accessor :duration_obj
+
+ def parse_hash(input)
+ iso_str = 'P'
+ input.each_key do |keys|
+ raise StandardError, "The key #{keys} is not recognized" unless UNITS.key?(keys)
+ end
+ UNITS.each do |unit, abrev|
+ iso_str += input[unit].to_s + abrev if input.key?(unit) && !input[unit].zero?
+ iso_str += 'T' if unit == :days
+ end
+ iso_str = iso_str.strip
+ iso_str = iso_str.chomp('T') if iso_str[-1].eql? 'T'
+ ISO8601::Duration.new(iso_str)
+ end
+
+ def update_member_variables
+ @seconds = @duration_obj.seconds.nil? ? 0 : @duration_obj.seconds.to_s.split('S')[0].to_i
+ @minutes = @duration_obj.minutes.nil? ? 0 : @duration_obj.minutes.to_s.split('H')[0].to_i
+ @hours = @duration_obj.hours.nil? ? 0 : @duration_obj.hours.to_s.split('H')[0].to_i
+ @days = @duration_obj.days.nil? ? 0 : @duration_obj.days.to_s.split('D')[0].to_i
+ @weeks = @duration_obj.weeks.nil? ? 0 : @duration_obj.weeks.to_s.split('W')[0].to_i
+ @months = @duration_obj.months.nil? ? 0 : @duration_obj.months.to_s.split('M')[0].to_i
+ @years = @duration_obj.years.nil? ? 0 : @duration_obj.years.to_s.split('Y')[0].to_i
+ end
+
+ def dur_obj_to_hash(dur_obj)
+ result_hash = {}
+ result_hash[:seconds] = dur_obj.seconds.nil? ? 0 : dur_obj.seconds.to_s.split('S')[0].to_i
+ result_hash[:minutes] = dur_obj.minutes.nil? ? 0 : dur_obj.minutes.to_s.split('H')[0].to_i
+ result_hash[:hours] = dur_obj.hours.nil? ? 0 : dur_obj.hours.to_s.split('H')[0].to_i
+ result_hash[:days] = dur_obj.days.nil? ? 0 : dur_obj.days.to_s.split('D')[0].to_i
+ result_hash[:weeks] = dur_obj.weeks.nil? ? 0 : dur_obj.weeks.to_s.split('W')[0].to_i
+ result_hash[:months] = dur_obj.months.nil? ? 0 : dur_obj.months.to_s.split('M')[0].to_i
+ result_hash[:years] = dur_obj.years.nil? ? 0 : dur_obj.years.to_s.split('Y')[0].to_i
+ result_hash
+ end
+ end
+end
diff --git a/components/abstractions/lib/microsoft_kiota_abstractions/serialization/parsable.rb b/components/abstractions/lib/microsoft_kiota_abstractions/serialization/parsable.rb
new file mode 100644
index 0000000..600101b
--- /dev/null
+++ b/components/abstractions/lib/microsoft_kiota_abstractions/serialization/parsable.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module MicrosoftKiotaAbstractions
+ module Parsable
+ def get_field_deserializers
+ raise NotImplementedError
+ end
+
+ def serialize(_writer)
+ raise NotImplementedError
+ end
+ end
+end
diff --git a/components/abstractions/lib/microsoft_kiota_abstractions/serialization/parse_node.rb b/components/abstractions/lib/microsoft_kiota_abstractions/serialization/parse_node.rb
new file mode 100644
index 0000000..028b821
--- /dev/null
+++ b/components/abstractions/lib/microsoft_kiota_abstractions/serialization/parse_node.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+module MicrosoftKiotaAbstractions
+ module ParseNode
+ def get_string_value
+ raise NotImplementedError
+ end
+
+ def get_boolean_value
+ raise NotImplementedError
+ end
+
+ def get_number_value
+ raise NotImplementedError
+ end
+
+ def get_guid_value
+ raise NotImplementedError
+ end
+
+ def get_date_value
+ raise NotImplementedError
+ end
+
+ def get_time_value
+ raise NotImplementedError
+ end
+
+ def get_date_time_value
+ raise NotImplementedError
+ end
+
+ def get_duration_value
+ raise NotImplementedError
+ end
+
+ def get_collection_of_primitive_values
+ raise NotImplementedError
+ end
+
+ def get_collection_of_object_values(_factory)
+ raise NotImplementedError
+ end
+
+ def get_object_value(_factory)
+ raise NotImplementedError
+ end
+
+ def assign_field_values(_item)
+ raise NotImplementedError
+ end
+
+ def get_enum_value(_type)
+ raise NotImplementedError
+ end
+
+ def get_child_node(_name)
+ raise NotImplementedError
+ end
+ end
+end
diff --git a/components/abstractions/lib/microsoft_kiota_abstractions/serialization/parse_node_factory.rb b/components/abstractions/lib/microsoft_kiota_abstractions/serialization/parse_node_factory.rb
new file mode 100644
index 0000000..7b661c2
--- /dev/null
+++ b/components/abstractions/lib/microsoft_kiota_abstractions/serialization/parse_node_factory.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+module MicrosoftKiotaAbstractions
+ module ParseNodeFactory
+ def self.get_parse_node(_content_type, _content)
+ raise NotImplementedError
+ end
+ end
+end
diff --git a/components/abstractions/lib/microsoft_kiota_abstractions/serialization/parse_node_factory_registry.rb b/components/abstractions/lib/microsoft_kiota_abstractions/serialization/parse_node_factory_registry.rb
new file mode 100644
index 0000000..5bc7bab
--- /dev/null
+++ b/components/abstractions/lib/microsoft_kiota_abstractions/serialization/parse_node_factory_registry.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+require_relative 'parse_node_factory'
+
+module MicrosoftKiotaAbstractions
+ class ParseNodeFactoryRegistry
+ include ParseNodeFactory
+
+ class << self
+ attr_accessor :default_instance
+
+ def default_instance = @default_instance ||= ParseNodeFactoryRegistry.new
+ end
+
+ def default_instance
+ self.class.default_instance
+ end
+
+ def content_type_associated_factories
+ @content_type_associated_factories ||= {}
+ end
+
+ def get_parse_node(content_type, content)
+ raise StandardError, 'content type cannot be undefined or empty' unless content_type
+ raise StandardError, 'content cannot be undefined or empty' unless content
+
+ vendor_specific_content_type = content_type.split(';').first
+ factory = @content_type_associated_factories[vendor_specific_content_type]
+ return factory.get_parse_node(vendor_specific_content_type, content) if factory
+
+ clean_content_type = get_clean_content_type(vendor_specific_content_type)
+ factory = @content_type_associated_factories[clean_content_type]
+ return factory.get_parse_node(clean_content_type, content) if factory
+
+ raise StandardError, "Content type #{content_type} does not have a factory to be parsed"
+ end
+
+ private
+
+ def get_clean_content_type(content_type)
+ plus_index = content_type.rindex('+')
+ return content_type unless plus_index
+
+ slash_index = content_type.rindex('/', plus_index)
+ return content_type unless slash_index && slash_index < plus_index
+
+ "#{content_type[0..slash_index]}#{content_type[(plus_index + 1)..]}"
+ end
+ end
+end
diff --git a/lib/microsoft_kiota_abstractions/serialization/parse_node_helper.rb b/components/abstractions/lib/microsoft_kiota_abstractions/serialization/parse_node_helper.rb
similarity index 90%
rename from lib/microsoft_kiota_abstractions/serialization/parse_node_helper.rb
rename to components/abstractions/lib/microsoft_kiota_abstractions/serialization/parse_node_helper.rb
index 35e33c0..f695f83 100644
--- a/lib/microsoft_kiota_abstractions/serialization/parse_node_helper.rb
+++ b/components/abstractions/lib/microsoft_kiota_abstractions/serialization/parse_node_helper.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module MicrosoftKiotaAbstractions
class ParseNodeHelper
def self.merge_deserializers_for_intersection_wrapper(*targets)
diff --git a/components/abstractions/lib/microsoft_kiota_abstractions/serialization/serialization_writer.rb b/components/abstractions/lib/microsoft_kiota_abstractions/serialization/serialization_writer.rb
new file mode 100644
index 0000000..216eb4c
--- /dev/null
+++ b/components/abstractions/lib/microsoft_kiota_abstractions/serialization/serialization_writer.rb
@@ -0,0 +1,73 @@
+# frozen_string_literal: true
+
+module MicrosoftKiotaAbstractions
+ module SerializationWriter
+ def write_string_value(_key, _value)
+ raise NotImplementedError
+ end
+
+ def write_boolean_value(_key, _value)
+ raise NotImplementedError
+ end
+
+ def write_number_value(_key, _value)
+ raise NotImplementedError
+ end
+
+ def write_float_value(_key, _value)
+ raise NotImplementedError
+ end
+
+ def get_date_value(_key, _value)
+ raise NotImplementedError
+ end
+
+ def write_guid_value(_key, _value)
+ raise NotImplementedError
+ end
+
+ def write_date_value(_key, _value)
+ raise NotImplementedError
+ end
+
+ def write_time_value(_key, _value)
+ raise NotImplementedError
+ end
+
+ def write_date_time_value(_key, _value)
+ raise NotImplementedError
+ end
+
+ def write_duration_value(_key, _value)
+ raise NotImplementedError
+ end
+
+ def write_collection_of_primitive_values(_key, _value)
+ raise NotImplementedError
+ end
+
+ def write_collection_of_object_values(_key, _value)
+ raise NotImplementedError
+ end
+
+ def write_enum_value(_key, _value)
+ raise NotImplementedError
+ end
+
+ def get_serialized_content
+ raise NotImplementedError
+ end
+
+ def write_additional_data(_type)
+ raise NotImplementedError
+ end
+
+ def write_any_value(_key, _value)
+ raise NotImplementedError
+ end
+
+ def write_object_value(_key, _value, *_additional_values_to_merge)
+ raise NotImplementedError
+ end
+ end
+end
diff --git a/components/abstractions/lib/microsoft_kiota_abstractions/serialization/serialization_writer_factory.rb b/components/abstractions/lib/microsoft_kiota_abstractions/serialization/serialization_writer_factory.rb
new file mode 100644
index 0000000..b6ad0f3
--- /dev/null
+++ b/components/abstractions/lib/microsoft_kiota_abstractions/serialization/serialization_writer_factory.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+module MicrosoftKiotaAbstractions
+ module SerializationWriterFactory
+ def get_serialization_writer(_content_type)
+ raise NotImplementedError
+ end
+ end
+end
diff --git a/components/abstractions/lib/microsoft_kiota_abstractions/serialization/serialization_writer_factory_registry.rb b/components/abstractions/lib/microsoft_kiota_abstractions/serialization/serialization_writer_factory_registry.rb
new file mode 100644
index 0000000..16f98f1
--- /dev/null
+++ b/components/abstractions/lib/microsoft_kiota_abstractions/serialization/serialization_writer_factory_registry.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+require_relative 'serialization_writer_factory'
+
+module MicrosoftKiotaAbstractions
+ class SerializationWriterFactoryRegistry
+ include SerializationWriterFactory
+
+ class << self
+ attr_accessor :default_instance
+
+ def default_instance = @default_instance ||= SerializationWriterFactoryRegistry.new
+ end
+
+ def default_instance
+ self.class.default_instance
+ end
+
+ def content_type_associated_factories
+ @content_type_associated_factories ||= {}
+ end
+
+ def get_serialization_writer(content_type)
+ raise StandardError, 'content type cannot be undefined or empty' unless content_type
+
+ vendor_specific_content_type = content_type.split(';').first
+ factory = @content_type_associated_factories[vendor_specific_content_type]
+ return factory.get_serialization_writer(vendor_specific_content_type) if factory
+
+ clean_content_type = get_clean_content_type(vendor_specific_content_type)
+ factory = @content_type_associated_factories[clean_content_type]
+ return factory.get_serialization_writer(clean_content_type) if factory
+
+ raise StandardError, "Content type #{content_type} does not have a factory to be serialized"
+ end
+
+ private
+
+ def get_clean_content_type(content_type)
+ plus_index = content_type.rindex('+')
+ return content_type unless plus_index
+
+ slash_index = content_type.rindex('/', plus_index)
+ return content_type unless slash_index && slash_index < plus_index
+
+ "#{content_type[0..slash_index]}#{content_type[(plus_index + 1)..]}"
+ end
+ end
+end
diff --git a/lib/microsoft_kiota_abstractions/version.rb b/components/abstractions/lib/microsoft_kiota_abstractions/version.rb
similarity index 58%
rename from lib/microsoft_kiota_abstractions/version.rb
rename to components/abstractions/lib/microsoft_kiota_abstractions/version.rb
index 528a94a..fc50b3a 100644
--- a/lib/microsoft_kiota_abstractions/version.rb
+++ b/components/abstractions/lib/microsoft_kiota_abstractions/version.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
module MicrosoftKiotaAbstractions
- VERSION = "0.16.0"
+ VERSION = '0.17.0' # x-release-please-version
end
diff --git a/microsoft_kiota_abstractions.gemspec b/components/abstractions/microsoft_kiota_abstractions.gemspec
similarity index 61%
rename from microsoft_kiota_abstractions.gemspec
rename to components/abstractions/microsoft_kiota_abstractions.gemspec
index a24f43f..1be55ab 100644
--- a/microsoft_kiota_abstractions.gemspec
+++ b/components/abstractions/microsoft_kiota_abstractions.gemspec
@@ -9,27 +9,26 @@ Gem::Specification.new do |spec|
spec.email = 'graphsdkpub+ruby@microsoft.com'
spec.description = 'Microsoft Kiota Abstractions - Ruby abstractions for building library agnostic http client'
spec.summary = 'The Kiota abstractions are language specific libraries defining the basic constructs Kiota projects need once an SDK has been generated from an OpenAPI definition.'
- spec.homepage = 'https://microsoft.github.io/kiota/'
+ spec.homepage = 'https://learn.microsoft.com/openapi/kiota/'
spec.license = 'MIT'
spec.metadata = {
- 'bug_tracker_uri' => 'https://github.com/microsoft/kiota-abstractions-ruby/issues',
- 'changelog_uri' => 'https://github.com/microsoft/kiota-abstractions-ruby/blob/main/CHANGELOG.md',
- 'homepage_uri' => spec.homepage,
- 'source_code_uri' => 'https://github.com/microsoft/kiota-abstractions-ruby',
- 'github_repo' => 'ssh://github.com/microsoft/kiota-abstractions-ruby'
+ 'bug_tracker_uri' => 'https://github.com/microsoft/kiota-ruby/issues',
+ 'changelog_uri' => 'https://github.com/microsoft/kiota-ruby/blob/main/CHANGELOG.md',
+ 'homepage_uri' => spec.homepage,
+ 'source_code_uri' => 'https://github.com/microsoft/kiota-ruby/tree/main/components/abstractions',
+ 'github_repo' => 'ssh://github.com/microsoft/kiota-ruby',
+ 'rubygems_mfa_required' => 'true'
}
spec.required_ruby_version = '>= 3.3.0'
- # Specify which files should be added to the gem when it is released.
- # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
spec.files = Dir.chdir(File.expand_path(__dir__)) do
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
end
spec.bindir = 'bin'
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
spec.require_paths = ['lib']
- spec.add_runtime_dependency 'stduritemplate', '>= 0.0.39', '< 1.1.0'
- spec.add_runtime_dependency 'iso8601', '~> 0.13.0'
+ spec.add_dependency 'iso8601', '~> 0.13.0'
+ spec.add_dependency 'stduritemplate', '>= 0.0.39', '< 1.1.0'
spec.add_development_dependency 'rake', '~> 13.0'
spec.add_development_dependency 'rspec', '~> 3.0'
spec.add_development_dependency 'rubocop'
diff --git a/components/abstractions/spec/access_token_provider_mock.rb b/components/abstractions/spec/access_token_provider_mock.rb
new file mode 100644
index 0000000..07546f5
--- /dev/null
+++ b/components/abstractions/spec/access_token_provider_mock.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+require 'microsoft_kiota_abstractions'
+
+class AccessTokenProviderMock
+ extend MicrosoftKiotaAbstractions::AccessTokenProvider
+
+ DUMMY_TOKEN = 'DummyToken'
+ def get_authorization_token(_uri, _additional_properties = {})
+ Fiber.new do
+ DUMMY_TOKEN
+ end
+ end
+end
diff --git a/spec/microsoft_kiota_abstractions_spec.rb b/components/abstractions/spec/microsoft_kiota_abstractions_spec.rb
similarity index 52%
rename from spec/microsoft_kiota_abstractions_spec.rb
rename to components/abstractions/spec/microsoft_kiota_abstractions_spec.rb
index d441520..2a4e562 100644
--- a/spec/microsoft_kiota_abstractions_spec.rb
+++ b/components/abstractions/spec/microsoft_kiota_abstractions_spec.rb
@@ -1,110 +1,116 @@
# frozen_string_literal: true
+
require 'uri'
require 'microsoft_kiota_abstractions'
require_relative 'access_token_provider_mock'
RSpec.describe MicrosoftKiotaAbstractions do
- it "has a version number" do
+ it 'has a version number' do
expect(MicrosoftKiotaAbstractions::VERSION).not_to be nil
end
- it "tests library method" do
+ it 'tests library method' do
request_obj = MicrosoftKiotaAbstractions::RequestInformation.new
expect(!request_obj).to eq(false)
end
- it "creates a anonymous token provider" do
- token_provider = MicrosoftKiotaAbstractions::AnonymousAuthenticationProvider.new()
+ it 'creates a anonymous token provider' do
+ token_provider = MicrosoftKiotaAbstractions::AnonymousAuthenticationProvider.new
expect(token_provider).not_to be nil
# Authentication does nothing besides returning an empty Fiber
token_provider.authenticate_request(nil).resume
end
- it "creates a token authentication provider with existing authorization header" do
- access_token_provider = AccessTokenProviderMock.new()
+ it 'creates a token authentication provider with existing authorization header' do
+ access_token_provider = AccessTokenProviderMock.new
token_provider = MicrosoftKiotaAbstractions::BaseBearerTokenAuthenticationProvider.new(access_token_provider)
expect(token_provider).not_to be nil
request_obj = MicrosoftKiotaAbstractions::RequestInformation.new
- request_obj.headers.add(MicrosoftKiotaAbstractions::BaseBearerTokenAuthenticationProvider::AUTHORIZATION_HEADER_KEY, "SAMPLE")
+ request_obj.headers.add(
+ MicrosoftKiotaAbstractions::BaseBearerTokenAuthenticationProvider::AUTHORIZATION_HEADER_KEY, 'SAMPLE'
+ )
# Authentication does nothing besides returning an empty Fiber
token_provider.authenticate_request(request_obj).resume
# The request header should not have changed
- expect(request_obj.headers.get(MicrosoftKiotaAbstractions::BaseBearerTokenAuthenticationProvider::AUTHORIZATION_HEADER_KEY).at(0)).to eq "SAMPLE"
+ expect(request_obj.headers.get(MicrosoftKiotaAbstractions::BaseBearerTokenAuthenticationProvider::AUTHORIZATION_HEADER_KEY).at(0)).to eq 'SAMPLE'
end
- it "creates a token authentication provider with mock access token" do
- access_token_provider = AccessTokenProviderMock.new()
+ it 'creates a token authentication provider with mock access token' do
+ access_token_provider = AccessTokenProviderMock.new
token_provider = MicrosoftKiotaAbstractions::BaseBearerTokenAuthenticationProvider.new(access_token_provider)
expect(token_provider).not_to be nil
request_obj = MicrosoftKiotaAbstractions::RequestInformation.new
# We have to set a URI, otherwise the code will fail ("undefined method 'chars' for nil")
- request_obj.uri = "http://sample.com"
+ request_obj.uri = 'http://sample.com'
token_provider.authenticate_request(request_obj).resume
# The request header should now contain the "DUMMY_TOKEN" value:
expect(request_obj.headers.get(MicrosoftKiotaAbstractions::BaseBearerTokenAuthenticationProvider::AUTHORIZATION_HEADER_KEY).at(0)).to eq "Bearer #{AccessTokenProviderMock::DUMMY_TOKEN}"
end
- it "returns the raw URI when set via setter" do
+ it 'returns the raw URI when set via setter' do
request_obj = MicrosoftKiotaAbstractions::RequestInformation.new
- request_obj.path_parameters["term"] = "search"
- request_obj.query_parameters["q1"] = "option1"
- request_obj.uri = "https://www.bing.com"
- expect(request_obj.uri).to eq(URI("https://www.bing.com"))
+ request_obj.path_parameters['term'] = 'search'
+ request_obj.query_parameters['q1'] = 'option1'
+ request_obj.uri = 'https://www.bing.com'
+ expect(request_obj.uri).to eq(URI('https://www.bing.com'))
expect(request_obj.path_parameters).to eq({})
expect(request_obj.query_parameters).to eq({})
end
- it "returns the raw URI when set via raw url parmeter" do
+ it 'returns the raw URI when set via raw url parmeter' do
request_obj = MicrosoftKiotaAbstractions::RequestInformation.new
- request_obj.path_parameters["request-raw-url"] = "https://www.bing.com"
- expect(request_obj.path_parameters).to eq({ "request-raw-url" => "https://www.bing.com"})
- request_obj.path_parameters["term"] = "search"
- request_obj.query_parameters["q1"] = "option1"
- expect(request_obj.uri).to eq(URI("https://www.bing.com"))
+ request_obj.path_parameters['request-raw-url'] = 'https://www.bing.com'
+ expect(request_obj.path_parameters).to eq({ 'request-raw-url' => 'https://www.bing.com' })
+ request_obj.path_parameters['term'] = 'search'
+ request_obj.query_parameters['q1'] = 'option1'
+ expect(request_obj.uri).to eq(URI('https://www.bing.com'))
expect(request_obj.path_parameters).to eq({})
expect(request_obj.query_parameters).to eq({})
end
- it "returns a templated url" do
+ it 'returns a templated url' do
request_obj = MicrosoftKiotaAbstractions::RequestInformation.new
- request_obj.url_template = "https://www.bing.com/{term}{?q1,q2}"
- request_obj.path_parameters["term"] = "search"
- request_obj.query_parameters["q1"] = "option1"
- expect(request_obj.uri).to eq(URI("https://www.bing.com/search?q1=option1"))
+ request_obj.url_template = 'https://www.bing.com/{term}{?q1,q2}'
+ request_obj.path_parameters['term'] = 'search'
+ request_obj.query_parameters['q1'] = 'option1'
+ expect(request_obj.uri).to eq(URI('https://www.bing.com/search?q1=option1'))
end
- it "initializes a duration with ISO-formatted string or hash" do
- time1 = MicrosoftKiotaAbstractions::ISODuration.new("P2Y1MT2H")
- time2 = MicrosoftKiotaAbstractions::ISODuration.new({ :years => 2, :months => 1, :hours => 2 } )
+ it 'initializes a duration with ISO-formatted string or hash' do
+ time1 = MicrosoftKiotaAbstractions::ISODuration.new('P2Y1MT2H')
+ time2 = MicrosoftKiotaAbstractions::ISODuration.new({ years: 2, months: 1, hours: 2 })
expect(time1).to eq(time2)
end
- it "fails on malformed string inputs" do
- expect { MicrosoftKiotaAbstractions::ISODuration.new("P2Y1M3WT2H") }.to raise_error ISO8601::Errors::UnknownPattern
+ it 'fails on malformed string inputs' do
+ expect { MicrosoftKiotaAbstractions::ISODuration.new('P2Y1M3WT2H') }.to raise_error ISO8601::Errors::UnknownPattern
end
- it "fails on malformed hash inputs" do
- expect { MicrosoftKiotaAbstractions::ISODuration.new({ :laughter => 2, :months => 1, :hours => 2 }) }.to raise_error('The key laughter is not recognized')
+ it 'fails on malformed hash inputs' do
+ expect do
+ MicrosoftKiotaAbstractions::ISODuration.new({ laughter: 2, months: 1,
+ hours: 2 })
+ end.to raise_error('The key laughter is not recognized')
end
- it "handles addition" do
- time1 = MicrosoftKiotaAbstractions::ISODuration.new("P2Y1MT2H")
- time2 = MicrosoftKiotaAbstractions::ISODuration.new({ :years => 2, :months => 1, :hours => 2 } )
+ it 'handles addition' do
+ time1 = MicrosoftKiotaAbstractions::ISODuration.new('P2Y1MT2H')
+ time2 = MicrosoftKiotaAbstractions::ISODuration.new({ years: 2, months: 1, hours: 2 })
time3 = time1 + time2
- expect(time3.string).to eq(MicrosoftKiotaAbstractions::ISODuration.new("P4Y2MT4H").string)
+ expect(time3.string).to eq(MicrosoftKiotaAbstractions::ISODuration.new('P4Y2MT4H').string)
end
- it "handles subtraction" do
- time1 = MicrosoftKiotaAbstractions::ISODuration.new("P4Y2MT2H")
- time2 = MicrosoftKiotaAbstractions::ISODuration.new({ :years => 1, :months => 1, :hours => 2 } )
+ it 'handles subtraction' do
+ time1 = MicrosoftKiotaAbstractions::ISODuration.new('P4Y2MT2H')
+ time2 = MicrosoftKiotaAbstractions::ISODuration.new({ years: 1, months: 1, hours: 2 })
time3 = time1 - time2
- expect(time3.string).to eq(MicrosoftKiotaAbstractions::ISODuration.new("P3Y1M").string)
+ expect(time3.string).to eq(MicrosoftKiotaAbstractions::ISODuration.new('P3Y1M').string)
end
- it "handles equality comparisons" do
- time1 = MicrosoftKiotaAbstractions::ISODuration.new("P4Y2MT2H")
- time2 = MicrosoftKiotaAbstractions::ISODuration.new({ :years => 4, :months => 2, :hours => 2 } )
+ it 'handles equality comparisons' do
+ time1 = MicrosoftKiotaAbstractions::ISODuration.new('P4Y2MT2H')
+ time2 = MicrosoftKiotaAbstractions::ISODuration.new({ years: 4, months: 2, hours: 2 })
expect(time1).to eq(time2)
end
@@ -114,24 +120,28 @@
end
it 'initializes non-empty/cased allowed hosts properly' do
- ahv = MicrosoftKiotaAbstractions::AllowedHostsValidator.new(['microsoft.com', 'Graph.microsoft.com', 'DOD-graph.microsoft.us'])
+ ahv = MicrosoftKiotaAbstractions::AllowedHostsValidator.new(['microsoft.com', 'Graph.microsoft.com',
+ 'DOD-graph.microsoft.us'])
valid_hosts = ahv.allowed_hosts
- expect(valid_hosts).to eq({'microsoft.com' => true, 'graph.microsoft.com' => true, 'dod-graph.microsoft.us' => true})
+ expect(valid_hosts).to eq({ 'microsoft.com' => true, 'graph.microsoft.com' => true,
+ 'dod-graph.microsoft.us' => true })
end
it 'tests the setter for allowed hosts on allowed hosts validator' do
- ahv = MicrosoftKiotaAbstractions::AllowedHostsValidator.new(['microsoft.com', 'Graph.microsoft.com', 'DOD-graph.microsoft.us'])
+ ahv = MicrosoftKiotaAbstractions::AllowedHostsValidator.new(['microsoft.com', 'Graph.microsoft.com',
+ 'DOD-graph.microsoft.us'])
ahv.allowed_hosts = ['MICROSOFT.com', 'GRAPH.microsoft.COM', 'DOD-graph.microsoft.us', 'graph.microsoft.de']
- expect(ahv.allowed_hosts).to eq({'microsoft.com' => true, 'graph.microsoft.com' => true, 'dod-graph.microsoft.us' => true, 'graph.microsoft.de' => true})
+ expect(ahv.allowed_hosts).to eq({ 'microsoft.com' => true, 'graph.microsoft.com' => true,
+ 'dod-graph.microsoft.us' => true, 'graph.microsoft.de' => true })
end
it 'tests url_host_valid? method on malformed and valid urls' do
ahv = MicrosoftKiotaAbstractions::AllowedHostsValidator.new(['www.google.com', 'example.com', 'Graph.microsoft.com',
- 'DOD-graph.microsoft.us', "cool/groovy/art"])
- url1 = ahv.url_host_valid?("https://www.google.com")
- url2 = ahv.url_host_valid?("htts://google.com")
- url3 = ahv.url_host_valid?("cool/groovy/art")
- url4 = ahv.url_host_valid?("https://example.com")
+ 'DOD-graph.microsoft.us', 'cool/groovy/art'])
+ url1 = ahv.url_host_valid?('https://www.google.com')
+ url2 = ahv.url_host_valid?('htts://google.com')
+ url3 = ahv.url_host_valid?('cool/groovy/art')
+ url4 = ahv.url_host_valid?('https://example.com')
url5 = ahv.url_host_valid?('https%3A%2F%2Fwww.example.com')
url6 = ahv.url_host_valid?('%3A%2F%2F')
expect(url1).to eq(true)
diff --git a/components/abstractions/spec/parse_node_factory_mock.rb b/components/abstractions/spec/parse_node_factory_mock.rb
new file mode 100644
index 0000000..35c7062
--- /dev/null
+++ b/components/abstractions/spec/parse_node_factory_mock.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+require 'microsoft_kiota_abstractions'
+class ParseNodeFactoryMock
+ include MicrosoftKiotaAbstractions::ParseNodeFactory
+
+ def get_valid_content_type
+ 'application/json'
+ end
+
+ def get_parse_node(_clean_content_type, _content)
+ {}
+ end
+end
diff --git a/components/abstractions/spec/parse_node_factory_registry_spec.rb b/components/abstractions/spec/parse_node_factory_registry_spec.rb
new file mode 100644
index 0000000..72d57b1
--- /dev/null
+++ b/components/abstractions/spec/parse_node_factory_registry_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'microsoft_kiota_abstractions'
+require_relative 'parse_node_factory_mock'
+RSpec.describe MicrosoftKiotaAbstractions do
+ values = []
+ values << 'application/json'
+ values << 'application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8'
+ values << 'application/vnd.github.mercy-preview+json'
+ values << 'application/vnd.github.mercy-preview+json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8'
+ values << "application/#{Array.new(1000, 'vendor').join('.')}+json"
+ serialized_value = '[1]'
+ MicrosoftKiotaAbstractions::ParseNodeFactoryRegistry.default_instance.content_type_associated_factories['application/json'] =
+ ParseNodeFactoryMock.new
+ it 'gets the parse node' do
+ values.each do |value|
+ expect(MicrosoftKiotaAbstractions::ParseNodeFactoryRegistry.default_instance.get_parse_node(value,
+ serialized_value)).not_to be nil
+ end
+ end
+end
diff --git a/spec/parse_node_helper_spec.rb b/components/abstractions/spec/parse_node_helper_spec.rb
similarity index 100%
rename from spec/parse_node_helper_spec.rb
rename to components/abstractions/spec/parse_node_helper_spec.rb
diff --git a/components/abstractions/spec/query_parameters_mock.rb b/components/abstractions/spec/query_parameters_mock.rb
new file mode 100644
index 0000000..0c53acc
--- /dev/null
+++ b/components/abstractions/spec/query_parameters_mock.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+class QueryParametersMock
+ ##
+ # Include count of items
+ attr_accessor :count
+ ##
+ # Filter items by property values
+ attr_accessor :filter
+ ##
+ # Order items by property values
+ attr_accessor :orderby
+ ##
+ # Search items by search phrases
+ attr_accessor :search
+ ##
+ # Select properties to be returned
+ attr_accessor :select
+ ##
+ # Skip the first n items
+ attr_accessor :skip
+ ##
+ # Show only the first n items
+ attr_accessor :top
+
+ ##
+ ## Maps the query parameters names to their encoded names for the URI template parsing.
+ ## @param originalName The original query parameter name in the class.
+ ## @return a string
+ ##
+ def get_query_parameter(original_name)
+ case original_name
+ when 'count'
+ '%24count'
+ when 'filter'
+ '%24filter'
+ when 'orderby'
+ '%24orderby'
+ when 'search'
+ '%24search'
+ when 'select'
+ '%24select'
+ when 'skip'
+ '%24skip'
+ when 'top'
+ '%24top'
+ else
+ originalName
+ end
+ end
+end
diff --git a/components/abstractions/spec/request_headers_spec.rb b/components/abstractions/spec/request_headers_spec.rb
new file mode 100644
index 0000000..6403803
--- /dev/null
+++ b/components/abstractions/spec/request_headers_spec.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+require 'microsoft_kiota_abstractions'
+RSpec.describe MicrosoftKiotaAbstractions do
+ it 'adds a request header to the request information' do
+ request_info = MicrosoftKiotaAbstractions::RequestInformation.new
+ request_info.headers.add('key', 'value')
+ expect(request_info.headers.get_all.length).to eq(1)
+ expect(request_info.headers.get('key').length).to eq(1)
+ expect(request_info.headers.get('key').first).to eq('value')
+ end
+
+ it 'adds a request header to the request information when one value is already present' do
+ request_info = MicrosoftKiotaAbstractions::RequestInformation.new
+ request_info.headers.add('key', 'value')
+ request_info.headers.add('key', 'value2')
+ expect(request_info.headers.get_all.length).to eq(1)
+ expect(request_info.headers.get('key').length).to eq(2)
+ expect(request_info.headers.get('key').first).to eq('value')
+ expect(request_info.headers.get('key').last).to eq('value2')
+ end
+
+ it 'try to add a request header to the request information' do
+ request_info = MicrosoftKiotaAbstractions::RequestInformation.new
+ result1 = request_info.headers.try_add('key', 'value')
+ result2 = request_info.headers.try_add('key', 'value2')
+ expect(result1).to eq(true)
+ expect(result2).to eq(false)
+ expect(request_info.headers.get_all.length).to eq(1)
+ expect(request_info.headers.get('key').length).to eq(1)
+ expect(request_info.headers.get('key').first).to eq('value')
+ end
+
+ it 'removes a request header from the request information' do
+ request_info = MicrosoftKiotaAbstractions::RequestInformation.new
+ request_info.headers.add('key', 'value')
+ expect(request_info.headers.get_all.length).to eq(1)
+ request_info.headers.remove('key')
+ expect(request_info.headers.get_all.length).to eq(0)
+ end
+
+ it 'doesnt fail when removing a value if none are present' do
+ request_info = MicrosoftKiotaAbstractions::RequestInformation.new
+ request_info.headers.remove('key')
+ expect(request_info.headers.get_all.length).to eq(0)
+ end
+
+ it 'clears the request headers from the request information' do
+ request_info = MicrosoftKiotaAbstractions::RequestInformation.new
+ request_info.headers.add('key', 'value')
+ expect(request_info.headers.get_all.length).to eq(1)
+ request_info.headers.clear
+ expect(request_info.headers.get_all.length).to eq(0)
+ end
+end
diff --git a/components/abstractions/spec/request_information_spec.rb b/components/abstractions/spec/request_information_spec.rb
new file mode 100644
index 0000000..3ad5c9c
--- /dev/null
+++ b/components/abstractions/spec/request_information_spec.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+require 'microsoft_kiota_abstractions'
+require_relative 'request_option_mock'
+require_relative 'query_parameters_mock'
+
+RSpec.describe MicrosoftKiotaAbstractions do
+ it 'adds a request option to the request information' do
+ request_info = MicrosoftKiotaAbstractions::RequestInformation.new
+ mock_option = RequestOptionMock.new
+ mock_option.value = 'value'
+ request_info.add_request_options(mock_option)
+ expect(request_info.get_request_options.length).to eq(1)
+ expect(request_info.get_request_option('key')).to eq(mock_option)
+ end
+
+ it 'removes a request option from the request information' do
+ request_info = MicrosoftKiotaAbstractions::RequestInformation.new
+ mock_option = RequestOptionMock.new
+ mock_option.value = 'value'
+ request_info.add_request_options(mock_option)
+ expect(request_info.get_request_options.length).to eq(1)
+ request_info.remove_request_options('key')
+ expect(request_info.get_request_options.length).to eq(0)
+ end
+
+ it 'adds query parameters with their escaped values' do
+ request_info = MicrosoftKiotaAbstractions::RequestInformation.new
+ query_parameters = QueryParametersMock.new
+ query_parameters.select = 'foo,bar'
+ request_info.set_query_string_parameters_from_raw_object(query_parameters)
+ expect(request_info.query_parameters.length).to eq(1)
+ expect(request_info.query_parameters['%24select']).to eq('foo,bar')
+ expect(request_info.query_parameters['select']).to be_nil
+ end
+
+ it "doesn't fail adding query parameters with anonymous object" do
+ request_info = MicrosoftKiotaAbstractions::RequestInformation.new
+ query_parameters = {
+ select: 'foo,bar'
+ }
+ request_info.set_query_string_parameters_from_raw_object(query_parameters)
+ expect(request_info.query_parameters.length).to eq(0)
+ end
+end
diff --git a/spec/request_option_mock.rb b/components/abstractions/spec/request_option_mock.rb
similarity index 70%
rename from spec/request_option_mock.rb
rename to components/abstractions/spec/request_option_mock.rb
index 4b91552..49a28fb 100644
--- a/spec/request_option_mock.rb
+++ b/components/abstractions/spec/request_option_mock.rb
@@ -1,8 +1,12 @@
+# frozen_string_literal: true
+
require 'microsoft_kiota_abstractions'
class RequestOptionMock
include MicrosoftKiotaAbstractions::RequestOption
+
attr_accessor :value
- def get_key()
- return "key"
+
+ def get_key
+ 'key'
end
-end
\ No newline at end of file
+end
diff --git a/components/abstractions/spec/serialization_writer_factory_mock.rb b/components/abstractions/spec/serialization_writer_factory_mock.rb
new file mode 100644
index 0000000..82d503d
--- /dev/null
+++ b/components/abstractions/spec/serialization_writer_factory_mock.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+require 'microsoft_kiota_abstractions'
+class SerializationWriterFactoryMock
+ include MicrosoftKiotaAbstractions::SerializationWriterFactory
+
+ def get_valid_content_type
+ 'application/json'
+ end
+
+ def get_serialization_writer(_clean_content)
+ {}
+ end
+end
diff --git a/components/abstractions/spec/serialization_writer_factory_registry_spec.rb b/components/abstractions/spec/serialization_writer_factory_registry_spec.rb
new file mode 100644
index 0000000..5722b03
--- /dev/null
+++ b/components/abstractions/spec/serialization_writer_factory_registry_spec.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require 'microsoft_kiota_abstractions'
+require_relative 'serialization_writer_factory_mock'
+RSpec.describe MicrosoftKiotaAbstractions do
+ values = []
+ values << 'application/json'
+ values << 'application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8'
+ values << 'application/vnd.github.mercy-preview+json'
+ values << 'application/vnd.github.mercy-preview+json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8'
+ values << "application/#{Array.new(1000, 'vendor').join('.')}+json"
+ MicrosoftKiotaAbstractions::SerializationWriterFactoryRegistry.default_instance.content_type_associated_factories['application/json'] =
+ SerializationWriterFactoryMock.new
+ it 'gets the serialization writer' do
+ values.each do |value|
+ expect(MicrosoftKiotaAbstractions::SerializationWriterFactoryRegistry.default_instance.get_serialization_writer(value)).not_to be nil
+ end
+ end
+end
diff --git a/spec/spec_helper.rb b/components/abstractions/spec/spec_helper.rb
similarity index 81%
rename from spec/spec_helper.rb
rename to components/abstractions/spec/spec_helper.rb
index b960d8c..7ee4005 100644
--- a/spec/spec_helper.rb
+++ b/components/abstractions/spec/spec_helper.rb
@@ -2,7 +2,7 @@
RSpec.configure do |config|
# Enable flags like --only-failures and --next-failure
- config.example_status_persistence_file_path = ".rspec_status"
+ config.example_status_persistence_file_path = '.rspec_status'
# Disable RSpec exposing methods globally on `Module` and `main`
config.disable_monkey_patching!
diff --git a/components/authentication/oauth/Gemfile b/components/authentication/oauth/Gemfile
new file mode 100644
index 0000000..f4859ea
--- /dev/null
+++ b/components/authentication/oauth/Gemfile
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+source 'https://rubygems.org'
+
+gem 'microsoft_kiota_abstractions', path: '../../abstractions'
+
+gemspec
diff --git a/components/authentication/oauth/Rakefile b/components/authentication/oauth/Rakefile
new file mode 100644
index 0000000..82bb534
--- /dev/null
+++ b/components/authentication/oauth/Rakefile
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+require 'bundler/gem_tasks'
+require 'rspec/core/rake_task'
+
+RSpec::Core::RakeTask.new(:spec)
+
+task default: :spec
diff --git a/components/authentication/oauth/lib/microsoft_kiota_authentication_oauth.rb b/components/authentication/oauth/lib/microsoft_kiota_authentication_oauth.rb
new file mode 100644
index 0000000..8af70d2
--- /dev/null
+++ b/components/authentication/oauth/lib/microsoft_kiota_authentication_oauth.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+require_relative 'microsoft_kiota_authentication_oauth/version'
+require_relative 'microsoft_kiota_authentication_oauth/contexts/authorization_code_context'
+require_relative 'microsoft_kiota_authentication_oauth/contexts/client_credential_context'
+require_relative 'microsoft_kiota_authentication_oauth/contexts/on_behalf_of_context'
+require_relative 'microsoft_kiota_authentication_oauth/contexts/oauth_context'
+require_relative 'microsoft_kiota_authentication_oauth/contexts/oauth_custom_flow'
+require_relative 'microsoft_kiota_authentication_oauth/extensions/oauth2_ext'
+require_relative 'microsoft_kiota_authentication_oauth/oauth_access_token_provider'
+require_relative 'microsoft_kiota_authentication_oauth/oauth_authentication_provider'
+
+module MicrosoftKiotaAuthenticationOAuth
+end
diff --git a/components/authentication/oauth/lib/microsoft_kiota_authentication_oauth/contexts/authorization_code_context.rb b/components/authentication/oauth/lib/microsoft_kiota_authentication_oauth/contexts/authorization_code_context.rb
new file mode 100644
index 0000000..43855d1
--- /dev/null
+++ b/components/authentication/oauth/lib/microsoft_kiota_authentication_oauth/contexts/authorization_code_context.rb
@@ -0,0 +1,87 @@
+# frozen_string_literal: true
+
+require 'oauth2'
+require_relative 'oauth_context'
+
+module MicrosoftKiotaAuthenticationOAuth
+ # Token request context class for the authorization code grant type.
+ class AuthorizationCodeContext < MicrosoftKiotaAuthenticationOAuth::OAuthContext
+ attr_reader :grant_type, :redirect_uri, :additional_params,
+ :tenant_id, :client_id, :client_secret, :auth_code, :oauth_provider
+ attr_writer :scopes
+
+ # This is the initializer for AuthorizationCodeContext, the token request context when
+ # using the authorization code grant flow.
+ # :params
+ # tenant_id: a string containing the tenant id
+ # client_id: a string containing the client id
+ # client_secret: a string containing the client secret
+ # redirect_uri: a string containing redirect_uri
+ # auth_code: a string containting the auth code; default is nil, can be updated post-initialization
+ def initialize(tenant_id, client_id, client_secret, redirect_uri, auth_code = nil)
+ raise StandardError, 'redirect_uri cannot be nil/empty' if redirect_uri.nil? || redirect_uri.empty?
+
+ @tenant_id = tenant_id
+ @client_id = client_id
+ @client_secret = client_secret
+ @auth_code = auth_code
+ @redirect_uri = redirect_uri
+ @scopes = nil
+ @oauth_provider = nil
+ @grant_type = 'authorization code'
+
+ if @tenant_id.nil? || @client_id.nil? || @client_secret.nil? || @tenant_id.empty? || @client_id.empty? || @client_secret.empty?
+ raise StandardError, 'tenant_id, client_id, and client_secret cannot be empty'
+ end
+ end
+
+ # setter for auth_code
+ def auth_code=(code)
+ raise StandardError, 'auth_code cannot be empty/nil.' if code.nil? || code.empty?
+
+ @auth_code = code
+ end
+
+ # This function generates an authorize URL for obtaining the auth code.
+ # :params
+ # scopes: an array of stings, where each string is a scope
+ # additional_params: hash of symbols to string values, ie { response_mode: 'fragment', prompt: 'login' }
+ # default is empty hash
+ def generate_authorize_url(scopes, additional_params = {})
+ @additional_params = additional_params
+
+ initialize_scopes(scopes)
+ initialize_oauth_provider
+
+ parameters = { scope: @scopes, redirect_uri: @redirect_uri, access_type: 'offline', prompt: 'consent' }
+ parameters = parameters.merge(additional_params)
+ @oauth_provider.auth_code.authorize_url(parameters)
+ end
+
+ def get_token
+ @oauth_provider.auth_code.get_token(@auth_code, redirect_uri: @redirect_uri)
+ end
+
+ def initialize_oauth_provider
+ @oauth_provider = OAuth2::Client.new(@client_id, @client_secret,
+ site: 'https://login.microsoftonline.com',
+ authorize_url: "/#{@tenant_id}/oauth2/v2.0/authorize",
+ token_url: "/#{@tenant_id}/oauth2/v2.0/token")
+ end
+
+ def initialize_scopes(scopes)
+ scope_str = ''
+ scopes.each { |scope| scope_str += "#{scope} " }
+ raise StandardError, 'scopes cannot be empty/nil.' if scope_str.empty?
+
+ scope_str = "offline_access #{scope_str}"
+
+ @scopes = scope_str
+ end
+
+ private
+
+ attr_writer :grant_type, :redirect_uri, :additional_params,
+ :tenant_id, :client_id, :client_secret, :oauth_provider
+ end
+end
diff --git a/components/authentication/oauth/lib/microsoft_kiota_authentication_oauth/contexts/client_credential_context.rb b/components/authentication/oauth/lib/microsoft_kiota_authentication_oauth/contexts/client_credential_context.rb
new file mode 100644
index 0000000..c0f28aa
--- /dev/null
+++ b/components/authentication/oauth/lib/microsoft_kiota_authentication_oauth/contexts/client_credential_context.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+require 'oauth2'
+require_relative 'oauth_context'
+
+module MicrosoftKiotaAuthenticationOAuth
+ # Token request context class for the client credential grant type.
+ class ClientCredentialContext < MicrosoftKiotaAuthenticationOAuth::OAuthContext
+ attr_reader :grant_type, :additional_params, :tenant_id, :client_id, :client_secret, :oauth_provider
+ attr_writer :scopes
+
+ # This is the initializer for ClientCredentialContext, the token request context when
+ # using the client credential grant flow.
+ # :params
+ # tenant_id: a string containing the tenant id
+ # client_id: a string containing the client id
+ # client_secret: a string containing the client secret
+ # additional_params: hash of symbols to string values, ie { response_mode: 'fragment', prompt: 'login' }
+ # default is empty hash
+ def initialize(tenant_id, client_id, client_secret, additional_params = {})
+ @tenant_id = tenant_id
+ @client_id = client_id
+ @client_secret = client_secret
+ @additional_params = additional_params
+ @scopes = nil
+ @oauth_provider = nil
+ @grant_type = 'client credential'
+
+ if @tenant_id.nil? || @client_id.nil? || @client_secret.nil? || @tenant_id.empty? || @client_id.empty? || @client_secret.empty?
+ raise StandardError, 'tenant_id, client_id and client_secret cannot be empty'
+ end
+ end
+
+ def get_token
+ @oauth_provider.client_credentials.get_token({ scope: @scopes })
+ end
+
+ def initialize_oauth_provider
+ @oauth_provider = OAuth2::Client.new(@client_id, @client_secret,
+ site: 'https://login.microsoftonline.com',
+ authorize_url: "/#{@tenant_id}/oauth2/v2.0/authorize",
+ token_url: "/#{@tenant_id}/oauth2/v2.0/token")
+ end
+
+ # Function to initialize the scope for the client credential context object.
+ # Only a single scope is supported for this flow and it's expected to be schme://service/.default
+ def initialize_scopes(scopes = [])
+ @scopes = scopes[0] unless scopes.empty?
+ end
+
+ private
+
+ attr_writer :grant_type, :additional_params, :tenant_id, :client_id, :client_secret, :oauth_provider
+ end
+end
diff --git a/components/authentication/oauth/lib/microsoft_kiota_authentication_oauth/contexts/oauth_context.rb b/components/authentication/oauth/lib/microsoft_kiota_authentication_oauth/contexts/oauth_context.rb
new file mode 100644
index 0000000..851cee2
--- /dev/null
+++ b/components/authentication/oauth/lib/microsoft_kiota_authentication_oauth/contexts/oauth_context.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+require 'oauth2'
+require_relative 'oauth_custom_flow'
+
+module MicrosoftKiotaAuthenticationOAuth
+ # Base class for token request contexs.
+ class OAuthContext
+ attr_accessor :scopes
+ attr_reader :oauth_provider
+
+ include MicrosoftKiotaAuthenticationOAuth::OAuthCustomFlow
+
+ def get_token
+ OAuthCustomFlow.get_token
+ end
+
+ def initialize_scopes(_scopes = [])
+ @scopes = OAuthCustomFlow.get_scopes
+ end
+
+ def initialize_oauth_provider
+ @oauth_provider = OAuthCustomFlow.get_oauth_provider
+ end
+
+ private
+
+ attr_writer :oauth_provider
+ end
+end
diff --git a/components/authentication/oauth/lib/microsoft_kiota_authentication_oauth/contexts/oauth_custom_flow.rb b/components/authentication/oauth/lib/microsoft_kiota_authentication_oauth/contexts/oauth_custom_flow.rb
new file mode 100644
index 0000000..38090c1
--- /dev/null
+++ b/components/authentication/oauth/lib/microsoft_kiota_authentication_oauth/contexts/oauth_custom_flow.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+require 'oauth2'
+
+module MicrosoftKiotaAuthenticationOAuth
+ # Module that can be optionally implemented for supporting custom token grant flows.
+ # To use a cutsom token grant flow, implement the functions below and
+ # use MicrosoftKiotaAuthenticationOAuth::OAuthContext.new as your token_request_context
+ # object for the use by the MicrosoftKiotaAuthenticationOAuth::OAuthAccessTokenProvider
+ module OAuthCustomFlow
+ # Function that returns an oauth client using the oauth2 gem
+ def self.get_oauth_provider
+ raise NotImplementedError
+ end
+
+ # Function that returns a space seperated string of scopes, beginning with
+ # the offline_access scope if relevant
+ def self.get_scopes
+ raise NotImplementedError
+ end
+
+ # Function that returns the access token
+ def self.get_token
+ raise NotImplementedError
+ end
+ end
+end
diff --git a/components/authentication/oauth/lib/microsoft_kiota_authentication_oauth/contexts/on_behalf_of_context.rb b/components/authentication/oauth/lib/microsoft_kiota_authentication_oauth/contexts/on_behalf_of_context.rb
new file mode 100644
index 0000000..bc8650b
--- /dev/null
+++ b/components/authentication/oauth/lib/microsoft_kiota_authentication_oauth/contexts/on_behalf_of_context.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+require 'oauth2'
+require_relative 'oauth_context'
+
+module MicrosoftKiotaAuthenticationOAuth
+ # Token request context class for the on behlaf of grant type.
+ class OnBehalfOfContext < MicrosoftKiotaAuthenticationOAuth::OAuthContext
+ attr_reader :grant_type, :additional_params, :tenant_id, :client_id, :client_secret, :oauth_provider
+ attr_writer :scopes
+
+ # This is the initializer for OnBehalfOfContext, the token request context when
+ # using the client credential grant flow.
+ # :params
+ # tenant_id: a string containing the tenant id
+ # client_id: a string containing the client id
+ # client_secret: a string containing the client secret
+ # assertion: string containing assertion (access token used in the request)
+ # additional_params: hash of symbols to string values, ie { response_mode: 'fragment', prompt: 'login' }
+ # default is empty hash
+ def initialize(tenant_id, client_id, client_secret, assertion, additional_params = {})
+ raise StandardError, 'assertion cannot be empty' if assertion.nil? || assertion.empty?
+
+ @tenant_id = tenant_id
+ @client_id = client_id
+ @client_secret = client_secret
+ @assertion = assertion
+ @additional_params = additional_params
+ @scopes = nil
+ @oauth_provider = nil
+ @grant_type = 'urn:ietf:params:Oauth:grant-type:jwt-bearer'
+
+ if @tenant_id.nil? || @client_id.nil? || @client_secret.nil? || @client_secret.empty? || @tenant_id.empty? || @client_id.empty?
+ raise StandardError, 'tenant_id, client_secret, and client_id cannot be empty'
+ end
+ end
+
+ def get_token
+ params = {
+ grant_type: @grant_type,
+ assertion: @assertion,
+ scope: @scopes,
+ requested_token_use: 'on_behalf_of'
+ }
+ @oauth_provider.on_behalf_of.get_token(params)
+ end
+
+ def initialize_oauth_provider
+ @oauth_provider = OAuth2::Client.new(@client_id, @client_secret,
+ site: 'https://login.microsoftonline.com',
+ authorize_url: "/#{@tenant_id}/oauth2/v2.0/authorize",
+ token_url: "/#{@tenant_id}/oauth2/v2.0/token")
+ end
+
+ def initialize_scopes(scopes)
+ scope_str = ''
+ scopes.each { |scope| scope_str += "#{scope} " }
+
+ raise StandardError, 'scopes cannot be empty/nil.' if scope_str.empty?
+
+ scope_str = "offline_access #{scope_str}"
+
+ @scopes = scope_str
+ end
+
+ private
+
+ attr_writer :grant_type, :additional_params, :tenant_id, :client_id,
+ :client_secret, :oauth_provider
+ end
+end
diff --git a/components/authentication/oauth/lib/microsoft_kiota_authentication_oauth/extensions/oauth2_ext.rb b/components/authentication/oauth/lib/microsoft_kiota_authentication_oauth/extensions/oauth2_ext.rb
new file mode 100644
index 0000000..db788a5
--- /dev/null
+++ b/components/authentication/oauth/lib/microsoft_kiota_authentication_oauth/extensions/oauth2_ext.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+require 'oauth2'
+
+# Extension of Oauth2 Library to Include On Behalf Of Grant Type
+module OAuth2
+ module Strategy
+ class OnBehalfOf < Base
+ def get_token(params, response_opts = {})
+ @client.get_token(params, response_opts)
+ end
+ end
+ end
+end
+
+module OAuth2
+ class Client
+ def on_behalf_of
+ @on_behalf_of ||= OAuth2::Strategy::OnBehalfOf.new(self)
+ end
+ end
+end
diff --git a/components/authentication/oauth/lib/microsoft_kiota_authentication_oauth/oauth_access_token_provider.rb b/components/authentication/oauth/lib/microsoft_kiota_authentication_oauth/oauth_access_token_provider.rb
new file mode 100644
index 0000000..fbb3b60
--- /dev/null
+++ b/components/authentication/oauth/lib/microsoft_kiota_authentication_oauth/oauth_access_token_provider.rb
@@ -0,0 +1,87 @@
+# frozen_string_literal: true
+
+require 'microsoft_kiota_abstractions'
+require 'oauth2'
+require_relative 'extensions/oauth2_ext'
+require_relative 'contexts/client_credential_context'
+require_relative 'contexts/authorization_code_context'
+require_relative 'contexts/on_behalf_of_context'
+require_relative 'contexts/oauth_context'
+require_relative 'contexts/oauth_custom_flow'
+
+module MicrosoftKiotaAuthenticationOAuth
+ # Access Token Provider class implementation
+ class OAuthAccessTokenProvider
+ # This is the initializer for OAuthAccessTokenProvider.
+ # :params
+ # token_request_context: a instance of one of our token request context or a custom implementation
+ # allowed_hosts: an array of strings, where each string is an allowed host, default is empty
+ # scopes: an array of strings, where each string is a scope, default is empty array
+ def initialize(token_request_context, allowed_hosts = [], scopes = [])
+ raise StandardError, 'Parameter token_request_context cannot be nil.' if token_request_context.nil?
+
+ @token_request_context = token_request_context
+
+ unless @token_request_context.is_a?(MicrosoftKiotaAuthenticationOAuth::OAuthContext)
+ raise StandardError,
+ 'Parameter token_request_context must be an instance of one of our grant flow context classes.'
+ end
+
+ @cached_token = nil
+
+ @host_validator = if allowed_hosts.nil? || allowed_hosts.empty?
+ MicrosoftKiotaAbstractions::AllowedHostsValidator.new([])
+ else
+ MicrosoftKiotaAbstractions::AllowedHostsValidator.new(allowed_hosts)
+ end
+ @token_request_context.initialize_oauth_provider
+ @scopes = if scopes.nil?
+ []
+ else
+ scopes
+ end
+ end
+
+ # This function obtains the authorization token.
+ # :params
+ # uri: a string containing the uri
+ # additional_params: hash of symbols to string values, ie { response_mode: 'fragment', prompt: 'login' }
+ # default is empty hash
+ def get_authorization_token(uri, _additional_properties = {})
+ nil if !uri || !@host_validator.url_host_valid?(uri)
+
+ parsed_url = URI(uri)
+
+ raise StandardError, 'Only https is supported' if parsed_url.scheme != 'https'
+
+ @scopes << "#{parsed_url.scheme}://#{parsed_url.host}/.default" if @scopes.empty?
+ @token_request_context.initialize_scopes(@scopes)
+ Fiber.new do
+ if @cached_token
+ token = OAuth2::AccessToken.from_hash(@token_request_context.oauth_provider, @cached_token)
+ token.token unless token.nil? || token.expired?
+
+ if token.expired?
+ token = token.refresh!
+ @cached_token = token.to_hash
+ token.token
+ end
+ end
+
+ nil
+ token = @token_request_context.get_token
+
+ unless token.nil?
+ @cached_token = token.to_hash
+ token.token
+ end
+ end
+ end
+
+ attr_reader :scopes, :host_validator
+
+ protected
+
+ attr_writer :host_validator, :token_credential, :scopes, :cached_token
+ end
+end
diff --git a/components/authentication/oauth/lib/microsoft_kiota_authentication_oauth/oauth_authentication_provider.rb b/components/authentication/oauth/lib/microsoft_kiota_authentication_oauth/oauth_authentication_provider.rb
new file mode 100644
index 0000000..e7cfb95
--- /dev/null
+++ b/components/authentication/oauth/lib/microsoft_kiota_authentication_oauth/oauth_authentication_provider.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'microsoft_kiota_abstractions'
+require_relative 'oauth_access_token_provider'
+
+module MicrosoftKiotaAuthenticationOAuth
+ class OAuthAuthenticationProvider < MicrosoftKiotaAbstractions::BaseBearerTokenAuthenticationProvider
+ def initialize(token_request_context, allowed_hosts, scopes)
+ super(MicrosoftKiotaAuthenticationOAuth::OAuthAccessTokenProvider.new(token_request_context, allowed_hosts,
+ scopes))
+ end
+ end
+end
diff --git a/components/authentication/oauth/lib/microsoft_kiota_authentication_oauth/version.rb b/components/authentication/oauth/lib/microsoft_kiota_authentication_oauth/version.rb
new file mode 100644
index 0000000..f9c45a3
--- /dev/null
+++ b/components/authentication/oauth/lib/microsoft_kiota_authentication_oauth/version.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+module MicrosoftKiotaAuthenticationOAuth
+ VERSION = '0.17.0' # x-release-please-version
+end
diff --git a/components/authentication/oauth/microsoft_kiota_authentication_oauth.gemspec b/components/authentication/oauth/microsoft_kiota_authentication_oauth.gemspec
new file mode 100644
index 0000000..68e070c
--- /dev/null
+++ b/components/authentication/oauth/microsoft_kiota_authentication_oauth.gemspec
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+require_relative 'lib/microsoft_kiota_authentication_oauth/version'
+
+Gem::Specification.new do |spec|
+ spec.name = 'microsoft_kiota_authentication_oauth'
+ spec.version = MicrosoftKiotaAuthenticationOAuth::VERSION
+ spec.authors = 'Microsoft Corporation'
+ spec.email = 'graphsdkpub+ruby@microsoft.com'
+ spec.description = 'Kiota Authentication implementation with oauth2'
+ spec.summary = 'Microsoft Kiota Authentication OAuth - Kiota Ruby Authentication OAuth library'
+ spec.homepage = 'https://learn.microsoft.com/openapi/kiota/'
+ spec.license = 'MIT'
+ spec.metadata = {
+ 'bug_tracker_uri' => 'https://github.com/microsoft/kiota-ruby/issues',
+ 'changelog_uri' => 'https://github.com/microsoft/kiota-ruby/blob/main/CHANGELOG.md',
+ 'homepage_uri' => spec.homepage,
+ 'source_code_uri' => 'https://github.com/microsoft/kiota-ruby/tree/main/components/authentication/oauth',
+ 'github_repo' => 'ssh://github.com/microsoft/kiota-ruby',
+ 'rubygems_mfa_required' => 'true'
+ }
+ spec.required_ruby_version = '>= 3.3.0'
+
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
+ end
+ spec.bindir = 'bin'
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
+ spec.require_paths = ['lib']
+ spec.add_dependency 'microsoft_kiota_abstractions', '>= 0.17', '< 0.18'
+ spec.add_dependency 'oauth2', '~> 2.0'
+ spec.add_development_dependency 'rake', '~> 13.0'
+ spec.add_development_dependency 'rspec', '~> 3.0'
+ spec.add_development_dependency 'rubocop'
+end
diff --git a/components/authentication/oauth/spec/microsoft_kiota_authentication_oauth_spec.rb b/components/authentication/oauth/spec/microsoft_kiota_authentication_oauth_spec.rb
new file mode 100644
index 0000000..9499491
--- /dev/null
+++ b/components/authentication/oauth/spec/microsoft_kiota_authentication_oauth_spec.rb
@@ -0,0 +1,93 @@
+# frozen_string_literal: true
+
+require 'uri'
+require_relative 'spec_helper'
+
+RSpec.describe MicrosoftKiotaAuthenticationOAuth do
+ it '(client credential context) throws when tenant_id/client_secret is nil/empty' do
+ expect do
+ MicrosoftKiotaAuthenticationOAuth::ClientCredentialContext.new(nil, nil, nil, {})
+ end.to raise_error(StandardError)
+ expect do
+ MicrosoftKiotaAuthenticationOAuth::ClientCredentialContext.new('tenant_id', 'client_id', 'client_secret',
+ {})
+ end.not_to raise_error
+ expect do
+ MicrosoftKiotaAuthenticationOAuth::ClientCredentialContext.new('', 'client_id', 'client_secret',
+ {})
+ end.to raise_error(StandardError)
+ expect do
+ MicrosoftKiotaAuthenticationOAuth::ClientCredentialContext.new('tenant_id', '', 'client_secret',
+ {})
+ end.to raise_error(StandardError)
+ expect do
+ MicrosoftKiotaAuthenticationOAuth::ClientCredentialContext.new('tenant_id', 'client_id', '',
+ {})
+ end.to raise_error(StandardError)
+ end
+
+ it '(auth code context) throws when tenant_id/client_secret is nil/empty' do
+ expect do
+ MicrosoftKiotaAuthenticationOAuth::AuthorizationCodeContext.new(nil, nil, nil, nil)
+ end.to raise_error(StandardError)
+ expect do
+ MicrosoftKiotaAuthenticationOAuth::AuthorizationCodeContext.new('tenant_id', 'client_id', 'client_secret',
+ 'redirect_uri')
+ end.not_to raise_error
+ expect do
+ MicrosoftKiotaAuthenticationOAuth::AuthorizationCodeContext.new('', 'client_id', 'client_secret', 'redirect_uri',
+ 'code')
+ end.to raise_error(StandardError)
+ expect do
+ MicrosoftKiotaAuthenticationOAuth::AuthorizationCodeContext.new('tenant_id', '', 'client_secret',
+ '')
+ end.to raise_error(StandardError)
+ expect do
+ MicrosoftKiotaAuthenticationOAuth::AuthorizationCodeContext.new('tenant_id', 'client_id', '',
+ 'redirect_uri')
+ end.to raise_error(StandardError)
+ expect do
+ MicrosoftKiotaAuthenticationOAuth::AuthorizationCodeContext.new('tenant_id', '', 'client_secret',
+ 'redirect_uri')
+ end.to raise_error(StandardError)
+ end
+
+ it '(on behalf of) throws when tenant_id/client_secret is nil/empty' do
+ expect do
+ MicrosoftKiotaAuthenticationOAuth::OnBehalfOfContext.new(nil, nil, nil, nil)
+ end.to raise_error(StandardError)
+ expect do
+ MicrosoftKiotaAuthenticationOAuth::OnBehalfOfContext.new('tenant_id', 'client_id', 'client_secret',
+ 'assertion')
+ end.not_to raise_error
+ expect do
+ MicrosoftKiotaAuthenticationOAuth::OnBehalfOfContext.new('', 'client_id', 'client_secret',
+ 'assertion')
+ end.to raise_error(StandardError)
+ expect do
+ MicrosoftKiotaAuthenticationOAuth::OnBehalfOfContext.new('tenant_id', '', 'client_secret',
+ 'assertion')
+ end.to raise_error(StandardError)
+ expect do
+ MicrosoftKiotaAuthenticationOAuth::OnBehalfOfContext.new('tenant_id', 'client_id', '',
+ 'assertion')
+ end.to raise_error(StandardError)
+ expect do
+ MicrosoftKiotaAuthenticationOAuth::OnBehalfOfContext.new('tenant_id', 'client_id', 'client_secret',
+ '')
+ end.to raise_error(StandardError)
+ end
+
+ it 'throws when OAuthContext is used, but a custom flow is not implemented' do
+ expect { MicrosoftKiotaAuthenticationOAuth::OAuthContext.get_token }.to raise_error(NoMethodError)
+ end
+
+ it 'recognizes contexts as an OAuthContext' do
+ expect(MicrosoftKiotaAuthenticationOAuth::ClientCredentialContext.new('tenant_id', 'client_id', 'client_secret',
+ {}).is_a?(MicrosoftKiotaAuthenticationOAuth::OAuthContext)).to eq(true)
+ expect(MicrosoftKiotaAuthenticationOAuth::OnBehalfOfContext.new('tenant_id', 'client_id', 'client_secret',
+ 'assertion').is_a?(MicrosoftKiotaAuthenticationOAuth::OAuthContext)).to eq(true)
+ expect(MicrosoftKiotaAuthenticationOAuth::AuthorizationCodeContext.new('tenant_id', 'client_id', 'client_secret',
+ 'redirect_uri').is_a?(MicrosoftKiotaAuthenticationOAuth::OAuthContext)).to eq(true)
+ end
+end
diff --git a/components/authentication/oauth/spec/spec_helper.rb b/components/authentication/oauth/spec/spec_helper.rb
new file mode 100644
index 0000000..d105438
--- /dev/null
+++ b/components/authentication/oauth/spec/spec_helper.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require 'microsoft_kiota_abstractions'
+require_relative '../lib/microsoft_kiota_authentication_oauth/contexts/client_credential_context'
+require_relative '../lib/microsoft_kiota_authentication_oauth/contexts/authorization_code_context'
+require_relative '../lib/microsoft_kiota_authentication_oauth/contexts/on_behalf_of_context'
+require_relative '../lib/microsoft_kiota_authentication_oauth/contexts/oauth_context'
+require_relative '../lib/microsoft_kiota_authentication_oauth/contexts/oauth_custom_flow'
+require_relative '../lib/microsoft_kiota_authentication_oauth/extensions/oauth2_ext'
+require_relative '../lib/microsoft_kiota_authentication_oauth/oauth_access_token_provider'
+require_relative '../lib/microsoft_kiota_authentication_oauth/oauth_authentication_provider'
+
+RSpec.configure do |config|
+ # Enable flags like --only-failures and --next-failure
+ config.example_status_persistence_file_path = '.rspec_status'
+
+ # Disable RSpec exposing methods globally on `Module` and `main`
+ config.disable_monkey_patching!
+end
diff --git a/components/http/.rspec b/components/http/.rspec
new file mode 100644
index 0000000..34c5164
--- /dev/null
+++ b/components/http/.rspec
@@ -0,0 +1,3 @@
+--format documentation
+--color
+--require spec_helper
diff --git a/components/http/Gemfile b/components/http/Gemfile
new file mode 100644
index 0000000..efe05f1
--- /dev/null
+++ b/components/http/Gemfile
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+source 'https://rubygems.org'
+
+gem 'microsoft_kiota_abstractions', path: '../abstractions'
+
+gemspec
diff --git a/components/http/Rakefile b/components/http/Rakefile
new file mode 100644
index 0000000..82bb534
--- /dev/null
+++ b/components/http/Rakefile
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+require 'bundler/gem_tasks'
+require 'rspec/core/rake_task'
+
+RSpec::Core::RakeTask.new(:spec)
+
+task default: :spec
diff --git a/components/http/lib/microsoft_kiota_faraday.rb b/components/http/lib/microsoft_kiota_faraday.rb
new file mode 100644
index 0000000..4b2f3c7
--- /dev/null
+++ b/components/http/lib/microsoft_kiota_faraday.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require_relative 'microsoft_kiota_faraday/version'
+require_relative 'microsoft_kiota_faraday/middleware/response_handler_option'
+require_relative 'microsoft_kiota_faraday/middleware/parameters_name_decoding_option'
+require_relative 'microsoft_kiota_faraday/middleware/parameters_name_decoding_handler'
+require_relative 'microsoft_kiota_faraday/middleware/user_agent_option'
+require_relative 'microsoft_kiota_faraday/middleware/user_agent_handler'
+require_relative 'microsoft_kiota_faraday/kiota_client_factory'
+require_relative 'microsoft_kiota_faraday/faraday_request_adapter'
+
+module MicrosoftKiotaFaraday
+end
diff --git a/components/http/lib/microsoft_kiota_faraday/faraday_request_adapter.rb b/components/http/lib/microsoft_kiota_faraday/faraday_request_adapter.rb
new file mode 100644
index 0000000..1f426b2
--- /dev/null
+++ b/components/http/lib/microsoft_kiota_faraday/faraday_request_adapter.rb
@@ -0,0 +1,179 @@
+# frozen_string_literal: true
+
+require 'microsoft_kiota_abstractions'
+require 'faraday'
+require 'net/http'
+require_relative 'kiota_client_factory'
+require_relative 'middleware/response_handler_option'
+
+module MicrosoftKiotaFaraday
+ class FaradayRequestAdapter
+ include MicrosoftKiotaAbstractions::RequestAdapter
+
+ attr_accessor :authentication_provider, :content_type_header_key, :parse_node_factory,
+ :serialization_writer_factory, :client
+
+ def initialize(authentication_provider,
+ parse_node_factory = MicrosoftKiotaAbstractions::ParseNodeFactoryRegistry.default_instance, serialization_writer_factory = MicrosoftKiotaAbstractions::SerializationWriterFactoryRegistry.default_instance, client = KiotaClientFactory.get_default_http_client)
+ raise StandardError, 'authentication provider cannot be null' unless authentication_provider
+
+ @authentication_provider = authentication_provider
+ @content_type_header_key = 'Content-Type'
+ @parse_node_factory = parse_node_factory
+ if @parse_node_factory.nil?
+ @parse_node_factory = MicrosoftKiotaAbstractions::ParseNodeFactoryRegistry.default_instance
+ end
+ @serialization_writer_factory = serialization_writer_factory
+ if @serialization_writer_factory.nil?
+ @serialization_writer_factory = MicrosoftKiotaAbstractions::SerializationWriterFactoryRegistry.default_instance
+ end
+ @client = client
+ @client = KiotaClientFactory.get_default_http_client if @client.nil?
+ @base_url = ''
+ end
+
+ def set_base_url(base_url)
+ @base_url = base_url
+ end
+
+ def get_base_url
+ @base_url
+ end
+
+ def get_serialization_writer_factory
+ @serialization_writer_factory
+ end
+
+ def send_async(request_info, factory, errors_mapping)
+ raise StandardError, 'request_info cannot be null' unless request_info
+ raise StandardError, 'factory cannot be null' unless factory
+
+ Fiber.new do
+ set_base_url_for_request_information(request_info)
+ @authentication_provider.authenticate_request(request_info).resume
+ request = get_request_from_request_info(request_info)
+ response = @client.run_request(request.http_method, request.path, request.body, request.headers)
+
+ response_handler = get_response_handler(request_info)
+ response_handler&.call(response)&.resume
+ throw_if_failed_reponse(response, errors_mapping)
+ root_node = get_root_parse_node(response)
+ root_node.get_object_value(factory)
+ end
+ end
+
+ def get_response_handler(request_info)
+ unless request_info.nil?
+ option = request_info.get_request_option(MicrosoftKiotaFaraday::Middleware::ResponseHandlerOption::RESPONSE_HANDLER_KEY)
+ end
+ option.async_callback unless !option || option.nil?
+ end
+
+ def get_root_parse_node(response)
+ raise StandardError, 'response cannot be null' unless response
+
+ response_content_type = get_response_content_type(response)
+ raise StandardError, 'no response content type found for deserialization' unless response_content_type
+ return if response.body.nil? || response.body.empty?
+
+ @parse_node_factory.get_parse_node(response_content_type, response.body)
+ end
+
+ def throw_if_failed_reponse(response, errors_mapping)
+ raise StandardError, 'response cannot be null' unless response
+
+ status_code = response.status
+ return if status_code < 400
+
+ error_factory = errors_mapping[status_code] unless errors_mapping.nil?
+ error_factory = errors_mapping['4XX'] unless !error_factory.nil? || errors_mapping.nil? || status_code > 500
+ unless !error_factory.nil? || errors_mapping.nil? || status_code < 500 || status_code > 600
+ error_factory = errors_mapping['5XX']
+ end
+ unless !error_factory.nil? || errors_mapping.nil? || status_code < 400 || status_code > 600
+ error_factory = errors_mapping['XXX']
+ end
+ if error_factory.nil?
+ raise MicrosoftKiotaAbstractions::ApiError,
+ "The server returned an unexpected status code and no error factory is registered for this code:#{status_code}"
+ end
+
+ root_node = get_root_parse_node(response)
+ error = root_node.get_object_value(error_factory) unless root_node.nil?
+ raise error unless error.nil?
+
+ raise MicrosoftKiotaAbstractions::ApiError, "The server returned an unexpected status code:#{status_code}"
+ end
+
+ def get_request_from_request_info(request_info)
+ set_base_url_for_request_information(request_info)
+ case request_info.http_method
+ when :GET
+ request = @client.build_request(:get)
+ when :POST
+ request = @client.build_request(:post)
+ when :PATCH
+ request = @client.build_request(:patch)
+ when :DELETE
+ request = @client.build_request(:delete)
+ when :OPTIONS
+ request = @client.build_request(:options)
+ when :CONNECT
+ request = @client.build_request(:connect)
+ when :PUT
+ request = @client.build_request(:put)
+ when :TRACE
+ request = @client.build_request(:trace)
+ when :HEAD
+ request = @client.build_request(:head)
+ else
+ raise StandardError, 'unsupported http method'
+ end
+ request.path = request_info.uri
+ unless request_info.headers.nil?
+ request.headers = Faraday::Utils::Headers.new
+ request_info.headers.get_all.select do |k, v|
+ request.headers[k] = if v.is_a? Array
+ v.join(',')
+ elsif v.is_a? String
+ v
+ else
+ v.to_s
+ end
+ end
+ end
+ request.body = request_info.content unless request_info.content.nil? || request_info.content.empty?
+ # TODO: the json serialization writer returns a string at the moment, change to body_stream when this is fixed
+ request_options = request_info.get_request_options
+ if !request_options.nil? && !request_options.empty?
+ request.options = Faraday::RequestOptions.new if request.options.nil?
+ request_options.each do |value|
+ request.options.context[value.get_key] = value
+ end
+ end
+ request
+ end
+
+ def get_response_content_type(response)
+ response.headers['content-type'].split(';')[0].downcase
+ rescue StandardError
+ nil
+ end
+
+ def convert_to_native_request_async(request_info)
+ raise StandardError, 'request_info cannot be null' unless request_info
+
+ Fiber.new do
+ set_base_url_for_request_information(request_info)
+ @authentication_provider.authenticate_request(request_info).resume
+ return get_request_from_request_info(request_info)
+ end
+ end
+
+ private
+
+ def set_base_url_for_request_information(request_info)
+ request_info.path_parameters['baseurl'] = @base_url
+ end
+ end
+end
diff --git a/components/http/lib/microsoft_kiota_faraday/kiota_client_factory.rb b/components/http/lib/microsoft_kiota_faraday/kiota_client_factory.rb
new file mode 100644
index 0000000..f19e091
--- /dev/null
+++ b/components/http/lib/microsoft_kiota_faraday/kiota_client_factory.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+require 'net/https'
+require 'faraday'
+require_relative 'middleware/parameters_name_decoding_handler'
+require_relative 'middleware/user_agent_handler'
+module MicrosoftKiotaFaraday
+ class KiotaClientFactory
+ def self.get_default_middleware
+ [
+ MicrosoftKiotaFaraday::Middleware::ParametersNameDecodingHandler,
+ MicrosoftKiotaFaraday::Middleware::UserAgentHandler
+ ]
+ end
+
+ def self.get_default_http_client(middleware = nil, default_middleware_options = [])
+ if middleware.nil? # empty is fine in case the user doesn't want to use any middleware
+ middleware = get_default_middleware
+ end
+ connection_options = {}
+ connection_options[:request] = {}
+ connection_options[:request][:context] = {}
+ unless default_middleware_options.nil? || default_middleware_options.empty?
+ default_middleware_options.each do |value|
+ connection_options[:request][:context][value.get_key] = value
+ end
+ end
+ Faraday::Connection.new(nil, connection_options) do |builder|
+ builder.adapter Faraday.default_adapter
+ builder.ssl.verify = true
+ builder.ssl.verify_mode = OpenSSL::SSL::VERIFY_PEER
+ middleware.each do |handler|
+ builder.use handler
+ end
+ end
+ end
+ end
+end
diff --git a/components/http/lib/microsoft_kiota_faraday/middleware/parameters_name_decoding_handler.rb b/components/http/lib/microsoft_kiota_faraday/middleware/parameters_name_decoding_handler.rb
new file mode 100644
index 0000000..0933189
--- /dev/null
+++ b/components/http/lib/microsoft_kiota_faraday/middleware/parameters_name_decoding_handler.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'faraday'
+require_relative 'parameters_name_decoding_option'
+module MicrosoftKiotaFaraday
+ module Middleware
+ class ParametersNameDecodingHandler < Faraday::Middleware
+ @@default_option = ParametersNameDecodingOption.new
+ def call(request_env)
+ unless request_env[:request].nil? || request_env[:request][:context].nil?
+ request_option = request_env[:request][:context][@@default_option.get_key]
+ end
+ request_option = @@default_option if request_option.nil?
+ unless request_env[:url].nil? || !request_option.enabled || request_option.characters_to_decode.nil? || request_option.characters_to_decode.empty?
+ request_url = request_env[:url].to_s
+ request_option.characters_to_decode.each do |character|
+ request_url = request_url.gsub(get_regex_for_character(character), character)
+ end
+ request_env[:url] = URI.parse(request_url)
+ end
+ @app&.call(request_env)
+ end
+
+ def get_regex_for_character(character)
+ @regex_cache ||= {}
+ @regex_cache[character] = Regexp.new("%#{character.ord.to_s(16)}", true) if @regex_cache[character].nil?
+ @regex_cache[character]
+ end
+ end
+ end
+end
diff --git a/components/http/lib/microsoft_kiota_faraday/middleware/parameters_name_decoding_option.rb b/components/http/lib/microsoft_kiota_faraday/middleware/parameters_name_decoding_option.rb
new file mode 100644
index 0000000..c9ed3e5
--- /dev/null
+++ b/components/http/lib/microsoft_kiota_faraday/middleware/parameters_name_decoding_option.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'microsoft_kiota_abstractions'
+module MicrosoftKiotaFaraday
+ module Middleware
+ class ParametersNameDecodingOption
+ include MicrosoftKiotaAbstractions::RequestOption
+
+ attr_accessor :enabled, :characters_to_decode
+
+ def initialize(enabled = true, characters_to_decode = ['$', '.', '-', '~'])
+ @enabled = enabled
+ @characters_to_decode = characters_to_decode
+ end
+
+ def get_key
+ 'parametersNameDecoding'
+ end
+ end
+ end
+end
diff --git a/components/http/lib/microsoft_kiota_faraday/middleware/response_handler_option.rb b/components/http/lib/microsoft_kiota_faraday/middleware/response_handler_option.rb
new file mode 100644
index 0000000..555227b
--- /dev/null
+++ b/components/http/lib/microsoft_kiota_faraday/middleware/response_handler_option.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+require 'microsoft_kiota_abstractions'
+module MicrosoftKiotaFaraday
+ module Middleware
+ class ResponseHandlerOption
+ RESPONSE_HANDLER_KEY = 'responseHandler'
+ # a lambda that takes the native response type and returns a Fiber with a MicrosoftKiotaAbstractions::Parsable
+ attr_accessor :async_callback
+
+ def get_key
+ RESPONSE_HANDLER_KEY
+ end
+ end
+ end
+end
diff --git a/components/http/lib/microsoft_kiota_faraday/middleware/user_agent_handler.rb b/components/http/lib/microsoft_kiota_faraday/middleware/user_agent_handler.rb
new file mode 100644
index 0000000..964bf4e
--- /dev/null
+++ b/components/http/lib/microsoft_kiota_faraday/middleware/user_agent_handler.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+require 'faraday'
+require_relative 'user_agent_option'
+module MicrosoftKiotaFaraday
+ module Middleware
+ class UserAgentHandler < Faraday::Middleware
+ @@default_option = UserAgentOption.new
+ @@user_agent_key = 'User-Agent'
+ def call(request_env)
+ unless request_env[:request].nil? || request_env[:request][:context].nil?
+ request_option = request_env[:request][:context][@@default_option.get_key]
+ end
+ request_option = @@default_option if request_option.nil?
+ unless request_env[:request_headers].nil? || !request_option.enabled || request_option.product_name.nil? || request_option.product_name.empty? || request_option.product_version.nil? || request_option.product_version.empty?
+ existing_value = request_env[:request_headers][@@user_agent_key]
+ additional_value = "#{request_option.product_name}/#{request_option.product_version}"
+ if !existing_value || existing_value.empty?
+ request_env[:request_headers][@@user_agent_key] = additional_value
+ elsif !existing_value.include? additional_value
+ request_env[:request_headers][@@user_agent_key] = "#{existing_value} #{additional_value}"
+ end
+ end
+ @app&.call(request_env)
+ end
+ end
+ end
+end
diff --git a/components/http/lib/microsoft_kiota_faraday/middleware/user_agent_option.rb b/components/http/lib/microsoft_kiota_faraday/middleware/user_agent_option.rb
new file mode 100644
index 0000000..d93beb1
--- /dev/null
+++ b/components/http/lib/microsoft_kiota_faraday/middleware/user_agent_option.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+require 'microsoft_kiota_abstractions'
+require_relative '../version'
+module MicrosoftKiotaFaraday
+ module Middleware
+ class UserAgentOption
+ include MicrosoftKiotaAbstractions::RequestOption
+
+ attr_accessor :enabled, :product_name, :product_version
+
+ def initialize
+ @enabled = true
+ @product_name = 'kiota-ruby'
+ @product_version = MicrosoftKiotaFaraday::VERSION
+ end
+
+ def get_key
+ 'userAgent'
+ end
+ end
+ end
+end
diff --git a/components/http/lib/microsoft_kiota_faraday/version.rb b/components/http/lib/microsoft_kiota_faraday/version.rb
new file mode 100644
index 0000000..51cc640
--- /dev/null
+++ b/components/http/lib/microsoft_kiota_faraday/version.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+module MicrosoftKiotaFaraday
+ VERSION = '0.17.0' # x-release-please-version
+end
diff --git a/components/http/microsoft_kiota_faraday.gemspec b/components/http/microsoft_kiota_faraday.gemspec
new file mode 100644
index 0000000..2cb5e0d
--- /dev/null
+++ b/components/http/microsoft_kiota_faraday.gemspec
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+require_relative 'lib/microsoft_kiota_faraday/version'
+
+Gem::Specification.new do |spec|
+ spec.name = 'microsoft_kiota_faraday'
+ spec.version = MicrosoftKiotaFaraday::VERSION
+ spec.authors = 'Microsoft Corporation'
+ spec.email = 'graphsdkpub+ruby@microsoft.com'
+ spec.description = 'Kiota HttpCore implementation with Faraday'
+ spec.summary = 'Microsoft Kiota Faraday - Kiota Ruby http request adapter for running requests'
+ spec.homepage = 'https://learn.microsoft.com/openapi/kiota/'
+ spec.license = 'MIT'
+ spec.metadata = {
+ 'bug_tracker_uri' => 'https://github.com/microsoft/kiota-ruby/issues',
+ 'changelog_uri' => 'https://github.com/microsoft/kiota-ruby/blob/main/CHANGELOG.md',
+ 'homepage_uri' => spec.homepage,
+ 'source_code_uri' => 'https://github.com/microsoft/kiota-ruby/tree/main/components/http',
+ 'github_repo' => 'ssh://github.com/microsoft/kiota-ruby',
+ 'rubygems_mfa_required' => 'true'
+ }
+ spec.required_ruby_version = '>= 3.3.0'
+
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
+ end
+ spec.bindir = 'bin'
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
+ spec.require_paths = ['lib']
+ spec.add_dependency 'faraday', '~> 2.7', '>= 2.7.2'
+ spec.add_dependency 'microsoft_kiota_abstractions', '>= 0.17', '< 0.18'
+ spec.add_development_dependency 'rake', '~> 13.0'
+ spec.add_development_dependency 'rspec', '~> 3.0'
+ spec.add_development_dependency 'rubocop'
+end
diff --git a/components/http/spec/authentication_provider.rb b/components/http/spec/authentication_provider.rb
new file mode 100644
index 0000000..b4af8a1
--- /dev/null
+++ b/components/http/spec/authentication_provider.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+require 'microsoft_kiota_abstractions'
+
+class AuthenticationProvider
+ include MicrosoftKiotaAbstractions::AuthenticationProvider
+end
diff --git a/components/http/spec/microsoft_kiota_faraday.rb b/components/http/spec/microsoft_kiota_faraday.rb
new file mode 100644
index 0000000..eca567c
--- /dev/null
+++ b/components/http/spec/microsoft_kiota_faraday.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require_relative 'authentication_provider'
+
+RSpec.describe MicrosoftKiotaFaraday do
+ it 'has a version number' do
+ expect(MicrosoftKiotaFaraday::VERSION).not_to be nil
+ end
+
+ it 'does something useful' do
+ expect(true).to eq(true)
+ end
+
+ it 'can instantiate a request adapter' do
+ auth_provider = AuthenticationProvider.new
+ adapter = MicrosoftKiotaFaraday::FaradayRequestAdapter.new(auth_provider)
+ expect(adapter).to_not be nil
+ end
+end
diff --git a/components/http/spec/microsoft_kiota_faraday/faraday_request_adapter_spec.rb b/components/http/spec/microsoft_kiota_faraday/faraday_request_adapter_spec.rb
new file mode 100644
index 0000000..12a8863
--- /dev/null
+++ b/components/http/spec/microsoft_kiota_faraday/faraday_request_adapter_spec.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+RSpec.describe MicrosoftKiotaFaraday::FaradayRequestAdapter do
+ subject(:adapter) { described_class.new(authentication_provider) }
+
+ let(:authentication_provider) { double('authentication_provider') }
+ let(:headers) { { 'content-type' => 'application/json' } }
+ let(:body) { { key: 'value' }.to_json }
+
+ describe '#get_root_parse_node' do
+ context 'when response is null' do
+ it 'raises an error' do
+ expect { adapter.get_root_parse_node(nil) }.to raise_error(StandardError, 'response cannot be null')
+ end
+ end
+
+ context 'when response content type is not found' do
+ let(:response) { instance_double(Faraday::Response, body:, headers: {}) }
+
+ it 'raises an error' do
+ expect do
+ adapter.get_root_parse_node(response)
+ end.to raise_error(StandardError,
+ 'no response content type found for deserialization')
+ end
+ end
+
+ context 'when response body is nil' do
+ let(:response) { instance_double(Faraday::Response, body: nil, headers:) }
+
+ it 'returns nil' do
+ expect(adapter.get_root_parse_node(response)).to be_nil
+ end
+ end
+
+ context 'when response body is empty' do
+ let(:response) { instance_double(Faraday::Response, body: '', headers:) }
+
+ it 'returns nil' do
+ expect(adapter.get_root_parse_node(response)).to be_nil
+ end
+ end
+
+ context 'when response body is not nil' do
+ subject(:adapter) { described_class.new(authentication_provider, parse_node_factory) }
+
+ let(:response) { instance_double(Faraday::Response, body:, headers:) }
+ let(:parse_node_factory) { double('parse_node_factory') }
+ let(:parse_node) { double('parse_node') }
+
+ before do
+ allow(parse_node_factory).to receive(:get_parse_node).with('application/json', body).and_return(parse_node)
+ end
+
+ it 'returns the parse node' do
+ expect(adapter.get_root_parse_node(response)).to eq(parse_node)
+ end
+ end
+ end
+end
diff --git a/components/http/spec/parameters_name_decoding_handler_spec.rb b/components/http/spec/parameters_name_decoding_handler_spec.rb
new file mode 100644
index 0000000..3869e2d
--- /dev/null
+++ b/components/http/spec/parameters_name_decoding_handler_spec.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+require 'faraday'
+
+# frozen_string_literal: true
+RSpec.describe MicrosoftKiotaFaraday do
+ it 'decodes encoded query parameters' do
+ values = {}
+ values['?%24select=diplayName&api%2Dversion=2'] = '?$select=diplayName&api-version=2'
+ values['?%24select=diplayName&api%7Eversion=2'] = '?$select=diplayName&api~version=2'
+ values['?%24select=diplayName&api%2Eversion=2'] = '?$select=diplayName&api.version=2'
+ values['/api-version/?%24select=diplayName&api%2Eversion=2'] = '/api-version/?$select=diplayName&api.version=2'
+ values[''] = ''
+
+ handler = MicrosoftKiotaFaraday::Middleware::ParametersNameDecodingHandler.new
+ values.each do |key, value|
+ env = {
+ url: URI.parse("https://graph.microsoft.com/v1.0/users#{key}")
+ }
+ handler.call(env)
+ expect(env[:url].to_s).to eq("https://graph.microsoft.com/v1.0/users#{value}")
+ end
+ end
+
+ it "doesn't decode when disabled on request" do
+ values = {}
+ values['?%24select=diplayName&api%2Dversion=2'] = '?%24select=diplayName&api%2Dversion=2'
+ values['?%24select=diplayName&api%7Eversion=2'] = '?%24select=diplayName&api%7Eversion=2'
+ values['?%24select=diplayName&api%2Eversion=2'] = '?%24select=diplayName&api%2Eversion=2'
+ values['/api-version/?%24select=diplayName&api%2Eversion=2'] =
+ '/api-version/?%24select=diplayName&api%2Eversion=2'
+ values[''] = ''
+
+ option = MicrosoftKiotaFaraday::Middleware::ParametersNameDecodingOption.new(false)
+ handler = MicrosoftKiotaFaraday::Middleware::ParametersNameDecodingHandler.new
+ values.each do |key, value|
+ env = {
+ url: URI.parse("https://graph.microsoft.com/v1.0/users#{key}"),
+ request: {
+ context: {
+ option.get_key => option
+ }
+ }
+ }
+ handler.call(env)
+ expect(env[:url].to_s).to eq("https://graph.microsoft.com/v1.0/users#{value}")
+ end
+ end
+end
diff --git a/components/http/spec/spec_helper.rb b/components/http/spec/spec_helper.rb
new file mode 100644
index 0000000..227d8c8
--- /dev/null
+++ b/components/http/spec/spec_helper.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+require 'microsoft_kiota_faraday'
+
+Dir["#{File.dirname(__FILE__)}/./../lib/*.rb"].each { |f| load(f) }
+
+RSpec.configure do |config|
+ # Enable flags like --only-failures and --next-failure
+ config.example_status_persistence_file_path = '.rspec_status'
+
+ # Disable RSpec exposing methods globally on `Module` and `main`
+ config.disable_monkey_patching!
+
+ config.expect_with :rspec do |c|
+ c.syntax = :expect
+ end
+end
diff --git a/components/http/spec/user_agent_handler_spec.rb b/components/http/spec/user_agent_handler_spec.rb
new file mode 100644
index 0000000..6d40ea8
--- /dev/null
+++ b/components/http/spec/user_agent_handler_spec.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+require 'faraday'
+
+# frozen_string_literal: true
+RSpec.describe MicrosoftKiotaFaraday do
+ user_agent_key = 'User-Agent'
+ url = 'https://graph.microsoft.com/v1.0/users'
+ it 'adds the user agent product' do
+ handler = MicrosoftKiotaFaraday::Middleware::UserAgentHandler.new
+ env = {
+ url: URI.parse(url),
+ request_headers: {}
+ }
+ handler.call(env)
+ expect(env[:request_headers][user_agent_key].split('/')[0]).to eq('kiota-ruby')
+ end
+
+ it 'adds the user agent product once' do
+ handler = MicrosoftKiotaFaraday::Middleware::UserAgentHandler.new
+ env = {
+ url: URI.parse(url),
+ request_headers: {}
+ }
+ handler.call(env)
+ handler.call(env)
+ expect(env[:request_headers][user_agent_key].split('kiota-ruby').length).to eq(2)
+ end
+ it 'doesnt add the header when disabled' do
+ handler = MicrosoftKiotaFaraday::Middleware::UserAgentHandler.new
+ opt = MicrosoftKiotaFaraday::Middleware::UserAgentOption.new
+ opt.enabled = false
+ env = {
+ url: URI.parse(url),
+ request_headers: {},
+ request: {
+ context: {
+ opt.get_key => opt
+ }
+ }
+ }
+ handler.call(env)
+ handler.call(env)
+ expect(env[:request_headers][user_agent_key]).to be_nil
+ end
+end
diff --git a/components/serialization/json/Gemfile b/components/serialization/json/Gemfile
new file mode 100644
index 0000000..f4859ea
--- /dev/null
+++ b/components/serialization/json/Gemfile
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+source 'https://rubygems.org'
+
+gem 'microsoft_kiota_abstractions', path: '../../abstractions'
+
+gemspec
diff --git a/components/serialization/json/Rakefile b/components/serialization/json/Rakefile
new file mode 100644
index 0000000..82bb534
--- /dev/null
+++ b/components/serialization/json/Rakefile
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+require 'bundler/gem_tasks'
+require 'rspec/core/rake_task'
+
+RSpec::Core::RakeTask.new(:spec)
+
+task default: :spec
diff --git a/components/serialization/json/lib/microsoft_kiota_serialization_json.rb b/components/serialization/json/lib/microsoft_kiota_serialization_json.rb
new file mode 100644
index 0000000..128b3e6
--- /dev/null
+++ b/components/serialization/json/lib/microsoft_kiota_serialization_json.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+require_relative 'microsoft_kiota_serialization_json/json_parse_node'
+require_relative 'microsoft_kiota_serialization_json/json_parse_node_factory'
+require_relative 'microsoft_kiota_serialization_json/json_serialization_writer'
+require_relative 'microsoft_kiota_serialization_json/json_serialization_writer_factory'
+require_relative 'microsoft_kiota_serialization_json/version'
+
+module MicrosoftKiotaSerializationJson
+end
diff --git a/components/serialization/json/lib/microsoft_kiota_serialization_json/json_parse_node.rb b/components/serialization/json/lib/microsoft_kiota_serialization_json/json_parse_node.rb
new file mode 100644
index 0000000..b1a8ca0
--- /dev/null
+++ b/components/serialization/json/lib/microsoft_kiota_serialization_json/json_parse_node.rb
@@ -0,0 +1,139 @@
+# frozen_string_literal: true
+
+require 'time'
+require 'date'
+require 'json'
+require 'uuidtools'
+require 'microsoft_kiota_abstractions'
+
+module MicrosoftKiotaSerializationJson
+ class JsonParseNode
+ include MicrosoftKiotaAbstractions::ParseNode
+
+ def initialize(node)
+ @current_node = node
+ end
+
+ def get_string_value
+ @current_node.to_s
+ end
+
+ def get_boolean_value
+ @current_node
+ end
+
+ def get_number_value
+ @current_node.to_i
+ end
+
+ def get_float_value
+ @current_node.to_f
+ end
+
+ def get_guid_value
+ UUIDTools::UUID.parse(@current_node)
+ end
+
+ def get_date_value
+ Date.parse(@current_node)
+ end
+
+ def get_time_value
+ Time.parse(@current_node)
+ end
+
+ def get_date_time_value
+ DateTime.parse(@current_node)
+ end
+
+ def get_duration_value
+ MicrosoftKiotaAbstractions::ISODuration.new(@current_node)
+ end
+
+ def get_collection_of_primitive_values(type)
+ @current_node.map do |object|
+ next if object.nil?
+
+ current_parse_node = JsonParseNode.new(object)
+ case type
+ when String
+ current_parse_node.get_string_value
+ when Float
+ current_parse_node.get_float_value
+ when Integer
+ current_parse_node.get_float_value
+ when 'Boolean'
+ current_parse_node.get_float_value
+ when DateTime
+ current_parse_node.get_date_time_value
+ when Time
+ current_parse_node.get_time_value
+ when Date
+ current_parse_node.get_date_value
+ when MicrosoftKiotaAbstractions::ISODuration
+ current_parse_node.get_duration_value
+ when UUIDTools::UUID
+ current_parse_node.get_guid_value
+ else
+ current_parse_node.get_string_value
+ end
+ rescue StandardError => e
+ raise e.class, `Failed to fetch #{type} type`
+ end
+ end
+
+ def get_collection_of_object_values(factory)
+ raise StandardError, 'Factory cannot be null' if factory.nil?
+
+ @current_node.map do |object|
+ next if object.nil?
+
+ current_parse_node = JsonParseNode.new(object)
+ current_parse_node.get_object_value(factory)
+ end
+ end
+
+ def get_object_value(factory)
+ raise StandardError, 'Factory cannot be null' if factory.nil?
+
+ item = factory.call(self)
+ assign_field_values(item)
+ item
+ rescue StandardError => e
+ raise e.class, 'Error during deserialization'
+ end
+
+ def assign_field_values(item)
+ fields = item.get_field_deserializers
+ @current_node.each do |k, v|
+ next if v.nil?
+
+ deserializer = fields[k]
+ if deserializer
+ deserializer.call(JsonParseNode.new(v))
+ elsif item.additional_data
+ item.additional_data[k] = v
+ else
+ item.additional_data = Hash.new({ k => v })
+ end
+ end
+ end
+
+ def get_enum_values(_type)
+ raw_values = get_string_value
+ raw_values.split(',').map(&:strip)
+ end
+
+ def get_enum_value(type)
+ items = get_enum_values(type).map(&:to_sym)
+ items[0] if items.length.positive?
+ end
+
+ def get_child_node(name)
+ raise StandardError, 'Name cannot be null' if name.nil? || name.empty?
+
+ raw_value = @current_node[name]
+ JsonParseNode.new(raw_value) if raw_value
+ end
+ end
+end
diff --git a/components/serialization/json/lib/microsoft_kiota_serialization_json/json_parse_node_factory.rb b/components/serialization/json/lib/microsoft_kiota_serialization_json/json_parse_node_factory.rb
new file mode 100644
index 0000000..b96f805
--- /dev/null
+++ b/components/serialization/json/lib/microsoft_kiota_serialization_json/json_parse_node_factory.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'json'
+require 'microsoft_kiota_abstractions'
+
+module MicrosoftKiotaSerializationJson
+ class JsonParseNodeFactory
+ include MicrosoftKiotaAbstractions::ParseNodeFactory
+
+ def get_valid_content_type
+ 'application/json'
+ end
+
+ def get_parse_node(content_type, content)
+ if !content_type
+ raise StandardError, 'content type cannot be undefined or empty'
+ elsif get_valid_content_type != content_type
+ raise StandardError, `expected a #{get_valid_content_type} content type`
+ end
+ raise StandardError, 'content cannot be undefined or empty' unless content
+
+ JsonParseNode.new(JSON.parse(content))
+ end
+ end
+end
diff --git a/components/serialization/json/lib/microsoft_kiota_serialization_json/json_serialization_writer.rb b/components/serialization/json/lib/microsoft_kiota_serialization_json/json_serialization_writer.rb
new file mode 100644
index 0000000..f354d89
--- /dev/null
+++ b/components/serialization/json/lib/microsoft_kiota_serialization_json/json_serialization_writer.rb
@@ -0,0 +1,172 @@
+# frozen_string_literal: true
+
+require 'time'
+require 'date'
+require 'json'
+require 'uuidtools'
+require 'microsoft_kiota_abstractions'
+
+module MicrosoftKiotaSerializationJson
+ class JsonSerializationWriter
+ include MicrosoftKiotaAbstractions::SerializationWriter
+
+ def initialize
+ @writer = {}
+ end
+
+ attr_reader :writer
+
+ def write_string_value(key, value)
+ raise StandardError, 'no key or value included in write_string_value(key, value)' if !key && !value
+ return value.to_s unless key
+
+ @writer[key] = (value || nil)
+ end
+
+ def write_boolean_value(key, value)
+ raise StandardError, 'no key or value included in write_boolean_value(key, value)' if !key && !value
+ return value unless key
+
+ @writer[key] = value
+ end
+
+ def write_number_value(key, value)
+ raise StandardError, 'no key or value included in write_number_value(key, value)' if !key && !value
+ return value unless key
+
+ @writer[key] = value
+ end
+
+ def write_float_value(key, value)
+ raise StandardError, 'no key or value included in write_float_value(key, value)' if !key && !value
+ return value unless key
+
+ @writer[key] = value
+ end
+
+ def write_guid_value(key, value)
+ raise StandardError, 'no key or value included in write_guid_value(key, value)' if !key && !value
+ return value.to_s unless key
+
+ @writer[key] = (value.to_s if value)
+ end
+
+ def write_date_value(key, value)
+ raise StandardError, 'no key or value included in write_date_value(key, value)' if !key && !value
+ return value.strftime('%Y-%m-%d') unless key
+
+ @writer[key] = (value.strftime('%Y-%m-%d') if value)
+ end
+
+ def write_time_value(key, value)
+ raise StandardError, 'no key or value included in write_time_value(key, value)' if !key && !value
+ return value.strftime('%H:%M:%S%Z') unless key
+
+ @writer[key] = (value.strftime('%H:%M:%S%Z') if value)
+ end
+
+ def write_date_time_value(key, value)
+ raise StandardError, 'no key or value included in write_date_time_value(key, value)' if !key && !value
+ return value.strftime('%Y-%m-%dT%H:%M:%S%Z') unless key
+
+ @writer[key] = (value.strftime('%Y-%m-%dT%H:%M:%S%Z') if value)
+ end
+
+ def write_duration_value(key, value)
+ raise StandardError, 'no key or value included in write_duration_value(key, value)' if !key && !value
+ return value.string unless key
+
+ @writer[key] = (value.string if value)
+ end
+
+ def write_collection_of_primitive_values(key, values)
+ return unless values
+ unless key
+ return values.map do |v|
+ write_any_value(nil, v)
+ end
+ end
+ @writer[key] = values.map do |v|
+ write_any_value(key, v)
+ end
+ end
+
+ def write_collection_of_object_values(key, values)
+ return unless values
+ return values.map { |v| write_object_value(nil, v) } unless key
+
+ @writer[key] = values.map { |v| object_value_hash(v) }
+ end
+
+ def write_object_value(key, value, *additional_values_to_merge)
+ return unless value
+
+ if key
+ @writer[key] = object_value_hash(value, *additional_values_to_merge)
+ else
+ value.serialize(self)
+ additional_values_to_merge.each { |v| v&.serialize(self) }
+ end
+ end
+
+ def write_enum_value(key, values)
+ write_string_value(key, values.to_s)
+ end
+
+ def get_serialized_content
+ @writer.to_json # TODO: encode to byte array to stay content type agnostic
+ end
+
+ def write_additional_data(value)
+ return unless value
+
+ value.each do |x, y|
+ write_any_value(x, y)
+ end
+ end
+
+ private
+
+ def object_value_hash(value, *additional_values_to_merge)
+ temp = JsonSerializationWriter.new
+ value.serialize(temp)
+ additional_values_to_merge.each { |v| v&.serialize(temp) }
+ temp.writer
+ end
+
+ public
+
+ def write_any_value(key, value)
+ if value
+ if !value.nil? == value
+ value
+ elsif value.instance_of? String
+ write_string_value(key, value)
+ elsif value.instance_of? Integer
+ write_number_value(key, value)
+ elsif value.instance_of? Float
+ write_float_value(key, value)
+ elsif value.instance_of? DateTime
+ write_date_time_value(key, value)
+ elsif value.instance_of? Time
+ write_time_value(key, value)
+ elsif value.instance_of? Date
+ write_date_value(key, value)
+ elsif value.instance_of? MicrosoftKiotaAbstractions::ISODuration
+ write_duration_value(key, value)
+ elsif value.instance_of? Array
+ write_collection_of_primitive_values(key, value)
+ elsif value.is_a? Object
+ value.to_s
+ else
+ raise StandardError, "encountered unknown value type during serialization #{value}"
+ end
+ else
+ raise StandardError, 'no key included when writing json property' unless key
+
+ @writer[key] = nil
+
+ end
+ end
+ end
+end
diff --git a/components/serialization/json/lib/microsoft_kiota_serialization_json/json_serialization_writer_factory.rb b/components/serialization/json/lib/microsoft_kiota_serialization_json/json_serialization_writer_factory.rb
new file mode 100644
index 0000000..01f77fb
--- /dev/null
+++ b/components/serialization/json/lib/microsoft_kiota_serialization_json/json_serialization_writer_factory.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+require 'microsoft_kiota_abstractions'
+
+module MicrosoftKiotaSerializationJson
+ class JsonSerializationWriterFactory
+ include MicrosoftKiotaAbstractions::SerializationWriterFactory
+
+ def get_valid_content_type
+ 'application/json'
+ end
+
+ def get_serialization_writer(content_type)
+ if !content_type
+ raise StandardError, 'content type cannot be undefined or empty'
+ elsif get_valid_content_type != content_type
+ raise StandardError, `expected a #{get_valid_content_type} content type`
+ end
+
+ JsonSerializationWriter.new
+ end
+ end
+end
diff --git a/components/serialization/json/lib/microsoft_kiota_serialization_json/version.rb b/components/serialization/json/lib/microsoft_kiota_serialization_json/version.rb
new file mode 100644
index 0000000..9e0816e
--- /dev/null
+++ b/components/serialization/json/lib/microsoft_kiota_serialization_json/version.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+module MicrosoftKiotaSerializationJson
+ VERSION = '0.17.0' # x-release-please-version
+end
diff --git a/components/serialization/json/microsoft_kiota_serialization_json.gemspec b/components/serialization/json/microsoft_kiota_serialization_json.gemspec
new file mode 100644
index 0000000..71bcc5c
--- /dev/null
+++ b/components/serialization/json/microsoft_kiota_serialization_json.gemspec
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+require_relative 'lib/microsoft_kiota_serialization_json/version'
+
+Gem::Specification.new do |spec|
+ spec.name = 'microsoft_kiota_serialization_json'
+ spec.version = MicrosoftKiotaSerializationJson::VERSION
+ spec.authors = 'Microsoft Corporation'
+ spec.email = 'graphsdkpub+ruby@microsoft.com'
+ spec.description = 'Implementation of Kiota Serialization interfaces for JSON'
+ spec.summary = 'Microsoft Kiota Serialization - Ruby serialization for building library agnostic http client'
+ spec.homepage = 'https://learn.microsoft.com/openapi/kiota/'
+ spec.license = 'MIT'
+ spec.metadata = {
+ 'bug_tracker_uri' => 'https://github.com/microsoft/kiota-ruby/issues',
+ 'changelog_uri' => 'https://github.com/microsoft/kiota-ruby/blob/main/CHANGELOG.md',
+ 'homepage_uri' => spec.homepage,
+ 'source_code_uri' => 'https://github.com/microsoft/kiota-ruby/tree/main/components/serialization/json',
+ 'github_repo' => 'ssh://github.com/microsoft/kiota-ruby',
+ 'rubygems_mfa_required' => 'true'
+ }
+ spec.required_ruby_version = '>= 3.3.0'
+
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
+ end
+ spec.bindir = 'bin'
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
+ spec.require_paths = ['lib']
+ spec.add_dependency 'json', '>= 2.6.3', '< 2.22.0'
+ spec.add_dependency 'microsoft_kiota_abstractions', '>= 0.17', '< 0.18'
+ spec.add_dependency 'uuidtools', '>= 2.2', '< 3.1'
+ spec.add_development_dependency 'rake', '~> 13.0'
+ spec.add_development_dependency 'rspec', '~> 3.0'
+ spec.add_development_dependency 'rubocop'
+end
diff --git a/components/serialization/json/spec/files/body_type.rb b/components/serialization/json/spec/files/body_type.rb
new file mode 100644
index 0000000..9480e68
--- /dev/null
+++ b/components/serialization/json/spec/files/body_type.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+module Files
+ BodyType = {
+ Text: :Text,
+ Html: :Html
+ }.freeze
+end
diff --git a/components/serialization/json/spec/files/email_address.rb b/components/serialization/json/spec/files/email_address.rb
new file mode 100644
index 0000000..06492d8
--- /dev/null
+++ b/components/serialization/json/spec/files/email_address.rb
@@ -0,0 +1,95 @@
+# frozen_string_literal: true
+
+require 'microsoft_kiota_abstractions'
+
+module Files
+ class EmailAddress
+ include MicrosoftKiotaAbstractions::Parsable
+ include MicrosoftKiotaAbstractions::AdditionalDataHolder
+
+ ##
+ # Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well.
+ ##
+ # The email address of the person or entity.
+ ##
+ # The display name of the person or entity.
+ ##
+ ## Gets the additionalData property value. Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well.
+ ## @return a i_dictionary
+ ##
+ attr_accessor :additional_data
+
+ ##
+ ## Sets the additionalData property value. Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well.
+ ## @param value Value to set for the AdditionalData property.
+ ## @return a void
+ ##
+
+ ##
+ ## Gets the address property value. The email address of the person or entity.
+ ## @return a string
+ ##
+ attr_accessor :address
+
+ ##
+ ## Sets the address property value. The email address of the person or entity.
+ ## @param value Value to set for the address property.
+ ## @return a void
+ ##
+
+ ##
+ ## Instantiates a new emailAddress and sets the default values.
+ ## @return a void
+ ##
+ def initialize
+ @additional_data = {}
+ end
+
+ ##
+ ## Creates a new instance of the appropriate class based on discriminator value
+ ## @param parseNode The parse node to use to read the discriminator value and create the object
+ ## @return a email_address
+ ##
+ def self.create_from_discriminator_value(parse_node)
+ raise StandardError, 'parse_node cannot be null' if parse_node.nil?
+
+ EmailAddress.new
+ end
+
+ ##
+ ## The deserialization information for the current model
+ ## @return a i_dictionary
+ ##
+ def get_field_deserializers
+ {
+ 'address' => ->(n) { @address = n.get_string_value },
+ 'name' => ->(n) { @name = n.get_string_value }
+ }
+ end
+
+ ##
+ ## Gets the name property value. The display name of the person or entity.
+ ## @return a string
+ ##
+ attr_accessor :name
+
+ ##
+ ## Sets the name property value. The display name of the person or entity.
+ ## @param value Value to set for the name property.
+ ## @return a void
+ ##
+
+ ##
+ ## Serializes information the current object
+ ## @param writer Serialization writer to use to serialize this model
+ ## @return a void
+ ##
+ def serialize(writer)
+ raise StandardError, 'writer cannot be null' if writer.nil?
+
+ writer.write_string_value('address', @address)
+ writer.write_string_value('name', @name)
+ writer.write_additional_data(@additional_data)
+ end
+ end
+end
diff --git a/components/serialization/json/spec/files/entity.rb b/components/serialization/json/spec/files/entity.rb
new file mode 100644
index 0000000..6b25dbe
--- /dev/null
+++ b/components/serialization/json/spec/files/entity.rb
@@ -0,0 +1,79 @@
+# frozen_string_literal: true
+
+require 'microsoft_kiota_abstractions'
+
+module Files
+ class Entity
+ include MicrosoftKiotaAbstractions::Parsable
+ include MicrosoftKiotaAbstractions::AdditionalDataHolder
+
+ ##
+ # Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well.
+ ##
+ # The unique idenfier for an entity. Read-only.
+ ##
+ ## Gets the additionalData property value. Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well.
+ ## @return a i_dictionary
+ ##
+ attr_accessor :additional_data
+
+ ##
+ ## Sets the additionalData property value. Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well.
+ ## @param value Value to set for the AdditionalData property.
+ ## @return a void
+ ##
+
+ ##
+ ## Instantiates a new entity and sets the default values.
+ ## @return a void
+ ##
+ def initialize
+ @additional_data = {}
+ end
+
+ ##
+ ## Creates a new instance of the appropriate class based on discriminator value
+ ## @param parseNode The parse node to use to read the discriminator value and create the object
+ ## @return a entity
+ ##
+ def self.create_from_discriminator_value(parse_node)
+ raise StandardError, 'parse_node cannot be null' if parse_node.nil?
+
+ Entity.new
+ end
+
+ ##
+ ## The deserialization information for the current model
+ ## @return a i_dictionary
+ ##
+ def get_field_deserializers
+ {
+ 'id' => ->(n) { @id = n.get_string_value }
+ }
+ end
+
+ ##
+ ## Gets the id property value. The unique idenfier for an entity. Read-only.
+ ## @return a string
+ ##
+ attr_accessor :id
+
+ ##
+ ## Sets the id property value. The unique idenfier for an entity. Read-only.
+ ## @param value Value to set for the id property.
+ ## @return a void
+ ##
+
+ ##
+ ## Serializes information the current object
+ ## @param writer Serialization writer to use to serialize this model
+ ## @return a void
+ ##
+ def serialize(writer)
+ raise StandardError, 'writer cannot be null' if writer.nil?
+
+ writer.write_string_value('id', @id)
+ writer.write_additional_data(@additional_data)
+ end
+ end
+end
diff --git a/components/serialization/json/spec/files/files.rb b/components/serialization/json/spec/files/files.rb
new file mode 100644
index 0000000..b742b32
--- /dev/null
+++ b/components/serialization/json/spec/files/files.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+require 'microsoft_kiota_abstractions'
+require_relative 'body_type'
+require_relative 'email_address'
+require_relative 'entity'
+require_relative 'item_body'
+require_relative 'message'
+require_relative 'messages_response'
+require_relative 'outlook_item'
+require_relative 'recipient'
+
+module Files
+end
diff --git a/components/serialization/json/spec/files/item_body.rb b/components/serialization/json/spec/files/item_body.rb
new file mode 100644
index 0000000..79d8f3f
--- /dev/null
+++ b/components/serialization/json/spec/files/item_body.rb
@@ -0,0 +1,95 @@
+# frozen_string_literal: true
+
+require 'microsoft_kiota_abstractions'
+
+module Files
+ class ItemBody
+ include MicrosoftKiotaAbstractions::Parsable
+ include MicrosoftKiotaAbstractions::AdditionalDataHolder
+
+ ##
+ # Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well.
+ ##
+ # The content of the item.
+ ##
+ # The contentType property
+ ##
+ ## Gets the additionalData property value. Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well.
+ ## @return a i_dictionary
+ ##
+ attr_accessor :additional_data
+
+ ##
+ ## Sets the additionalData property value. Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well.
+ ## @param value Value to set for the AdditionalData property.
+ ## @return a void
+ ##
+
+ ##
+ ## Instantiates a new itemBody and sets the default values.
+ ## @return a void
+ ##
+ def initialize
+ @additional_data = {}
+ end
+
+ ##
+ ## Gets the content property value. The content of the item.
+ ## @return a string
+ ##
+ attr_accessor :content
+
+ ##
+ ## Sets the content property value. The content of the item.
+ ## @param value Value to set for the content property.
+ ## @return a void
+ ##
+
+ ##
+ ## Gets the contentType property value. The contentType property
+ ## @return a body_type
+ ##
+ attr_accessor :content_type
+
+ ##
+ ## Sets the contentType property value. The contentType property
+ ## @param value Value to set for the contentType property.
+ ## @return a void
+ ##
+
+ ##
+ ## Creates a new instance of the appropriate class based on discriminator value
+ ## @param parseNode The parse node to use to read the discriminator value and create the object
+ ## @return a item_body
+ ##
+ def self.create_from_discriminator_value(parse_node)
+ raise StandardError, 'parse_node cannot be null' if parse_node.nil?
+
+ ItemBody.new
+ end
+
+ ##
+ ## The deserialization information for the current model
+ ## @return a i_dictionary
+ ##
+ def get_field_deserializers
+ {
+ 'content' => ->(n) { @content = n.get_string_value },
+ 'contentType' => ->(n) { @content_type = n.get_enum_value(Files::BodyType) }
+ }
+ end
+
+ ##
+ ## Serializes information the current object
+ ## @param writer Serialization writer to use to serialize this model
+ ## @return a void
+ ##
+ def serialize(writer)
+ raise StandardError, 'writer cannot be null' if writer.nil?
+
+ writer.write_string_value('content', @content)
+ writer.write_enum_value('contentType', @content_type)
+ writer.write_additional_data(@additional_data)
+ end
+ end
+end
diff --git a/components/serialization/json/spec/files/message.rb b/components/serialization/json/spec/files/message.rb
new file mode 100644
index 0000000..b84bb63
--- /dev/null
+++ b/components/serialization/json/spec/files/message.rb
@@ -0,0 +1,559 @@
+# frozen_string_literal: true
+
+require 'date'
+require 'microsoft_kiota_abstractions'
+require_relative 'outlook_item'
+
+module Files
+ class Message < Files::OutlookItem
+ include MicrosoftKiotaAbstractions::Parsable
+
+ attr_accessor :guid_id
+
+ ##
+ # The fileAttachment and itemAttachment attachments for the message.
+ ##
+ # The Bcc: recipients for the message.
+ ##
+ # The body property
+ ##
+ # The first 255 characters of the message body. It is in text format.
+ ##
+ # The Cc: recipients for the message.
+ ##
+ # The ID of the conversation the email belongs to.
+ ##
+ # Indicates the position of the message within the conversation.
+ ##
+ # The collection of open extensions defined for the message. Nullable.
+ ##
+ # The flag property
+ ##
+ # The from property
+ ##
+ # Indicates whether the message has attachments. This property doesn't include inline attachments, so if a message contains only inline attachments, this property is false. To verify the existence of inline attachments, parse the body property to look for a src attribute, such as
.
+ ##
+ # The importance property
+ ##
+ # The inferenceClassification property
+ ##
+ # The internetMessageHeaders property
+ ##
+ # The internetMessageId property
+ ##
+ # The isDeliveryReceiptRequested property
+ ##
+ # The isDraft property
+ ##
+ # The isRead property
+ ##
+ # The isReadReceiptRequested property
+ ##
+ # The collection of multi-value extended properties defined for the message. Nullable.
+ ##
+ # The parentFolderId property
+ ##
+ # The receivedDateTime property
+ ##
+ # The replyTo property
+ ##
+ # The sender property
+ ##
+ # The sentDateTime property
+ ##
+ # The collection of single-value extended properties defined for the message. Nullable.
+ ##
+ # The subject property
+ ##
+ # The toRecipients property
+ ##
+ # The uniqueBody property
+ ##
+ # The webLink property
+ ##
+ ## Gets the attachments property value. The fileAttachment and itemAttachment attachments for the message.
+ ## @return a attachment
+ ##
+ attr_accessor :attachments
+
+ ##
+ ## Sets the attachments property value. The fileAttachment and itemAttachment attachments for the message.
+ ## @param value Value to set for the attachments property.
+ ## @return a void
+ ##
+
+ ##
+ ## Gets the bccRecipients property value. The Bcc: recipients for the message.
+ ## @return a recipient
+ ##
+ attr_accessor :bcc_recipients
+
+ ##
+ ## Sets the bccRecipients property value. The Bcc: recipients for the message.
+ ## @param value Value to set for the bccRecipients property.
+ ## @return a void
+ ##
+
+ ##
+ ## Gets the body property value. The body property
+ ## @return a item_body
+ ##
+ attr_accessor :body
+
+ ##
+ ## Sets the body property value. The body property
+ ## @param value Value to set for the body property.
+ ## @return a void
+ ##
+
+ ##
+ ## Gets the bodyPreview property value. The first 255 characters of the message body. It is in text format.
+ ## @return a string
+ ##
+ attr_accessor :body_preview
+
+ ##
+ ## Sets the bodyPreview property value. The first 255 characters of the message body. It is in text format.
+ ## @param value Value to set for the bodyPreview property.
+ ## @return a void
+ ##
+
+ ##
+ ## Gets the ccRecipients property value. The Cc: recipients for the message.
+ ## @return a recipient
+ ##
+ attr_accessor :cc_recipients
+
+ ##
+ ## Sets the ccRecipients property value. The Cc: recipients for the message.
+ ## @param value Value to set for the ccRecipients property.
+ ## @return a void
+ ##
+
+ ##
+ ## Instantiates a new message and sets the default values.
+ ## @return a void
+ ##
+
+ ##
+ ## Gets the conversationId property value. The ID of the conversation the email belongs to.
+ ## @return a string
+ ##
+ attr_accessor :conversation_id
+
+ ##
+ ## Sets the conversationId property value. The ID of the conversation the email belongs to.
+ ## @param value Value to set for the conversationId property.
+ ## @return a void
+ ##
+
+ ##
+ ## Gets the conversationIndex property value. Indicates the position of the message within the conversation.
+ ## @return a binary
+ ##
+ attr_accessor :conversation_index
+
+ ##
+ ## Sets the conversationIndex property value. Indicates the position of the message within the conversation.
+ ## @param value Value to set for the conversationIndex property.
+ ## @return a void
+ ##
+
+ ##
+ ## Creates a new instance of the appropriate class based on discriminator value
+ ## @param parseNode The parse node to use to read the discriminator value and create the object
+ ## @return a message
+ ##
+ def self.create_from_discriminator_value(parse_node)
+ raise StandardError, 'parse_node cannot be null' if parse_node.nil?
+
+ Message.new
+ end
+
+ ##
+ ## Gets the extensions property value. The collection of open extensions defined for the message. Nullable.
+ ## @return a extension
+ ##
+ attr_accessor :extensions
+
+ ##
+ ## Sets the extensions property value. The collection of open extensions defined for the message. Nullable.
+ ## @param value Value to set for the extensions property.
+ ## @return a void
+ ##
+
+ ##
+ ## Gets the flag property value. The flag property
+ ## @return a followup_flag
+ ##
+ attr_accessor :flag
+
+ ##
+ ## Sets the flag property value. The flag property
+ ## @param value Value to set for the flag property.
+ ## @return a void
+ ##
+
+ ##
+ ## Gets the from property value. The from property
+ ## @return a recipient
+ ##
+ attr_accessor :from
+
+ ##
+ ## Sets the from property value. The from property
+ ## @param value Value to set for the from property.
+ ## @return a void
+ ##
+
+ ##
+ ## The deserialization information for the current model
+ ## @return a i_dictionary
+ ##
+ def get_field_deserializers
+ super.merge({
+ 'guidId' => ->(n) { @guid_id = n.get_guid_value },
+ 'bccRecipients' => lambda { |n|
+ @bcc_recipients = n.get_collection_of_object_values(lambda { |pn|
+ Files::Recipient.create_from_discriminator_value(pn)
+ })
+ },
+ 'body' => lambda { |n|
+ @body = n.get_object_value(lambda { |pn|
+ Files::ItemBody.create_from_discriminator_value(pn)
+ })
+ },
+ 'bodyPreview' => ->(n) { @body_preview = n.get_string_value },
+ 'ccRecipients' => lambda { |n|
+ @cc_recipients = n.get_collection_of_object_values(lambda { |pn|
+ Files::Recipient.create_from_discriminator_value(pn)
+ })
+ },
+ 'conversationId' => ->(n) { @conversation_id = n.get_string_value },
+ 'conversationIndex' => ->(n) { @conversation_index = n.get_string_value },
+ 'from' => lambda { |n|
+ @from = n.get_object_value(lambda { |pn|
+ Files::Recipient.create_from_discriminator_value(pn)
+ })
+ },
+ 'hasAttachments' => ->(n) { @has_attachments = n.get_boolean_value },
+ 'internetMessageId' => ->(n) { @internet_message_id = n.get_string_value },
+ 'isDeliveryReceiptRequested' => lambda { |n|
+ @is_delivery_receipt_requested = n.get_boolean_value
+ },
+ 'isDraft' => ->(n) { @is_draft = n.get_boolean_value },
+ 'isRead' => ->(n) { @is_read = n.get_boolean_value },
+ 'isReadReceiptRequested' => lambda { |n|
+ @is_read_receipt_requested = n.get_boolean_value
+ },
+ 'parentFolderId' => ->(n) { @parent_folder_id = n.get_string_value },
+ 'receivedDateTime' => ->(n) { @received_date_time = n.get_date_time_value },
+ 'replyTo' => lambda { |n|
+ @reply_to = n.get_collection_of_object_values(lambda { |pn|
+ Files::Recipient.create_from_discriminator_value(pn)
+ })
+ },
+ 'sender' => lambda { |n|
+ @sender = n.get_object_value(lambda { |pn|
+ Files::Recipient.create_from_discriminator_value(pn)
+ })
+ },
+ 'sentDateTime' => ->(n) { @sent_date_time = n.get_date_time_value },
+ 'subject' => ->(n) { @subject = n.get_string_value },
+ 'toRecipients' => lambda { |n|
+ @to_recipients = n.get_collection_of_object_values(lambda { |pn|
+ Files::Recipient.create_from_discriminator_value(pn)
+ })
+ },
+ 'uniqueBody' => lambda { |n|
+ @unique_body = n.get_object_value(lambda { |pn|
+ Files::ItemBody.create_from_discriminator_value(pn)
+ })
+ },
+ 'webLink' => ->(n) { @web_link = n.get_string_value }
+ })
+ end
+
+ ##
+ ## Gets the hasAttachments property value. Indicates whether the message has attachments. This property doesn't include inline attachments, so if a message contains only inline attachments, this property is false. To verify the existence of inline attachments, parse the body property to look for a src attribute, such as
.
+ ## @return a boolean
+ ##
+ attr_accessor :has_attachments
+
+ ##
+ ## Sets the hasAttachments property value. Indicates whether the message has attachments. This property doesn't include inline attachments, so if a message contains only inline attachments, this property is false. To verify the existence of inline attachments, parse the body property to look for a src attribute, such as
.
+ ## @param value Value to set for the hasAttachments property.
+ ## @return a void
+ ##
+
+ ##
+ ## Gets the importance property value. The importance property
+ ## @return a importance
+ ##
+ attr_accessor :importance
+
+ ##
+ ## Sets the importance property value. The importance property
+ ## @param value Value to set for the importance property.
+ ## @return a void
+ ##
+
+ ##
+ ## Gets the inferenceClassification property value. The inferenceClassification property
+ ## @return a inference_classification_type
+ ##
+ attr_accessor :inference_classification
+
+ ##
+ ## Sets the inferenceClassification property value. The inferenceClassification property
+ ## @param value Value to set for the inferenceClassification property.
+ ## @return a void
+ ##
+
+ ##
+ ## Gets the internetMessageHeaders property value. The internetMessageHeaders property
+ ## @return a internet_message_header
+ ##
+ attr_accessor :internet_message_headers
+
+ ##
+ ## Sets the internetMessageHeaders property value. The internetMessageHeaders property
+ ## @param value Value to set for the internetMessageHeaders property.
+ ## @return a void
+ ##
+
+ ##
+ ## Gets the internetMessageId property value. The internetMessageId property
+ ## @return a string
+ ##
+ attr_accessor :internet_message_id
+
+ ##
+ ## Sets the internetMessageId property value. The internetMessageId property
+ ## @param value Value to set for the internetMessageId property.
+ ## @return a void
+ ##
+
+ ##
+ ## Gets the isDeliveryReceiptRequested property value. The isDeliveryReceiptRequested property
+ ## @return a boolean
+ ##
+ attr_accessor :is_delivery_receipt_requested
+
+ ##
+ ## Sets the isDeliveryReceiptRequested property value. The isDeliveryReceiptRequested property
+ ## @param value Value to set for the isDeliveryReceiptRequested property.
+ ## @return a void
+ ##
+
+ ##
+ ## Gets the isDraft property value. The isDraft property
+ ## @return a boolean
+ ##
+ attr_accessor :is_draft
+
+ ##
+ ## Sets the isDraft property value. The isDraft property
+ ## @param value Value to set for the isDraft property.
+ ## @return a void
+ ##
+
+ ##
+ ## Gets the isRead property value. The isRead property
+ ## @return a boolean
+ ##
+ attr_accessor :is_read
+
+ ##
+ ## Sets the isRead property value. The isRead property
+ ## @param value Value to set for the isRead property.
+ ## @return a void
+ ##
+
+ ##
+ ## Gets the isReadReceiptRequested property value. The isReadReceiptRequested property
+ ## @return a boolean
+ ##
+ attr_accessor :is_read_receipt_requested
+
+ ##
+ ## Sets the isReadReceiptRequested property value. The isReadReceiptRequested property
+ ## @param value Value to set for the isReadReceiptRequested property.
+ ## @return a void
+ ##
+
+ ##
+ ## Gets the multiValueExtendedProperties property value. The collection of multi-value extended properties defined for the message. Nullable.
+ ## @return a multi_value_legacy_extended_property
+ ##
+ attr_accessor :multi_value_extended_properties
+
+ ##
+ ## Sets the multiValueExtendedProperties property value. The collection of multi-value extended properties defined for the message. Nullable.
+ ## @param value Value to set for the multiValueExtendedProperties property.
+ ## @return a void
+ ##
+
+ ##
+ ## Gets the parentFolderId property value. The parentFolderId property
+ ## @return a string
+ ##
+ attr_accessor :parent_folder_id
+
+ ##
+ ## Sets the parentFolderId property value. The parentFolderId property
+ ## @param value Value to set for the parentFolderId property.
+ ## @return a void
+ ##
+
+ ##
+ ## Gets the receivedDateTime property value. The receivedDateTime property
+ ## @return a date_time
+ ##
+ attr_accessor :received_date_time
+
+ ##
+ ## Sets the receivedDateTime property value. The receivedDateTime property
+ ## @param value Value to set for the receivedDateTime property.
+ ## @return a void
+ ##
+
+ ##
+ ## Gets the replyTo property value. The replyTo property
+ ## @return a recipient
+ ##
+ attr_accessor :reply_to
+
+ ##
+ ## Sets the replyTo property value. The replyTo property
+ ## @param value Value to set for the replyTo property.
+ ## @return a void
+ ##
+
+ ##
+ ## Gets the sender property value. The sender property
+ ## @return a recipient
+ ##
+ attr_accessor :sender
+
+ ##
+ ## Sets the sender property value. The sender property
+ ## @param value Value to set for the sender property.
+ ## @return a void
+ ##
+
+ ##
+ ## Gets the sentDateTime property value. The sentDateTime property
+ ## @return a date_time
+ ##
+ attr_accessor :sent_date_time
+
+ ##
+ ## Sets the sentDateTime property value. The sentDateTime property
+ ## @param value Value to set for the sentDateTime property.
+ ## @return a void
+ ##
+
+ ##
+ ## Serializes information the current object
+ ## @param writer Serialization writer to use to serialize this model
+ ## @return a void
+ ##
+ def serialize(writer)
+ raise StandardError, 'writer cannot be null' if writer.nil?
+
+ super
+ writer.write_guid_value('guidId', @guid_id)
+ writer.write_collection_of_object_values('attachments', @attachments)
+ writer.write_collection_of_object_values('bccRecipients', @bcc_recipients)
+ writer.write_object_value('body', @body)
+ writer.write_string_value('bodyPreview', @body_preview)
+ writer.write_collection_of_object_values('ccRecipients', @cc_recipients)
+ writer.write_string_value('conversationId', @conversation_id)
+ # writer.write_object_value("conversationIndex", @conversation_index) byte array is not supported yet
+ writer.write_collection_of_object_values('extensions', @extensions)
+ writer.write_object_value('flag', @flag)
+ writer.write_object_value('from', @from)
+ writer.write_boolean_value('hasAttachments', @has_attachments)
+ writer.write_enum_value('importance', @importance)
+ writer.write_enum_value('inferenceClassification', @inference_classification)
+ writer.write_collection_of_object_values('internetMessageHeaders', @internet_message_headers)
+ writer.write_string_value('internetMessageId', @internet_message_id)
+ writer.write_boolean_value('isDeliveryReceiptRequested', @is_delivery_receipt_requested)
+ writer.write_boolean_value('isDraft', @is_draft)
+ writer.write_boolean_value('isRead', @is_read)
+ writer.write_boolean_value('isReadReceiptRequested', @is_read_receipt_requested)
+ writer.write_collection_of_object_values('multiValueExtendedProperties', @multi_value_extended_properties)
+ writer.write_string_value('parentFolderId', @parent_folder_id)
+ writer.write_date_time_value('receivedDateTime', @received_date_time)
+ writer.write_collection_of_object_values('replyTo', @reply_to)
+ writer.write_object_value('sender', @sender)
+ writer.write_date_time_value('sentDateTime', @sent_date_time)
+ writer.write_collection_of_object_values('singleValueExtendedProperties', @single_value_extended_properties)
+ writer.write_string_value('subject', @subject)
+ writer.write_collection_of_object_values('toRecipients', @to_recipients)
+ writer.write_object_value('uniqueBody', @unique_body)
+ writer.write_string_value('webLink', @web_link)
+ end
+
+ ##
+ ## Gets the singleValueExtendedProperties property value. The collection of single-value extended properties defined for the message. Nullable.
+ ## @return a single_value_legacy_extended_property
+ ##
+ attr_accessor :single_value_extended_properties
+
+ ##
+ ## Sets the singleValueExtendedProperties property value. The collection of single-value extended properties defined for the message. Nullable.
+ ## @param value Value to set for the singleValueExtendedProperties property.
+ ## @return a void
+ ##
+
+ ##
+ ## Gets the subject property value. The subject property
+ ## @return a string
+ ##
+ attr_accessor :subject
+
+ ##
+ ## Sets the subject property value. The subject property
+ ## @param value Value to set for the subject property.
+ ## @return a void
+ ##
+
+ ##
+ ## Gets the toRecipients property value. The toRecipients property
+ ## @return a recipient
+ ##
+ attr_accessor :to_recipients
+
+ ##
+ ## Sets the toRecipients property value. The toRecipients property
+ ## @param value Value to set for the toRecipients property.
+ ## @return a void
+ ##
+
+ ##
+ ## Gets the uniqueBody property value. The uniqueBody property
+ ## @return a item_body
+ ##
+ attr_accessor :unique_body
+
+ ##
+ ## Sets the uniqueBody property value. The uniqueBody property
+ ## @param value Value to set for the uniqueBody property.
+ ## @return a void
+ ##
+
+ ##
+ ## Gets the webLink property value. The webLink property
+ ## @return a string
+ ##
+ attr_accessor :web_link
+
+ ##
+ ## Sets the webLink property value. The webLink property
+ ## @param value Value to set for the webLink property.
+ ## @return a void
+ ##
+ end
+end
diff --git a/components/serialization/json/spec/files/messages_response.rb b/components/serialization/json/spec/files/messages_response.rb
new file mode 100644
index 0000000..50e6815
--- /dev/null
+++ b/components/serialization/json/spec/files/messages_response.rb
@@ -0,0 +1,99 @@
+# frozen_string_literal: true
+
+require 'microsoft_kiota_abstractions'
+
+module Files
+ class MessageCollectionResponse
+ include MicrosoftKiotaAbstractions::Parsable
+ include MicrosoftKiotaAbstractions::AdditionalDataHolder
+
+ ##
+ # Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well.
+ ##
+ # The OdataNextLink property
+ ##
+ # The value property
+ ##
+ ## Gets the additionalData property value. Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well.
+ ## @return a i_dictionary
+ ##
+ attr_accessor :additional_data
+
+ ##
+ ## Sets the additionalData property value. Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well.
+ ## @param value Value to set for the AdditionalData property.
+ ## @return a void
+ ##
+
+ ##
+ ## Instantiates a new MessageCollectionResponse and sets the default values.
+ ## @return a void
+ ##
+ def initialize
+ @additional_data = {}
+ end
+
+ ##
+ ## Creates a new instance of the appropriate class based on discriminator value
+ ## @param parseNode The parse node to use to read the discriminator value and create the object
+ ## @return a message_collection_response
+ ##
+ def self.create_from_discriminator_value(parse_node)
+ raise StandardError, 'parse_node cannot be null' if parse_node.nil?
+
+ MessageCollectionResponse.new
+ end
+
+ ##
+ ## The deserialization information for the current model
+ ## @return a i_dictionary
+ ##
+ def get_field_deserializers
+ {
+ '@odata.nextLink' => ->(n) { @odata_next_link = n.get_string_value },
+ 'value' => lambda { |n|
+ @value = n.get_collection_of_object_values(lambda { |pn|
+ Files::Message.create_from_discriminator_value(pn)
+ })
+ }
+ }
+ end
+
+ ##
+ ## Gets the @odata.nextLink property value. The OdataNextLink property
+ ## @return a string
+ ##
+ attr_accessor :odata_next_link
+
+ ##
+ ## Sets the @odata.nextLink property value. The OdataNextLink property
+ ## @param value Value to set for the OdataNextLink property.
+ ## @return a void
+ ##
+
+ ##
+ ## Serializes information the current object
+ ## @param writer Serialization writer to use to serialize this model
+ ## @return a void
+ ##
+ def serialize(writer)
+ raise StandardError, 'writer cannot be null' if writer.nil?
+
+ writer.write_string_value('@odata.nextLink', @odata_next_link)
+ writer.write_collection_of_object_values('value', @value)
+ writer.write_additional_data(@additional_data)
+ end
+
+ ##
+ ## Gets the value property value. The value property
+ ## @return a message
+ ##
+ attr_accessor :value
+
+ ##
+ ## Sets the value property value. The value property
+ ## @param value Value to set for the value property.
+ ## @return a void
+ ##
+ end
+end
diff --git a/components/serialization/json/spec/files/outlook_item.rb b/components/serialization/json/spec/files/outlook_item.rb
new file mode 100644
index 0000000..088daee
--- /dev/null
+++ b/components/serialization/json/spec/files/outlook_item.rb
@@ -0,0 +1,113 @@
+# frozen_string_literal: true
+
+require 'date'
+require 'microsoft_kiota_abstractions'
+require_relative 'entity'
+
+module Files
+ class OutlookItem < Files::Entity
+ include MicrosoftKiotaAbstractions::Parsable
+
+ ##
+ # The categories associated with the item
+ ##
+ # Identifies the version of the item. Every time the item is changed, changeKey changes as well. This allows Exchange to apply changes to the correct version of the object. Read-only.
+ ##
+ # The Timestamp type represents date and time information using ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 is 2014-01-01T00:00:00Z
+ ##
+ # The Timestamp type represents date and time information using ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 is 2014-01-01T00:00:00Z
+ ##
+ ## Gets the categories property value. The categories associated with the item
+ ## @return a string
+ ##
+ attr_accessor :categories
+
+ ##
+ ## Sets the categories property value. The categories associated with the item
+ ## @param value Value to set for the categories property.
+ ## @return a void
+ ##
+
+ ##
+ ## Gets the changeKey property value. Identifies the version of the item. Every time the item is changed, changeKey changes as well. This allows Exchange to apply changes to the correct version of the object. Read-only.
+ ## @return a string
+ ##
+ attr_accessor :change_key
+
+ ##
+ ## Sets the changeKey property value. Identifies the version of the item. Every time the item is changed, changeKey changes as well. This allows Exchange to apply changes to the correct version of the object. Read-only.
+ ## @param value Value to set for the changeKey property.
+ ## @return a void
+ ##
+
+ ##
+ ## Instantiates a new outlookItem and sets the default values.
+ ## @return a void
+ ##
+
+ ##
+ ## Gets the createdDateTime property value. The Timestamp type represents date and time information using ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 is 2014-01-01T00:00:00Z
+ ## @return a date_time
+ ##
+ attr_accessor :created_date_time
+
+ ##
+ ## Sets the createdDateTime property value. The Timestamp type represents date and time information using ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 is 2014-01-01T00:00:00Z
+ ## @param value Value to set for the createdDateTime property.
+ ## @return a void
+ ##
+
+ ##
+ ## Creates a new instance of the appropriate class based on discriminator value
+ ## @param parseNode The parse node to use to read the discriminator value and create the object
+ ## @return a outlook_item
+ ##
+ def self.create_from_discriminator_value(parse_node)
+ raise StandardError, 'parse_node cannot be null' if parse_node.nil?
+
+ OutlookItem.new
+ end
+
+ ##
+ ## The deserialization information for the current model
+ ## @return a i_dictionary
+ ##
+ def get_field_deserializers
+ super.merge({
+ 'categories' => lambda { |n|
+ @categories = n.get_collection_of_primitive_values(String)
+ },
+ 'changeKey' => ->(n) { @change_key = n.get_string_value },
+ 'createdDateTime' => ->(n) { @created_date_time = n.get_date_time_value },
+ 'lastModifiedDateTime' => ->(n) { @last_modified_date_time = n.get_date_time_value }
+ })
+ end
+
+ ##
+ ## Gets the lastModifiedDateTime property value. The Timestamp type represents date and time information using ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 is 2014-01-01T00:00:00Z
+ ## @return a date_time
+ ##
+ attr_accessor :last_modified_date_time
+
+ ##
+ ## Sets the lastModifiedDateTime property value. The Timestamp type represents date and time information using ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 is 2014-01-01T00:00:00Z
+ ## @param value Value to set for the lastModifiedDateTime property.
+ ## @return a void
+ ##
+
+ ##
+ ## Serializes information the current object
+ ## @param writer Serialization writer to use to serialize this model
+ ## @return a void
+ ##
+ def serialize(writer)
+ raise StandardError, 'writer cannot be null' if writer.nil?
+
+ super
+ writer.write_collection_of_primitive_values('categories', @categories)
+ writer.write_string_value('changeKey', @change_key)
+ writer.write_date_time_value('createdDateTime', @created_date_time)
+ writer.write_date_time_value('lastModifiedDateTime', @last_modified_date_time)
+ end
+ end
+end
diff --git a/components/serialization/json/spec/files/recipient.rb b/components/serialization/json/spec/files/recipient.rb
new file mode 100644
index 0000000..506bbfc
--- /dev/null
+++ b/components/serialization/json/spec/files/recipient.rb
@@ -0,0 +1,83 @@
+# frozen_string_literal: true
+
+require 'microsoft_kiota_abstractions'
+
+module Files
+ class Recipient
+ include MicrosoftKiotaAbstractions::Parsable
+ include MicrosoftKiotaAbstractions::AdditionalDataHolder
+
+ ##
+ # Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well.
+ ##
+ # The emailAddress property
+ ##
+ ## Gets the additionalData property value. Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well.
+ ## @return a i_dictionary
+ ##
+ attr_accessor :additional_data
+
+ ##
+ ## Sets the additionalData property value. Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well.
+ ## @param value Value to set for the AdditionalData property.
+ ## @return a void
+ ##
+
+ ##
+ ## Instantiates a new recipient and sets the default values.
+ ## @return a void
+ ##
+ def initialize
+ @additional_data = {}
+ end
+
+ ##
+ ## Creates a new instance of the appropriate class based on discriminator value
+ ## @param parseNode The parse node to use to read the discriminator value and create the object
+ ## @return a recipient
+ ##
+ def self.create_from_discriminator_value(parse_node)
+ raise StandardError, 'parse_node cannot be null' if parse_node.nil?
+
+ Recipient.new
+ end
+
+ ##
+ ## Gets the emailAddress property value. The emailAddress property
+ ## @return a email_address
+ ##
+ attr_accessor :email_address
+
+ ##
+ ## Sets the emailAddress property value. The emailAddress property
+ ## @param value Value to set for the emailAddress property.
+ ## @return a void
+ ##
+
+ ##
+ ## The deserialization information for the current model
+ ## @return a i_dictionary
+ ##
+ def get_field_deserializers
+ {
+ 'emailAddress' => lambda { |n|
+ @email_address = n.get_object_value(lambda { |pn|
+ Files::EmailAddress.create_from_discriminator_value(pn)
+ })
+ }
+ }
+ end
+
+ ##
+ ## Serializes information the current object
+ ## @param writer Serialization writer to use to serialize this model
+ ## @return a void
+ ##
+ def serialize(writer)
+ raise StandardError, 'writer cannot be null' if writer.nil?
+
+ writer.write_object_value('emailAddress', @email_address)
+ writer.write_additional_data(@additional_data)
+ end
+ end
+end
diff --git a/components/serialization/json/spec/json_serialization_writer_composed_type_spec.rb b/components/serialization/json/spec/json_serialization_writer_composed_type_spec.rb
new file mode 100644
index 0000000..b6b5bee
--- /dev/null
+++ b/components/serialization/json/spec/json_serialization_writer_composed_type_spec.rb
@@ -0,0 +1,273 @@
+# frozen_string_literal: true
+
+require_relative 'spec_helper'
+require 'microsoft_kiota_abstractions'
+
+module TestModels
+ class SimpleParsable
+ include MicrosoftKiotaAbstractions::Parsable
+
+ attr_accessor :name, :age
+
+ def get_field_deserializers
+ {
+ 'name' => ->(n) { @name = n.get_string_value },
+ 'age' => ->(n) { @age = n.get_number_value }
+ }
+ end
+
+ def serialize(writer)
+ writer.write_string_value('name', @name)
+ writer.write_number_value('age', @age)
+ end
+
+ def self.create_from_discriminator_value(_parse_node)
+ SimpleParsable.new
+ end
+ end
+
+ class AnotherParsable
+ include MicrosoftKiotaAbstractions::Parsable
+
+ attr_accessor :email
+
+ def get_field_deserializers
+ { 'email' => ->(n) { @email = n.get_string_value } }
+ end
+
+ def serialize(writer)
+ writer.write_string_value('email', @email)
+ end
+
+ def self.create_from_discriminator_value(_parse_node)
+ AnotherParsable.new
+ end
+ end
+
+ class UnionTypeWrapper
+ include MicrosoftKiotaAbstractions::Parsable
+ include MicrosoftKiotaAbstractions::ComposedTypeWrapper
+
+ attr_accessor :simple, :another
+
+ def get_field_deserializers
+ return @simple.get_field_deserializers if @simple
+ return @another.get_field_deserializers if @another
+
+ {}
+ end
+
+ def serialize(writer)
+ if @simple
+ writer.write_object_value(nil, @simple)
+ elsif @another
+ writer.write_object_value(nil, @another)
+ end
+ end
+
+ def self.create_from_discriminator_value(_parse_node)
+ UnionTypeWrapper.new
+ end
+ end
+
+ class IntersectionTypeWrapper
+ include MicrosoftKiotaAbstractions::Parsable
+ include MicrosoftKiotaAbstractions::ComposedTypeWrapper
+
+ attr_accessor :simple, :another
+
+ def get_field_deserializers
+ MicrosoftKiotaAbstractions::ParseNodeHelper
+ .merge_deserializers_for_intersection_wrapper(@simple, @another)
+ end
+
+ def serialize(writer)
+ writer.write_object_value(nil, @simple, @another)
+ end
+
+ def self.create_from_discriminator_value(_parse_node)
+ IntersectionTypeWrapper.new
+ end
+ end
+end
+
+RSpec.describe MicrosoftKiotaSerializationJson::JsonSerializationWriter do
+ describe '#write_object_value' do
+ it 'serializes a regular object with a key' do
+ writer = MicrosoftKiotaSerializationJson::JsonSerializationWriter.new
+ obj = TestModels::SimpleParsable.new
+ obj.name = 'Alice'
+ obj.age = 30
+
+ writer.write_object_value('person', obj)
+ expect(writer.writer['person']).to eq({ 'name' => 'Alice', 'age' => 30 })
+ end
+
+ it 'serializes a regular object with additional values merged under a key' do
+ writer = MicrosoftKiotaSerializationJson::JsonSerializationWriter.new
+ obj1 = TestModels::SimpleParsable.new
+ obj1.name = 'Alice'
+ obj1.age = 30
+ obj2 = TestModels::AnotherParsable.new
+ obj2.email = 'alice@example.com'
+
+ writer.write_object_value('person', obj1, obj2)
+ expect(writer.writer['person']).to eq({ 'name' => 'Alice', 'age' => 30, 'email' => 'alice@example.com' })
+ end
+
+ it 'skips nil additional values' do
+ writer = MicrosoftKiotaSerializationJson::JsonSerializationWriter.new
+ obj = TestModels::SimpleParsable.new
+ obj.name = 'Bob'
+ obj.age = 22
+
+ writer.write_object_value('person', obj, nil, nil)
+ expect(writer.writer['person']).to eq({ 'name' => 'Bob', 'age' => 22 })
+ end
+
+ it 'returns nil when value is nil' do
+ writer = MicrosoftKiotaSerializationJson::JsonSerializationWriter.new
+ result = writer.write_object_value('key', nil)
+ expect(result).to be_nil
+ expect(writer.writer).to eq({})
+ end
+
+ it 'serializes into self when key is nil for a non-composed type' do
+ writer = MicrosoftKiotaSerializationJson::JsonSerializationWriter.new
+ obj = TestModels::SimpleParsable.new
+ obj.name = 'Eve'
+ obj.age = 40
+
+ writer.write_object_value(nil, obj)
+ expect(writer.writer).to eq({ 'name' => 'Eve', 'age' => 40 })
+ end
+ end
+
+ describe '#write_object_value with union types' do
+ it 'serializes the first branch of a union into the current writer' do
+ writer = MicrosoftKiotaSerializationJson::JsonSerializationWriter.new
+ union = TestModels::UnionTypeWrapper.new
+ inner = TestModels::SimpleParsable.new
+ inner.name = 'Charlie'
+ inner.age = 25
+ union.simple = inner
+
+ writer.write_object_value(nil, union)
+ expect(writer.writer).to eq({ 'name' => 'Charlie', 'age' => 25 })
+ end
+
+ it 'serializes the second branch of a union into the current writer' do
+ writer = MicrosoftKiotaSerializationJson::JsonSerializationWriter.new
+ union = TestModels::UnionTypeWrapper.new
+ inner = TestModels::AnotherParsable.new
+ inner.email = 'test@example.com'
+ union.another = inner
+
+ writer.write_object_value(nil, union)
+ expect(writer.writer).to eq({ 'email' => 'test@example.com' })
+ end
+
+ it 'produces valid JSON for a union type' do
+ writer = MicrosoftKiotaSerializationJson::JsonSerializationWriter.new
+ union = TestModels::UnionTypeWrapper.new
+ inner = TestModels::SimpleParsable.new
+ inner.name = 'Charlie'
+ inner.age = 25
+ union.simple = inner
+
+ writer.write_object_value(nil, union)
+ json = writer.get_serialized_content
+ parsed = JSON.parse(json)
+ expect(parsed).to eq({ 'name' => 'Charlie', 'age' => 25 })
+ end
+ end
+
+ describe '#write_object_value with intersection types' do
+ it 'merges all intersection members into the current writer' do
+ writer = MicrosoftKiotaSerializationJson::JsonSerializationWriter.new
+ intersection = TestModels::IntersectionTypeWrapper.new
+ obj1 = TestModels::SimpleParsable.new
+ obj1.name = 'Dana'
+ obj1.age = 28
+ obj2 = TestModels::AnotherParsable.new
+ obj2.email = 'dana@example.com'
+ intersection.simple = obj1
+ intersection.another = obj2
+
+ writer.write_object_value(nil, intersection)
+ expect(writer.writer).to eq({ 'name' => 'Dana', 'age' => 28, 'email' => 'dana@example.com' })
+ end
+
+ it 'produces valid JSON for an intersection type' do
+ writer = MicrosoftKiotaSerializationJson::JsonSerializationWriter.new
+ intersection = TestModels::IntersectionTypeWrapper.new
+ obj1 = TestModels::SimpleParsable.new
+ obj1.name = 'Dana'
+ obj1.age = 28
+ obj2 = TestModels::AnotherParsable.new
+ obj2.email = 'dana@example.com'
+ intersection.simple = obj1
+ intersection.another = obj2
+
+ writer.write_object_value(nil, intersection)
+ json = writer.get_serialized_content
+ parsed = JSON.parse(json)
+ expect(parsed).to eq({ 'name' => 'Dana', 'age' => 28, 'email' => 'dana@example.com' })
+ end
+ end
+
+ describe '#write_collection_of_object_values' do
+ it 'serializes a collection of objects under a key' do
+ writer = MicrosoftKiotaSerializationJson::JsonSerializationWriter.new
+ obj1 = TestModels::SimpleParsable.new
+ obj1.name = 'Alice'
+ obj1.age = 30
+ obj2 = TestModels::SimpleParsable.new
+ obj2.name = 'Bob'
+ obj2.age = 25
+
+ writer.write_collection_of_object_values('people', [obj1, obj2])
+ expect(writer.writer['people']).to eq([
+ { 'name' => 'Alice', 'age' => 30 },
+ { 'name' => 'Bob', 'age' => 25 }
+ ])
+ end
+
+ it 'serializes into self when key is nil' do
+ writer = MicrosoftKiotaSerializationJson::JsonSerializationWriter.new
+ obj1 = TestModels::SimpleParsable.new
+ obj1.name = 'Alice'
+ obj1.age = 30
+
+ writer.write_collection_of_object_values(nil, [obj1])
+ expect(writer.writer).to eq({ 'name' => 'Alice', 'age' => 30 })
+ end
+
+ it 'does not contaminate the parent writer' do
+ writer = MicrosoftKiotaSerializationJson::JsonSerializationWriter.new
+ writer.write_string_value('top_level', 'value')
+ obj = TestModels::SimpleParsable.new
+ obj.name = 'Alice'
+ obj.age = 30
+
+ writer.write_collection_of_object_values('people', [obj])
+ expect(writer.writer.keys).to contain_exactly('top_level', 'people')
+ end
+
+ it 'produces valid JSON with a collection' do
+ writer = MicrosoftKiotaSerializationJson::JsonSerializationWriter.new
+ obj1 = TestModels::SimpleParsable.new
+ obj1.name = 'Alice'
+ obj1.age = 30
+ obj2 = TestModels::AnotherParsable.new
+ obj2.email = 'bob@example.com'
+
+ writer.write_collection_of_object_values('items', [obj1])
+ writer.write_object_value('contact', obj2)
+ json = writer.get_serialized_content
+ parsed = JSON.parse(json)
+ expect(parsed['items']).to eq([{ 'name' => 'Alice', 'age' => 30 }])
+ expect(parsed['contact']).to eq({ 'email' => 'bob@example.com' })
+ end
+ end
+end
diff --git a/components/serialization/json/spec/microsoft_kiota_serialization_json_spec.rb b/components/serialization/json/spec/microsoft_kiota_serialization_json_spec.rb
new file mode 100644
index 0000000..1b852ff
--- /dev/null
+++ b/components/serialization/json/spec/microsoft_kiota_serialization_json_spec.rb
@@ -0,0 +1,78 @@
+# frozen_string_literal: true
+
+require_relative 'spec_helper'
+require_relative 'files/files'
+require 'microsoft_kiota_abstractions'
+require 'json'
+
+RSpec.describe MicrosoftKiotaSerializationJson do
+ it 'has a version number' do
+ expect(MicrosoftKiotaSerializationJson::VERSION).not_to be nil
+ end
+
+ it 'can build jsonParseNode' do
+ json_parse_node = MicrosoftKiotaSerializationJson::JsonParseNode.new(JSON.parse('{"value": [{"hasAttachments": false}] }'))
+ expect(json_parse_node).not_to be nil
+ expect(json_parse_node.get_string_value.gsub(/\s+/, '')).to eq('{"value"=>[{"hasAttachments"=>false}]}')
+ end
+
+ it 'can deserialize payload' do
+ file = File.open("#{File.dirname(__FILE__)}/sample.json")
+ data = file.read
+ file.close
+ message_response = MicrosoftKiotaSerializationJson::JsonParseNodeFactory.new.get_parse_node('application/json',
+ data)
+ object_value = message_response.get_object_value(lambda { |pn|
+ Files::MessageCollectionResponse.create_from_discriminator_value(pn)
+ })
+
+ ## Object Value tests
+ expect(object_value.instance_of?(Files::MessageCollectionResponse)).to eq(true)
+ expect(object_value.value[0].instance_of?(Files::Message)).to eq(true)
+ expect(object_value.value[0].body.instance_of?(Files::ItemBody)).to eq(true)
+ expect(object_value.value[0].cc_recipients[0].instance_of?(Files::Recipient)).to eq(true)
+ expect(object_value.value[0].cc_recipients[0].email_address.instance_of?(Files::EmailAddress)).to eq(true)
+
+ ## String tests
+ expect(object_value.odata_next_link.instance_of?(String)).to eq(true)
+ expect(object_value.value[0].body_preview.instance_of?(String)).to eq(true)
+
+ ## Boolean tests
+ expect(%w[true false].include?(object_value.value[0].is_draft.to_s.downcase)).to eq(true)
+ expect(%w[true false].include?(object_value.value[0].is_read.to_s.downcase)).to eq(true)
+ expect(%w[true false].include?(object_value.value[0].body_preview.to_s.downcase)).to eq(false)
+
+ ## Number tests
+ expect(object_value.additional_data['numb'].instance_of?(Integer)).to eq(true)
+
+ ## GUID tests
+ expect(object_value.value[0].guid_id.instance_of?(UUIDTools::UUID)).to eq(true)
+
+ ## Date tests
+ expect(object_value.value[0].received_date_time).to eq(nil)
+ expect(object_value.value[0].sent_date_time.instance_of?(DateTime)).to eq(true)
+
+ ## Collection of Primitive values tests
+ expect(object_value.additional_data['primativeValues'].instance_of?(Array)).to eq(true)
+
+ ## Collection of object values tests
+ expect(object_value.value.instance_of?(Array)).to eq(true)
+
+ ## Enum tests
+ expect(object_value.value[0].body.content_type.instance_of?(Symbol)).to eq(true)
+ end
+
+ it 'can serialize payload' do
+ file = File.open("#{File.dirname(__FILE__)}/sample.json")
+ data = file.read
+ file.close
+ message_response = MicrosoftKiotaSerializationJson::JsonParseNodeFactory.new.get_parse_node('application/json',
+ data)
+ object_value = message_response.get_object_value(lambda { |pn|
+ Files::MessageCollectionResponse.create_from_discriminator_value(pn)
+ })
+ serializer = MicrosoftKiotaSerializationJson::JsonSerializationWriterFactory.new.get_serialization_writer('application/json')
+ object_value.serialize(serializer)
+ expect(object_value.value[0].id.to_s == serializer.writer['value'][0]['id']).to eq(true)
+ end
+end
diff --git a/components/serialization/json/spec/sample.json b/components/serialization/json/spec/sample.json
new file mode 100644
index 0000000..ecd6eb9
--- /dev/null
+++ b/components/serialization/json/spec/sample.json
@@ -0,0 +1,73 @@
+{
+ "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('607f7b25-541a-4af6-b2f6-562bdf65b448')/messages",
+ "@odata.nextLink": "https://graph.microsoft.com/v1.0/me/messages?$skip=10",
+ "numb": 22,
+ "primativeValues": ["a","b",1,2],
+ "value": [
+ {
+ "guidId": "093e9e30-440c-4374-84ea-a95821d7cb4c",
+ "@odata.etag": "W/\"CQAAABYAAABLW5j2RED8SKPe/uUseM8lAAAqleh7\"",
+ "id": "AAMkADY3ZWJmMDUzLWU5ZmQtNDU2ZS05MTk0LWMxNTg0OTQxNDA1ZgBGAAAAAABUU3b30v09Q7_8TGMESZIYBwBLW5j2RED8SKPe-uUseM8lAAAAAAEMAABLW5j2RED8SKPe-uUseM8lAAAqxrxGAAA=",
+ "createdDateTime": "2021-08-02T18:14:36Z",
+ "lastModifiedDateTime": "2021-08-02T18:14:38Z",
+ "changeKey": "CQAAABYAAABLW5j2RED8SKPe/uUseM8lAAAqleh7",
+ "categories": ["cat1", "cat2", "cat3"],
+ "receivedDateTime": null,
+ "sentDateTime": "2021-08-02T18:14:14Z",
+ "hasAttachments": false,
+ "internetMessageId": "",
+ "subject": "Re: Our processor does not receive events for Permanent Delete",
+ "bodyPreview": "Hi @Jun Cao,I want to get all deletes (soft + hard) for emails for which our other processors have processed data and patched a property. Our processors ingest and maintain secondary FileItems in the WorkingSet based on links and attachments shared in",
+ "importance": "normal",
+ "parentFolderId": "AQMkADY3ZWJmMDUzLWU5ZmQtNDU2ZS05MTk0LWMxNTg0OTQxNDA1ZgAuAAADVFN299L9PUO-vExjBEmSGAEAS1uY9kRA-Eij3v7lLHjPJQAAAgEMAAAA",
+ "conversationId": "AAQkADY3ZWJmMDUzLWU5ZmQtNDU2ZS05MTk0LWMxNTg0OTQxNDA1ZgAQAD4eTN3FHLlHh-j-zvIITkI=",
+ "conversationIndex": "AQHXhYCbPh5M3cUcuUeH+P/O8ghOQqtcA1OJgAAMjReAA9KG24AAb7pZgAAgpbCAAA6myw==",
+ "isDeliveryReceiptRequested": null,
+ "isReadReceiptRequested": false,
+ "isRead": false,
+ "isDraft": false,
+ "webLink": "https://outlook.office365.com/owa/",
+ "inferenceClassification": "focused",
+ "body": {
+ "contentType": "html",
+ "content": ""
+ },
+ "sender": {
+ "emailAddress": {
+ "name": "Kristian Elsebø",
+ "address": "krelse@exchange.microsoft.com"
+ }
+ },
+ "from": {
+ "emailAddress": {
+ "name": "Kristian Elsebø",
+ "address": "krelse@exchange.microsoft.com"
+ }
+ },
+ "toRecipients": [
+ {
+ "emailAddress": {
+ "name": "Jun Cao",
+ "address": "juncao@microsoft.com"
+ }
+ },
+ {
+ "emailAddress": {
+ "name": "Martin Owen",
+ "address": "mowen@microsoft.com"
+ }
+ }
+ ],
+ "ccRecipients": [
+ {
+ "emailAddress": {
+ "name": "FAST Everything Shared",
+ "address": "fastshared@microsoft.com"
+ }
+ }
+ ],
+ "bccRecipients": [],
+ "replyTo": []
+ }
+ ]
+}
diff --git a/components/serialization/json/spec/spec_helper.rb b/components/serialization/json/spec/spec_helper.rb
new file mode 100644
index 0000000..5e1b016
--- /dev/null
+++ b/components/serialization/json/spec/spec_helper.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+require 'microsoft_kiota_abstractions'
+
+Dir["#{File.dirname(__FILE__)}/./../lib/*.rb"].each { |f| load(f) }
+
+RSpec.configure do |config|
+ # Enable flags like --only-failures and --next-failure
+ config.example_status_persistence_file_path = '.rspec_status'
+
+ # Disable RSpec exposing methods globally on `Module` and `main`
+ config.disable_monkey_patching!
+
+ config.expect_with :rspec do |c|
+ c.syntax = :expect
+ end
+end
diff --git a/lib/microsoft_kiota_abstractions.rb b/lib/microsoft_kiota_abstractions.rb
deleted file mode 100644
index b73722b..0000000
--- a/lib/microsoft_kiota_abstractions.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "microsoft_kiota_abstractions/authentication/authentication_provider"
-require_relative "microsoft_kiota_abstractions/authentication/base_bearer_token_authentication_provider"
-require_relative "microsoft_kiota_abstractions/authentication/anonymous_authentication_provider"
-require_relative "microsoft_kiota_abstractions/api_error"
-require_relative "microsoft_kiota_abstractions/http_method"
-require_relative "microsoft_kiota_abstractions/base_request_builder"
-require_relative "microsoft_kiota_abstractions/api_client_builder"
-require_relative "microsoft_kiota_abstractions/request_adapter"
-require_relative "microsoft_kiota_abstractions/request_configuration"
-require_relative "microsoft_kiota_abstractions/request_option"
-require_relative "microsoft_kiota_abstractions/request_headers"
-require_relative "microsoft_kiota_abstractions/request_information"
-require_relative "microsoft_kiota_abstractions/version"
-require_relative "microsoft_kiota_abstractions/serialization/parsable"
-require_relative "microsoft_kiota_abstractions/serialization/iso_duration"
-require_relative "microsoft_kiota_abstractions/serialization/additional_data_holder"
-require_relative "microsoft_kiota_abstractions/serialization/parse_node"
-require_relative "microsoft_kiota_abstractions/serialization/parse_node_factory"
-require_relative "microsoft_kiota_abstractions/serialization/parse_node_factory_registry"
-require_relative "microsoft_kiota_abstractions/serialization/serialization_writer"
-require_relative "microsoft_kiota_abstractions/serialization/serialization_writer_factory"
-require_relative "microsoft_kiota_abstractions/serialization/serialization_writer_factory_registry"
-require_relative "microsoft_kiota_abstractions/serialization/composed_type_wrapper"
-require_relative "microsoft_kiota_abstractions/serialization/parse_node_helper"
-
-module MicrosoftKiotaAbstractions
-end
diff --git a/lib/microsoft_kiota_abstractions/api_error.rb b/lib/microsoft_kiota_abstractions/api_error.rb
deleted file mode 100644
index a842823..0000000
--- a/lib/microsoft_kiota_abstractions/api_error.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-require_relative 'serialization/parsable'
-module MicrosoftKiotaAbstractions
- class ApiError < StandardError
- include MicrosoftKiotaAbstractions::Parsable
-
- ##
- ## The deserialization information for the current model
- ## @return a i_dictionary
- ##
- def get_field_deserializers()
- return Hash.new
- end
- ##
- ## Serializes information the current object
- ## @param writer Serialization writer to use to serialize this model
- ## @return a void
- ##
- def serialize(writer)
- raise StandardError, 'writer cannot be null' if writer.nil?
- end
-
- end
-end
\ No newline at end of file
diff --git a/lib/microsoft_kiota_abstractions/authentication/authentication_provider.rb b/lib/microsoft_kiota_abstractions/authentication/authentication_provider.rb
deleted file mode 100644
index 25aebf6..0000000
--- a/lib/microsoft_kiota_abstractions/authentication/authentication_provider.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-module MicrosoftKiotaAbstractions
- module AuthenticationProvider
- def authenticate_request(request, additional_properties = {})
- raise NotImplementedError.new
- end
- end
-end
diff --git a/lib/microsoft_kiota_abstractions/base_request_builder.rb b/lib/microsoft_kiota_abstractions/base_request_builder.rb
deleted file mode 100644
index 6b69b0e..0000000
--- a/lib/microsoft_kiota_abstractions/base_request_builder.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-module MicrosoftKiotaAbstractions
- ##
- # Base class for request builders. Performs basic validation and defines common properties.
- class BaseRequestBuilder
- ##
- # Path parameters for the request
- @path_parameters
- ##
- # The request adapter to use to execute the requests.
- @request_adapter
- ##
- # Url template to use to build the URL for the current request builder
- @url_template
- ##
- ## Instantiates a new BaseRequestBuilder and sets the default values.
- ## @param path_parameters Path parameters for the request
- ## @param request_adapter The request adapter to use to execute the requests.
- ## @param url_template Url template to use to build the URL for the current request builder
- ## @return a void
- ##
- def initialize(path_parameters, request_adapter, url_template)
- raise StandardError, 'request_adapter cannot be null' if request_adapter.nil?
- raise StandardError, 'url_template cannot be null' if url_template.nil? || url_template.empty?
- @request_adapter = request_adapter
- unless path_parameters.nil? then
- if path_parameters.is_a? Hash then
- @path_parameters = path_parameters.clone
- elsif path_parameters.is_a? String then
- @path_parameters = { "request-raw-url" => path_parameters }
- end
- end
- @path_parameters = Hash.new if path_parameters.nil?
- @url_template = url_template
- end
- end
-end
\ No newline at end of file
diff --git a/lib/microsoft_kiota_abstractions/request_adapter.rb b/lib/microsoft_kiota_abstractions/request_adapter.rb
deleted file mode 100644
index b12a4e7..0000000
--- a/lib/microsoft_kiota_abstractions/request_adapter.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-require_relative 'request_information'
-
-module MicrosoftKiotaAbstractions
- module RequestAdapter
-
- def send_async(request_info, factory, errors_mapping)
- raise NotImplementedError.new
- end
-
- # TODO we're most likley missing something for enums and collections or at least at the implemenation level
-
- def get_serialization_writer_factory()
- raise NotImplementedError.new
- end
-
- def set_base_url(base_url)
- raise NotImplementedError.new
- end
-
- def get_base_url()
- raise NotImplementedError.new
- end
-
- # Converts the given RequestInformation into a native HTTP request.
- def convert_to_native_request_async(request_info)
- raise NotImplementedError.new
- end
-
- end
-end
diff --git a/lib/microsoft_kiota_abstractions/request_configuration.rb b/lib/microsoft_kiota_abstractions/request_configuration.rb
deleted file mode 100644
index 5c8abf4..0000000
--- a/lib/microsoft_kiota_abstractions/request_configuration.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-require_relative 'request_headers'
-
-module MicrosoftKiotaAbstractions
- ##
- # Configuration for the request such as headers, query parameters, and middleware options.
- class RequestConfiguration
- ##
- # Request headers
- attr_accessor :headers
- ##
- # Request options
- attr_accessor :options
- ##
- # Request query parameters
- attr_accessor :query_parameters
-
- def initialize
- @headers = RequestHeaders.new
- @options = Array.new
- end
- end
-end
\ No newline at end of file
diff --git a/lib/microsoft_kiota_abstractions/request_headers.rb b/lib/microsoft_kiota_abstractions/request_headers.rb
deleted file mode 100644
index 307ecf0..0000000
--- a/lib/microsoft_kiota_abstractions/request_headers.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-module MicrosoftKiotaAbstractions
- class RequestHeaders
- def initialize()
- @headers = Hash.new
- end
- def add(key, value)
- if key.nil? || key.empty? || value.nil? || value.empty? then
- raise ArgumentError, 'key and value cannot be nil or empty'
- end
- existing_value = @headers[key]
- if existing_value.nil? then
- if value.kind_of?(Array) then
- @headers[key] = value
- else
- @headers[key] = Array[value.to_s]
- end
- else
- if value.kind_of?(Array) then
- @headers[key] = existing_value | value
- else
- existing_value << value.to_s
- end
- end
- end
- def try_add(key, value)
- if key.nil? || key.empty? || value.nil? || value.empty? then
- raise ArgumentError, 'key and value cannot be nil or empty'
- end
- existing_value = @headers[key]
- if existing_value.nil? || existing_value.empty? then
- @headers[key] = Array[value.to_s]
- return true
- else
- return false
- end
- end
- def get(key)
- if key.nil? || key.empty? then
- raise ArgumentError, 'key cannot be nil or empty'
- end
- return @headers[key]
- end
- def remove(key)
- if key.nil? || key.empty? then
- raise ArgumentError, 'key cannot be nil or empty'
- end
- @headers.delete(key)
- end
- def clear()
- @headers.clear()
- end
- def get_all()
- return @headers
- end
- end
-end
\ No newline at end of file
diff --git a/lib/microsoft_kiota_abstractions/request_information.rb b/lib/microsoft_kiota_abstractions/request_information.rb
deleted file mode 100644
index f78c9e9..0000000
--- a/lib/microsoft_kiota_abstractions/request_information.rb
+++ /dev/null
@@ -1,132 +0,0 @@
-require 'uri'
-require 'stduritemplate'
-require_relative 'http_method'
-require_relative 'request_headers'
-
-module MicrosoftKiotaAbstractions
- class RequestInformation
- attr_reader :content, :http_method, :headers
- attr_accessor :url_template, :path_parameters, :query_parameters
- @@binary_content_type = 'application/octet-stream'
- @@content_type_header = 'Content-Type'
- @@raw_url_key = 'request-raw-url'
-
- def initialize()
- @headers = RequestHeaders.new
- @query_parameters = Hash.new
- @path_parameters = Hash.new
- end
-
- def uri=(arg)
- if arg.nil? || arg.empty?
- raise ArgumentError, 'arg cannot be nil or empty'
- end
- self.path_parameters.clear()
- self.query_parameters.clear()
- @uri = URI(arg)
- end
-
- def uri
- if @uri != nil
- return @uri
- else
- if self.path_parameters[@@raw_url_key] != nil
- self.uri = self.path_parameters[@@raw_url_key]
- return @uri
- else
- return URI(StdUriTemplate.expand(@url_template, self.path_parameters.merge(self.query_parameters)))
- end
- end
- end
-
- def add_request_options(request_options_to_add)
- unless request_options_to_add.nil? then
- @request_options ||= Hash.new
- unless request_options_to_add.kind_of?(Array) then
- request_options_to_add = [request_options_to_add]
- end
- request_options_to_add.each do |request_option|
- key = request_option.get_key
- @request_options[key] = request_option
- end
- end
- end
-
- def get_request_options()
- if @request_options.nil? then
- return []
- else
- return @request_options.values
- end
- end
-
- def get_request_option(key)
- if @request_options.nil? || key.nil? || key.empty? then
- return nil
- else
- return @request_options[key]
- end
- end
-
- def remove_request_options(keys)
- unless keys.nil? || @request_options.nil? then
- unless keys.kind_of?(Array) then
- keys = [keys]
- end
- keys.each do |key|
- @request_options.delete(key)
- end
- end
- end
-
- def http_method=(method)
- @http_method = HttpMethod::HTTP_METHOD[method]
- end
-
- def set_stream_content(value = $stdin, content_type)
- @content = value
- if content_type.nil? || content_type.empty?
- content_type = @@binary_content_type
- end
- @headers.try_add(@@content_type_header, content_type)
- end
-
- def set_content_from_parsable(request_adapter, content_type, values)
- begin
- writer = request_adapter.get_serialization_writer_factory().get_serialization_writer(content_type)
- @headers.try_add(@@content_type_header, content_type)
- if values != nil && values.kind_of?(Array)
- writer.write_collection_of_object_values(nil, values)
- else
- writer.write_object_value(nil, values);
- end
- @content = writer.get_serialized_content();
- rescue => exception
- raise Exception.new "could not serialize payload"
- end
- end
-
- def add_headers_from_raw_object(h)
- h.get_all.select{|x,y| @headers.add(x.to_s, y)} unless !h
- end
-
- def set_query_string_parameters_from_raw_object(q)
- if !q || q.is_a?(Hash) || q.is_a?(Array)
- return
- end
- q.class.instance_methods(false).select{|x|
- method_name = x.to_s
- unless method_name == "compare_by_identity" || method_name == "get_query_parameter" || method_name.end_with?("=") || method_name.end_with?("?") || method_name.end_with?("!") then
- begin
- key = q.get_query_parameter(method_name)
- rescue => exception
- key = method_name
- end
- value = eval("q.#{method_name}")
- self.query_parameters[key] = value unless value.nil?
- end
- }
- end
-
- end
-end
diff --git a/lib/microsoft_kiota_abstractions/request_option.rb b/lib/microsoft_kiota_abstractions/request_option.rb
deleted file mode 100644
index ce47d69..0000000
--- a/lib/microsoft_kiota_abstractions/request_option.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-module MicrosoftKiotaAbstractions
- module RequestOption
- def get_key()
- raise NotImplementedError.new
- end
- end
-end
\ No newline at end of file
diff --git a/lib/microsoft_kiota_abstractions/serialization/additional_data_holder.rb b/lib/microsoft_kiota_abstractions/serialization/additional_data_holder.rb
deleted file mode 100644
index 13cb1b9..0000000
--- a/lib/microsoft_kiota_abstractions/serialization/additional_data_holder.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-module MicrosoftKiotaAbstractions
- module AdditionalDataHolder
- def additional_data
- @additional_data ||= Hash.new
- end
- end
-end
diff --git a/lib/microsoft_kiota_abstractions/serialization/iso_duration.rb b/lib/microsoft_kiota_abstractions/serialization/iso_duration.rb
deleted file mode 100644
index 74b49d5..0000000
--- a/lib/microsoft_kiota_abstractions/serialization/iso_duration.rb
+++ /dev/null
@@ -1,209 +0,0 @@
-# frozen_string_literal: true
-require 'iso8601'
-
-module MicrosoftKiotaAbstractions
- # Wrapper Class for ISO8601::Duration
- # Integer support for :years, :months, :weeks, :days, :hours, :minutes, :seconds
- # Initialize with a hash of symbols to integers eg { :years => 3, :days => 4, seconds: => 2}
- # or with an ISO8601 formated string eg "PT3H12M5S".
- class ISODuration
- attr_reader :years, :months, :weeks, :days, :hours, :minutes, :seconds
-
- UNITS = { :years => 'Y',
- :months => 'M',
- :weeks => 'W',
- :days => 'D',
- :hours => 'H',
- :minutes => 'M',
- :seconds => 'S'}
-
- CONVERSIONS = {
- :ms_to_s => 1000,
- :s_to_m => 60,
- :m_to_h => 60,
- :h_to_d => 24,
- :d_to_w => 7,
- :m_to_y => 12
- }
- def initialize(input)
- if input.is_a? String
- @duration_obj = ISO8601::Duration.new(input)
- elsif input.is_a? Hash
- @duration_obj = parse_hash(input)
- else
- raise StandardError, 'Must provide initialize ISODuration by providing a hash or an ISO8601-formatted string.'
- end
- update_member_variables
- normalize
- end
-
- def string
- input = { :seconds => @seconds, :minutes => @minutes, :hours => @hours,
- :days => @days, :weeks => @weeks, :months => @months,
- :years => @years }
- iso_str = 'P'
- UNITS.each do |unit, abrev|
- iso_str += input[unit].to_s + abrev unless input[unit].zero?
- iso_str += 'T' if unit == :days
- end
- iso_str = iso_str.strip
- iso_str = iso_str.chomp('T') if (iso_str[-1]).eql? 'T'
- iso_str
- end
-
- def normalize
- if @seconds >= CONVERSIONS[:s_to_m]
- @minutes += (@seconds / CONVERSIONS[:s_to_m]).floor
- @seconds %= CONVERSIONS[:s_to_m]
- end
- if @minutes >= CONVERSIONS[:m_to_h]
- @hours += (@minutes / CONVERSIONS[:m_to_h]).floor
- @minutes %= CONVERSIONS[:m_to_h]
- end
- if @hours >= CONVERSIONS[:h_to_d]
- @days += (@hours / CONVERSIONS[:h_to_d]).floor
- @hours %= CONVERSIONS[:h_to_d]
- end
- if @days >= CONVERSIONS[:d_to_w] && @months == 0 && @years == 0
- @weeks += (@days / CONVERSIONS[:d_to_w]).floor
- @days %= CONVERSIONS[:d_to_w]
- end
- if @months > CONVERSIONS[:m_to_y]
- @years += (@months / CONVERSIONS[:m_to_y]).floor
- @months %= CONVERSIONS[:m_to_y]
- end
- end
-
- def seconds=(value)
- input = { :seconds => value, :minutes => @minutes, :hours => @hours,
- :days => @days, :weeks => @weeks, :months => @months,
- :years => @years }
- @duration_obj = parse_hash(input)
- @seconds = value
- normalize
- end
-
- def minutes=(value)
- input = { :seconds => @seconds, :minutes => value, :hours => @hours,
- :days => @days, :weeks => @weeks, :months => @months,
- :years => @years }
- @duration_obj = parse_hash(input)
- @minutes = value
- normalize
- end
-
- def hours=(value)
- input = { :seconds => @seconds, :minutes => @minutes, :hours => value,
- :days => @days, :weeks => @weeks, :months => @months,
- :years => @years }
- @duration_obj = parse_hash(input)
- @hours = value
- normalize
- end
-
- def days=(value)
- input = { :seconds => @seconds, :minutes => @minutes, :hours => @hours,
- :days => value, :weeks => @weeks, :months => @months,
- :years => @years }
- @duration_obj = parse_hash(input)
- @days = value
- normalize
- end
-
- def weeks=(value)
- input = { :seconds => @seconds, :minutes => @minutes, :hours => @hours,
- :days => @days, :weeks => value, :months => @months,
- :years => @years }
- @duration_obj = parse_hash(input)
- @weeks = value
- normalize
- end
-
- def months=(value)
- input = { :seconds => @seconds, :minutes => @minutes, :hours => @hours,
- :days => @days, :weeks => @weeks, :months => value,
- :years => @years }
- @duration_obj = parse_hash(input)
- @months = value
- normalize
- end
-
- def years=(value)
- input = { :seconds => @seconds, :minutes => @minutes, :hours => @hours,
- :days => @days, :weeks => @weeks, :months => @months,
- :years => value }
- @duration_obj = parse_hash(input)
- @years = value
- normalize
- end
-
- def abs
- @duration_obj = @duration_obj.abs
- update_member_variables
- return self
- end
-
- def +(other)
- new_obj = self.duration_obj + other.duration_obj
- MicrosoftKiotaAbstractions::ISODuration.new(dur_obj_to_hash(new_obj))
- end
-
- def -(other)
- new_obj = self.duration_obj - other.duration_obj
- MicrosoftKiotaAbstractions::ISODuration.new(dur_obj_to_hash(new_obj))
- end
-
- def ==(other)
- @duration_obj == other.duration_obj
- end
-
- def -@
- @duration_obj = -@duration_obj
- update_member_variables
- end
-
- def eql?(other)
- @duration_obj == other.duration_obj
- end
-
- protected
-
- attr_accessor :duration_obj
-
- def parse_hash(input)
- iso_str = 'P'
- input.each do |keys, values|
- raise StandardError, "The key #{keys} is not recognized" unless UNITS.key?(keys)
- end
- UNITS.each do |unit, abrev|
- iso_str += input[unit].to_s + abrev if input.key?(unit) && !input[unit].zero?
- iso_str += 'T' if unit == :days
- end
- iso_str = iso_str.strip
- iso_str = iso_str.chomp('T') if (iso_str[-1]).eql? 'T'
- ISO8601::Duration.new(iso_str)
- end
-
- def update_member_variables
- @seconds = @duration_obj.seconds.nil? ? 0 : ((@duration_obj.seconds.to_s).split('S')[0]).to_i
- @minutes = @duration_obj.minutes.nil? ? 0 : ((@duration_obj.minutes.to_s).split('H')[0]).to_i
- @hours = @duration_obj.hours.nil? ? 0 : ((@duration_obj.hours.to_s).split('H')[0]).to_i
- @days = @duration_obj.days.nil? ? 0 : ((@duration_obj.days.to_s).split('D')[0]).to_i
- @weeks = @duration_obj.weeks.nil? ? 0 : ((@duration_obj.weeks.to_s).split('W')[0]).to_i
- @months = @duration_obj.months.nil? ? 0 : ((@duration_obj.months.to_s).split('M')[0]).to_i
- @years = @duration_obj.years.nil? ? 0 : ((@duration_obj.years.to_s).split('Y')[0]).to_i
- end
-
- def dur_obj_to_hash(dur_obj)
- result_hash = {}
- result_hash[:seconds] = dur_obj.seconds.nil? ? 0 : ((dur_obj.seconds.to_s).split('S')[0]).to_i
- result_hash[:minutes] = dur_obj.minutes.nil? ? 0 : ((dur_obj.minutes.to_s).split('H')[0]).to_i
- result_hash[:hours] = dur_obj.hours.nil? ? 0 : ((dur_obj.hours.to_s).split('H')[0]).to_i
- result_hash[:days] = dur_obj.days.nil? ? 0 : ((dur_obj.days.to_s).split('D')[0]).to_i
- result_hash[:weeks] = dur_obj.weeks.nil? ? 0 : ((dur_obj.weeks.to_s).split('W')[0]).to_i
- result_hash[:months] = dur_obj.months.nil? ? 0 : ((dur_obj.months.to_s).split('M')[0]).to_i
- result_hash[:years] = dur_obj.years.nil? ? 0 : ((dur_obj.years.to_s).split('Y')[0]).to_i
- result_hash
- end
- end
-end
diff --git a/lib/microsoft_kiota_abstractions/serialization/parsable.rb b/lib/microsoft_kiota_abstractions/serialization/parsable.rb
deleted file mode 100644
index a5a6785..0000000
--- a/lib/microsoft_kiota_abstractions/serialization/parsable.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-module MicrosoftKiotaAbstractions
- module Parsable
- def get_field_deserializers
- raise NotImplementedError.new
- end
-
- def serialize(writer)
- raise NotImplementedError.new
- end
- end
-end
diff --git a/lib/microsoft_kiota_abstractions/serialization/parse_node.rb b/lib/microsoft_kiota_abstractions/serialization/parse_node.rb
deleted file mode 100644
index f3dacfb..0000000
--- a/lib/microsoft_kiota_abstractions/serialization/parse_node.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-module MicrosoftKiotaAbstractions
- module ParseNode
-
- def get_string_value()
- raise NotImplementedError.new
- end
-
- def get_boolean_value()
- raise NotImplementedError.new
- end
-
- def get_number_value()
- raise NotImplementedError.new
- end
-
- def get_guid_value()
- raise NotImplementedError.new
- end
-
- def get_date_value()
- raise NotImplementedError.new
- end
-
- def get_time_value()
- raise NotImplementedError.new
- end
-
- def get_date_time_value()
- raise NotImplementedError.new
- end
-
- def get_duration_value()
- raise NotImplementedError.new
- end
-
- def get_collection_of_primitive_values()
- raise NotImplementedError.new
- end
-
- def get_collection_of_object_values(factory)
- raise NotImplementedError.new
- end
-
- def get_object_value(factory)
- raise NotImplementedError.new
- end
-
- def assign_field_values(item)
- raise NotImplementedError.new
- end
-
- def get_enum_value(type)
- raise NotImplementedError.new
- end
-
- def get_child_node(name)
- raise NotImplementedError.new
- end
-
- end
-end
diff --git a/lib/microsoft_kiota_abstractions/serialization/parse_node_factory.rb b/lib/microsoft_kiota_abstractions/serialization/parse_node_factory.rb
deleted file mode 100644
index 78e22af..0000000
--- a/lib/microsoft_kiota_abstractions/serialization/parse_node_factory.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-module MicrosoftKiotaAbstractions
- module ParseNodeFactory
- def ParseNodeFactory.get_parse_node(content_type, content)
- raise NotImplementedError.new
- end
- end
-end
diff --git a/lib/microsoft_kiota_abstractions/serialization/parse_node_factory_registry.rb b/lib/microsoft_kiota_abstractions/serialization/parse_node_factory_registry.rb
deleted file mode 100644
index da4196c..0000000
--- a/lib/microsoft_kiota_abstractions/serialization/parse_node_factory_registry.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-require_relative 'parse_node_factory'
-
-module MicrosoftKiotaAbstractions
- class ParseNodeFactoryRegistry
- include ParseNodeFactory
-
- class << self
- attr_accessor :default_instance
- def default_instance; @default_instance ||= ParseNodeFactoryRegistry.new; end
- end
-
- def default_instance
- self.class.default_instance
- end
-
- def content_type_associated_factories
- @content_type_associated_factories ||= Hash.new
- end
-
- def get_parse_node(content_type, content)
- if !content_type
- raise Exception.new 'content type cannot be undefined or empty'
- end
- if !content
- raise Exception.new 'content cannot be undefined or empty'
- end
- vendor_specific_content_type = content_type.split(';').first
- factory = @content_type_associated_factories[vendor_specific_content_type]
- if factory
- return factory.get_parse_node(vendor_specific_content_type, content)
- end
-
- clean_content_type = vendor_specific_content_type.gsub(/[^\/]+\+/i, '')
- factory = @content_type_associated_factories[clean_content_type]
- if factory
- return factory.get_parse_node(clean_content_type, content)
- end
- raise Exception.new "Content type #{contentType} does not have a factory to be parsed"
- end
-
- end
-end
diff --git a/lib/microsoft_kiota_abstractions/serialization/serialization_writer.rb b/lib/microsoft_kiota_abstractions/serialization/serialization_writer.rb
deleted file mode 100644
index 3746f67..0000000
--- a/lib/microsoft_kiota_abstractions/serialization/serialization_writer.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-module MicrosoftKiotaAbstractions
- module SerializationWriter
-
- def write_string_value(key, value)
- raise NotImplementedError.new
- end
-
- def write_boolean_value(key, value)
- raise NotImplementedError.new
- end
-
- def write_number_value(key, value)
- raise NotImplementedError.new
- end
-
- def write_float_value(key, value)
- raise NotImplementedError.new
- end
-
- def get_date_value(key, value)
- raise NotImplementedError.new
- end
-
- def write_guid_value(key, value)
- raise NotImplementedError.new
- end
-
- def write_date_value(key, value)
- raise NotImplementedError.new
- end
-
- def write_time_value(key, value)
- raise NotImplementedError.new
- end
-
- def write_date_time_value(key, value)
- raise NotImplementedError.new
- end
-
- def write_duration_value(key, value)
- raise NotImplementedError.new
- end
-
- def write_collection_of_primitive_values(key, value)
- raise NotImplementedError.new
- end
-
- def write_collection_of_object_values(key, value)
- raise NotImplementedError.new
- end
-
- def write_enum_value(key, value)
- raise NotImplementedError.new
- end
-
- def get_serialized_content()
- raise NotImplementedError.new
- end
-
- def write_additional_data(type)
- raise NotImplementedError.new
- end
-
- def write_any_value(key, value)
- raise NotImplementedError.new
- end
-
- def write_object_value(key, value, *additional_values_to_merge)
- raise NotImplementedError.new
- end
-
- end
-end
diff --git a/lib/microsoft_kiota_abstractions/serialization/serialization_writer_factory.rb b/lib/microsoft_kiota_abstractions/serialization/serialization_writer_factory.rb
deleted file mode 100644
index 640ce59..0000000
--- a/lib/microsoft_kiota_abstractions/serialization/serialization_writer_factory.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-module MicrosoftKiotaAbstractions
- module SerializationWriterFactory
-
- def get_serialization_writer(content_type)
- raise NotImplementedError.new
- end
-
- end
-end
diff --git a/lib/microsoft_kiota_abstractions/serialization/serialization_writer_factory_registry.rb b/lib/microsoft_kiota_abstractions/serialization/serialization_writer_factory_registry.rb
deleted file mode 100644
index 08a3365..0000000
--- a/lib/microsoft_kiota_abstractions/serialization/serialization_writer_factory_registry.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-require_relative 'serialization_writer_factory'
-
-module MicrosoftKiotaAbstractions
- class SerializationWriterFactoryRegistry
- include SerializationWriterFactory
-
- class << self
- attr_accessor :default_instance
- def default_instance; @default_instance ||= SerializationWriterFactoryRegistry.new; end
- end
-
- def default_instance
- self.class.default_instance
- end
-
- def content_type_associated_factories
- @content_type_associated_factories ||= Hash.new
- end
-
- def get_serialization_writer(content_type)
- if !content_type
- raise Exception.new 'content type cannot be undefined or empty'
- end
- vendor_specific_content_type = content_type.split(';').first
- factory = @content_type_associated_factories[vendor_specific_content_type]
- if factory
- return factory.get_serialization_writer(vendor_specific_content_type)
- end
-
- clean_content_type = vendor_specific_content_type.gsub(/[^\/]+\+/i, '')
- factory = @content_type_associated_factories[clean_content_type]
- if factory
- return factory.get_serialization_writer(clean_content_type)
- end
-
- raise Exception.new "Content type #{contentType} does not have a factory to be serialized"
- end
-
- end
-end
diff --git a/release-please-config.json b/release-please-config.json
index 3cef212..76498f2 100644
--- a/release-please-config.json
+++ b/release-please-config.json
@@ -1,15 +1,18 @@
{
"$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json",
+ "release-type": "simple",
+ "include-v-in-tag": true,
+ "include-component-in-tag": false,
+ "bump-minor-pre-major": true,
"packages": {
".": {
- "release-type": "ruby",
- "package-name": "microsoft_kiota_abstractions",
"changelog-path": "CHANGELOG.md",
- "include-v-in-tag": true,
- "include-component-in-tag": false,
- "bump-minor-pre-major": true,
- "version-file": "lib/microsoft_kiota_abstractions/version.rb"
+ "extra-files": [
+ "components/abstractions/lib/microsoft_kiota_abstractions/version.rb",
+ "components/serialization/json/lib/microsoft_kiota_serialization_json/version.rb",
+ "components/http/lib/microsoft_kiota_faraday/version.rb",
+ "components/authentication/oauth/lib/microsoft_kiota_authentication_oauth/version.rb"
+ ]
}
- },
- "bootstrap-sha": "aada60935d93a41dd422c94db2e129f24eb30ac9"
+ }
}
diff --git a/spec/access_token_provider_mock.rb b/spec/access_token_provider_mock.rb
deleted file mode 100644
index 31e60f4..0000000
--- a/spec/access_token_provider_mock.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-require 'microsoft_kiota_abstractions'
-
-class AccessTokenProviderMock
- extend MicrosoftKiotaAbstractions::AccessTokenProvider
-
- DUMMY_TOKEN = 'DummyToken'
- def get_authorization_token(uri, additional_properties = {})
- Fiber.new do
- DUMMY_TOKEN
- end
- end
-end
\ No newline at end of file
diff --git a/spec/parse_node_factory_mock.rb b/spec/parse_node_factory_mock.rb
deleted file mode 100644
index 37af7bb..0000000
--- a/spec/parse_node_factory_mock.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-require 'microsoft_kiota_abstractions'
-class ParseNodeFactoryMock
- include MicrosoftKiotaAbstractions::ParseNodeFactory
-
- def get_valid_content_type
- 'application/json'
- end
- def get_parse_node(clean_content_type, content)
- return {}
- end
-end
\ No newline at end of file
diff --git a/spec/parse_node_factory_registry_spec.rb b/spec/parse_node_factory_registry_spec.rb
deleted file mode 100644
index 7b7732d..0000000
--- a/spec/parse_node_factory_registry_spec.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-require 'microsoft_kiota_abstractions'
-require_relative 'parse_node_factory_mock'
-RSpec.describe MicrosoftKiotaAbstractions do
- values = []
- values << "application/json"
- values << "application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8"
- values << "application/vnd.github.mercy-preview+json"
- values << "application/vnd.github.mercy-preview+json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8"
- serialized_value = "[1]"
- MicrosoftKiotaAbstractions::ParseNodeFactoryRegistry.default_instance.content_type_associated_factories["application/json"] = ParseNodeFactoryMock.new
- it "gets the parse node" do
- values.each do |value|
- expect(MicrosoftKiotaAbstractions::ParseNodeFactoryRegistry.default_instance.get_parse_node(value, serialized_value)).not_to be nil
- end
- end
-end
\ No newline at end of file
diff --git a/spec/query_parameters_mock.rb b/spec/query_parameters_mock.rb
deleted file mode 100644
index e4c3bbf..0000000
--- a/spec/query_parameters_mock.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-class QueryParametersMock
-
- ##
- # Include count of items
- attr_accessor :count
- ##
- # Filter items by property values
- attr_accessor :filter
- ##
- # Order items by property values
- attr_accessor :orderby
- ##
- # Search items by search phrases
- attr_accessor :search
- ##
- # Select properties to be returned
- attr_accessor :select
- ##
- # Skip the first n items
- attr_accessor :skip
- ##
- # Show only the first n items
- attr_accessor :top
- ##
- ## Maps the query parameters names to their encoded names for the URI template parsing.
- ## @param originalName The original query parameter name in the class.
- ## @return a string
- ##
- def get_query_parameter(original_name)
- case original_name
- when "count"
- return "%24count"
- when "filter"
- return "%24filter"
- when "orderby"
- return "%24orderby"
- when "search"
- return "%24search"
- when "select"
- return "%24select"
- when "skip"
- return "%24skip"
- when "top"
- return "%24top"
- else
- return originalName
- end
- end
-end
\ No newline at end of file
diff --git a/spec/request_headers_spec.rb b/spec/request_headers_spec.rb
deleted file mode 100644
index ea5dd17..0000000
--- a/spec/request_headers_spec.rb
+++ /dev/null
@@ -1,53 +0,0 @@
-require 'microsoft_kiota_abstractions'
-RSpec.describe MicrosoftKiotaAbstractions do
- it "adds a request header to the request information" do
- request_info = MicrosoftKiotaAbstractions::RequestInformation.new
- request_info.headers.add("key", "value")
- expect(request_info.headers.get_all.length).to eq(1)
- expect(request_info.headers.get("key").length).to eq(1)
- expect(request_info.headers.get("key").first).to eq("value")
- end
-
- it "adds a request header to the request information when one value is already present" do
- request_info = MicrosoftKiotaAbstractions::RequestInformation.new
- request_info.headers.add("key", "value")
- request_info.headers.add("key", "value2")
- expect(request_info.headers.get_all.length).to eq(1)
- expect(request_info.headers.get("key").length).to eq(2)
- expect(request_info.headers.get("key").first).to eq("value")
- expect(request_info.headers.get("key").last).to eq("value2")
- end
-
- it "try to add a request header to the request information" do
- request_info = MicrosoftKiotaAbstractions::RequestInformation.new
- result1 = request_info.headers.try_add("key", "value")
- result2 = request_info.headers.try_add("key", "value2")
- expect(result1).to eq(true)
- expect(result2).to eq(false)
- expect(request_info.headers.get_all.length).to eq(1)
- expect(request_info.headers.get("key").length).to eq(1)
- expect(request_info.headers.get("key").first).to eq("value")
- end
-
- it "removes a request header from the request information" do
- request_info = MicrosoftKiotaAbstractions::RequestInformation.new
- request_info.headers.add("key", "value")
- expect(request_info.headers.get_all.length).to eq(1)
- request_info.headers.remove("key")
- expect(request_info.headers.get_all.length).to eq(0)
- end
-
- it "doesnt fail when removing a value if none are present" do
- request_info = MicrosoftKiotaAbstractions::RequestInformation.new
- request_info.headers.remove("key")
- expect(request_info.headers.get_all.length).to eq(0)
- end
-
- it "clears the request headers from the request information" do
- request_info = MicrosoftKiotaAbstractions::RequestInformation.new
- request_info.headers.add("key", "value")
- expect(request_info.headers.get_all.length).to eq(1)
- request_info.headers.clear
- expect(request_info.headers.get_all.length).to eq(0)
- end
-end
\ No newline at end of file
diff --git a/spec/request_information_spec.rb b/spec/request_information_spec.rb
deleted file mode 100644
index 445bc85..0000000
--- a/spec/request_information_spec.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-require 'microsoft_kiota_abstractions'
-require_relative 'request_option_mock'
-require_relative 'query_parameters_mock'
-
-RSpec.describe MicrosoftKiotaAbstractions do
-
- it "adds a request option to the request information" do
- request_info = MicrosoftKiotaAbstractions::RequestInformation.new
- mock_option = RequestOptionMock.new
- mock_option.value = "value"
- request_info.add_request_options(mock_option)
- expect(request_info.get_request_options().length).to eq(1)
- expect(request_info.get_request_option("key")).to eq(mock_option)
- end
-
- it "removes a request option from the request information" do
- request_info = MicrosoftKiotaAbstractions::RequestInformation.new
- mock_option = RequestOptionMock.new
- mock_option.value = "value"
- request_info.add_request_options(mock_option)
- expect(request_info.get_request_options().length).to eq(1)
- request_info.remove_request_options("key")
- expect(request_info.get_request_options().length).to eq(0)
- end
-
- it "adds query parameters with their escaped values" do
- request_info = MicrosoftKiotaAbstractions::RequestInformation.new
- query_parameters = QueryParametersMock.new
- query_parameters.select = "foo,bar"
- request_info.set_query_string_parameters_from_raw_object(query_parameters)
- expect(request_info.query_parameters.length).to eq(1)
- expect(request_info.query_parameters["%24select"]).to eq("foo,bar")
- expect(request_info.query_parameters["select"]).to be_nil
- end
-
- it "doesn't fail adding query parameters with anonymous object" do
- request_info = MicrosoftKiotaAbstractions::RequestInformation.new
- query_parameters = {
- select: "foo,bar"
- }
- request_info.set_query_string_parameters_from_raw_object(query_parameters)
- expect(request_info.query_parameters.length).to eq(0)
- end
-
-end
\ No newline at end of file
diff --git a/spec/serialization_writer_factory_mock.rb b/spec/serialization_writer_factory_mock.rb
deleted file mode 100644
index f48f32b..0000000
--- a/spec/serialization_writer_factory_mock.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-require 'microsoft_kiota_abstractions'
-class SerializationWriterFactoryMock
- include MicrosoftKiotaAbstractions::SerializationWriterFactory
-
- def get_valid_content_type
- 'application/json'
- end
- def get_serialization_writer(clean_content)
- return {}
- end
-end
\ No newline at end of file
diff --git a/spec/serialization_writer_factory_registry_spec.rb b/spec/serialization_writer_factory_registry_spec.rb
deleted file mode 100644
index 0e3e165..0000000
--- a/spec/serialization_writer_factory_registry_spec.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-require 'microsoft_kiota_abstractions'
-require_relative 'serialization_writer_factory_mock'
-RSpec.describe MicrosoftKiotaAbstractions do
- values = []
- values << "application/json"
- values << "application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8"
- values << "application/vnd.github.mercy-preview+json"
- values << "application/vnd.github.mercy-preview+json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8"
- MicrosoftKiotaAbstractions::SerializationWriterFactoryRegistry.default_instance.content_type_associated_factories["application/json"] = SerializationWriterFactoryMock.new
- it "gets the serialization writer" do
- values.each do |value|
- expect(MicrosoftKiotaAbstractions::SerializationWriterFactoryRegistry.default_instance.get_serialization_writer(value)).not_to be nil
- end
- end
-end
\ No newline at end of file
diff --git a/version.txt b/version.txt
new file mode 100644
index 0000000..c5523bd
--- /dev/null
+++ b/version.txt
@@ -0,0 +1 @@
+0.17.0