Compare commits

...

493 Commits

Author SHA1 Message Date
Adam Hathcock fdc0842b03 Merge pull request #388 from specklesystems/dev
.NET Build and Publish / build (push) Has been cancelled
Main to dev (no squash)
2025-09-12 12:04:04 +01:00
Adam Hathcock 530387b87c Remove the cache that avoids recalculating IDs from JSON (#384)
Co-authored-by: Jedd Morgan <45512892+JR-Morgan@users.noreply.github.com>
Co-authored-by: Claire Kuang <kuang.claire@gmail.com>
2025-09-12 10:47:53 +00:00
Adam Hathcock b16e32d1ff fix: Correctly pass options to object saver (#387)
* Correctly pass options to object saver

* formatting
2025-09-12 10:30:47 +00:00
Jedd Morgan d91fccbb10 Merge pull request #386 from specklesystems/jrm/local-account-ids
chore(sdk): deprecate local ids
2025-09-11 11:03:27 +00:00
Jedd Morgan 62f687b589 Merge pull request #385 from specklesystems/jrm/hashed-account-fallbacks
.NET Build and Publish / build (push) Has been cancelled
chore(sdk)!: Remove fallback behaviour from hashed account info
2025-09-10 14:50:27 +01:00
Adam Hathcock c0d4d951df Merge pull request #383 from specklesystems/dependabot/github_actions/actions/setup-dotnet-5
Bump actions/setup-dotnet from 4 to 5
2025-09-09 08:26:29 +01:00
dependabot[bot] 4e1753e1fd Bump actions/setup-dotnet from 4 to 5
Bumps [actions/setup-dotnet](https://github.com/actions/setup-dotnet) from 4 to 5.
- [Release notes](https://github.com/actions/setup-dotnet/releases)
- [Commits](https://github.com/actions/setup-dotnet/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/setup-dotnet
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-08 19:09:58 +00:00
Jedd Morgan 23d5dd44bc Merge pull request #382 from specklesystems/dev
.NET Build and Publish / build (push) Has been cancelled
Dev -> Main for release
2025-09-08 10:54:56 +01:00
Jedd Morgan 4c615ae8c6 Back Merge Main -> dev (#381)
Co-authored-by: Adam Hathcock <adamhathcock@users.noreply.github.com>
2025-09-08 10:43:16 +01:00
Jedd Morgan d5ee9fb76c Merge branch 'dev' into jrm/dev-main 2025-09-08 10:42:30 +01:00
Björn Steinhagen ea118bcdbb fix: collection order (#380)
* fix: collection order

* chore: format

* refactor: keeping depth first
2025-09-08 09:21:02 +00:00
Adam Hathcock ba456ee3eb Merge pull request #378 from specklesystems/dev
.NET Build and Publish / build (push) Has been cancelled
Dev to main for release (NO SQUASH)
2025-08-28 09:33:09 +01:00
Adam Hathcock 10d283a9f7 Report increment rather than total position (#377)
* Report increment rather than total position

* Report progress before saving SQLite
2025-08-26 16:45:53 +01:00
dependabot[bot] 647c4733cb Bump actions/checkout from 4 to 5 (#376)
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-20 10:32:24 +01:00
Jedd Morgan 30c9b17dab Merge pull request #374 from specklesystems/dev
.NET Build and Publish / build (push) Has been cancelled
Dev -> Main
2025-08-06 13:39:59 +01:00
Jedd Morgan f7ddc19086 Merge pull request #375 from specklesystems/jrm/main-dev-7
Main -> Dev
2025-08-06 13:28:59 +01:00
Jedd Morgan 6d06901b4f Merge branch 'dev' into jrm/main-dev-7 2025-08-06 13:13:39 +01:00
Jedd Morgan 4b588fc287 Do not dispose the activity factory (#372)
.NET Build and Publish / build (push) Has been cancelled
2025-08-04 14:21:50 +00:00
Jedd Morgan 786e683d89 Merge pull request #371 from specklesystems/dev
.NET Build and Publish / build (push) Has been cancelled
Dev -> Main for 3.5.0 stable
2025-08-01 14:49:47 +01:00
Jedd Morgan 8d999f4f9c Update README.md (#370) 2025-07-30 07:53:10 +00:00
Jedd Morgan bb7542e254 chore(ci): Remove Gitversion (#369)
* Strip out gitversion

* Pr workflow

* fix?

* fix x2

* pass envvars properly
2025-07-30 08:41:32 +01:00
Jedd Morgan d6f6254a92 feat(file-import): Added file import resource and blob api functions (#367)
.NET Build and Publish / build (push) Has been cancelled
* add file import resource

* disabled health check

* re-enable healthcheck

* git ignore volumes

* disabled importer

* start_period

* Skipped broken tests

* Verify tests

* Fixed tests

* reverted volumes path

* Update docker-compose.yml
2025-07-29 14:52:12 +00:00
Jedd Morgan f60f85b639 Merge pull request #368 from specklesystems/jrm/main-dev-5
chore: main -> dev
2025-07-28 18:01:43 +01:00
Jedd Morgan bcdf73cc70 Updated active workspace query (#365) 2025-07-25 08:42:43 +01:00
Adam Hathcock 47e72ee1a7 Merge pull request #364 from specklesystems/dev
.NET Build and Publish / build (push) Has been cancelled
Main to dev
2025-07-23 14:19:52 +01:00
Adam Hathcock f3de5324db Merge pull request #362 from specklesystems/main
Main to dev
2025-07-23 13:44:14 +01:00
Adam Hathcock 4dd6db886f insert or replace always...don't use ignore or insert (#363)
* SaveObject is always insert or replace.  Never use insert or ignore

* add/fix tests

* always replace even for bulk
2025-07-23 12:16:08 +00:00
Adam Hathcock 4b82db8ea2 Merge pull request #361 from specklesystems/dev
.NET Build and Publish / build (push) Has been cancelled
Main to dev
2025-07-23 10:23:04 +01:00
Adam Hathcock 9e7f26f7a6 Add ModelCacheManager class and use it (#356)
* Introduce ModelCacheManager to manage cache and sizes and deletions

* move and abstract

* add tests and format

* Update src/Speckle.Sdk/Caching/ModelCacheManager.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Clean up

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-07-23 10:07:57 +01:00
Adam Hathcock b19f8c4219 Merge pull request #358 from specklesystems/dev
.NET Build and Publish / build (push) Has been cancelled
(NO SQUASH) Main to dev for release
2025-07-21 15:49:49 +01:00
Adam Hathcock c517e61517 Merge pull request #360 from specklesystems/main-dev
Main to dev
2025-07-21 15:47:38 +01:00
Adam Hathcock b3e0623856 Merge remote-tracking branch 'origin/main' into main-dev 2025-07-21 15:36:30 +01:00
Adam Hathcock e5d1ef2448 Merge pull request #354 from specklesystems/main-dev
Merge pull request #348 from specklesystems/dev
2025-07-21 11:12:54 +01:00
Adam Hathcock 83c3de05fa Merge remote-tracking branch 'origin/dev' into main-dev 2025-07-21 11:02:02 +01:00
Adam Hathcock 507ded7d4a Fix shallow copy allocations and perf (#357)
* add more DynamicBase Tests

* Move ShallowCopy to dynamic and try to be faster with copy

* Correct tests for macOS

* use cache obsolete attribute

* Update src/Speckle.Sdk/Models/DynamicBase.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update tests/Speckle.Sdk.Tests.Unit/Models/DynamicBaseTests.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update tests/Speckle.Sdk.Tests.Unit/Models/DynamicBaseTests.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix AI

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-07-21 11:01:00 +01:00
Adam Hathcock e15029bab3 Merge pull request #350 from specklesystems/dev
.NET Build and Publish / build (push) Has been cancelled
(dev to main) If we're already cancelling, ignore extra exceptions (#349)
2025-07-14 10:34:06 +01:00
Adam Hathcock a43fd44206 Stop recording an exception that's rethrown (#355)
* Stop recording an exception that's rethrown

* Update src/Speckle.Sdk/Api/GraphQL/Client.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-07-14 10:15:40 +01:00
Adam Hathcock 1bcd8ac3a4 Merge branch 'dev' into main-dev 2025-07-03 10:42:05 +01:00
Adam Hathcock a8dc93e22b Adds detail to message so that user isn't going WTF SDK (#351)
* Adds detail to message so that user isn't going WTF SDK

* update exception tests
2025-07-03 09:39:53 +00:00
Jedd Morgan 5a0f883b98 Add compatibility with :local docker images (#353)
Co-authored-by: Adam Hathcock <adamhathcock@users.noreply.github.com>
2025-07-03 10:28:35 +01:00
Adam Hathcock a5d035671a If we're already cancelling, ignore extra exceptions (#349)
* If we're already cancelling, ignore extra exceptions

* Do more robust cancellation

* Try to have more robust disposal and cancellation check
2025-07-01 10:20:32 +01:00
Adam Hathcock cd6ebad619 Merge pull request #348 from specklesystems/dev
.NET Build and Publish / build (push) Has been cancelled
New release for connectors
2025-06-30 15:15:51 +01:00
Adam Hathcock 33c2e6e1a4 Better handle graphql commit errors (#343)
* Better handle graphql commit errors

* add graphql error test
2025-06-30 10:54:44 +00:00
Adam Hathcock b97702adb1 Small fixes to SDK (#347)
* Increase channel capacity to make things more performant

* Avoid logging send cancellation exceptions, caller did it

* Try to avoid collection modified errors when cancelling by more aggressive checks

* oops, rethrow, don't catch
2025-06-30 10:37:30 +00:00
Adam Hathcock 80c4f694ec Merge pull request #346 from specklesystems/main-dev
Main to dev
2025-06-30 11:26:36 +01:00
Adam Hathcock fb5042004f Merge remote-tracking branch 'origin/dev' into main-dev 2025-06-30 08:58:57 +01:00
Adam Hathcock c0a9291632 Merge pull request #344 from specklesystems/oguzhan/level-proxies
.NET Build and Publish / build (push) Has been cancelled
Feat(objects): level proxies
2025-06-23 15:05:15 +01:00
oguzhankoral b783d2acb6 Format 2025-06-23 15:57:24 +03:00
oguzhankoral 93539adc1e Add level proxies 2025-06-23 15:42:48 +03:00
Adam Hathcock 98005933de Remove DistinctBy as we don't use it (#342) 2025-06-19 09:34:34 +01:00
Adam Hathcock 50906b172a Merge pull request #340 from specklesystems/dev
.NET Build and Publish / build (push) Has been cancelled
2025-06-11 17:35:27 +01:00
Adam Hathcock 05f7353925 Revert "Merge pull request #335 from specklesystems/adam/cnx-1786-allow-multiple-sends-to-access-sqlite-in-a-non-locking-2" (#339)
This reverts commit 59019bf846, reversing
changes made to 3afaf61a1a.

Co-authored-by: Adam Hathcock <adam@Adams-Mac-mini.localdomain>
2025-06-11 15:32:06 +00:00
Adam Hathcock 8328498553 Merge pull request #338 from specklesystems/dev
.NET Build and Publish / build (push) Has been cancelled
Dev to Main (no squash)
2025-06-11 11:07:20 +01:00
Adam Hathcock 59019bf846 Merge pull request #335 from specklesystems/adam/cnx-1786-allow-multiple-sends-to-access-sqlite-in-a-non-locking-2
Use an object saver per stream instead of sqlite manager per stream
2025-06-11 10:50:34 +01:00
Adam Hathcock 3afaf61a1a Merge pull request #337 from specklesystems/main
Main to dev (no squash)
2025-06-11 10:50:18 +01:00
Adam Hathcock 424609fad0 fix tests 2025-06-10 13:18:34 +01:00
Adam Hathcock 46c067308e Fix DI dependency and tests 2025-06-10 11:39:42 +01:00
Adam Hathcock 0e33e8df8f add tests 2025-06-10 11:33:17 +01:00
Adam Hathcock bc81c21e9d format 2025-06-10 11:15:30 +01:00
Adam Hathcock 7f8b59d348 Pool object savers instead of sqlite 2025-06-10 11:15:01 +01:00
Adam Hathcock 44ba61e4a5 Adjustments to avoid sqlite "database is locked" errors (#333)
* add new exception test

* Make memory tests and file path tests be explicit

* set the default write parallelism to 1

* set to single reader for caching channel

* format

* Try to have consistent DB locked error test

* always a single reader of the channel

* Remove extra snapshot

* Revert "Try to have consistent DB locked error test"

This reverts commit 93669c57a3.

* remove extra test that doesn't do anything
2025-06-09 16:24:39 +00:00
Adam Hathcock 4f7b470901 Merge pull request #329 from specklesystems/dev
.NET Build and Publish / build (push) Has been cancelled
SDK 3.4 release (do not squash)
2025-06-05 13:59:43 +01:00
Jedd Morgan 8c6426d617 Updated one more usage of newtonsoft (#332)
Co-authored-by: Adam Hathcock <adamhathcock@users.noreply.github.com>
2025-06-05 10:39:16 +00:00
Adam Hathcock 5562ce1a2d Add detail to the message in logs (#331) 2025-06-05 09:54:36 +01:00
Jedd Morgan 7019b8d7c6 Fix(automate): STJ camel casing (#330)
* stj required

* More requireds

* Use JSON serializer settings for camel case rule

* readonly

* static naming
2025-06-04 15:56:50 +00:00
Adam Hathcock 58a0326060 Receive should sort the root closures to see a speed improvement (#311)
* Maybe really fixes closures

* fornat

* add ai generated tests

* fix tests

* fix tests

* added test with correct number of closures?

* closures are self contained.  don't increment on attached properties

* format

* MergeClosure should reuse if exists, not just set

* Add generated tests and sort the parser correctly when using get closures

* add extra options to not sort and make sorting default for receive

* hide private method
2025-06-04 13:54:26 +00:00
Adam Hathcock 55f83919d1 Don't log aggregate exceptions that only contain cancelled exceptions (#326)
* Don't log aggregate exceptions that only contain cancelled exceptions

* check if all are not cancelled
2025-06-04 12:59:51 +00:00
Adam Hathcock 46c57b18be Cancel before kicking off tasks to ensure they throw (#328) 2025-06-04 13:49:03 +01:00
Adam Hathcock 7b5ada57cd Changing uploaded to uploading to better show progress than just rate (#321) 2025-06-03 16:27:02 +00:00
Adam Hathcock e29b27bcd3 Add some debugging stats about the sent or received payloads to add debugging when things are massive (#319) 2025-06-03 14:15:37 +00:00
Jedd Morgan ff1b688321 refactor(accountmanager): Refactor account manager for automate (#320)
* First pass refactor account manager

* Use GraphQLClient factory in account manager also

* update account references

* cleanup

* Added test + comments

* more docstrings

* More tests
2025-06-03 12:54:44 +00:00
Adam Hathcock 0be143d391 Make nulls appear as soon as possible (#324) 2025-06-03 12:09:55 +00:00
Adam Hathcock c0a66a297a Add info to send/receives for debugging (#325) 2025-06-03 12:48:05 +01:00
Adam Hathcock aad604e819 Merge pull request #323 from specklesystems/main-dev
Main to dev
2025-06-03 09:41:16 +01:00
Adam Hathcock 48313cb082 Merge remote-tracking branch 'origin/dev' into main-dev 2025-06-02 15:50:19 +01:00
kekesidavid 0361a6e5b7 Merge pull request #318 from specklesystems/david/move-text-class-update-pr-to-main
.NET Build and Publish / build (push) Has been cancelled
fix (sdk) Text class updates: removed origin from Text class and added screenAligned prop
2025-06-02 09:22:57 +02:00
David Kekesi 0e97782c29 fixed comment 2025-06-02 09:12:12 +02:00
David Kekesi 298dedc3af text class update pr moved to main 2025-05-30 19:01:02 +02:00
Adam Hathcock 422403d499 fix concurrent tests 2 - This should wait for cancellation to happen (#316)
* Fix test to be deterministic

* This should wait for cancellation to happen

* update csharpier
2025-05-30 14:17:04 +00:00
Adam Hathcock b652ffa773 Fix test to be deterministic (#315) 2025-05-30 12:30:57 +00:00
Adam Hathcock 68ace02e2d Use custom md5 just for account/user IDs, not anything real (#314)
* Use custom md5 just for account/user IDs, not anything real

* test fixes

* To lower and upper as needed
2025-05-30 12:15:44 +00:00
Jedd Morgan b6be7a351f feat(automate): Add automate SDK (#313)
* First pass

* First pass adding service registraiton

* Finished up service registration

* Json exception

* Moved to the right place

* Fixed tests

* Added some missing docs strings

* Reflecting Gergo's specklepy changes

* Correct the DI registration

* Readme

* No warn beta packages

* Format

* renamed misleading variable

* Fixed lock files

* Disable SQLite for automate
2025-05-30 13:05:14 +01:00
Adam Hathcock 1039e75d0c Calculate closures correctly (#309)
* Maybe really fixes closures

* fornat

* add ai generated tests

* fix tests

* fix tests

* added test with correct number of closures?

* closures are self contained.  don't increment on attached properties

* format

* MergeClosure should reuse if exists, not just set

* add not null on a method
2025-05-27 14:05:10 +01:00
Jedd Morgan 0f8752d5ab feat(api): Improvements to GrahpQL error handling (#304)
* Graphql extras

* extra server resource test

* usings

* Fixed test
2025-05-20 12:44:23 +00:00
Adam Hathcock 64a93345d6 Merge pull request #310 from specklesystems/main
Main to dev (no squash)
2025-05-19 12:00:56 +01:00
Jedd Morgan efc38d8f5c Added Workspace project visibility (#307)
.NET Build and Publish / build (push) Has been cancelled
2025-05-14 21:37:39 +03:00
Jedd Morgan e3ca75abe1 removed csharp 4.7 dependency from .net8 target (#306) 2025-05-14 13:12:37 +01:00
Adam Hathcock b479d368ad SLNX added, only supported in IDEs and .NET 9+ (#294) 2025-05-14 09:35:43 +00:00
Adam Hathcock 8d3985f93b Merge pull request #305 from specklesystems/dev
.NET Build and Publish / build (push) Has been cancelled
Dev to Main
2025-05-14 10:19:51 +01:00
Jedd Morgan 915a18dc98 Merge pull request #303 from specklesystems/jrm/main-dev
Main -> Dev
2025-05-13 11:38:56 +01:00
Jedd Morgan 5fcb3223d6 Merge branch 'dev' into jrm/main-dev 2025-05-13 11:28:13 +01:00
Adam Hathcock 21851c06d2 Use WhenAll instead of WhenAny and avoid manual task exception processing (#300)
* No reason to process exceptions manually

* formatting

* use a pool for gathering child task results

* Use a smaller whenany with a cancellation

* formatting
2025-05-13 10:00:53 +01:00
Adam Hathcock 3a9a633d30 Add empty DataObject tests (#301)
* Add empty DataObject tests

* format
2025-05-09 14:51:03 +00:00
Jedd Morgan 7f092d529c feat(api): Add ActiveUserResource.GetProjectsWithPermissions (#299)
.NET Build and Publish / build (push) Has been cancelled
* Fixed Mistakes (#296)

* Added extra permission checks (#297)

* Add extra query for project with permissions

---------

Co-authored-by: Adam Hathcock <adamhathcock@users.noreply.github.com>
Co-authored-by: Adam Hathcock <adam@hathcock.uk>
2025-05-08 15:11:53 +00:00
Jedd Morgan a4f0e0e4aa Added extra permission checks (#297)
.NET Build and Publish / build (push) Has been cancelled
2025-05-08 09:25:08 +00:00
Jedd Morgan 227729a0df Fixed Mistakes (#296)
.NET Build and Publish / build (push) Has been cancelled
2025-05-07 17:01:56 +00:00
Jedd Morgan 178085f3f8 dev -> main (#295)
.NET Build and Publish / build (push) Has been cancelled
* Sanitize test references

* add registration tests to SDK and ignore classes that can't be made

* add additional test

* chore(dev) Update to csharpier 1.0 (#284)

* Update to csharpier 1.0

* Fix check and nowarn

* format

* Update dependencies (#285)

* Added extra test for GetMembers (#290)

* Added extra test for GetMembers

* fixed tests

* verify

* Format

* Run the module init on unit tests and make it json

* update deps

* gitignore support was disabled in csharpier 1.0.1

---------

Co-authored-by: Adam Hathcock <adam@hathcock.uk>

* Add workspaces queries (#291)

* Add workspaces queries

* Format

* extra tweaks

* init speckle verify

* Add workspace creation state

* Add workspace creation test

* test exceptional cases

* GetActiveWorkspace tests

* fixed test

---------

Co-authored-by: Adam Hathcock <adamhathcock@users.noreply.github.com>
Co-authored-by: Adam Hathcock <adam@hathcock.uk>
2025-05-06 18:02:59 +03:00
Adam Hathcock 9794195e9c Merge pull request #293 from specklesystems/main-dev
.NET Build and Publish / build (push) Has been cancelled
Main to dev (NO SQUASH)
2025-05-06 14:00:54 +01:00
Adam Hathcock a61c442930 Merge branch 'dev' into main-dev 2025-05-06 13:50:16 +01:00
Jedd Morgan 68a407905d Add workspaces queries (#291)
* Add workspaces queries

* Format

* extra tweaks

* init speckle verify

* Add workspace creation state

* Add workspace creation test

* test exceptional cases

* GetActiveWorkspace tests

* fixed test
2025-05-01 21:23:30 +03:00
Adam Hathcock 0f2abaf532 Merge remote-tracking branch 'origin/dev' into main-dev 2025-04-30 16:24:06 +01:00
Adam Hathcock 07634b6f6a Merge remote-tracking branch 'origin/dev' into main-dev 2025-04-30 16:22:39 +01:00
Jedd Morgan e938725d35 Added extra test for GetMembers (#290)
* Added extra test for GetMembers

* fixed tests

* verify

* Format

* Run the module init on unit tests and make it json

* update deps

* gitignore support was disabled in csharpier 1.0.1

---------

Co-authored-by: Adam Hathcock <adam@hathcock.uk>
2025-04-30 16:13:41 +01:00
Adam Hathcock d3369e3ce5 Merge pull request #289 from specklesystems/main-dev
Main to dev (don't squash)
2025-04-30 16:00:46 +01:00
KatKatKateryna d75a61d775 Add text class (#271)
.NET Build and Publish / build (push) Has been cancelled
* draft class

* corrections

* edits

* max width

* remove import

* typo

* naming

* move directories

* delete from old location

* comment

* formatting

---------

Co-authored-by: Claire Kuang <kuang.claire@gmail.com>
2025-04-30 10:56:29 +02:00
Adam Hathcock 2ae4003afb Merge branch 'main' into main-dev 2025-04-28 10:52:58 +01:00
Adam Hathcock 24db4c4ae4 Merge pull request #288 from specklesystems/adam/no-drop-writes
.NET Build and Publish / build (push) Has been cancelled
fix (main) Don't drop items to write when sending fast
2025-04-28 10:18:48 +01:00
Adam Hathcock edf63d4a1b fix build issue 2025-04-28 09:39:46 +01:00
Adam Hathcock b5b0922e7f Revert to write async 2025-04-28 09:35:02 +01:00
Adam Hathcock ff390f772d just wait for space instead of another task and reduce size to 1000 2025-04-25 18:24:34 +01:00
Adam Hathcock d69f0bba2a fmt 2025-04-25 18:13:05 +01:00
Adam Hathcock 33c14fc14c Remove extras 2025-04-25 18:09:04 +01:00
Adam Hathcock 536e58aacc Don't drop items to write when sending fast 2025-04-25 17:45:01 +01:00
Adam Hathcock 88188aace6 Merge pull request #287 from specklesystems/main-dev
Main to dev (NO SQUASH)
2025-04-24 12:12:06 +01:00
Adam Hathcock ad44a7cdbc Merge branch 'dev' into main-dev 2025-04-24 12:01:32 +01:00
Adam Hathcock 38449dca9a Update dependencies (#285) 2025-04-24 11:59:26 +01:00
Adam Hathcock 764eb43838 Merge branch 'dev' into main-dev 2025-04-24 11:52:02 +01:00
Adam Hathcock a84e6d89ca chore(dev) Update to csharpier 1.0 (#284)
* Update to csharpier 1.0

* Fix check and nowarn

* format
2025-04-24 10:45:09 +00:00
Adam Hathcock 377829adae fix(main) exception test correction and token usage (#283)
.NET Build and Publish / build (push) Has been cancelled
* add parallelism on exception after count test

* use scoped token source correctly

* format

* Centralized token usage and made sqlite busy timeout be 5 seconds

* restore write parallelism to 4

* add to comment
2025-04-24 10:40:46 +00:00
Adam Hathcock a479440b66 Merge pull request #286 from specklesystems/adam/check-registration
feature (dev) check registration
2025-04-24 11:29:27 +01:00
Adam Hathcock cc9639b179 Merge pull request #282 from specklesystems/adam/error-fix
fix(main) Wrong error message being displayed in UI
2025-04-24 11:29:10 +01:00
Adam Hathcock d44b4fa52b add additional test 2025-04-24 08:33:42 +01:00
Adam Hathcock ea6ca8c555 add registration tests to SDK and ignore classes that can't be made 2025-04-23 15:57:03 +01:00
Adam Hathcock 113f0fd551 Sanitize test references 2025-04-23 15:42:57 +01:00
Adam Hathcock bcc4e25970 Merge pull request #280 from specklesystems/main-dev
Main->Dev
2025-04-23 13:04:37 +01:00
Adam Hathcock b733ce5f29 fix snapshot test message 2025-04-22 11:09:50 +01:00
Adam Hathcock 1c8b2b82d7 Wrong error message being displayed in UI 2025-04-22 10:13:59 +01:00
Jedd Morgan 11cd2dc1cb Update ProjectResourceExceptionalTests.cs (#279) 2025-04-11 12:27:04 +00:00
Adam Hathcock 3789898ea2 Merge pull request #278 from specklesystems/dev
.NET Build and Publish / build (push) Has been cancelled
SDK 3.2 release from dev to main
2025-04-09 12:35:06 +01:00
Adam Hathcock 0b3318f9e1 Merge pull request #277 from specklesystems/main-dev
Main to dev again
2025-04-09 11:56:35 +01:00
Adam Hathcock 7589ad5f05 Merge remote-tracking branch 'origin/dev' into main-dev 2025-04-09 11:45:06 +01:00
Adam Hathcock 6df32262bd fix: Update HostAppVersion.cs (#276)
Adding v2026 for next autodesk releases support.

Co-authored-by: Jonathon Broughton <760691+jsdbroughton@users.noreply.github.com>
2025-04-09 10:42:40 +00:00
Adam Hathcock 001ca1c287 Update some dependencies (#275) 2025-04-09 10:31:23 +00:00
Adam Hathcock 59e459559b Merge branch 'dev' into main-dev 2025-04-09 11:22:51 +01:00
Adam Hathcock d305fe59cb feat(sdk) clean up registration of sdk to not be connector specific (#274)
* First pass of ObjectSaver and better in-memory usage

* fix some tests

* add commit to match deserialize process

* correct more tests

* format

* make a deserialize factory

* fix tests? and format

* use distinct

* Fix mismerge

* Fix serialization issues with tests

* fix merges

* follow copilot suggestions

* remove disables

* change registration to take strings and TypeLoader isn't public

* remove unused transports

* more test fixes

* fmt

* add Application object back
2025-04-08 09:49:31 +00:00
Adam Hathcock f163b2822e (feat) add memory serialize and make relevant tests use it (#252)
* First pass of ObjectSaver and better in-memory usage

* fix some tests

* add commit to match deserialize process

* correct more tests

* format

* make a deserialize factory

* fix tests? and format

* use distinct

* Fix mismerge

* Fix serialization issues with tests

* fix merges

* follow copilot suggestions

* remove disables
2025-04-08 10:21:47 +01:00
Adam Hathcock 630bb38b8b fix: Update HostAppVersion.cs (#273)
Adding v2026 for next autodesk releases support.

Co-authored-by: Jonathon Broughton <760691+jsdbroughton@users.noreply.github.com>
2025-04-07 13:43:22 +01:00
Adam Hathcock bacff2da34 Merge branch 'dev' into main-dev 2025-04-07 12:46:07 +01:00
Adam Hathcock 129d5285ed Merge branch 'main' into main-dev 2025-04-07 12:45:09 +01:00
Adam Hathcock 5d07fe0ea0 refactor error handling to no propagate through channels. (#268)
* refactor error handling to no propagate through channels.  Use cancellation to shut down on exception

* don't try to shutdown scheduler when exception happens...handle tokens in a tree

* some cleanup

* ConfigureAwait(false) again

* Add test and clean up exception handling

* fmt

* fixed tests
2025-04-07 11:49:47 +01:00
Adam Hathcock 062e3c2838 Make packs require tests too (#254) 2025-04-07 10:10:41 +00:00
Adam Hathcock f4cc4bc77e Merge pull request #272 from specklesystems/adam/add-2026
.NET Build and Publish / build (push) Has been cancelled
fix: Update HostAppVersion.cs for 2026
2025-04-07 10:55:25 +01:00
Jonathon Broughton d395f03219 fix: Update HostAppVersion.cs
Adding v2026 for next autodesk releases support.
2025-04-07 10:10:18 +01:00
Adam Hathcock 56ed399d70 Removes log statement that is confusing people when viewing log files (#267) 2025-03-26 14:21:06 +00:00
Adam Hathcock 7e0766fc7f Merge pull request #262 from specklesystems/main-dev
Main to dev
2025-03-25 10:24:16 +00:00
Adam Hathcock 0df343ebe1 Merge remote-tracking branch 'origin/main' into main-dev 2025-03-25 09:02:02 +00:00
Oğuzhan Koral 3cad57ceb3 Update object instead save (#266)
.NET Build and Publish / build (push) Has been cancelled
2025-03-24 20:24:15 +03:00
Oğuzhan Koral 11937ad7c9 Handle refresh token on catch (#265)
.NET Build and Publish / build (push) Has been cancelled
2025-03-24 13:39:23 +03:00
Adam Hathcock 8210fde69a Merge pull request #264 from specklesystems/oguzhan/parameter-for-app-id-secret
.NET Build and Publish / build (push) Has been cancelled
Chore(accounts): Extract hard coded app as parameter into function
2025-03-20 15:29:50 +00:00
oguzhankoral fa6f90621e Extract hard coded app as parameter into function 2025-03-20 18:18:23 +03:00
Adam Hathcock f6f1852664 Merge branch 'dev' into main-dev 2025-03-17 12:36:33 +00:00
Adam Hathcock b3f4190614 Merge pull request #260 from specklesystems/adam/fix-cancel-check
.NET Build and Publish / build (push) Has been cancelled
Cancellation check for sending needs to not be wrapped
2025-03-17 12:21:44 +00:00
Adam Hathcock 2fc0024cd2 Cancellation check for sending needs to not be wrapped 2025-03-17 12:08:42 +00:00
Adam Hathcock 300a5627fd Merge pull request #259 from specklesystems/revit-levels
.NET Build and Publish / build (push) Has been cancelled
feat(objects): adds level to revitobject
2025-03-17 11:06:13 +00:00
Claire Kuang 22f029fe33 Update RevitObject.cs 2025-03-17 10:32:47 +00:00
Claire Kuang c728266c88 Update RevitObject.cs 2025-03-17 10:31:43 +00:00
Claire Kuang 7f2d57cdad adds level 2025-03-17 10:05:41 +00:00
Adam Hathcock 81a22bd4cc Merge pull request #256 from specklesystems/main-dev
Main to dev
2025-03-13 10:39:11 +00:00
Adam Hathcock f64da099ab Merge branch 'dev' into main-dev 2025-03-13 08:48:36 +00:00
Adam Hathcock f4ba200640 Merge branch 'main' into main-dev 2025-03-13 08:47:23 +00:00
Adam Hathcock 4e84766be9 Merge pull request #253 from specklesystems/regions-PR-to-main
.NET Build and Publish / build (push) Has been cancelled
2025-03-12 17:55:01 +00:00
KatKatKateryna 73a95aded0 Regions class (#241)
* region class

* comments

* adjusted constructor

* todos

* comment

* change displayValur to curves

* small refactor

* assign correct property

* generalize display value

* some minor xml changes

* transform meshes; bbox not required

* remove comment

* Update Region.cs

---------

Co-Authored-By: Claire Kuang <kuang.claire@gmail.com>
Co-Authored-By: Adam Hathcock <adamhathcock@users.noreply.github.com>
2025-03-12 17:38:28 +00:00
KatKatKateryna 404600a839 Regions class (#241)
* region class

* comments

* adjusted constructor

* todos

* comment

* change displayValur to curves

* small refactor

* assign correct property

* generalize display value

* some minor xml changes

* transform meshes; bbox not required

* remove comment

* Update Region.cs

---------

Co-authored-by: Claire Kuang <kuang.claire@gmail.com>
Co-authored-by: Adam Hathcock <adamhathcock@users.noreply.github.com>
2025-03-12 19:10:45 +08:00
Jedd Morgan 93d517eab7 test(objects): Verify tests for serialization (#227)
* Objects Verify Tests

* VerifyTests

* Verify as array with deterministic order

* lock

* Updated verified
2025-03-12 08:29:30 +00:00
Adam Hathcock 4110d90107 Merge pull request #245 from specklesystems/adam/more-code-cov2
Client tests and another SpeckleHttp one
2025-03-11 13:54:14 +00:00
Adam Hathcock 2d134bf7e1 make ExecuteWithResiliencePolicies internal 2025-03-11 13:24:39 +00:00
Adam Hathcock 686d0fd31c Merge remote-tracking branch 'origin/dev' into adam/more-code-cov2 2025-03-11 13:15:32 +00:00
Adam Hathcock b06878bbe1 Merge pull request #242 from specklesystems/remove-more-attributes
Remove more attributes
2025-03-11 12:09:56 +00:00
Adam Hathcock 64114167a8 Merge branch 'dev' into adam/more-code-cov2 2025-03-11 12:07:03 +00:00
Adam Hathcock 0c7cd75353 Merge branch 'dev' into remove-more-attributes 2025-03-11 11:58:47 +00:00
Adam Hathcock 3c5679ad2a Merge pull request #251 from specklesystems/main-dev
Main to dev
2025-03-11 11:58:12 +00:00
Adam Hathcock b043623021 Merge remote-tracking branch 'origin/dev' into main-dev 2025-03-10 09:36:28 +00:00
Adam Hathcock bd0997913a Add back the integration test 2025-03-10 09:31:56 +00:00
Adam Hathcock ac0ab3904c Merge pull request #250 from specklesystems/fix-main
.NET Build and Publish / build (push) Has been cancelled
Fix main again: version the nuget correctly
2025-03-10 09:03:53 +00:00
Adam Hathcock 5c9d672a2b Really fix publish version 2025-03-10 08:50:52 +00:00
Jedd Morgan a79f0fd035 Deprecated public visibility (#249) 2025-03-08 17:50:52 +00:00
Adam Hathcock 18d6653282 Merge pull request #247 from specklesystems/fix-main
.NET Build and Publish / build (push) Has been cancelled
Fix main
2025-03-07 14:54:53 +00:00
Adam Hathcock d58a656c8a make private 2025-03-07 14:43:48 +00:00
Adam Hathcock 720d049145 format 2025-03-07 14:35:37 +00:00
Adam Hathcock 129688a646 Fix restore tools and comment out integration test for now 2025-03-07 14:34:24 +00:00
Adam Hathcock fa66258b23 Merge pull request #246 from specklesystems/release-to-main
Release to main
2025-03-07 14:27:19 +00:00
Adam Hathcock 9f0c572993 also on tags 2025-03-07 14:01:19 +00:00
Adam Hathcock 158baff5b0 Merge branch 'update-build-stamp' into release-to-main 2025-03-07 14:01:10 +00:00
Adam Hathcock 7a29d27e46 Merge remote-tracking branch 'origin/dev' into adam/more-code-cov2 2025-03-07 11:14:32 +00:00
Adam Hathcock 82e3d37dd1 graphql test with client 2025-03-07 11:12:31 +00:00
Adam Hathcock 9695ec8c51 SpeckleHttp coverage (#244)
* Show code coverage for dev

* SpeckleHttp coverage and moved base stuff around

* add SpeckleHttpTests
2025-03-07 10:48:01 +00:00
Adam Hathcock 15fa319433 Show code coverage for dev (#243) 2025-03-07 10:26:13 +00:00
Adam Hathcock 793bbb9cd3 Complete speckle http 2025-03-07 09:29:05 +00:00
Adam Hathcock 3291010d43 add SpeckleHttpTests 2025-03-07 09:09:25 +00:00
Adam Hathcock 14732ce174 SpeckleHttp coverage and moved base stuff around 2025-03-07 09:03:07 +00:00
Adam Hathcock ba655988b0 Show code coverage for dev 2025-03-07 08:39:51 +00:00
Adam Hathcock 96822c4e66 Fix tests 2025-03-06 16:55:01 +00:00
Adam Hathcock 08356de1ad Merge remote-tracking branch 'origin/dev' into remove-more-attributes 2025-03-06 13:46:28 +00:00
Adam Hathcock 375f5071ae Improve test coverage by adding tests and removing unused code (#240)
* maybe all objects need to be false

* fmt

* remove extra code form hosts

* fix build

* add speckle serializer exception test

* add DownloadObjects and DownloadSingleObject test

* fmt

* add HasObjects test

* BaseItem tests

* adjust code and add test for UploadObjects

* Remove try/catch

* can't test compressed?  use lib to parse multipart

* remove unused verify snapshots
2025-03-06 13:20:11 +00:00
Adam Hathcock 5900a3c178 compiles 2025-03-06 12:00:57 +00:00
Adam Hathcock d7bf324029 Remove more unused attributes 2025-03-06 11:59:13 +00:00
Adam Hathcock c784fbf462 remove unused verify snapshots 2025-03-05 14:14:42 +00:00
Adam Hathcock 26f1802787 can't test compressed? use lib to parse multipart 2025-03-05 14:13:05 +00:00
Adam Hathcock a96e0f8c8e Remove try/catch 2025-03-05 12:38:34 +00:00
Adam Hathcock 9f36c9cfe5 adjust code and add test for UploadObjects 2025-03-05 12:18:19 +00:00
Adam Hathcock 4959f277e8 BaseItem tests 2025-03-05 11:10:21 +00:00
Adam Hathcock ea08b83f7a add HasObjects test 2025-03-05 09:54:31 +00:00
Adam Hathcock b24dc685fa fmt 2025-03-05 09:44:32 +00:00
Adam Hathcock 7cad14fe25 add DownloadObjects and DownloadSingleObject test 2025-03-05 09:34:44 +00:00
Adam Hathcock 4d552b6834 add speckle serializer exception test 2025-03-04 16:44:15 +00:00
Adam Hathcock 378a91995e fix build 2025-03-04 16:41:59 +00:00
Adam Hathcock 53b66dd26b remove extra code form hosts 2025-03-04 13:29:36 +00:00
Adam Hathcock 9dd04c0881 fmt 2025-03-03 16:39:17 +00:00
Adam Hathcock 474c18c29f maybe all objects need to be false 2025-03-03 16:32:02 +00:00
Adam Hathcock b676da4ac4 disable .net connection pooling...use our own to free up the files (#238) 2025-03-03 16:07:23 +00:00
Adam Hathcock fe964f4c8e Use IAsyncDisposable on scheduler which also waits for completion (#235)
* Use IAsyncDisposable on scheduler which also waits for completion

* formatting
2025-03-03 14:50:38 +00:00
Adam Hathcock 1fea4cc01b Add a logging statement for when batch size was larger than expected (25 megs) (#232) 2025-02-27 15:44:35 +00:00
Adam Hathcock c3d716f6fd fix: an exception in the underlying code results in UnobservedTaskExceptions and not ending of the send process. (#237)
* Cancel all channels when first exception happens then throw that exception

* Use single exception to end things.

* fix verifications

* fmt

* Fix tests as stacktrace was removed

* Handle one exception and cancel on receive

* moved ThrowIfFailed and made throw speckle exceptions

* Fixed tests

* fmt
2025-02-27 14:04:02 +00:00
Jedd Morgan 236cca2663 Updated docker compose file (#236) 2025-02-19 16:55:34 +00:00
Adam Hathcock f20064c9f0 update usage to read shell instead of file 2025-02-19 15:42:08 +00:00
Adam Hathcock 6f1b22d13a Merge remote-tracking branch 'origin/dev' into update-build-stamp 2025-02-19 15:33:31 +00:00
Jedd Morgan 23f95dd38d Fixed mistake in Version Create Docs (#231) 2025-02-18 09:57:54 +00:00
Adam Hathcock 9eb767a4f6 Revert back to content read. Probably some timeout being hit but reverting for now. (#234) 2025-02-18 09:43:20 +00:00
Jedd Morgan 358680cb9a NET core target to return IReadonlySet for freeze (#233) 2025-02-17 16:56:57 +00:00
Adam Hathcock 87ae033f61 Batches size now affects sending size accurately. Use extensions to … (#230)
* Batches size now affects sending size accurately.  Use extensions to help test this

* format

* add more and use extensions

* Rework to make things clear
2025-02-17 15:52:30 +00:00
Adam Hathcock e5a09155a2 Serialize now waits for the scheduler to be completed before returning (#225)
* Serialize now waits for the scheduler to be completed before returning

* formatting

* wait in deserialize too

* Pass cancellation token to download, refactor how things are passed/created

* responses are now streamed and cancel them earlier

* format

* add manual empty message for sending that definitely knows when the channels are empty

* Fix configure awaits

* more configure await false
2025-02-17 10:59:10 +00:00
Adam Hathcock 988599fbb5 Update ranges to allow higher and update other deps (#229) 2025-02-14 10:07:43 +00:00
Claire Kuang baa5f54edb Merge pull request #217 from specklesystems/jedd/cnx-1114-add-support-for-vertex-normals
Vertex Normals
2025-02-13 12:41:57 +00:00
Jedd Morgan d580fd0bc1 Merge remote-tracking branch 'origin/dev' into jedd/cnx-1114-add-support-for-vertex-normals 2025-02-13 10:56:17 +00:00
Adam Hathcock 2352306269 add ability for objectloader to skip server too. (#228)
* add ability for objectloader to skip server too.  add test so both cache and server can't be skipped

* move testing project to correct dir

* remove extra file
2025-02-13 09:41:07 +00:00
Jedd Morgan f0bafee076 gql api changes (#226) 2025-02-12 13:50:13 +00:00
Adam Hathcock ef19bfa69d fix dependencies 2025-02-10 13:41:39 +00:00
Adam Hathcock 45601f1a2f modify build to have correct version 2025-02-10 13:35:59 +00:00
Adam Hathcock adf3298baf release branch is main 2025-02-10 10:38:58 +00:00
Adam Hathcock 8f5e5f675b fmt 2025-02-10 10:36:50 +00:00
Adam Hathcock 9217e67a9d Merge remote-tracking branch 'origin/dev' into update-build-stamp 2025-02-10 10:27:26 +00:00
Jedd Morgan fe68607a52 Smaller chunks for consistency 2025-02-05 16:47:01 +00:00
Jedd Morgan 88d15a5c9c Merge remote-tracking branch 'origin/dev' into jedd/cnx-1114-add-support-for-vertex-normals 2025-02-05 15:54:47 +00:00
Adam Hathcock 3072047129 Use priority scheduler like serialize process to constrain Task enqueuing (#223)
* Use priority scheduler like serialize process to constrain Task enqueuing

* renamespace

* Fix tests and format
2025-02-05 15:36:26 +00:00
Adam Hathcock 316379b04c Update to AwesomeAssertions and update verify (#224)
* Update to AwesomeAssertions and update verify

* attempt to solve disposal problem
2025-02-05 14:03:28 +00:00
Adam Hathcock b056d98645 don't dispose the blocking collection when cancelling (#222)
* don't dispose the blocking collection

* dispose deserialize process correctly

* don't use enumerable and token

* format
2025-02-04 13:14:31 +00:00
Oğuzhan Koral 7329155d7a Fix: Return fast before traverse for wrong ids (#221)
* Return fast before traverse for wrong ids

* add and freeze all ids for a shortcut lookup

* add comment

---------

Co-authored-by: Adam Hathcock <adam@hathcock.uk>
2025-02-03 14:35:33 +00:00
Jedd Morgan c9a5103da7 added workflows back into sln (#219) 2025-02-03 12:49:59 +00:00
Adam Hathcock dbdf4892db dispose BC only when all threads are done. (#220)
* dispose BC only when all threads are done.

* format
2025-02-03 12:10:29 +00:00
Adam Hathcock 3aa993cecb Add cancellation tests (#218)
* Don't log cancelling

* redo exception handling for receive

* remove null test case

* clean up with Id/Json and more cancels

* Change the exception stacks

* fix serialization test

* make a custom scrubber for internalized exceptions

* clean up

* fix namespaces again :(

* adjust the scrubber

* try to make tests more predictable

* rework exceptions again

* strip out compile files used

* formatting

* custom exception validation

* fix init

* Move serialization to own class

* save serialize test

* add deep clean

* add cancellation test on save to cache

* cancellation tests

* format

* do DI correctly

* receive cancel works
2025-01-30 13:42:15 +00:00
Jedd Morgan 327f05adca Merge branch 'dev' into jedd/cnx-1114-add-support-for-vertex-normals 2025-01-27 13:40:48 +00:00
Jedd Morgan ec0d4bf1e3 Vertex Normals 2025-01-27 13:40:30 +00:00
Jedd Morgan 73afa28026 Reamed workflow actions for clarity (#215) 2025-01-27 13:35:06 +00:00
Jedd Morgan f0c7169be8 Small QOL tweaks to Version.Create and ProjectModelsFilter (#210)
* Version Create now returns a Version

* ProjectModelsFilter now has optional args
2025-01-24 12:19:54 +00:00
Jedd Morgan ee10e9d3fc author on Model is now made nullable (#214) 2025-01-24 12:09:12 +00:00
Adam Hathcock 93912d6712 Fix cancellation in schedular. It's no longer optional (#213)
* Fix cancellation in schedular.  It's no longer optional

* formatting

* fix tests because of stacktrace
2025-01-24 11:24:51 +00:00
Adam Hathcock f81fc97a91 Add exception handling for SerializeProcess with CancellationTokenSource (#211)
* Add exception handling for SerializeProcess with CancellationTokenSource

* formatting

* add exception test to make sure we handle a server exception

* add extra exception and handling to stop

* add comment and another test

* one last chance for user to cancel

* formatting
2025-01-23 17:06:08 +00:00
Claire Kuang cc23c147be Merge pull request #200 from specklesystems/claire/cnx-931-create-archicadobject-in-speckle-sharp-sdk
feat(objects): cnx 931 create archicadobject
2025-01-22 11:36:33 +00:00
Claire Kuang 02892a96fe Update ArchicadObject.cs 2025-01-21 20:51:19 +00:00
Claire Kuang ba143fe44b Merge branch 'dev' into claire/cnx-931-create-archicadobject-in-speckle-sharp-sdk 2025-01-21 18:02:07 +00:00
Jedd Morgan 3a71a10cf1 First pass increasing test coverage (#209)
* point tests

* Mesh Tests and removal of unused functions

* Vector tests

* more tests
2025-01-21 14:19:10 +00:00
Adam Hathcock bafd130ece Snapshot testing (#208)
* snapshot testing with verify

* formatting

* add back old serialization tests

* pass verify

* use json correctly

* formatting

* Don't use Quibble and order ourselves because ordering doesn't matter

* whitespace on snapshot

* Better json diffing?  Quibble is back

* add common project

* add object unit tests to see how verify would work

* format

* move random exes to new solution folder

* update lock files
2025-01-16 13:46:53 +00:00
Claire Kuang f79ae7e058 Merge pull request #202 from specklesystems/jedd/cxpla-154-enforce-nullability-analysers-in-objects-and-use-required
Jedd/cxpla 154 enforce nullability analysers in objects and use required
2025-01-15 18:54:08 +00:00
Claire Kuang 77170bf9f3 Merge branch 'dev' into jedd/cxpla-154-enforce-nullability-analysers-in-objects-and-use-required 2025-01-15 17:19:07 +00:00
Adam Hathcock 69167dc206 update some deps and add locks to versions for known packages (#207) 2025-01-15 16:11:04 +00:00
Adam Hathcock 19a5ccfb74 Merge branch 'dev' into claire/cnx-931-create-archicadobject-in-speckle-sharp-sdk 2025-01-14 08:44:47 +00:00
Adam Hathcock b3c6a75387 add a task.yield for a cached model to let progress happen (#204) 2025-01-14 08:44:10 +00:00
Oğuzhan Koral c6556fa2ef Merge branch 'dev' into claire/cnx-931-create-archicadobject-in-speckle-sharp-sdk 2025-01-14 10:37:40 +03:00
Claire Kuang 3bc40fb0bb removes classification and adds elements prop 2025-01-13 15:55:09 +00:00
Adam Hathcock 4370af5376 Allow SDK to report requested downloaded objects and minor adjustments (#203)
* Allow SDK to report requested downloaded objects and minor adjustments

* Remove xyz get server info test
2025-01-13 12:48:28 +00:00
Jedd Morgan 912971d8de reverted unnecessary change to DataObject 2025-01-10 18:29:57 +00:00
Jedd Morgan 9318d85cc8 Merge remote-tracking branch 'origin/dev' into jedd/cxpla-154-enforce-nullability-analysers-in-objects-and-use-required 2025-01-10 15:34:19 +00:00
KatKatKateryna deddb216e5 Gis objects cleaning (#181)
* add Polygon to Geometry; add GisObject

* cleaning objects

* removed final GIS classes

* remove IGisFeature interface

* required keywords for CRS

* required boundary; renaming

* delete the rest of the classes

---------

Co-authored-by: Claire Kuang <kuang.claire@gmail.com>
Co-authored-by: Jedd Morgan <45512892+JR-Morgan@users.noreply.github.com>
2025-01-10 15:33:12 +00:00
Jedd Morgan 465d69ba00 Enforce correct nullability with required 2025-01-10 13:37:18 +00:00
Adam Hathcock 14d959834f Convert to Xunit (#196)
* xunit unit tests

* most pass with formatting

* convert objects to xunit

* remove nunit

* format

* merge fixes

* switch objects to fluent assertions

* update to fluent assertions

* more FA

* convert all to FA

* Format

* Fix tests

* formatting

* hopefully made credential test better

* Catch more specific exception

* use another more specific exception

* Fix tests

* update to xunit

* update packages
2025-01-09 15:32:28 +00:00
Adam Hathcock 465f635142 Add details to sqlite exceptions (#198)
* add ServerObjectManagerFactory

* add usage of a command pool

* add more disposal

* save saving increase

* fix tests

* fixes

* push out concurrency and disposablity

* Add a custom task scheduler

* Better usage, don't wait to enqueue to save to channels

* Completely pre-cal batch size to avoid spinning issues

* Try to fix cache counting

* properly dispose things

* format

* clean up

* adjust count and save on current thread

* move batch it's own file

* update a few packages

* fix build and add batch tests

* revert and format

* Revert "save saving increase"

This reverts commit 3b50c857fb.

* revert change

* adjust and add tests

* Dispose sqlite manager properly

* Make Batch a IMemoryOwner to allow for pooling

* Fix tests

* Upgrade some deps

* try to make tests more explicit

* remove return value

* Add detailed SqLiteJsonCacheException

* details changes
2025-01-09 11:04:14 +00:00
Adam Hathcock ed5bdc91ed Sqlite pooling for connections and commands (#193)
* add ServerObjectManagerFactory

* add usage of a command pool

* add more disposal

* save saving increase

* fix tests

* fixes

* push out concurrency and disposablity

* Add a custom task scheduler

* Better usage, don't wait to enqueue to save to channels

* Completely pre-cal batch size to avoid spinning issues

* Try to fix cache counting

* properly dispose things

* format

* clean up

* adjust count and save on current thread

* move batch it's own file

* update a few packages

* fix build and add batch tests

* revert and format

* Revert "save saving increase"

This reverts commit 3b50c857fb.

* revert change

* adjust and add tests

* Dispose sqlite manager properly

* Make Batch a IMemoryOwner to allow for pooling

* Fix tests

* Upgrade some deps

* try to make tests more explicit

* remove return value

* Use named tuple for all objects
2025-01-08 11:04:32 +00:00
Claire Kuang 0023d2ca2a Merge branch 'dev' into claire/cnx-931-create-archicadobject-in-speckle-sharp-sdk 2025-01-06 14:23:42 +00:00
Claire Kuang ab487991b6 Update ArchicadObject.cs 2025-01-06 14:07:12 +00:00
Claire Kuang 142eefdf39 adds archicad data object and interface
also removes unused gis classes
2025-01-06 14:05:28 +00:00
Adam Hathcock ebccf6ff79 update build stamp and tooling 2025-01-03 16:22:58 +00:00
Adam Hathcock 11fe8e8cce Use CancellationSource to properly dispose of threads in PriorityScheduler (#197)
* Use CancellationSource to properly dispose of threads in PriorityScheduler

* formatting
2025-01-03 14:25:29 +00:00
Adam Hathcock 1fe1a54dcf Custom task scheduler for serialization, fix batch size calc (#194)
* Add a custom task scheduler

* Better usage, don't wait to enqueue to save to channels

* Completely pre-cal batch size to avoid spinning issues

* Try to fix cache counting

* properly dispose things

* format

* clean up

* adjust count and save on current thread

* move batch it's own file

* update a few packages

* fix build and add batch tests
2025-01-03 12:26:19 +00:00
Adam Hathcock a1b9030dba Fixes Markdown to be non HTML based for github and nuget (#195) 2025-01-02 10:12:46 +00:00
Adam Hathcock eec400d0cf Fix DataObject inheritance (#192) 2024-12-19 14:34:15 +00:00
Adam Hathcock 991b31265f Fix data chunks getting written with closure tables (#191)
* Never write closures for datachunks

* add tests and format

* add another test with array and reuses reference

* Remove a writeline in tests
2024-12-17 16:49:17 +03:00
Adam Hathcock 675d896e0d Add method to replace in sqlite (#190) 2024-12-16 15:01:53 +03:00
Adam Hathcock defcee165a Closures are kept for children instead of global (#189)
* disable channels when skipping things

* pass child closures to current.  Current closures out to parent.

* fix build

* adjust options

* use a dictionary pool and pool correctly

* add pools for data chunks

* format
2024-12-13 11:00:21 +00:00
Adam Hathcock 722df50d34 Fix sending caching (#188)
* add list pool creation

* add back base cache for closures

* use bounded channels and tell them to wait

* format and add exception

* adding back json cache?

* nevermind

* format

* add option to skip total finding

* add some comments
2024-12-10 11:21:12 +00:00
Björn Steinhagen 431bb459fc etabs versions (#187)
- support for etabs v21 and v22
- sap 2000 is already covered with v25 and v26
2024-12-05 23:20:45 +03:00
Adam Hathcock a393f7ca8b add explicit interface tests (#186) 2024-12-05 11:29:44 +00:00
Claire Kuang 650fad3b22 Merge pull request #185 from specklesystems/claire/cnx-849
feat(objects): cnx 849 finalized DataObjects
2024-12-04 12:31:07 +00:00
Claire Kuang 81007e0ecf pr fixes 2024-12-04 12:14:17 +00:00
Claire Kuang d29450f0a9 Merge branch 'claire/cnx-849' of https://github.com/specklesystems/speckle-sharp-sdk into claire/cnx-849 2024-12-03 22:30:33 +00:00
Claire Kuang 1e5bf903a2 update tests 2024-12-03 22:30:24 +00:00
Claire Kuang 878edf7c8f Merge branch 'dev' into claire/cnx-849 2024-12-03 22:18:24 +00:00
Claire Kuang ab0ff7b792 removes unnecessary classes 2024-12-03 22:13:46 +00:00
Claire Kuang b5999e3361 adds properties field to DataObject 2024-12-03 19:48:24 +00:00
Adam Hathcock d904c68c10 Nullable fixes - nullability on Base (#184)
* Remove operator overloading and Equals/GetHashCode which caused problems

* properly have nullability annotations on Base

* redeux known nullables

* fmt

* more nullability

* fmt

* remove point equality operator

* Revert "Remove operator overloading and Equals/GetHashCode which caused problems"

This reverts commit 6b5d3f1462.

* Revert "remove point equality operator"

This reverts commit 9b14330147.

* revert nullable accounts

* fix build issues
2024-12-03 13:01:33 +00:00
Adam Hathcock daec64cf8e Remove the Base cache because it's not practically useful (#183) 2024-12-03 12:48:18 +00:00
Adam Hathcock 1844386235 Better options for serializer (#180)
* refactor options to use on factories, add dummies

* format

* reduce lists to yield return

* get primitives first to avoid to string

* fmt

* add cache base option
2024-11-29 15:43:10 +00:00
Adam Hathcock 05f90eae5c Use frozen collections (#178)
* add detail to exceptions

* Detachable nested objects work

* fmt

* Use frozen collections

* fix tests and formatting
2024-11-29 15:25:29 +00:00
Adam Hathcock 7bbc568022 Make ISqLiteJsonCacheManager and use it for new serialization and account manager (#179)
* Introduce ISqLiteJsonCacheManager with factory for cache manager and other uses

* AccountManager uses new sqlite

* format

* add extension
2024-11-27 12:14:16 +00:00
Adam Hathcock 7a1edbbf99 Fix externals refs again (#177)
* add detail to exceptions

* Detachable nested objects work

* fmt
2024-11-26 09:47:44 +00:00
Dimitrie Stefanescu 058e3cb946 Merge pull request #176 from specklesystems/claire/cnx-793-revit-cleanup-align-with-data-extraction-workflow
cleanup(objects): removes unused revit classes
2024-11-22 17:43:20 +00:00
Claire Kuang 08dd45cc32 Update Interfaces.cs 2024-11-22 12:28:14 +00:00
Claire Kuang d4173c1449 adds civil and tekla objects 2024-11-22 10:21:06 +00:00
Adam Hathcock 4b7c6e4641 fixed test to allow for new detachments 2024-11-22 09:52:59 +00:00
Adam Hathcock 2477423ba7 some tests adjusted 2024-11-22 09:12:10 +00:00
Claire Kuang 71ec9a6d11 rescopes data object classes 2024-11-21 17:53:37 +00:00
Claire Kuang 140b39f605 adds data object classes 2024-11-21 16:47:34 +00:00
Claire Kuang 1a0522cef3 removes unused revit classes 2024-11-20 18:26:38 +00:00
Adam Hathcock b343d9bd0d add Id and Json types (#165)
* Can debug dependencies

* Different exceptions

* Uses root id only after we found it to signal the end

* DataChunks are created later and need to be accounted for

* format

* use app ids in tests and references

* check sqlite cache after serialize

* use dummy to go through channels to end

* fmt

* Extend channel lib to batch by size

* fmt

* build fix

* adjust limits

* FIx sending

* Optimize reference generation

* more

* remove tolist

* rework closures to be constant and serializer only deals with current....references bases are cached

* fix chunk creation

* another bug fix

* clean up with factories

* add deserializer factory

* Needed to reference interface

* add Id and Json types

* Fix tests

* remove optional

* add another missing id write

* fix merge

* Fix new code
2024-11-20 09:51:10 +00:00
Adam Hathcock e32ec52071 Add closures for external references (#175)
* allow external references and fix closures

* format
2024-11-20 08:28:33 +00:00
Adam Hathcock 2bbe2a8b93 allow external references and fix closures (#174)
* allow external references and fix closures

* fix comment
2024-11-19 14:22:20 +00:00
Adam Hathcock 604e141468 Update CSharpier with better new usage (#172) 2024-11-19 14:10:30 +00:00
Jedd Morgan 39dcc5da0b Refactor MaybeThrowGraphqlException to throw AggregateException with all GraphQL errors (#169)
* first pass

* Updated tests

* Removed path from message
2024-11-19 13:22:52 +00:00
Jedd Morgan af35edf0a2 Breaking API changes for comments API (#173)
* Fixed breaking change to comments api

* fixed stuff

* oops
2024-11-19 12:15:17 +00:00
Jedd Morgan fbc7400524 Changed http handler to not throw on non-successful results (#170)
Co-authored-by: Adam Hathcock <adamhathcock@users.noreply.github.com>
2024-11-19 10:55:27 +00:00
dependabot[bot] 8a71b19f78 Bump codecov/codecov-action from 4 to 5 (#171)
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4 to 5.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v4...v5)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-19 09:33:26 +00:00
Jedd Morgan 105395e9fb Enforced msbuild warnings (#166)
* Enforced msbuild warnings

* removed inline suppression

* fix
2024-11-18 10:20:00 +00:00
Adam Hathcock 715bb7274a Batch by size, Closures and Detached items are computed differently (#164)
* Can debug dependencies

* Different exceptions

* Uses root id only after we found it to signal the end

* DataChunks are created later and need to be accounted for

* format

* use app ids in tests and references

* check sqlite cache after serialize

* use dummy to go through channels to end

* fmt

* Extend channel lib to batch by size

* fmt

* build fix

* adjust limits

* FIx sending

* Optimize reference generation

* more

* remove tolist

* rework closures to be constant and serializer only deals with current....references bases are cached

* fix chunk creation

* another bug fix

* clean up with factories

* add deserializer factory

* Needed to reference interface

* move around streamId

* some clean up

* Use StringBuilder pool on serialization to reduce memory pressure

* remove extra

* remove extra clears

* Fix a flaw in batchsize

* use default complete

* format

* loader should use 1 writer that is batched

* remove redundant ref gen

* Fix graphql commands by adding project id
2024-11-12 14:25:49 +00:00
Adam Hathcock 43445bc4ff Add SQLite transport2 (#162)
* Add SQLiteTransport2

* cleanup
2024-11-07 10:00:43 +00:00
Adam Hathcock 3bff2d5d57 Use Reference generator (#161)
* Optimize reference generation

* more

* use reference generator

* move

* remove using
2024-11-07 09:48:52 +00:00
Adam Hathcock 4784e7d432 Revert "feat: Use 16-core larger runner for github actions (#158)" (#160)
This reverts commit 378149a0af.
2024-11-06 12:19:52 +00:00
Alan Rynne 378149a0af feat: Use 16-core larger runner for github actions (#158) 2024-11-06 11:53:58 +00:00
Adam Hathcock 0240e3b49e Send Channel fixes (#155)
* Can debug dependencies

* Different exceptions

* Uses root id only after we found it to signal the end

* DataChunks are created later and need to be accounted for

* format

* use app ids in tests and references

* check sqlite cache after serialize

* use dummy to go through channels to end

* fmt

* fix tests and add more send events
2024-11-06 11:53:21 +00:00
Jedd Morgan d65993389b Obsolete warnings (#156) 2024-11-06 11:29:40 +00:00
Adam Hathcock 4cc78c4bc9 Serialize using a Channel (#146)
* Use a stack channel for deserialization

* multi-threaded

* add object dictionary pool

* more pooling

* adjust sqlite transport

* format

* Optimize IsPropNameValid

* object loader first pass

* save test

* add cache pre check

* save better deserialize

* mostly works

* uses tasks but slower at end

* rework to make more sense

* add check to avoid multi-deserialize

* modify max parallelism

* async enqueuing of tasks

* switch to more asyncenumerable

* fmt

* fmt

* cleanup sqlite

* make ServerObjectManager

* revert change

* add ability to skip cache check

* cache json to know what is loaded

* testing

* clean up usage

* clean up and added new op

* Fix exception handling

* fixing progress

* remove codejam

* Hides ObjectPool dependency

* fmt

* Use the 1.0 BCL async to try to be more compatible

* rename to dependencies

* Move Polly to internal dependencies

* format

* remove more old references

* remove stackchannel

* fixes for registration

* remove console writeline

* add cache check shortcut for root object

* start refactoring send

* recevie2 benchmark

* add test for deserialize new

* use channels for sending

* test and fixes

* Use same asyncinterfaces as Dynamo.  Merge fixes

* clean up

* fix download object progress

* put back from bad merge

* intermediate commit: separating get child function from serializer

* send didn't error

* add channels

* Use net48, netstandard2.1 and net8

* remove collection special case

* have to make a tree of tasks even though it may serialize things twice

* pre-id changing during serialize

* need AsyncInterfaces for net48 :(

* options changes

* revert to netstandard2.0 and net8.0

* fix totals

* revert httpcontext changes

* format

* clean up

* active tasks works when accounting for id not being stable

* add id tests

* more fixes

* works

* format

* Convert to BaseItem and use single SQLite checks to avoid locks

* use locks and batch sqlite operations

* hook up and handle null ids

* remove unused parameter

* remove progress from serializer itself

* invert has objects call

* readd object references

* format

* fix tests

* remove active tasks check

* bug fix for json cache

* remove locks from sqlite

* General Send test

* add childclosures

* redo extract all to be enumerable

* group tests in projects

* caching json does matter

* cache checking should be managed by channels

* format

* Merge pull request #152 from specklesystems/new-json-test

Uses a new objects test in Revit for serialization tests

* add skip

* add new roundtrip test

* fix finish

* clean up tests

* check happens in serialize...don't do it twice

* better progress reporting

* fix progress reporting

* only use detached properties when children gathering

* move detached tests

* add detached tests

* fix merge

* Fix progress change

* fix more tests

---------

Co-authored-by: Jedd Morgan <45512892+JR-Morgan@users.noreply.github.com>
Co-authored-by: Claire Kuang <kuang.claire@gmail.com>
2024-11-05 09:56:54 +00:00
Claire Kuang 8a148b892f refactor(objects): removes unused classes and constructors (#151)
* removes unused classes and gh schema constructors

* additional cleanup of backwards compatibility (v2)

* Update Arc.cs

* updates unit tests

* re-adds bbox to box

* updates tests

* pr fixes for backwards compatibility

* Uses a new objects test in Revit for serialization tests

* format

* updates revit model curve class to inherit from curve geometry, and adds deprecated v2 classes

* fixes transform unit tests

* fixes deprecated speckle type

* removes unnecessary new revit curve classes

---------

Co-authored-by: Adam Hathcock <adam@hathcock.uk>
Co-authored-by: Alan Rynne <alan@rynne.es>
2024-11-04 17:05:16 +00:00
Jedd Morgan fba0c46ed8 Added explicit nullability to GqlModels (#144)
* Added explicit nullability to GqlModels

* data and alignment

* ModelsWithVersions

* Models

* active user

* Invites and active user fixes

* Invite changes

* Subscriptions

* Fixed subscription tests

* corrected nullability of projectinput

* removed unused mutation responses

* format

---------

Co-authored-by: Alan Rynne <alan@rynne.es>
2024-11-04 16:52:15 +00:00
Claire Kuang 91c4090037 Merge pull request #154 from specklesystems/claire/cnx-699-update-github-links-to-point-to-v3-1
Update README.md to align with main github page
2024-11-04 11:12:27 +00:00
Claire Kuang c2962a668b Update README.md to align with main github page
https://linear.app/speckle/issue/CNX-699/update-github-links-to-point-to-v3
2024-11-01 17:42:31 +00:00
Adam Hathcock 27d3028880 Revert to SQlite 7.0.5 to exactly match V2's usage (#153)
* Revert to SQlite 7.0.5 to exactly match V2's usage

* update comment to be exact
2024-10-31 14:58:52 +00:00
Alan Rynne 93b3c37584 fix: Change SpecklePathProvider from internal to public (#150) 2024-10-28 13:04:34 +01:00
Adam Hathcock f5a8d1a738 Add cache download channels (#149)
* Use a stack channel for deserialization

* multi-threaded

* add object dictionary pool

* more pooling

* adjust sqlite transport

* format

* Optimize IsPropNameValid

* object loader first pass

* save test

* add cache pre check

* save better deserialize

* mostly works

* uses tasks but slower at end

* rework to make more sense

* add check to avoid multi-deserialize

* modify max parallelism

* async enqueuing of tasks

* switch to more asyncenumerable

* fmt

* fmt

* cleanup sqlite

* make ServerObjectManager

* revert change

* add ability to skip cache check

* cache json to know what is loaded

* testing

* clean up usage

* clean up and added new op

* Fix exception handling

* fixing progress

* remove codejam

* Hides ObjectPool dependency

* fmt

* Use the 1.0 BCL async to try to be more compatible

* rename to dependencies

* Move Polly to internal dependencies

* format

* remove more old references

* remove stackchannel

* fixes for registration

* remove console writeline

* add cache check shortcut for root object

* recevie2 benchmark

* add test for deserialize new

* Use same asyncinterfaces as Dynamo.  Merge fixes

* clean up

* fix download object progress

* add channels

* Use net48, netstandard2.1 and net8

* need AsyncInterfaces for net48 :(

* options changes

* revert to netstandard2.0 and net8.0

* fix totals

* revert httpcontext changes

* format

* add active tasks collection

* format

* remove more changes and remove unused method

* remove more comment changes

---------

Co-authored-by: Jedd Morgan <45512892+JR-Morgan@users.noreply.github.com>
2024-10-25 14:28:33 +01:00
Adam Hathcock e10cc38ca7 Give new dependencies lib ability to publish (#148) 2024-10-24 13:53:10 +00:00
Adam Hathcock b6d2d01068 Tasks hide new dependencies (#145)
* Use a stack channel for deserialization

* multi-threaded

* add object dictionary pool

* more pooling

* adjust sqlite transport

* format

* Optimize IsPropNameValid

* object loader first pass

* save test

* add cache pre check

* save better deserialize

* mostly works

* uses tasks but slower at end

* rework to make more sense

* add check to avoid multi-deserialize

* modify max parallelism

* async enqueuing of tasks

* switch to more asyncenumerable

* fmt

* fmt

* cleanup sqlite

* make ServerObjectManager

* revert change

* add ability to skip cache check

* cache json to know what is loaded

* testing

* clean up usage

* clean up and added new op

* Fix exception handling

* fixing progress

* remove codejam

* Hides ObjectPool dependency

* fmt

* Use the 1.0 BCL async to try to be more compatible

* rename to dependencies

* Move Polly to internal dependencies

* format

* remove more old references

* remove stackchannel

* fixes for registration

* remove console writeline

* add cache check shortcut for root object

* recevie2 benchmark

* add test for deserialize new

* Use same asyncinterfaces as Dynamo.  Merge fixes

* clean up

* fix download object progress

---------

Co-authored-by: Jedd Morgan <45512892+JR-Morgan@users.noreply.github.com>
2024-10-24 15:23:16 +02:00
Adam Hathcock cca8828565 Using Tasks for Deserialization (#143)
* Use a stack channel for deserialization

* multi-threaded

* add object dictionary pool

* more pooling

* adjust sqlite transport

* format

* Optimize IsPropNameValid

* object loader first pass

* save test

* add cache pre check

* save better deserialize

* mostly works

* uses tasks but slower at end

* rework to make more sense

* add check to avoid multi-deserialize

* modify max parallelism

* async enqueuing of tasks

* switch to more asyncenumerable

* fmt

* fmt

* cleanup sqlite

* make ServerObjectManager

* revert change

* add ability to skip cache check

* cache json to know what is loaded

* testing

* clean up usage

* clean up and added new op

* Fix exception handling

* fixing progress

* remove codejam

* remove stackchannel

* remove console writeline

* add cache check shortcut for root object

* recevie2 benchmark

---------

Co-authored-by: Jedd Morgan <45512892+JR-Morgan@users.noreply.github.com>
2024-10-22 14:14:39 +01:00
Adam Hathcock 3c783b3cac retry result can be null so handle it better (#142)
Co-authored-by: Alan Rynne <alan@rynne.es>
2024-10-17 09:38:09 +00:00
Jedd Morgan 8f8be7482a Added workspace id to v3 sdk (#134)
* Added workspace id to v3 sdk

* use init setter
2024-10-15 12:57:15 +01:00
Adam Hathcock 3b859ba398 Add headers to outgoing http requests for Open Telemetry (#141)
* Add otel headers to outgoing http client requests

* format
2024-10-14 10:40:29 +01:00
Adam Hathcock 4c52072e0a Optimize IsPropNameValid (#140)
* Optimize IsPropNameValid

* compare char to char
2024-10-11 09:44:45 +00:00
Dimitrie Stefanescu 1241589d18 Adds new classes for raw encoded objects (Brep, Extrusion and Subd) (#139)
* feat: adds wip classes for brep/subd/extrusion-x

* Get rid of dub code on ExtrusionX SubDX BrepX

* fix: Run format

* chore: formatting

* chore: more formatting

help dis annoying

---------

Co-authored-by: oguzhankoral <oguzhankoral@gmail.com>
Co-authored-by: Alan Rynne <alan@speckle.systems>
Co-authored-by: Adam Hathcock <adamhathcock@users.noreply.github.com>
2024-10-10 09:26:55 +00:00
Adam Hathcock 1a9d28e660 add metrics to sdk (#133)
* add metrics to sdk

* metrics for sends and receives

* format
2024-10-10 10:32:52 +02:00
Adam Hathcock e14913b8c3 Fix deserialization progress reporting (#137)
* Fix progress reporting for deserialization, remove children known count

* fix tests
2024-10-09 11:57:48 +01:00
Alan Rynne 0d7805d060 feat: Added new speckle exceptions and split into single files (#136)
* feat: Added new speckle exceptions and split into single files

* fix: Run format
2024-10-07 17:14:59 +02:00
Adam Hathcock 14359333b4 Nuget Updates (#132)
* update test packages

* update csharpier
2024-10-07 12:48:00 +02:00
Adam Hathcock 75d88c5f39 Use IProgress instead of custom type (#131)
* Use IProgress instead of custom type

* Format

* ProgressArgs are a readonly struct

* fix tests
2024-10-02 10:50:49 +01:00
Adam Hathcock 9a3eddf6d5 use array defaults (#129) 2024-09-27 11:00:21 +01:00
Jedd Morgan f541525a80 Regex experimentation (#128) 2024-09-26 13:58:48 +01:00
Adam Hathcock c3e8a95bf1 Merge pull request #126 from specklesystems/some-optimizations
Some  allocation optimizations
2024-09-26 12:51:13 +01:00
Adam Hathcock c2d0e1d0d4 use await instead of .Result 2024-09-26 08:13:58 +01:00
Adam Hathcock f0d83d8d43 Merge remote-tracking branch 'origin/dev' into some-optimizations 2024-09-26 08:13:04 +01:00
Adam Hathcock ba14a8c87f Use pool more 2024-09-25 16:35:58 +01:00
Jedd Morgan 065a2318d3 Jedd/cxpla 84 add commit context to receive trace (#125)
* Smells like v2

* Fixed issue with cancellation of ParallelServerApi

* activity ok

* Serialize json

* settags extension method

* Isbusy fix

* Final polish

* added CallerMemberName

* removed absractions
2024-09-25 16:35:38 +01:00
Adam Hathcock 40d025bb57 use pool and more ValueTask 2024-09-25 16:24:57 +01:00
Adam Hathcock ddeac27f04 Use pool and remove some async 2024-09-25 16:20:31 +01:00
Adam Hathcock d73bf365c2 Clean app plugin registration and all speckle plugin verisons (#123)
* Clean app plugin registration and all speckle plugin verisons

* fix naming
2024-09-20 09:32:29 +02:00
Adam Hathcock 198f1a2564 Remove STJ dependency (#122) 2024-09-19 14:11:16 +01:00
Jedd Morgan 694e9e1915 Fixed issue with cancellation of ParallelServerApi (#121) 2024-09-18 09:06:53 +00:00
Adam Hathcock 0f29aacf24 Making SDK non-static (#116)
* initial burn

* fix: Minor fixes, some pending

* fix: Minor fix + DeepClean target

* setup things to be injected

* things compile and activites are instanced

* compiles except tests

* tests compile

* fmt

* fix merge

* Activities are now an interface

* fmt

* fully remove logging DLL

* clean up

* fix tests

* more cleanup

* Fix integration tests

* clean up hash tests

* clean up path provider

* more cleanup for path

* merge fixes

* Merge fixes

* remove some extra classes

---------

Co-authored-by: Alan Rynne <alan@speckle.systems>
2024-09-17 15:51:50 +01:00
Jedd Morgan a28cf6d908 Merge pull request #119 from specklesystems/jrm/main-merge
Update Http Send trace (#118)
2024-09-16 15:42:37 +01:00
Jedd Morgan 2cb5d6e410 Fix using directives 2024-09-16 13:43:43 +01:00
Jedd Morgan 59628d5241 Merge remote-tracking branch 'origin/dev' into jrm/main-merge 2024-09-16 13:39:05 +01:00
Adam Hathcock bbe23f6996 Update Http Send trace (#118)
* Update Http Send trace

* format
2024-09-16 12:45:04 +02:00
Jedd Morgan df5b151c90 Test Coverage (#117) 2024-09-16 08:41:26 +01:00
Jedd Morgan ccb4f54550 Jedd/cxpla 55 add required keyword for more geometry types (#101)
* Sdk

* Objects

* Supressed IDE warnings via editor config instead of nowarn

* Nullability and other warnings

* using

* Required keyword on lines and meshes

* Fixed test project

* fixed tests

* Proxies

* Fixed equality of Point

* IEquatable

* Fixed issue with serialization of detached lists

* Added tests for jsonIgnore affecting id calc

* removed comments

* Fixed issue with fallback to double on large values

* Fixed undocumented large number support
2024-09-13 14:47:29 +01:00
Jedd Morgan 30a3533956 Simplified props files (#115)
* Simplified props files

* Private package
2024-09-12 12:06:50 +00:00
Adam Hathcock e07bfc18d5 Remove async from serializer (#113)
* Remove async from serializer

* Make GetId be sync

* fix chunking?

* Chunking Tests (#114)

* fmt

* Fixed speckle type

---------

Co-authored-by: Jedd Morgan <45512892+JR-Morgan@users.noreply.github.com>
2024-09-11 15:35:59 +01:00
Adam Hathcock 2ad14ca00b Fix serialization of ignored (#112)
* Fixed issue with serialization of detached lists

* Added tests for jsonIgnore affecting id calc

* use extra writer and pass tests

* avoid returning extra object

* fix tests

* Add span overload back

* fmt

---------

Co-authored-by: Jedd Morgan <45512892+JR-Morgan@users.noreply.github.com>
2024-09-10 13:17:46 +01:00
Jedd Morgan 450dbcce81 Sha256 hash with spans (#107)
* Sha256 hash with spans

* HashData

* NumericFormat

* Tests

* md5 test

* xml

* use utf16 encoding rather than utf8

---------

Co-authored-by: Alan Rynne <alan@rynne.es>
2024-09-09 12:43:32 +00:00
Jedd Morgan 296a00e2eb Ralph's suggested changes (#105) 2024-09-09 12:23:49 +00:00
Alan Rynne f085a3fb5a Merge pull request #109 from specklesystems/main
Back Merge main->Dev
2024-09-09 14:18:39 +02:00
Alan Rynne 56c4109210 fix(docker): Update docker-compose.yml server healthcheck (#108)
* fix: Use node location instead of relying on $PATH

* fix: Update to /readiness endpoint instead of /liveness
2024-09-09 11:21:43 +00:00
Adam Hathcock 92bcb51bf2 Disable snupkg for logging (#104) 2024-09-05 17:35:32 +01:00
Adam Hathcock ce3d610ac5 Add CancellationToken usage to Closure parsing (#103)
* Add CancellationToken usage to Closure parsing

* fmt
2024-09-05 16:53:26 +01:00
Adam Hathcock 1be044e442 Remove redundant Contains/GetHashCode (#102) 2024-09-05 15:12:58 +01:00
Adam Hathcock cc7d274f43 Add .NET 8 targets (#97)
* Add targets to csproj and fixed up logging

* Logging compiles

* SDK compiles

* Objects compiles

* fmt

* fix build naming

* remove net6.0

* more null fixes

* merge fixes
2024-09-05 15:12:22 +01:00
Adam Hathcock 0b1de566df Async GetObject and Async Deserialization (#95)
* Use Concurrent Dictionaries and ignore case on them to avoid ToLower

* remove single array allocation

* allocate GetClosures differently

* Use JsonReader for closures

* add comment

* use isdefined

* more readonly with less allocations

* sorts

* fmt

* use element type when making an array

* first pass

* Fix reading for object and array

* serialization works?

* Fix closure parsing

* things are way faster

* Deserialize is async

* fmt

* renames

* remove deserialize threads

* fmt

* faster to use ordinal compare

* serialization looks okay

* fix closure writing

* fixes

* use possibly different values for compute id

* use closure parser on download

* memory test for blobs

* decompose serialization

* fmt

* fmt

* for decomposing, values should be used instead of original

* set id after computing it

* redo more closure parsing

* fix memory test

* don't throw on try get deserialized

* fmt

* fix integration tests

* fix tests

* disable memory blob storage by default

* put back ?

* merge fixes and delete worker threads

* fmt

* serialization of old floats pass

* serialization of old floats pass

* rename class

* Use async/await on GetObject

* await deserialization

* fmt

* uncomment and fix tests

* don't allow things to exist in the closure table that doesn't exist

* detach blob tests

* rename serializer

* async more correct

* revert

* fix merge

* fix blob tests again

* more fixes

* Fix building

* async fixes

* more async fixes

* fix tests?

* rename GetId to GetIdAsync

* clean up

* more cleanup

* fmt

* fix test

* fix analyzer errors

* use ConcurrentDictionary to be thread safe
2024-09-04 13:45:56 +01:00
Jedd Morgan 5e0ea324c3 Re-introduced code analysers and fixed many violations (#92)
* Sdk

* Objects

* Supressed IDE warnings via editor config instead of nowarn

* Nullability and other warnings

* using

* Fixed warnings

* Important fix

* More fixes
2024-09-04 11:49:35 +00:00
Jedd Morgan b9180027c5 Detach Levels (#99) 2024-09-03 18:14:22 +01:00
Adam Hathcock 77a40a3af5 Merge pull request #98 from specklesystems/main
Main to dev
2024-09-03 16:39:07 +01:00
Adam Hathcock 22f4945d71 Json reader deserialize (#88)
* Use Concurrent Dictionaries and ignore case on them to avoid ToLower

* remove single array allocation

* allocate GetClosures differently

* Use JsonReader for closures

* add comment

* use isdefined

* more readonly with less allocations

* sorts

* fmt

* use element type when making an array

* first pass

* Fix reading for object and array

* serialization works?

* Fix closure parsing

* things are way faster

* Deserialize is async

* fmt

* renames

* remove deserialize threads

* fmt

* faster to use ordinal compare

* serialization looks okay

* fix closure writing

* fixes

* use possibly different values for compute id

* use closure parser on download

* memory test for blobs

* decompose serialization

* fmt

* fmt

* for decomposing, values should be used instead of original

* set id after computing it

* redo more closure parsing

* fix memory test

* don't throw on try get deserialized

* fmt

* fix integration tests

* fix tests

* disable memory blob storage by default

* put back ?

* merge fixes and delete worker threads

* fmt

* serialization of old floats pass

* serialization of old floats pass

* rename class

* uncomment and fix tests

* don't allow things to exist in the closure table that doesn't exist

* detach blob tests

* rename serializer

* revert

* fix blob tests again
2024-09-03 15:53:50 +01:00
Jedd Morgan c0f8949705 Jedd/cxpla 33 move performance test project (#87)
* Moved performance test project

* register types

* perf tests
2024-09-02 15:41:48 +00:00
Adam Hathcock 7883cd9d32 Don't use Serilog global static logger in v3 (#96)
* Don't use Serilog global static logger in v3

* make logger be internal only
2024-09-02 13:52:27 +01:00
Alan Rynne b7be9b6fb1 Merge pull request #94 from specklesystems/dev
dev -> main
2024-08-29 13:42:49 +02:00
Jedd Morgan 2b46792a82 Fixed issue with Km unit scalling (#93) 2024-08-28 13:27:42 +02:00
Adam Hathcock 4c3e572bfe clean up from progress (#78)
* progress intermediate commit

* add progress for download

* remove unused code

* remove batch sent callbacks

* multi-threaded deserialize works

* Progress for download and deserialization

* Fix tests

* Have less indeterminate deserialization

* fix deserialization

* make download faster with buffered stream

* put local receive back

* remove unused callback

* fmt

* Progress for serialization and upload

* fix uploading

* clean up from progress

* merge fixes and fmt
2024-08-22 11:18:16 +01:00
Adam Hathcock 0f116ad847 Base caching on TypeLoader (#82)
* Base caching on TypeLoader

* fmt

* add back types
2024-08-22 11:11:53 +01:00
Jedd Morgan 16b1b904af First pass for IBase (#81) 2024-08-21 17:57:33 +00:00
Jedd Morgan 9916048921 Long Send Resiliency (#89)
* LongSendTest

* Moved to separate project

* Server transport throws early

* raised timeouts

* Use poly for timeout

* Cleaned up some of the AsyncPolicy construction

* GraphQL Client back to 30 second timeout
2024-08-21 18:52:23 +01:00
Jedd Morgan 9bea79b3b2 Removed incorrect platform targets (#84)
Co-authored-by: Adam Hathcock <adamhathcock@users.noreply.github.com>
2024-08-19 21:32:23 +01:00
Adam Hathcock af1d7dfaf3 Check for TypeLoader.initialize correctly (#85) 2024-08-19 14:17:45 +01:00
Adam Hathcock 03a5706680 add initial log statement and fix log path (#80) 2024-08-19 12:45:01 +01:00
Adam Hathcock 42882cb71b Perf changes (#79)
* Use Concurrent Dictionaries and ignore case on them to avoid ToLower

* remove single array allocation

* allocate GetClosures differently

* Use JsonReader for closures

* add comment

* use isdefined

* more readonly with less allocations

* sorts

* fmt

* use element type when making an array
2024-08-19 12:05:51 +01:00
Jedd Morgan b14c8db8d3 Required keyword on various types (#76)
* Made bounding boxes nullable

* Required keyword for Polyline

* Curve

* others

* Interval

* Breps!

* more changes

* removed resolved todo comment

* Fixed comment

* resolved alan's comments

* surfaces
2024-08-16 13:21:05 +01:00
Adam Hathcock 2fec0ea791 Cleanup and use concurrent dictionary (#77) 2024-08-15 09:55:08 +01:00
Adam Hathcock dc4da49078 Add Progress for transfers (#74)
* progress intermediate commit

* add progress for download

* remove unused code

* remove batch sent callbacks

* multi-threaded deserialize works

* Progress for download and deserialization

* Fix tests

* Have less indeterminate deserialization

* fix deserialization

* make download faster with buffered stream

* put local receive back

* remove unused callback

* fmt
2024-08-15 10:43:41 +02:00
Adam Hathcock ea5ed874a3 Remove extra SaveObject (#75)
* Remove extra SaveObject

* fmt
2024-08-15 09:30:24 +02:00
Claire Kuang 70729d5ddd feat(gis): CNX-285 new gis feature classes (#73)
* new gis feature classes with interface for attributes

* updates file names to correspond with classes and adds multipatch feature class

---------

Co-authored-by: Adam Hathcock <adamhathcock@users.noreply.github.com>
2024-08-14 15:57:15 +00:00
Adam Hathcock e443840acf Do snupkgs are for Objects and Sdk...not logging (#72) 2024-08-13 20:26:53 +01:00
Adam Hathcock d269ac73dd Disallow SpeckleType inheritance (#71)
* Disallow SpeckleType inheritance

* fmt

* more tests
2024-08-13 14:32:58 +00:00
Jedd Morgan 148a11f83e Fixed source link (#70)
* Fixed source link pdb

* add snupackage
2024-08-13 14:56:04 +01:00
Jedd Morgan 66b3c5e60c Added DUI3 Operations.Send changes to Sdk (#68)
* Added DUI3 Operations.Send changes to Sdk

* Tests

* more tests

---------

Co-authored-by: Dimitrie Stefanescu <didimitrie@gmail.com>
2024-08-12 18:28:35 +01:00
Jedd Morgan cfc4018bd3 removed a bunch of obsolete (#65)
* removed a bunch of obsolete

* Accidental trailing char
2024-08-12 11:49:43 +01:00
Jedd Morgan 4b74ca8607 Some tweaks r.e. JsonIgnore (#64)
* Removed total children count

* Some random tweaks

* JsonIgnore tests

* Ignore base
2024-08-12 09:03:56 +00:00
Adam Hathcock 1c64a975c0 Add detail for OpenTelemetry (#67)
* Add detail for OpenTelemetry

* fmt

* review fixes

* more fixes
2024-08-08 16:04:24 +00:00
Jedd Morgan 78faa71592 Collection name space change (#66) 2024-08-08 12:32:41 +00:00
Adam Hathcock 6f5f044095 Adam/cxpla 6 kill remaining kit code in core (#59)
* compiles with relevant deletions

* Test fixes

* fix type loading

* type load for tests

* speckle objects renamespace

* rename Core to Sdk

* Fix test references

* tests renaming

* rename logging

* fmt

* start of adding an attribute to all base types

* convert all types and do basic test

* Fix most tests

* fix more tests

* fmt

* Build fix

* add changes and more tests

* Fix tests

* Fix integration tests
2024-08-08 10:52:19 +01:00
Jedd Morgan 0b240f0752 Removed total children count (#63) 2024-08-08 08:29:06 +01:00
Adam Hathcock 6d54be55db Use App and Version when doing otel service name (#61) 2024-08-07 12:54:07 +01:00
Adam Hathcock 7148aa0a6f Refining OTEL/Logging configuration (#57)
* More defined configuration

* more config changes and fmt

* fix usages of app versions

* add endpoints and remove seq

* forgot to commit

* Fixes around tracing

* use more strong typing

* add test
2024-08-06 16:24:55 +01:00
Adam Hathcock f8e4682670 Reduce thread usage by removing a possible unneeded Task.Run (#52)
* Reduce thread usage by removing a possible unneeded Task.Run

* fmt
2024-08-05 09:13:10 +01:00
Claire Kuang 9da1d791cc Restructures proxies, removes layer colors, and adds color proxy class (#58) 2024-08-02 18:24:58 +03:00
Adam Hathcock 77ffcead69 Speckle.Logging with ILRepack (#54)
* Revert SQLite to allow side by side

* Update Serilog to 3.1.1 and remove Sentry

* fmt

* Revert serilog change

* first pass

* downgrade to MELA 2.2 to avoid conflicts

* add otel

* Speckle.Logging proper

* move otel and logging to make core dependant

* readd configuration

* revert namespace and add console tracing

* fmt

* Remove extra usings

* readd serilog

* fix deps

* remove extras for build

* some reversions

* add more context

* Fix conversion

* More explicit

* Revert naming

* back to public loggerfactory

* Remove more obsolete things

* Drop ME.Logging dependency and expose logging interface

* restore integration test compose

* fmt

* remove the ME Logging dependency
2024-07-31 15:37:10 +01:00
Claire Kuang a9a9b6b525 Merge pull request #56 from specklesystems/curve-encoding-bug
fix(Curve): null display value on curves decoded in breps
2024-07-31 11:52:47 +01:00
Claire Kuang adcf81b5c8 Merge branch 'curve-encoding-bug' of https://github.com/specklesystems/speckle-sharp-sdk into curve-encoding-bug 2024-07-31 11:48:07 +01:00
Claire Kuang fc46610b5b Update RevitInstance.cs 2024-07-31 11:47:57 +01:00
Claire Kuang 69fceb4d09 Merge branch 'dev' into curve-encoding-bug 2024-07-31 11:42:15 +01:00
Claire Kuang 9671745fdb fixes null display value on curves decoded in breps 2024-07-31 11:36:27 +01:00
Adam Hathcock 787ad92ff2 Remove extra usings (#55)
* Remove extra usings

* readd serilog
2024-07-30 11:07:52 +01:00
Adam Hathcock e79716c5f0 Remove Sentry (#49)
* Revert SQLite to allow side by side

* Update Serilog to 3.1.1 and remove Sentry

* fmt

* Revert serilog change
2024-07-29 16:10:26 +01:00
Jedd Morgan 1f92335d6d retry policy for server api (#53) 2024-07-26 13:37:28 +01:00
Adam Hathcock 02f75c717c Add NotNull Empty and tests (#51) 2024-07-24 15:05:44 +01:00
Claire Kuang ce3e591a47 feat: CNX-19 adds render material proxy class (#50)
* adds render material proxy class

* Update RenderMaterial.cs

* Update RenderMaterial.cs

* refactors IProxyCollection interface

* Update RenderMaterial.cs
2024-07-24 11:43:39 +00:00
Adam Hathcock 059253ff39 Revert SQLite to allow side by side (#48) 2024-07-24 11:38:34 +01:00
Adam Hathcock 957a284332 Change DI sig for Server and adjust helpers (#46)
* Change DI sig for Server and adjust helpers

* Remove V1 server transport
2024-07-23 12:35:27 +01:00
Adam Hathcock 5c7a96b960 ensure proper disposal of transports from di factory (#44)
* Rework servertransport to have proper interface and factory

* fmt

* rename class

* exclude factory from tests
2024-07-18 16:13:17 +01:00
Adam Hathcock 58911632e3 add xml docs and they get added to nugets (#45) 2024-07-18 10:05:39 +01:00
Adam Hathcock 9e2f5d57de Merge pull request #43 from specklesystems/add-local
add local config
2024-07-18 09:00:31 +01:00
Adam Hathcock 64267d7697 add local config 2024-07-18 08:32:33 +01:00
Adam Hathcock ee94ac2bf9 Merge pull request #42 from specklesystems/fix-gitversion
Fix gitversion
2024-07-17 15:50:53 +01:00
Claire Kuang 5f8379806d Merge pull request #40 from specklesystems/claire/collections-refactor
refactor(Collections): changes namespace of collections and adds interfaces
2024-07-17 15:09:11 +01:00
Oğuzhan Koral 580521f3b0 Add group proxy (#41) 2024-07-17 15:47:39 +02:00
Adam Hathcock 18ad5f5c11 do pack local 2024-07-17 14:44:21 +01:00
Adam Hathcock fcf4e223f7 version based on branch and more git locally 2024-07-17 14:42:59 +01:00
Claire Kuang a16bc4eae0 updates tests 2024-07-17 14:28:51 +01:00
Claire Kuang a15390ab0d Update Collection.cs 2024-07-17 14:22:37 +01:00
Claire Kuang a2f0270a6e adds old collections namespace deprecation 2024-07-17 14:22:27 +01:00
Claire Kuang 04446b9e79 changes namespace of collections and adds interfaces 2024-07-17 10:40:55 +01:00
Dimitrie Stefanescu f408980a98 Merge pull request #38 from specklesystems/oguzhan/remove-point-value-prop
Have it back
2024-07-17 10:08:55 +01:00
oguzhankoral b70a0c6fe3 Have it back 2024-07-17 11:08:05 +02:00
Dimitrie Stefanescu 7f50e9a09a Merge pull request #37 from specklesystems/oguzhan/remove-point-value-prop
Remove value prop from Point object
2024-07-17 10:01:40 +01:00
oguzhankoral b52d8e0023 Remove value prop from Point object 2024-07-17 11:00:31 +02:00
Oğuzhan Koral e97597596a Merge pull request #36 from specklesystems/oguzhan/fix-point-value-getter
Remove the Point value prop getter
2024-07-17 09:37:17 +02:00
oguzhankoral 4536ecee87 Remove the Point value prop getter 2024-07-17 09:32:05 +02:00
Dimitrie Stefanescu 72b7123f7b Merge pull request #35 from specklesystems/claire/layer-constructor-fix
Fixes Layer class constructors
2024-07-16 17:44:40 +01:00
Claire Kuang 72fe3d1384 Update Layer.cs 2024-07-16 17:38:42 +01:00
Dimitrie Stefanescu 481a095ed3 Merge pull request #34 from specklesystems/dim/dui3/layers
feat(dui3): adds layer concept in core as a poc
2024-07-16 15:03:08 +01:00
Dimitrie Stefanescu e3a5af037e chore: formatting 2024-07-16 14:56:28 +01:00
Dimitrie Stefanescu fe27951d96 feat(dui3): adds layer concept in core as a poc 2024-07-16 14:49:37 +01:00
Jedd Morgan baf5ab0b14 Fixed mistake (#32) 2024-07-16 10:47:56 +01:00
Adam Hathcock 057aef10c0 Merge pull request #31 from specklesystems/fixed-versions
Use GitVersion.MsBuild
2024-07-16 10:16:01 +01:00
Adam Hathcock c35ce07337 remove extra versioning stuff 2024-07-16 10:09:41 +01:00
Jedd Morgan e088e139af fix(core): Fixed regression with displayValue helper functions (#30) 2024-07-16 11:06:50 +02:00
Adam Hathcock dc62aa22b9 Use GitVersion.MsBuild 2024-07-16 10:06:29 +01:00
Adam Hathcock cd67efdfff Use the non-prerelease DoubleNumerics package (#29) 2024-07-16 08:15:28 +00:00
Dimitrie Stefanescu f0124a76c1 Merge pull request #28 from specklesystems/oguzhan/add-name-prop-to-definition
Add name property to definition proxy
2024-07-16 08:45:38 +01:00
oguzhankoral 5d4e14e802 Add name property to definition proxy 2024-07-16 09:28:14 +02:00
Adam Hathcock a88f860c5e Merge pull request #27 from specklesystems/git-version
switch from minver to gitversion
2024-07-15 15:16:35 +01:00
Adam Hathcock 1112ec39ab clean up tests and altcover the integration tests 2024-07-12 15:42:40 +01:00
Adam Hathcock 3ec1007b7b format 2024-07-12 15:21:06 +01:00
Adam Hathcock 82d51af262 fix checkout 2024-07-12 15:20:00 +01:00
Adam Hathcock e83c0125ba oops be linux 2024-07-12 15:17:24 +01:00
Adam Hathcock b23e91651c switch from minver to gitversion 2024-07-12 15:15:19 +01:00
Jedd Morgan db88dbe6d0 Avoid wrapping cancellation exception (#26) 2024-07-11 14:58:08 +01:00
Jedd Morgan da792173ff Added new Version Mutations (#25) 2024-07-11 14:03:02 +01:00
Jedd Morgan 51f0c26838 Re added level public setter for Revit Column (#24)
* Readded revit wall level setter

* csharpier

* Revit Column
2024-07-11 09:33:06 +01:00
Jedd Morgan cb14c43381 Readded revit wall level setter (#23) 2024-07-10 16:56:19 +00:00
Adam Hathcock ea68a245b8 Use a different minver id for now 2024-07-10 17:01:06 +01:00
Adam Hathcock c5df445483 git version 2024-07-10 16:50:37 +01:00
Adam Hathcock adadaa4d91 add dev to main build 2024-07-10 16:47:08 +01:00
Adam Hathcock 6e46fd2f8a use more build fun for nugets (#22)
* add license file

* use more build for nugets
2024-07-10 15:45:06 +00:00
Adam Hathcock 5df0c4401e Empty 2024-07-10 16:31:23 +01:00
Adam Hathcock 6778b7086c All int tests on CI: Don't run non-int tests during int tests. Reduce logging level (#20)
* Add Integration tests to CI (#19)

* Add Instances base (#6)

* Use Uri for checks in GetAccounts function (#8)

* Add integration and perf tests to sln (#9)

* Remove perf tests (#10)

* remove perf tests

* do all unit tests

* Code coverage (#11)

* code coverage

* enable codecov for GA

* Update README.md

* Update coverage and dependencies (#12)

* Update coverage and dependencies

* fmt

* add codecov config

* merge DUI3/Alpha into sdk (#13)

* merge DUI3/Alpha into sdk

* formatting

* Merge Objects dui3/alpha -> dev (#14)

* merge DUI3/Alpha into sdk

* formatting

* Objects changes

* Objects tests

* Unit test project

* add coverage exclusion

* fix some tests and fix nullability errors

* update codecov to be less intrusive (#15)

* update codecov to be less intrusive

* fix codecov yaml

* add coverage exclusion

* Merge sharp `dui3/alpha` -> sdk `main` (#16)

* Merge

* csharpier format

* Fixed polysharp issues

* Integration Tests

* Fixes

* add build for docker compose

* add integration tests

* remove extra services

* update healthcheck for server

---------

Co-authored-by: Oğuzhan Koral <45078678+oguzhankoral@users.noreply.github.com>
Co-authored-by: Jedd Morgan <45512892+JR-Morgan@users.noreply.github.com>

* Don't run non-int tests during int tests.  Reduce logging level

---------

Co-authored-by: Oğuzhan Koral <45078678+oguzhankoral@users.noreply.github.com>
Co-authored-by: Jedd Morgan <45512892+JR-Morgan@users.noreply.github.com>
2024-07-10 13:52:19 +01:00
Adam Hathcock 2dcf89f6fe Merge pull request #21 from specklesystems/main
Main to dev
2024-07-10 13:42:14 +01:00
Adam Hathcock 3249265560 Merge branch 'dev' 2024-07-09 13:58:09 +01:00
Adam Hathcock 200b84f49a Main to dev (#18)
* Add Instances base (#6)

* Use Uri for checks in GetAccounts function (#8)

* Add integration and perf tests to sln (#9)

* Remove perf tests (#10)

* remove perf tests

* do all unit tests

* Code coverage (#11)

* code coverage

* enable codecov for GA

* Update README.md

* Update coverage and dependencies (#12)

* Update coverage and dependencies

* fmt

* add codecov config

* merge DUI3/Alpha into sdk (#13)

* merge DUI3/Alpha into sdk

* formatting

* Merge Objects dui3/alpha -> dev (#14)

* merge DUI3/Alpha into sdk

* formatting

* Objects changes

* Objects tests

* Unit test project

* update codecov to be less intrusive (#15)

* update codecov to be less intrusive

* fix codecov yaml

* add coverage exclusion

* Merge sharp `dui3/alpha` -> sdk `main` (#16)

* Merge

* csharpier format

* Fixed polysharp issues

* Integration Tests

* Fixes

* Some nullability fixes (#17)

* add coverage exclusion

* fix some tests and fix nullability errors

---------

Co-authored-by: Oğuzhan Koral <45078678+oguzhankoral@users.noreply.github.com>
Co-authored-by: Jedd Morgan <45512892+JR-Morgan@users.noreply.github.com>
2024-07-09 13:56:03 +01:00
Jedd Morgan 1268a08baf Merge sharp dui3/alpha -> sdk main (#16)
* Merge

* csharpier format

* Fixed polysharp issues

* Integration Tests

* Fixes
2024-07-09 12:32:24 +01:00
Adam Hathcock 46c3f9d1ac update codecov to be less intrusive (#15)
* update codecov to be less intrusive

* fix codecov yaml

* add coverage exclusion
2024-07-09 12:52:53 +02:00
Jedd Morgan 29e7e84f4e Merge Objects dui3/alpha -> dev (#14)
* merge DUI3/Alpha into sdk

* formatting

* Objects changes

* Objects tests

* Unit test project
2024-07-08 16:30:54 +01:00
Jedd Morgan b2883c91e4 merge DUI3/Alpha into sdk (#13)
* merge DUI3/Alpha into sdk

* formatting
2024-07-08 14:03:54 +01:00
Adam Hathcock 82b7ca1a26 Update coverage and dependencies (#12)
* Update coverage and dependencies

* fmt

* add codecov config
2024-07-04 10:14:38 +01:00
Adam Hathcock b56eac2f50 Update README.md 2024-07-04 09:44:40 +01:00
Adam Hathcock f26f79c3c8 Code coverage (#11)
* code coverage

* enable codecov for GA
2024-07-04 09:43:16 +01:00
Adam Hathcock a0b723b2cb Remove perf tests (#10)
* remove perf tests

* do all unit tests
2024-07-04 09:34:57 +01:00
Adam Hathcock 1b472be6b7 Add integration and perf tests to sln (#9) 2024-07-02 18:24:44 +01:00
Oğuzhan Koral 662984268b Use Uri for checks in GetAccounts function (#8) 2024-07-02 15:00:55 +01:00
Adam Hathcock 1d681f9166 Add Instances base (#6) 2024-06-27 17:42:07 +01:00
Adam Hathcock cfe5f330c9 trying to get the deterministic builds checkbox on nuget again, works locally 2024-06-25 16:29:14 +01:00
Adam Hathcock 17e6780357 trying to get the deterministic builds checkbox on nuget (#4) 2024-06-25 16:00:18 +01:00
Adam Hathcock 98132d2811 Make name Civil3d instead of Civil (#3) 2024-06-25 15:29:24 +01:00
Adam Hathcock d9d1865504 downgrade sqlite to match core 2024-06-25 10:57:44 +01:00
Adam Hathcock 405f3f4ee4 renamespace and other fixes (#2)
* renamespace

* add to sln and move

* manage package centrally

* add sourcelink and use GlobalPackageReference

* properly use globals

* fix nuget push

* fix readme

* add namespace handling for new types

* Removing used classes to stop viral spread of dependencies.  Some JSON usage was STJ and not newtonsoft

* fmt

* initial test

* serialization namespace test

* fmt

* put back old namespaces

* fix tests

* fixes while trying to do a roundtrip test

* remove namespace fix
2024-06-25 10:27:59 +01:00
Adam Hathcock ca350002ba add packing and minver (#1)
* add packing and minver

* update permissions

* fix build script

* fix it again :(

* fmt

* update sqlite to avoid rid warning
2024-06-21 13:18:10 +01:00
Adam Hathcock 4ea9e4b9aa reformat tests 2024-06-21 12:38:25 +01:00
Adam Hathcock 2269182922 fmt 2024-06-21 12:33:55 +01:00
Adam Hathcock d7dbd3349f start build 2024-06-21 12:33:24 +01:00
Adam Hathcock ebec2c5bd2 add misc 2024-06-21 10:40:54 +01:00
Adam Hathcock a74ead9bd7 tests pass and everything compiles 2024-06-21 10:36:21 +01:00
Adam Hathcock f46aa4f50b compiles and tests pass 2024-06-21 10:23:34 +01:00
Adam Hathcock afde379cda trying to move core 2024-06-21 08:42:42 +01:00
529 changed files with 45555 additions and 2 deletions
+13
View File
@@ -0,0 +1,13 @@
{
"version": 1,
"isRoot": true,
"tools": {
"csharpier": {
"version": "1.1.2",
"commands": [
"csharpier"
],
"rollForward": false
}
}
}
+26
View File
@@ -0,0 +1,26 @@
Directory.Build.targets
Directory.Build.props
**/bin/*
**/obj/*
_ReSharper.SharpCompress/
bin/
*.suo
*.user
TestArchives/Scratch/
TestArchives/Scratch2/
TestResults/
*.nupkg
packages/*/
project.lock.json
tests/TestArchives/Scratch
.vs
tools
.vscode
.idea/
.DS_Store
*.snupkg
coverage.xml
*.received.*
+7
View File
@@ -0,0 +1,7 @@
printWidth: 120
useTabs: false
indentSize: 2
preprocessorSymbolSets:
- ""
- "DEBUG"
- "DEBUG,CODE_STYLE"
+327
View File
@@ -0,0 +1,327 @@
root = true
# Don't use tabs for indentation.
[*]
indent_style = space
# Microsoft .NET properties
csharp_using_directive_placement = outside_namespace:silent
dotnet_style_parentheses_in_arithmetic_binary_operators = never_if_unnecessary:none
dotnet_style_parentheses_in_other_binary_operators = never_if_unnecessary:none
dotnet_style_parentheses_in_relational_binary_operators = never_if_unnecessary:none
# Standard properties
insert_final_newline = true
# (Please don't specify an indent_size here; that has too many unintended consequences.)
# Code files
[*.{cs,csx,vb,vbx}]
indent_size = 2
charset = utf-8
# Xml project files
[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}]
indent_size = 2
space_after_last_pi_attribute = false
# Xml config files
[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}]
indent_size = 2
space_after_last_pi_attribute = false
# JSON files
[*.json]
indent_size = 2
# Dotnet code style settings:
[*.{cs,vb}]
# Sort using and Import directives with System.* appearing first
dotnet_sort_system_directives_first = true
dotnet_separate_import_directive_groups = false
# Avoid "this." and "Me." if not necessary
dotnet_style_qualification_for_field = false:suggestion
dotnet_style_qualification_for_property = false:suggestion
dotnet_style_qualification_for_method = false:suggestion
dotnet_style_qualification_for_event = false:suggestion
# Use language keywords instead of framework type names for type references
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
dotnet_style_predefined_type_for_member_access = true:suggestion
# Parentheses preferences
dotnet_style_parentheses_in_arithmetic_binary_operators = never_if_unnecessary:silent
dotnet_style_parentheses_in_relational_binary_operators = never_if_unnecessary:silent
dotnet_style_parentheses_in_other_binary_operators = never_if_unnecessary:silent
dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent
# Modifier preferences
dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent
dotnet_style_readonly_field = true:suggestion
# Expression-level preferences
dotnet_style_object_initializer = true:suggestion
dotnet_style_collection_initializer = true:suggestion
dotnet_style_coalesce_expression = true:suggestion
dotnet_style_null_propagation = true:suggestion
dotnet_style_explicit_tuple_names = true:suggestion
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent
dotnet_style_prefer_inferred_tuple_names = true:suggestion
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
dotnet_style_prefer_auto_properties = true:warning
dotnet_style_prefer_conditional_expression_over_assignment = true:silent
dotnet_style_prefer_conditional_expression_over_return = true:silent
# CSharp code style settings:
[*.cs]
# Prefer "var" everywhere
csharp_style_var_elsewhere = false:none
csharp_style_var_for_built_in_types = false:none
csharp_style_var_when_type_is_apparent = false:none
# Prefer method-like constructs to have a block body
csharp_style_expression_bodied_methods = true:suggestion
csharp_style_expression_bodied_constructors = false:suggestion
csharp_style_expression_bodied_operators = true:suggestion
# Prefer property-like constructs to have an expression-body
csharp_style_expression_bodied_properties = true:suggestion
csharp_style_expression_bodied_indexers = true:suggestion
csharp_style_expression_bodied_accessors = true:suggestion
# Suggest more modern language features when available
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
csharp_style_inlined_variable_declaration = true:suggestion
csharp_style_throw_expression = true:suggestion
csharp_style_conditional_delegate_call = true:suggestion
csharp_style_namespace_declarations = file_scoped
# Newline settings
csharp_new_line_before_open_brace = all
csharp_new_line_before_else = true
csharp_new_line_before_catch = true
csharp_new_line_before_finally = true
csharp_new_line_before_members_in_object_initializers = true
csharp_new_line_before_members_in_anonymous_types = true
# Space preferences
csharp_space_after_cast = false
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_between_method_call_parameter_list_parentheses = false
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_parentheses = false
csharp_space_before_colon_in_inheritance_clause = true
csharp_space_after_colon_in_inheritance_clause = true
csharp_space_around_binary_operators = before_and_after
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
csharp_space_between_method_call_name_and_opening_parenthesis = false
csharp_space_between_method_call_empty_parameter_list_parentheses = false
# Wrapping preferences
csharp_preserve_single_line_statements = true
csharp_preserve_single_line_blocks = true
# SYMBOL NAMING RULES
# Copied from https://github.com/dotnet/roslyn/blob/main/.editorconfig
# Adapted rules:
# - Constants are ALL_UPPER
# - Non-private fields are PascalCase
# Non-private fields are PascalCase
dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.severity = warning
dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.symbols = non_private_readonly_fields
dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.style = non_private_readonly_field_style
dotnet_naming_symbols.non_private_readonly_fields.applicable_kinds = field
dotnet_naming_symbols.non_private_readonly_fields.applicable_accessibilities = public, protected, internal, protected_internal, private_protected
dotnet_naming_style.non_private_readonly_field_style.capitalization = pascal_case
# Constants are ALL_UPPER
dotnet_naming_rule.constants_should_be_all_upper.severity = warning
dotnet_naming_rule.constants_should_be_all_upper.symbols = constants
dotnet_naming_rule.constants_should_be_all_upper.style = constant_style
dotnet_naming_symbols.constants.applicable_kinds = field, local
dotnet_naming_symbols.constants.required_modifiers = const
dotnet_naming_style.constant_style.capitalization = all_upper
# Private static fields are camelCase and start with s_
dotnet_naming_rule.static_fields_should_be_camel_case.severity = warning
dotnet_naming_rule.static_fields_should_be_camel_case.symbols = static_fields
dotnet_naming_rule.static_fields_should_be_camel_case.style = static_field_style
dotnet_naming_symbols.static_fields.applicable_accessibilities = private
dotnet_naming_symbols.static_fields.applicable_kinds = field
dotnet_naming_symbols.static_fields.required_modifiers = static
dotnet_naming_style.static_field_style.capitalization = camel_case
dotnet_naming_style.static_field_style.required_prefix = s_
# Instance fields are camelCase and start with _
dotnet_naming_rule.instance_fields_should_be_camel_case.severity = warning
dotnet_naming_rule.instance_fields_should_be_camel_case.symbols = instance_fields
dotnet_naming_rule.instance_fields_should_be_camel_case.style = instance_field_style
dotnet_naming_symbols.instance_fields.applicable_kinds = field
dotnet_naming_style.instance_field_style.capitalization = camel_case
dotnet_naming_style.instance_field_style.required_prefix = _
# Locals and parameters are camelCase
dotnet_naming_rule.locals_should_be_camel_case.severity = warning
dotnet_naming_rule.locals_should_be_camel_case.symbols = locals_and_parameters
dotnet_naming_rule.locals_should_be_camel_case.style = camel_case_style
dotnet_naming_symbols.locals_and_parameters.applicable_kinds = parameter, local
dotnet_naming_style.camel_case_style.capitalization = camel_case
# Local functions are PascalCase
dotnet_naming_rule.local_functions_should_be_pascal_case.severity = warning
dotnet_naming_rule.local_functions_should_be_pascal_case.symbols = local_functions
dotnet_naming_rule.local_functions_should_be_pascal_case.style = local_function_style
dotnet_naming_symbols.local_functions.applicable_kinds = local_function
dotnet_naming_style.local_function_style.capitalization = pascal_case
# By default, name items with PascalCase
dotnet_naming_rule.members_should_be_pascal_case.severity = warning
dotnet_naming_rule.members_should_be_pascal_case.symbols = all_members
dotnet_naming_rule.members_should_be_pascal_case.style = pascal_case_style
dotnet_naming_symbols.all_members.applicable_kinds = *
dotnet_naming_style.pascal_case_style.capitalization = pascal_case
# Analyzer settings
dotnet_analyzer_diagnostic.category-Style.severity = warning # All rules will use this severity unless overriden
dotnet_diagnostic.ide0055.severity = none # Formatting rule: Incompatible with CSharpier
dotnet_diagnostic.ide0007.severity = none # Use var instead of explicit type: Preference
dotnet_diagnostic.ide0009.severity = none # Add this or Me qualification: Preference
dotnet_diagnostic.ide0200.severity = none # Remove unnecessary lambda expression: may be performance reasons not to
dotnet_diagnostic.ide0058.severity = none # Remove unnecessary expression value: Subjective
dotnet_diagnostic.ide0010.severity = none # Add missing cases to switch statement: Too verbose
dotnet_diagnostic.ide0200.severity = none # Remove unnecessary lambda expression: may be performance reasons not to
dotnet_diagnostic.ide0058.severity = none # Remove unnecessary expression value: Subjective
dotnet_diagnostic.ide0305.severity = none # Use collection expression for fluent: Can obfuscate intent
dotnet_diagnostic.ide0001.severity = suggestion # Name can be simplified: Non enforceable in build
dotnet_diagnostic.ide0046.severity = suggestion # Use conditional expression for return: Subjective
dotnet_diagnostic.ide0045.severity = suggestion # Use conditional expression for assignment: Subjective
dotnet_diagnostic.ide0078.severity = suggestion # Use pattern matching: Subjective
dotnet_diagnostic.ide0260.severity = suggestion # Use pattern matching: Subjective
dotnet_diagnostic.ide0022.severity = suggestion # Use expression body for method: Subjective
dotnet_diagnostic.ide0061.severity = suggestion # Use expression body for local functions: Subjective
dotnet_diagnostic.ide0063.severity = suggestion # Using directive can be simplified
dotnet_diagnostic.ide0066.severity = suggestion # Use switch expression: Subjective
dotnet_diagnostic.ide0029.severity = suggestion # Null check can be simplified: Subjective
dotnet_diagnostic.ide0030.severity = suggestion # Null check can be simplified: Subjective
dotnet_diagnostic.ide0270.severity = suggestion # Null check can be simplified: Subjective
dotnet_diagnostic.ide0042.severity = suggestion # Deconstruct variable declaration: Subjective
dotnet_diagnostic.ide0039.severity = suggestion # Use local function instead of lambda: Subjective
dotnet_diagnostic.ide0029.severity = suggestion # Null check can be simplified: Subjective
dotnet_diagnostic.ide0030.severity = suggestion # Null check can be simplified: Subjective
dotnet_diagnostic.ide0270.severity = suggestion # Null check can be simplified: Subjective
dotnet_diagnostic.ide0042.severity = suggestion # Deconstruct variable declaration: Subjective
dotnet_diagnostic.ide0028.severity = suggestion # Use collection initializers: Subjective
dotnet_diagnostic.ide0072.severity = suggestion # Populate switch statement: Subjective
dotnet_diagnostic.ide0074.severity = suggestion # Use compound assignment: Subjective
dotnet_diagnostic.ide0300.severity = suggestion # Use collection expression for array: Subjective, maybe aspirational
dotnet_diagnostic.ide0290.severity = suggestion # primary constructors: subjective, and readonly properties are not a thing
dotnet_diagnostic.ide0290.severity = suggestion # Use primary constructor: Subjective
dotnet_diagnostic.ide0037.severity = suggestion # Use inferred member names: Sometimes its nice to be explicit
dotnet_diagnostic.ide0301.severity = suggestion # Use collection expression for empty: Subjective, intent
dotnet_diagnostic.ide0021.severity = suggestion # Use expression body for constructors : Subjective
dotnet_diagnostic.ide0090.severity = suggestion # Simplify new expression : Subjective
dotnet_diagnostic.ide0047.severity = suggestion # Parentheses preferences: IDEs don't properly pick it up
dotnet_diagnostic.ide0130.severity = suggestion # Namespace does not match folder structure : Aspirational
dotnet_diagnostic.ide1006.severity = suggestion # Naming rule violation : Aspirational
# Maintainability rules
dotnet_diagnostic.ca1501.severity = warning # Avoid excessive inheritance
dotnet_diagnostic.ca1502.severity = warning # Avoid excessive complexity
dotnet_diagnostic.ca1505.severity = warning # Avoid unmaintainable code
dotnet_diagnostic.ca1506.severity = warning # Avoid excessive class coupling
dotnet_diagnostic.ca1507.severity = warning # Use nameof in place of string
dotnet_diagnostic.ca1508.severity = warning # Avoid dead conditional code
dotnet_diagnostic.ca1509.severity = warning # Invalid entry in code metrics configuration file
dotnet_diagnostic.ca1861.severity = suggestion # Prefer 'static readonly' fields over constant array arguments if the called method is called repeatedly and is not mutating the passed array (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1861)
# Performance rules
dotnet_diagnostic.ca1849.severity = suggestion # Call async methods when in an async method: May decrease performance
dotnet_diagnostic.ca1822.severity = suggestion # Mark member as static
dotnet_diagnostic.ca1859.severity = suggestion # Use concrete types when possible for improved performance
# Design rule
dotnet_diagnostic.ca1002.severity = suggestion # Do not expose generic lists
dotnet_diagnostic.ca1051.severity = warning # Do not declare visible instance fields
dotnet_diagnostic.ca1056.severity = suggestion # URI properties should not be strings
dotnet_diagnostic.ca1062.severity = none # Public method must check all parameters for null
# Naming
dotnet_diagnostic.ca1707.severity = none # Remove underscores in names
# Usage
dotnet_diagnostic.ca2227.severity = suggestion # Collection props should be read-only
dotnet_code_quality.ca1051.exclude_structs = true # CA1051 is excluded in structs
dotnet_code_quality.dispose_ownership_transfer_at_constructor = true # CA2000 has a lot of false positives without this
dotnet_code_quality.dispose_ownership_transfer_at_method_call = true # CA2000 has a lot of false positives without this
dotnet_code_quality.dispose_analysis_kind = NonExceptionPathsOnlyNotDisposed # CA2000 has a lot of false positives without this
# NUnit
dotnet_diagnostic.NUnit2001.severity = warning # Consider using Assert.That(expr, Is.False) instead of Assert.False(expr)
dotnet_diagnostic.NUnit2002.severity = warning # Consider using Assert.That(expr, Is.False) instead of Assert.IsFalse(expr)
dotnet_diagnostic.NUnit2003.severity = warning # Consider using Assert.That(expr, Is.True) instead of Assert.IsTrue(expr)
dotnet_diagnostic.NUnit2004.severity = warning # Consider using Assert.That(expr, Is.True) instead of Assert.True(expr)
dotnet_diagnostic.NUnit2005.severity = warning # Consider using Assert.That(actual, Is.EqualTo(expected)) instead of Assert.AreEqual(expected, actual)
dotnet_diagnostic.NUnit2006.severity = warning # Consider using Assert.That(actual, Is.Not.EqualTo(expected)) instead of Assert.AreNotEqual(expected, actual)
dotnet_diagnostic.NUnit2010.severity = warning # Use EqualConstraint for better assertion messages in case of failure
dotnet_diagnostic.NUnit2011.severity = warning # Use ContainsConstraint for better assertion messages in case of failure
dotnet_diagnostic.NUnit2011.severity = warning # Use StartsWithConstraint for better assertion messages in case of failure
dotnet_diagnostic.NUnit2011.severity = warning # Use EndsWithConstraint for better assertion messages in case of failure
dotnet_diagnostic.NUnit2014.severity = warning # Use SomeItemsConstraint for better assertion messages in case of failure
dotnet_diagnostic.NUnit2015.severity = warning # Consider using Assert.That(actual, Is.SameAs(expected)) instead of Assert.AreSame(expected, actual)
dotnet_diagnostic.NUnit2016.severity = warning # Consider using Assert.That(expr, Is.Null) instead of Assert.Null(expr)
dotnet_diagnostic.NUnit2017.severity = warning # Consider using Assert.That(expr, Is.Null) instead of Assert.IsNull(expr)
dotnet_diagnostic.NUnit2018.severity = warning # Consider using Assert.That(expr, Is.Not.Null) instead of Assert.NotNull(expr)
dotnet_diagnostic.NUnit2028.severity = warning # Consider using Assert.That(actual, Is.GreaterThanOrEqualTo(expected)) instead of Assert.GreaterOrEqual(actual, expected)
dotnet_diagnostic.NUnit2027.severity = warning # Consider using Assert.That(actual, Is.GreaterThan(expected)) instead of Assert.Greater(actual, expected)
dotnet_diagnostic.NUnit2029.severity = warning # Consider using Assert.That(actual, Is.LessThan(expected)) instead of Assert.Less(actual, expected)
dotnet_diagnostic.NUnit2030.severity = warning # Consider using Assert.That(actual, Is.LessThanOrEqualTo(expected)) instead of Assert.LessOrEqual(actual, expected)
dotnet_diagnostic.NUnit2031.severity = warning # Consider using Assert.That(actual, Is.Not.SameAs(expected)) instead of Assert.AreNotSame(expected, actual)
dotnet_diagnostic.NUnit2032.severity = warning # Consider using Assert.That(expr, Is.Zero) instead of Assert.Zero(expr)
dotnet_diagnostic.NUnit2033.severity = warning # Consider using Assert.That(expr, Is.Not.Zero) instead of Assert.NotZero(expr)
dotnet_diagnostic.NUnit2034.severity = warning # Consider using Assert.That(expr, Is.NaN) instead of Assert.IsNaN(expr)
dotnet_diagnostic.NUnit2035.severity = warning # Consider using Assert.That(collection, Is.Empty) instead of Assert.IsEmpty(collection)
dotnet_diagnostic.NUnit2036.severity = warning # Consider using Assert.That(collection, Is.Not.Empty) instead of Assert.IsNotEmpty(collection)
dotnet_diagnostic.NUnit2037.severity = warning # Consider using Assert.That(collection, Does.Contain(instance)) instead of Assert.Contains(instance, collection)
dotnet_diagnostic.NUnit2038.severity = warning # Consider using Assert.That(actual, Is.InstanceOf(expected)) instead of Assert.IsInstanceOf(expected, actual)
dotnet_diagnostic.NUnit2039.severity = warning # Consider using Assert.That(actual, Is.Not.InstanceOf(expected)) instead of Assert.IsNotInstanceOf(expected, actual)
[*.{appxmanifest,asax,ascx,aspx,axaml,build,c,c++,cc,cginc,compute,cp,cpp,cs,cshtml,cu,cuh,cxx,dtd,fs,fsi,fsscript,fsx,fx,fxh,h,hh,hlsl,hlsli,hlslinc,hpp,hxx,inc,inl,ino,ipp,ixx,master,ml,mli,mpp,mq4,mq5,mqh,nuspec,paml,razor,resw,resx,shader,skin,tpp,usf,ush,vb,xaml,xamlx,xoml,xsd}]
indent_style = space
indent_size = 2
tab_width = 2
# Verify
[*.{received,verified}.{json}]
charset = utf-8-bom
end_of_line = lf
indent_size = unset
indent_style = unset
insert_final_newline = false
tab_width = unset
trim_trailing_whitespace = false
+8
View File
@@ -0,0 +1,8 @@
# Set the default behavior, in case people don't have core.autocrlf set.
* text=auto
# need original files to be windows
*.txt text eol=crlf
# Verify
*.verified.json text eol=lf working-tree-encoding=UTF-8
+76
View File
@@ -0,0 +1,76 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
- Using welcoming and inclusive language
- Being respectful of differing viewpoints and experiences
- Gracefully accepting constructive criticism
- Focusing on what is best for the community
- Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
- The use of sexualized language or imagery and unwelcome sexual attention or
advances
- Trolling, insulting/derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or electronic
address, without explicit permission
- Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at hello@speckle.systems. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq
+58
View File
@@ -0,0 +1,58 @@
# Speckle Contribution Guidelines
## Introduction
Thank you for reading this! Speckle's a rather wide network of parts that depend on each other, either directly, indirectly or even just cosmetically.
> **Speckle** is a quite large ecosystem of moving parts. Any changes may have unintended effects, that can cause problems quickly for many people (and processes) that rely on Speckle.
This means that what might look like a simple quick change in one repo may have a big hidden cost that propagates around other parts of the project. We're all here to help each other, and this guide is meant to help you get started and promote a framework that can untangle all these dependecies through discussion!
## Bugs & Issues 🐞
### Found a new bug?
- First step is to check whether this is a new bug! We encourage you to search through the issues of the project in question **and** associated repos!
- If you come up with nothing, **open a new issue with a clear title and description**, as much relevant information as possible: system configuration, code samples & steps to reproduce the problem.
- Can't mention this often enough: tells us how to reproduce the problem! We will ignore or flag as such issues without reproduction steps.
- Try to reference & note all potentially affected projects.
### Sending a PR for Bug Fixes
You fixed something! Great! We hope you logged it first :) Make sure though that you've covered the lateral thinking needed for a bug report, as described above, also in your implementation! If there any tests, make sure they all pass. If there are none, it means they're missing - so add them!
### Code Style
When collaborating on a project in GitHub, it's important to follow coding conventions and style guidelines to ensure consistency and readability of the codebase. One commonly used convention is to use two spaces for indentation.
To use two spaces for indentation in GitHub, you can configure your text editor or IDE to use this indentation style. Once you've written your code, you can commit and push your changes to GitHub.
When collaborating with others on GitHub, it's important to communicate any changes to coding conventions or style guidelines, and to work together to maintain a consistent coding style throughout the project. Code reviews can also help ensure that code is well-formatted and easy to read.
## New Features 🎉
The golden rule is to Discuss First!
- Before embarking on adding a new feature, suggest it first as an issue with the `enhancement` label and/or title - this will allow relevant people to pitch in
- We'll now discuss your requirements and see how and if they fit within the Speckle ecosystem.
- The last step is to actually start writing code & submit a PR so we can follow along!
- All new features should, if and where possible, come with tests. We won't merge without!
> Many clients may potentially have overlapping scopes, some features might already be in dev somewhere else, or might have been postponed to the next major release due to api instability in that area. For example, adding a delete stream button in the accounts panel in rhino: this feature was planned for speckle admin, and the whole functionality of the accounts panel in rhino is to be greatly reduced!
## Cosmetic Patches ✨
Changes that are cosmetic in nature and do not add anything substantial to the stability or functionality of Speckle **will generally not be accepted**.
Why? However trivial the changes might seem, there might be subtle reasons for the original code to be as it is. Furthermore, there are a lot of potential hidden costs (that even maintainers themselves are not aware of fully!) and they eat up review time unncessarily.
> **Examples**: modifying the colour of an UI element in one client may have a big hidden cost and need propagation in several other clients that implement a similar ui element. Changing the default port or specifiying `localhost` instead of `0.0.0.0` breaks cross-vm debugging and developing.
## Wrap up
Don't worry if you get things wrong. We all do, including project owners: this document should've been here a long time ago. There's plenty of room for discussion on our community [forum](https://discourse.speckle.works).
🙌❤️💙💚💜🙌
+14
View File
@@ -0,0 +1,14 @@
# Coding standards, domain knowledge, and preferences that AI should follow
## C# Coding Standards
- Use the csharpier formatter for formatting C# code.
- Use the .editorconfig file for code style settings.
- Always use `var` when the type is obvious from the right side of the assignment.
- Always add braces for `if`, `else`, `for`, `foreach`, `while`, and `do` statements, even if they are single-line statements.
## Testing
- Use xUnit for unit testing.
- Use FluentAssertions for assertions in tests.
- Use Moq for mocking dependencies in tests.
+6
View File
@@ -0,0 +1,6 @@
version: 2
updates:
- package-ecosystem: "github-actions" # search for actions - there are other options available
directory: "/" # search in .github/workflows under root `/`
schedule:
interval: "weekly" # check for action update every week
+22
View File
@@ -0,0 +1,22 @@
# Git Commit Instructions
To ensure high-quality and consistent commits, please follow these guidelines:
1. **Format your code**
- Run the `csharpier` formatter on all C# files before committing.
- Ensure your code adheres to the `.editorconfig` settings.
2. **Write clear commit messages**
- Use the present tense ("Add feature" not "Added feature").
- Start with a short summary (max 72 characters), followed by a blank line and a detailed description if necessary.
3. **Test your changes**
- Run all unit tests before committing.
- Add or update xUnit tests as needed.
- Use AwesomeAssertions for assertions and Moq for mocking in tests.
4. **Review your changes**
- Double-check for accidental debug code or commented-out code.
- Ensure only relevant files are staged.
Thank you for helping maintain code quality!
+46
View File
@@ -0,0 +1,46 @@
name: .NET CI Build
on:
pull_request:
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Setup .NET
uses: actions/setup-dotnet@v5
with:
dotnet-version: 8.x.x
- uses: actions/cache@v4
with:
path: ~/.nuget/packages
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
- id: set-version
name: Set version to output
run: |
SEMVER="3.0.99.${{ github.run_number }}"
FILE_VERSION=$(echo "$SEMVER" | sed -E 's/^([0-9]+\.[0-9]+\.[0-9]+).*/\1/')
FILE_VERSION="$FILE_VERSION.${{ github.run_number }}"
echo "semver=$SEMVER" >> "$GITHUB_OUTPUT"
echo "fileVersion=$FILE_VERSION" >> "$GITHUB_OUTPUT"
echo $SEMVER
echo $FILE_VERSION
- name: 🔫 Build All
run: ./build.sh
env:
SEMVER: ${{ steps.set-version.outputs.SEMVER }}
FILE_VERSION: ${{ steps.set-version.outputs.FILE_VERSION }}
- name: Upload coverage reports to Codecov with GitHub Action
uses: codecov/codecov-action@v5
with:
files: tests/**/coverage.xml
token: ${{ secrets.CODECOV_TOKEN }}
+54
View File
@@ -0,0 +1,54 @@
name: .NET Build and Publish
on:
push:
tags: ["3.*"]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Setup .NET
uses: actions/setup-dotnet@v5
with:
dotnet-version: 8.x.x
- uses: actions/cache@v4
with:
path: ~/.nuget/packages
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
- id: set-version
name: Set version to output
run: |
TAG=${{ github.ref_name }}
if [[ "${{ github.ref }}" != refs/tags/* ]]; then
TAG="3.0.99.${{ github.run_number }}"
fi
SEMVER="${TAG}"
FILE_VERSION=$(echo "$TAG" | sed -E 's/^([0-9]+\.[0-9]+\.[0-9]+).*/\1/')
FILE_VERSION="$FILE_VERSION.${{ github.run_number }}"
echo "semver=$SEMVER" >> "$GITHUB_OUTPUT"
echo "fileVersion=$FILE_VERSION" >> "$GITHUB_OUTPUT"
echo $SEMVER
echo $FILE_VERSION
- name: 🔫 Build and Pack
run: ./build.sh pack
env:
SEMVER: ${{ steps.set-version.outputs.SEMVER }}
FILE_VERSION: ${{ steps.set-version.outputs.FILE_VERSION }}
- name: Upload coverage reports to Codecov with GitHub Action
uses: codecov/codecov-action@v5
with:
files: tests/**/coverage.xml
token: ${{ secrets.CODECOV_TOKEN }}
- name: Push to nuget.org
run: dotnet nuget push output/*.nupkg --source "https://api.nuget.org/v3/index.json" --api-key ${{secrets.CONNECTORS_NUGET_TOKEN }} --skip-duplicate
+24
View File
@@ -0,0 +1,24 @@
**/bin/*
**/obj/*
_ReSharper.SharpCompress/
bin/
*.suo
*.user
TestArchives/Scratch/
TestArchives/Scratch2/
TestResults/
*.nupkg
packages/*/
project.lock.json
tests/TestArchives/Scratch
.vs
tools
.vscode
.idea/
.volumes/
.DS_Store
*.snupkg
coverage.xml
*.received.*
+50
View File
@@ -0,0 +1,50 @@
# Speckle Contribution Guidelines
## Introduction
Thank you for reading this! Speckle's a rather wide network of parts that depend on each other, either directly, indirectly or even just cosmetically.
> **Speckle** is a quite large ecosystem of moving parts. Any changes may have unintended effects, that can cause problems quickly for many people (and processes) that rely on Speckle.
This means that what might look like a simple quick change in one repo may have a big hidden cost that propagates around other parts of the project. We're all here to help each other, and this guide is meant to help you get started and promote a framework that can untangle all these dependecies through discussion!
## Bugs & Issues 🐞
### Found a new bug?
- First step is to check whether this is a new bug! We encourage you to search through the issues of the project in question **and** associated repos!
- If you come up with nothing, **open a new issue with a clear title and description**, as much relevant information as possible: system configuration, code samples & steps to reproduce the problem.
- Can't mention this often enough: tells us how to reproduce the problem! We will ignore or flag as such issues without reproduction steps.
- Try to reference & note all potentially affected projects.
### Sending a PR for Bug Fixes
You fixed something! Great! We hope you logged it first :) Make sure though that you've covered the lateral thinking needed for a bug report, as described above, also in your implementation! If there any tests, make sure they all pass. If there are none, it means they're missing - so add them!
## New Features 🎉
The golden rule is to Discuss First!
- Before embarking on adding a new feature, suggest it first as an issue with the `enhancement` label and/or title - this will allow relevant people to pitch in
- We'll now discuss your requirements and see how and if they fit within the Speckle ecosystem.
- The last step is to actually start writing code & submit a PR so we can follow along!
- All new features should, if and where possible, come with tests. We won't merge without!
> Many clients may potentially have overlapping scopes, some features might already be in dev somewhere else, or might have been postponed to the next major release due to api instability in that area. For example, adding a delete stream button in the accounts panel in rhino: this feature was planned for speckle admin, and the whole functionality of the accounts panel in rhino is to be greatly reduced!
## Cosmetic Patches ✨
Changes that are cosmetic in nature and do not add anything substantial to the stability or functionality of Speckle **will generally not be accepted**.
Why? However trivial the changes might seem, there might be subtle reasons for the original code to be as it is. Furthermore, there are a lot of potential hidden costs (that even maintainers themselves are not aware of fully!) and they eat up review time unncessarily.
> **Examples**: modifying the colour of an UI element in one client may have a big hidden cost and need propagation in several other clients that implement a similar ui element. Changing the default port or specifiying `localhost` instead of `0.0.0.0` breaks cross-vm debugging and developing.
## Wrap up
Don't worry if you get things wrong. We all do, including project owners: this document should've been here a long time ago. There's plenty of room for discussion on our community [forum](https://discourse.speckle.works).
🙌❤️💙💚💜🙌
+4
View File
@@ -0,0 +1,4 @@
CA1502: 25
CA1501: 5
CA1506(Method): 50
CA1506(Type): 95
+73
View File
@@ -0,0 +1,73 @@
<Project>
<PropertyGroup Label="Compiler Properties">
<LangVersion>12</LangVersion>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
</PropertyGroup>
<PropertyGroup Label="Nugetspec Package Properties">
<!-- Defines common Nugetspec properties -->
<!-- Inheriting packable projects should define the rest of the nugetspec properties (PackageId, Description) -->
<!-- and may, if needed, override/extend any of these (e.g. PackageTags) -->
<Authors>Speckle</Authors>
<Copyright>Copyright (c) AEC Systems Ltd</Copyright>
<PackageProjectUrl>https://speckle.systems/</PackageProjectUrl>
<PackageIcon>logo.png</PackageIcon>
<PackageReadmeFile>README.md</PackageReadmeFile>
<RepositoryUrl>https://github.com/specklesystems/speckle-sharp-sdk</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageTags>speckle</PackageTags>
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
</PropertyGroup>
<PropertyGroup Label="Nuget Package Properties">
<IsPackable>false</IsPackable>
<!--Can be set to true in inheriting .props/.csproj files for projects that should be packed-->
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
</PropertyGroup>
<PropertyGroup Condition="'$(GITHUB_ACTIONS)' == 'true'">
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
</PropertyGroup>
<PropertyGroup Label="Analyers">
<EnableNetAnalyzers>true</EnableNetAnalyzers>
<AnalysisLevel>latest-AllEnabledByDefault</AnalysisLevel>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<!-- Ingored warnings, some aspirational but too noisy for now, some by design. -->
<NoWarn>
<!--Disabled by design-->
CA5399;CA1812;
<!--XML comment-->
CS1591;CS1573;
<!-- Globalization rules -->
CA1303;CA1304;CA1305;CA1307;CA1308;CA1309;CA1310;CA1311;
<!-- Logging -->
CA1848;CA1727;
<!-- Others we don't want -->
CA1815;CA1725;
<!-- Naming things is hard enough -->
CA1710;CA1711;CA1720;CA1724;
<!-- Aspirational -->
CA1502;CA1716;NETSDK1206;
$(NoWarn)
</NoWarn
>
</PropertyGroup>
<PropertyGroup>
<!-- Expose the repository root to all projects -->
<RepositoryRoot>$(MSBuildThisFileDirectory)</RepositoryRoot>
</PropertyGroup>
<ItemGroup>
<None Include="..\..\README.md" Pack="true" PackagePath="\" />
<None Condition="'$(IsPackable)' == 'true'" Include="..\..\logo.png" Pack="true" PackagePath="\" Visible="false" />
</ItemGroup>
<ItemGroup>
<!-- This file contains the configuration for some analyzer warnings, such as cyclomatic
complexity threshold -->
<AdditionalFiles Include="$(RepositoryRoot)CodeMetricsConfig.txt" />
</ItemGroup>
</Project>
+17
View File
@@ -0,0 +1,17 @@
<Project>
<PropertyGroup Condition="'$(IsTestProject)' == 'true'">
<NoWarn>
<!-- Things we need to test -->
CS0618;CA1034;CA2201;CA1051;CA1040;CA1724;
IDE0044;IDE0130;CA1508;
<!-- Analysers that provide no tangeable value to a test project -->
CA5394;CA2007;CA1852;CA1819;CA1711;CA1063;CA1816;CA2234;CS8618;CA1054;CA1810;CA2208;CA1019;CA1831;
$(NoWarn);
</NoWarn>
</PropertyGroup>
<Target Name="DeepClean">
<Message Text="Deep clean of $(MSBuildProjectName).csproj" Importance="high" />
<RemoveDir Directories="$(BaseIntermediateOutputPath)" />
<RemoveDir Directories="$(BaseOutputPath)" />
</Target>
</Project>
+42
View File
@@ -0,0 +1,42 @@
<Project>
<ItemGroup>
<PackageVersion Include="altcover" Version="9.0.1" />
<PackageVersion Include="AwesomeAssertions" Version="8.1.0" />
<PackageVersion Include="BenchmarkDotNet" Version="0.14.0" />
<PackageVersion Include="Bullseye" Version="6.0.0" />
<PackageVersion Include="GraphQL.Client" Version="6.0.0" />
<PackageVersion Include="Glob" Version="1.1.9" />
<PackageVersion Include="HttpMultipartParser" Version="9.0.0" />
<PackageVersion Include="ILRepack.FullAuto" Version="1.6.0" />
<PackageVersion Include="Microsoft.CSharp" Version="4.7.0" />
<!-- Keep at exactly 7.0.5 for side by side with V2 -->
<PackageVersion Include="Microsoft.Data.Sqlite" Version="[7.0.5,)" />
<PackageVersion Include="Microsoft.Extensions.ObjectPool" Version="9.0.4" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="[2.2.0,)" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="[2.2.0,)" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="[2.2.0,)" />
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="[5.0.0,)" />
<PackageVersion Include="Moq" Version="4.20.72" />
<PackageVersion Include="Newtonsoft.Json.Schema" Version="4.0.1" />
<PackageVersion Include="Open.ChannelExtensions" Version="9.1.0" />
<PackageVersion Include="Polly" Version="7.2.3" />
<PackageVersion Include="Polly.Contrib.WaitAndRetry" Version="1.1.1" />
<PackageVersion Include="Polly.Extensions.Http" Version="3.0.0" />
<PackageVersion Include="RichardSzalay.MockHttp" Version="7.0.0" />
<PackageVersion Include="Speckle.Newtonsoft.Json" Version="13.0.2" />
<PackageVersion Include="Speckle.DoubleNumerics" Version="4.1.0" />
<PackageVersion Include="SimpleExec" Version="12.0.0" />
<PackageVersion Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
<PackageVersion Include="System.Threading.Channels" Version="9.0.4" />
<PackageVersion Include="Verify.Quibble" Version="2.1.1" />
<PackageVersion Include="Verify.Xunit" Version="29.4.0" />
<PackageVersion Include="System.Text.Json" Version="8.0.5" />
<PackageVersion Include="xunit" Version="2.9.3" />
<PackageVersion Include="xunit.assert" Version="2.9.3" />
<PackageVersion Include="xunit.runner.visualstudio" Version="3.0.2" />
<GlobalPackageReference Include="PolySharp" Version="1.15.0" />
<GlobalPackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
<GlobalPackageReference Include="Speckle.InterfaceGenerator" Version="0.9.6" />
</ItemGroup>
</Project>
+17
View File
@@ -0,0 +1,17 @@
If it's your first time here - or you forgot about them - make sure you read the [contribution guidelines](CONTRIBUTING.md), and then feel free to delete this line!
### Expected vs. Actual Behavior
Describe the problem here.
### Reproduction Steps & System Config (win, osx, web, etc.)
Let us know how we can reproduce this, and attach relevant files (if any).
### Proposed Solution (if any)
Let us know what how you would solve this.
#### Optional: Affected Projects
Does this issue propagate to other dependencies or dependents? If so, list them here!
+201
View File
@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2020 AEC Systems
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+88 -2
View File
@@ -1,2 +1,88 @@
# speckle-sharp-sdk
The speckle core
![Speckle Box](/logo.png)
Speckle | Sharp | SDK
=================================================================================================================================
[![Twitter Follow](https://img.shields.io/twitter/follow/SpeckleSystems?style=social)](https://twitter.com/SpeckleSystems) [![Community forum users](https://img.shields.io/discourse/users?server=https%3A%2F%2Fspeckle.community&style=flat-square&logo=discourse&logoColor=white)](https://speckle.community) [![website](https://img.shields.io/badge/https://-speckle.systems-royalblue?style=flat-square)](https://speckle.systems) [![docs](https://img.shields.io/badge/docs-speckle.guide-orange?style=flat-square&logo=read-the-docs&logoColor=white)](https://speckle.guide/dev/)
> Speckle is the first AEC data hub that connects with your favorite AEC tools. Speckle exists to overcome the challenges of working in a fragmented industry where communication, creative workflows, and the exchange of data are often hindered by siloed software and processes. It is here to make the industry better.
### .NET SDK, Tests, and Objects
[![codecov](https://codecov.io/gh/specklesystems/speckle-sharp-sdk/branch/dev/graph/badge.svg?token=TTM5OGr38m)](https://codecov.io/gh/specklesystems/speckle-sharp-sdk)
<a href="https://www.nuget.org/packages/Speckle.Sdk/"><img alt="NuGet Version" src="https://img.shields.io/nuget/v/Speckle.Sdk?label=Speckle.Sdk"></a>
<a href="https://www.nuget.org/packages/Speckle.Objects/"><img alt="NuGet Version" src="https://img.shields.io/nuget/v/Speckle.Sdk?label=Speckle.Objects"></a>
<a href="https://www.nuget.org/packages/Speckle.Automate.Sdk/"><img alt="NuGet Version" src="https://img.shields.io/nuget/v/Speckle.Sdk?label=Speckle.Automate.Sdk"></a>
> [!WARNING]
> Releases Speckle.Sdk and Speckle.Objects are reliable for production use, but the APIs may not be wholly stable, and there may be breaking changes between releases, with little documentation.
# Repo structure
This repo is the home of our next-generation Speckle .NET SDK. It uses .NET Standard 2.0 and has been tested on Windows and MacOS.
- **SDK**
- [`Speckle.Sdk`](https://github.com/specklesystems/speckle-sharp-sdk/tree/dev/src/Speckle.Sdk): Send/Receive operations, Serialization, API wrappers, and more!.
- [`Speckle.Sdk.Dependencies`](https://github.com/specklesystems/speckle-sharp-sdk/tree/dev/src/Speckle.Sdk.Dependencies): Dependencies and code that shouldn't cause conflicts in Host Apps. This uses [IL Repack](https://github.com/gluck/il-repack) to merge together and interalized only to be used by Speckle.
- [`Speckle.Automate.Sdk`](https://github.com/specklesystems/speckle-sharp-sdk/tree/dev/src/Speckle.Automate.Sdk): .NET SDK for [Speckle Automate](https://www.speckle.systems/product/automate)
- **Speckle Objects**
- [`Speckle.Objects`](https://github.com/specklesystems/speckle-sharp-sdk/tree/dev/src/Speckle.Objects): The Speckle Objects classes used for conversions.
- **Tests**
- [`Tests`](https://github.com/specklesystems/speckle-sharp-sdk/tree/dev/tests): Unit, serialization, integration, and performance tests.
### Other repos
Make sure to also check and ⭐️ these other repositories:
- [`speckle-sharp-connectors`](https://github.com/specklesystems/speckle-sharp-connectors): our csharp repo of next gen connectors.
- [`speckle-server`](https://github.com/specklesystems/speckle-server): the speckle server.
- [`speckle-sketchup`](https://github.com/specklesystems/speckle-blender): Blender connector.
- [`speckle-sketchup`](https://github.com/specklesystems/speckle-sketchup): Sketchup connector.
- [`speckle-powerbi`](https://github.com/specklesystems/speckle-powerbi): PowerBi connector.
- and more [connectors & tooling](https://github.com/specklesystems/)!
## Documentation
Comprehensive developer and user documentation can be found in our:
### 📚 [Speckle Docs website](https://speckle.guide/dev/)
# Developing and Debugging
### Building
Ensure you're using a [8.0.4xx](https://dotnet.microsoft.com/en-us/download/dotnet/8.0) .NET SDK.
After cloning this repository, just restore all the NuGet packages and hit Build!
### Developing
It is highly recommended you use
- Either Jetbrains Rider or Visual Studio 2022
- Ensure your IDE is set to use [the correct .NET SDK version](https://github.com/specklesystems/speckle-sharp-sdk/blob/main/global.json) (newer major versions may work, but may incorrectly run analysers we haven't configured)
- You should install the cshapier plugin ([Rider](https://plugins.jetbrains.com/plugin/18243-csharpier), [VS](https://marketplace.visualstudio.com/items?itemName=csharpier.CSharpier)) and configure it to run on save
Docs are a bit patchy [https://docs.speckle.systems/developers/looking-for-developer-docs](https://docs.speckle.systems/developers/looking-for-developer-docs)
### Tests
There are several test projects. It is a requirement that all tests pass for PRs to be merged.
The Integration test projects require a local server to be running.
You must have docker installed. Then you can run `docker compose up --wait` from the root of the repo to start the required containers.
## Contributing
Before embarking on submitting a patch, please make sure you read:
- [Contribution Guidelines](CONTRIBUTING.md)
- [Code of Conduct](CODE_OF_CONDUCT.md)
# Security and Licensing
### Security
For any security vulnerabilities or concerns, please contact us directly at security[at]speckle.systems.
### License
Unless otherwise described, the code in this repository is licensed under the Apache-2.0 License. Please note that some modules, extensions or code herein might be otherwise licensed. This is indicated either in the root of the containing folder under a different license file, or in the respective file's header. If you have any questions, don't hesitate to get in touch with us via [email](mailto:hello@speckle.systems).
+139
View File
@@ -0,0 +1,139 @@
Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Sdk", "src\Speckle.Sdk\Speckle.Sdk.csproj", "{A413E196-3696-4F48-B635-04B5F76BF9C9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Sdk.Tests.Unit", "tests\Speckle.Sdk.Tests.Unit\Speckle.Sdk.Tests.Unit.csproj", "{99AE2273-12C5-4A9D-9FDD-19F8B394B5E2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Objects", "src\Speckle.Objects\Speckle.Objects.csproj", "{181F50AA-DD2A-4541-98EF-B868E2D06B9A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Objects.Tests.Unit", "tests\Speckle.Objects.Tests.Unit\Speckle.Objects.Tests.Unit.csproj", "{A0338FC0-3011-498F-AD09-01230FABD3ED}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{5CB96C27-FC5B-4A41-86B6-951AF99B8116}"
ProjectSection(SolutionItems) = preProject
src\graphql.config.yml = src\graphql.config.yml
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{35047EE7-AD1D-4741-80A7-8F0E874718E9}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "config", "config", "{DA2AED52-58F9-471E-8AD8-102FD36129E3}"
ProjectSection(SolutionItems) = preProject
.csharpierrc.yaml = .csharpierrc.yaml
.editorconfig = .editorconfig
Directory.Build.props = Directory.Build.props
Directory.Packages.props = Directory.Packages.props
global.json = global.json
README.md = README.md
docker-compose.yml = docker-compose.yml
CodeMetricsConfig.txt = CodeMetricsConfig.txt
Directory.Build.Targets = Directory.Build.Targets
.config\dotnet-tools.json = .config\dotnet-tools.json
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{58D37DA9-F948-48CA-9A73-F5BBBD533DBF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "build", "build\build.csproj", "{9B8DDEB5-37C7-49B5-984D-C65DE5FCB7B7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Sdk.Serialization.Tests", "tests\Speckle.Sdk.Serialization.Tests\Speckle.Sdk.Serialization.Tests.csproj", "{AA1E1E51-49AE-4F71-84B1-938E19695BE0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Sdk.Tests.Integration", "tests\Speckle.Sdk.Tests.Integration\Speckle.Sdk.Tests.Integration.csproj", "{4FB41A6D-D139-4111-8115-E3F9F6BEAF24}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{B623BD21-5CAA-43F9-A539-1835276C220E}"
ProjectSection(SolutionItems) = preProject
.github\workflows\pr.yml = .github\workflows\pr.yml
.github\workflows\release.yml = .github\workflows\release.yml
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Sdk.Tests.Performance", "tests\Speckle.Sdk.Tests.Performance\Speckle.Sdk.Tests.Performance.csproj", "{870E3396-E6F7-43AE-B120-E651FA4F46BD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Sdk.Serialization.Testing", "tests\Speckle.Sdk.Serialization.Testing\Speckle.Sdk.Serialization.Testing.csproj", "{FF922B6D-D416-4348-8CB8-0C8B28691070}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Sdk.Dependencies", "src\Speckle.Sdk.Dependencies\Speckle.Sdk.Dependencies.csproj", "{27584AB4-8ACD-4850-8CC2-7E5BC739FB78}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Sdk.Testing", "tests\Speckle.Sdk.Testing\Speckle.Sdk.Testing.csproj", "{7B617C0D-2354-415C-993C-5071D4113E27}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "performance", "performance", "{FFB07238-87E8-463A-AA39-3B38AAAA94C1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Automate.Sdk", "src\Speckle.Automate.Sdk\Speckle.Automate.Sdk.csproj", "{4EB20EFA-5A38-415E-B3FD-29CA3ACD1EF5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Automate.Sdk.Integration", "tests\Speckle.Automate.Sdk.Integration\Speckle.Automate.Sdk.Integration.csproj", "{B6129DC3-F285-4E5F-85E2-6D2533A4005E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{8781B61F-0308-488A-BEB2-1939E7CEEBE9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8781B61F-0308-488A-BEB2-1939E7CEEBE9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8781B61F-0308-488A-BEB2-1939E7CEEBE9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8781B61F-0308-488A-BEB2-1939E7CEEBE9}.Release|Any CPU.Build.0 = Release|Any CPU
{A413E196-3696-4F48-B635-04B5F76BF9C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A413E196-3696-4F48-B635-04B5F76BF9C9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A413E196-3696-4F48-B635-04B5F76BF9C9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A413E196-3696-4F48-B635-04B5F76BF9C9}.Release|Any CPU.Build.0 = Release|Any CPU
{99AE2273-12C5-4A9D-9FDD-19F8B394B5E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{99AE2273-12C5-4A9D-9FDD-19F8B394B5E2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{99AE2273-12C5-4A9D-9FDD-19F8B394B5E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{99AE2273-12C5-4A9D-9FDD-19F8B394B5E2}.Release|Any CPU.Build.0 = Release|Any CPU
{181F50AA-DD2A-4541-98EF-B868E2D06B9A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{181F50AA-DD2A-4541-98EF-B868E2D06B9A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{181F50AA-DD2A-4541-98EF-B868E2D06B9A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{181F50AA-DD2A-4541-98EF-B868E2D06B9A}.Release|Any CPU.Build.0 = Release|Any CPU
{A0338FC0-3011-498F-AD09-01230FABD3ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A0338FC0-3011-498F-AD09-01230FABD3ED}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A0338FC0-3011-498F-AD09-01230FABD3ED}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A0338FC0-3011-498F-AD09-01230FABD3ED}.Release|Any CPU.Build.0 = Release|Any CPU
{9B8DDEB5-37C7-49B5-984D-C65DE5FCB7B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9B8DDEB5-37C7-49B5-984D-C65DE5FCB7B7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9B8DDEB5-37C7-49B5-984D-C65DE5FCB7B7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9B8DDEB5-37C7-49B5-984D-C65DE5FCB7B7}.Release|Any CPU.Build.0 = Release|Any CPU
{AA1E1E51-49AE-4F71-84B1-938E19695BE0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AA1E1E51-49AE-4F71-84B1-938E19695BE0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AA1E1E51-49AE-4F71-84B1-938E19695BE0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AA1E1E51-49AE-4F71-84B1-938E19695BE0}.Release|Any CPU.Build.0 = Release|Any CPU
{4FB41A6D-D139-4111-8115-E3F9F6BEAF24}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4FB41A6D-D139-4111-8115-E3F9F6BEAF24}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4FB41A6D-D139-4111-8115-E3F9F6BEAF24}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4FB41A6D-D139-4111-8115-E3F9F6BEAF24}.Release|Any CPU.Build.0 = Release|Any CPU
{870E3396-E6F7-43AE-B120-E651FA4F46BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{870E3396-E6F7-43AE-B120-E651FA4F46BD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{870E3396-E6F7-43AE-B120-E651FA4F46BD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{870E3396-E6F7-43AE-B120-E651FA4F46BD}.Release|Any CPU.Build.0 = Release|Any CPU
{FF922B6D-D416-4348-8CB8-0C8B28691070}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FF922B6D-D416-4348-8CB8-0C8B28691070}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FF922B6D-D416-4348-8CB8-0C8B28691070}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FF922B6D-D416-4348-8CB8-0C8B28691070}.Release|Any CPU.Build.0 = Release|Any CPU
{27584AB4-8ACD-4850-8CC2-7E5BC739FB78}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{27584AB4-8ACD-4850-8CC2-7E5BC739FB78}.Debug|Any CPU.Build.0 = Debug|Any CPU
{27584AB4-8ACD-4850-8CC2-7E5BC739FB78}.Release|Any CPU.ActiveCfg = Release|Any CPU
{27584AB4-8ACD-4850-8CC2-7E5BC739FB78}.Release|Any CPU.Build.0 = Release|Any CPU
{7B617C0D-2354-415C-993C-5071D4113E27}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7B617C0D-2354-415C-993C-5071D4113E27}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7B617C0D-2354-415C-993C-5071D4113E27}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7B617C0D-2354-415C-993C-5071D4113E27}.Release|Any CPU.Build.0 = Release|Any CPU
{4EB20EFA-5A38-415E-B3FD-29CA3ACD1EF5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4EB20EFA-5A38-415E-B3FD-29CA3ACD1EF5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4EB20EFA-5A38-415E-B3FD-29CA3ACD1EF5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4EB20EFA-5A38-415E-B3FD-29CA3ACD1EF5}.Release|Any CPU.Build.0 = Release|Any CPU
{B6129DC3-F285-4E5F-85E2-6D2533A4005E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B6129DC3-F285-4E5F-85E2-6D2533A4005E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B6129DC3-F285-4E5F-85E2-6D2533A4005E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B6129DC3-F285-4E5F-85E2-6D2533A4005E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{A413E196-3696-4F48-B635-04B5F76BF9C9} = {5CB96C27-FC5B-4A41-86B6-951AF99B8116}
{181F50AA-DD2A-4541-98EF-B868E2D06B9A} = {5CB96C27-FC5B-4A41-86B6-951AF99B8116}
{99AE2273-12C5-4A9D-9FDD-19F8B394B5E2} = {35047EE7-AD1D-4741-80A7-8F0E874718E9}
{A0338FC0-3011-498F-AD09-01230FABD3ED} = {35047EE7-AD1D-4741-80A7-8F0E874718E9}
{9B8DDEB5-37C7-49B5-984D-C65DE5FCB7B7} = {58D37DA9-F948-48CA-9A73-F5BBBD533DBF}
{AA1E1E51-49AE-4F71-84B1-938E19695BE0} = {35047EE7-AD1D-4741-80A7-8F0E874718E9}
{4FB41A6D-D139-4111-8115-E3F9F6BEAF24} = {35047EE7-AD1D-4741-80A7-8F0E874718E9}
{B623BD21-5CAA-43F9-A539-1835276C220E} = {DA2AED52-58F9-471E-8AD8-102FD36129E3}
{27584AB4-8ACD-4850-8CC2-7E5BC739FB78} = {5CB96C27-FC5B-4A41-86B6-951AF99B8116}
{7B617C0D-2354-415C-993C-5071D4113E27} = {35047EE7-AD1D-4741-80A7-8F0E874718E9}
{FF922B6D-D416-4348-8CB8-0C8B28691070} = {FFB07238-87E8-463A-AA39-3B38AAAA94C1}
{870E3396-E6F7-43AE-B120-E651FA4F46BD} = {FFB07238-87E8-463A-AA39-3B38AAAA94C1}
{4EB20EFA-5A38-415E-B3FD-29CA3ACD1EF5} = {5CB96C27-FC5B-4A41-86B6-951AF99B8116}
{B6129DC3-F285-4E5F-85E2-6D2533A4005E} = {35047EE7-AD1D-4741-80A7-8F0E874718E9}
EndGlobalSection
EndGlobal
+3
View File
@@ -0,0 +1,3 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=QL/@EntryIndexedValue">QL</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=XYZ/@EntryIndexedValue">XYZ</s:String></wpf:ResourceDictionary>
+45
View File
@@ -0,0 +1,45 @@
<Solution>
<Folder Name="/build/">
<Project Path="build/build.csproj" />
</Folder>
<Folder Name="/config/">
<File Path=".config/dotnet-tools.json" />
<File Path=".csharpierrc.yaml" />
<File Path=".editorconfig" />
<File Path="CodeMetricsConfig.txt" />
<File Path="Directory.Build.props" />
<File Path="Directory.Build.Targets" />
<File Path="Directory.Packages.props" />
<File Path="docker-compose.yml" />
<File Path="global.json" />
<File Path="README.md" />
<File Path=".github\copilot-instructions.md" />
<File Path=".github\git-commit-instructions.md" />
</Folder>
<Folder Name="/config/workflows/">
<File Path=".github/workflows/pr.yml" />
<File Path=".github/workflows/release.yml" />
</Folder>
<Folder Name="/performance/">
<Project Path="tests/Speckle.Sdk.Serialization.Testing/Speckle.Sdk.Serialization.Testing.csproj" />
<Project Path="tests/Speckle.Sdk.Tests.Performance/Speckle.Sdk.Tests.Performance.csproj" />
</Folder>
<Folder Name="/src/">
<Project Path="src/Speckle.Automate.Sdk/Speckle.Automate.Sdk.csproj" />
<Project Path="src/Speckle.Objects/Speckle.Objects.csproj" />
<Project Path="src/Speckle.Sdk.Dependencies/Speckle.Sdk.Dependencies.csproj" />
<Project Path="src/Speckle.Sdk/Speckle.Sdk.csproj" />
</Folder>
<Folder Name="/tests/">
<Project Path="tests/Speckle.Sdk.Testing/Speckle.Sdk.Testing.csproj" />
</Folder>
<Folder Name="/tests/integration/">
<Project Path="tests/Speckle.Automate.Sdk.Integration/Speckle.Automate.Sdk.Integration.csproj" />
<Project Path="tests/Speckle.Sdk.Tests.Integration/Speckle.Sdk.Tests.Integration.csproj" />
</Folder>
<Folder Name="/tests/unit/">
<Project Path="tests/Speckle.Objects.Tests.Unit/Speckle.Objects.Tests.Unit.csproj" />
<Project Path="tests/Speckle.Sdk.Serialization.Tests/Speckle.Sdk.Serialization.Tests.csproj" />
<Project Path="tests/Speckle.Sdk.Tests.Unit/Speckle.Sdk.Tests.Unit.csproj" />
</Folder>
</Solution>
+3
View File
@@ -0,0 +1,3 @@
$ErrorActionPreference = "Stop";
dotnet run --project build/build.csproj -- $args
Executable
+4
View File
@@ -0,0 +1,4 @@
#!/usr/bin/env bash
set -euo pipefail
dotnet run --project build/build.csproj -- "$@"
+185
View File
@@ -0,0 +1,185 @@
using GlobExpressions;
using static Bullseye.Targets;
using static SimpleExec.Command;
const string CLEAN = "clean";
const string FORMAT = "format";
const string RESTORE_TOOLS = "restore-tools";
const string RESTORE = "restore";
const string BUILD = "build";
const string TEST = "test";
const string INTEGRATION = "integration";
const string PACK = "pack";
const string CLEAN_LOCKS = "clean-locks";
const string PERF = "perf";
const string DEEP_CLEAN = "deep-clean";
static (string semver, string fileVerison) GetVersions()
{
string semver =
Environment.GetEnvironmentVariable("SEMVER") ?? throw new ArgumentException("Expected SEMVER env var");
string fileVersion =
Environment.GetEnvironmentVariable("FILE_VERSION") ?? throw new ArgumentException("Expected FILE_VERSION env var");
return (semver, fileVersion);
}
Target(
CLEAN_LOCKS,
() =>
{
foreach (var f in Glob.Files(".", "**/*.lock.json"))
{
Console.WriteLine("Found and will delete: " + f);
File.Delete(f);
}
Console.WriteLine("Running restore now.");
Run("dotnet", "restore .\\Speckle.Sdk.sln");
}
);
Target(
CLEAN,
forEach: ["**/output"],
dir =>
{
IEnumerable<string> GetDirectories(string d)
{
return Glob.Directories(".", d);
}
void RemoveDirectory(string d)
{
if (Directory.Exists(d))
{
Console.WriteLine(d);
Directory.Delete(d, true);
}
}
foreach (var d in GetDirectories(dir))
{
RemoveDirectory(d);
}
}
);
Target(RESTORE_TOOLS, () => RunAsync("dotnet", "tool restore"));
Target(FORMAT, dependsOn: [RESTORE_TOOLS], () => RunAsync("dotnet", "csharpier check ."));
Target(RESTORE, dependsOn: [FORMAT], () => RunAsync("dotnet", "restore Speckle.Sdk.sln --locked-mode"));
Target(
BUILD,
dependsOn: [RESTORE],
async () =>
{
var (version, fileVersion) = GetVersions();
Console.WriteLine($"Version: {version} & {fileVersion}");
await RunAsync(
"dotnet",
$"build Speckle.Sdk.sln -c Release --no-restore -warnaserror -p:Version={version} -p:FileVersion={fileVersion}"
)
.ConfigureAwait(false);
}
);
Target(
TEST,
dependsOn: [BUILD],
Glob.Files(".", "**/*.Tests.Unit.csproj").Concat(Glob.Files(".", "**/*.Tests.csproj")),
async file =>
{
await RunAsync(
"dotnet",
$"test {file} -c Release --no-build --no-restore --verbosity=normal /p:AltCover=true /p:AltCoverAttributeFilter=ExcludeFromCodeCoverage /p:AltCoverVerbosity=Warning"
)
.ConfigureAwait(false);
}
);
Target(
INTEGRATION,
dependsOn: [BUILD],
async () =>
{
await RunAsync("docker", "compose -f docker-compose.yml up --wait").ConfigureAwait(false);
foreach (var test in Glob.Files(".", "**/*.Tests.Integration.csproj"))
{
await RunAsync(
"dotnet",
$"test {test} -c Release --no-build --no-restore --verbosity=normal /p:AltCover=true /p:AltCoverAttributeFilter=ExcludeFromCodeCoverage"
)
.ConfigureAwait(false);
}
await RunAsync("docker", "compose down").ConfigureAwait(false);
}
);
Target(
PERF,
Glob.Files(".", "**/*.Tests.Performance.csproj"),
async file =>
{
void CheckBuildDirectory(string dir, string build)
{
var binDir = Path.Combine(dir, "bin", build);
Console.WriteLine($"Checking: {binDir}");
if (Directory.Exists(binDir))
{
Directory.Delete(binDir, true);
Console.WriteLine($"Deleted: {binDir}");
}
}
var dir = Path.GetDirectoryName(file) ?? throw new InvalidOperationException();
CheckBuildDirectory(dir, "Release");
CheckBuildDirectory(dir, "Debug");
await RunAsync("dotnet", $"run --project {file} -c Release").ConfigureAwait(false);
}
);
Target(
DEEP_CLEAN,
() =>
{
foreach (var f in Glob.Directories(".", "**/bin"))
{
if (f.StartsWith("build"))
{
continue;
}
Console.WriteLine("Found and will delete: " + f);
Directory.Delete(f, true);
}
foreach (var f in Glob.Directories(".", "**/obj"))
{
if (f.StartsWith("Build"))
{
continue;
}
Console.WriteLine("Found and will delete: " + f);
Directory.Delete(f, true);
}
Console.WriteLine("Running restore now.");
Run("dotnet", "restore .\\Speckle.Sdk.sln --no-cache");
}
);
Target(
PACK,
dependsOn: [TEST],
async () =>
{
{
var (version, fileVersion) = GetVersions();
Console.WriteLine($"Version: {version} & {fileVersion}");
await RunAsync("dotnet", $"pack Speckle.Sdk.sln -c Release -o output --no-build -p:Version={version}")
.ConfigureAwait(false);
}
}
);
Target("default", dependsOn: [FORMAT, TEST, INTEGRATION], () => Console.WriteLine("Done!"));
await RunTargetsAndExitAsync(args).ConfigureAwait(true);
+11
View File
@@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Bullseye" />
<PackageReference Include="Glob" />
<PackageReference Include="SimpleExec" />
</ItemGroup>
</Project>
+57
View File
@@ -0,0 +1,57 @@
{
"version": 2,
"dependencies": {
"net8.0": {
"Bullseye": {
"type": "Direct",
"requested": "[6.0.0, )",
"resolved": "6.0.0",
"contentHash": "vgwwXfzs7jJrskWH7saHRMgPzziq/e86QZNWY1MnMxd7e+De7E7EX4K3C7yrvaK9y02SJoLxNxcLG/q5qUAghw=="
},
"Glob": {
"type": "Direct",
"requested": "[1.1.9, )",
"resolved": "1.1.9",
"contentHash": "AfK5+ECWYTP7G3AAdnU8IfVj+QpGjrh9GC2mpdcJzCvtQ4pnerAGwHsxJ9D4/RnhDUz2DSzd951O/lQjQby2Sw=="
},
"Microsoft.SourceLink.GitHub": {
"type": "Direct",
"requested": "[8.0.0, )",
"resolved": "8.0.0",
"contentHash": "G5q7OqtwIyGTkeIOAc3u2ZuV/kicQaec5EaRnc0pIeSnh9LUjj+PYQrJYBURvDt7twGl2PKA7nSN0kz1Zw5bnQ==",
"dependencies": {
"Microsoft.Build.Tasks.Git": "8.0.0",
"Microsoft.SourceLink.Common": "8.0.0"
}
},
"PolySharp": {
"type": "Direct",
"requested": "[1.15.0, )",
"resolved": "1.15.0",
"contentHash": "FbU0El+EEjdpuIX4iDbeS7ki1uzpJPx8vbqOzEtqnl1GZeAGJfq+jCbxeJL2y0EPnUNk8dRnnqR2xnYXg9Tf+g=="
},
"SimpleExec": {
"type": "Direct",
"requested": "[12.0.0, )",
"resolved": "12.0.0",
"contentHash": "ptxlWtxC8vM6Y6e3h9ZTxBBkOWnWrm/Sa1HT+2i1xcXY3Hx2hmKDZP5RShPf8Xr9D+ivlrXNy57ktzyH8kyt+Q=="
},
"Speckle.InterfaceGenerator": {
"type": "Direct",
"requested": "[0.9.6, )",
"resolved": "0.9.6",
"contentHash": "HKH7tYrYYlCK1ct483hgxERAdVdMtl7gUKW9ijWXxA1UsYR4Z+TrRHYmzZ9qmpu1NnTycSrp005NYM78GDKV1w=="
},
"Microsoft.Build.Tasks.Git": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ=="
},
"Microsoft.SourceLink.Common": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
}
}
}
}
+13
View File
@@ -0,0 +1,13 @@
coverage:
status:
project:
default:
informational: true
target: auto
threshold: 1%
base: auto
patch:
default:
informational: true
github_checks:
annotations: false
+120
View File
@@ -0,0 +1,120 @@
name: "speckle-server"
services:
####
# Speckle Server dependencies
#######
postgres:
image: "postgres:16.4-alpine3.20@sha256:d898b0b78a2627cb4ee63464a14efc9d296884f1b28c841b0ab7d7c42f1fffdf"
restart: always
environment:
POSTGRES_DB: speckle
POSTGRES_USER: speckle
POSTGRES_PASSWORD: speckle
volumes:
- postgres-data:/var/lib/postgresql/data/
healthcheck:
# the -U user has to match the POSTGRES_USER value
test: ["CMD-SHELL", "pg_isready -U speckle"]
interval: 5s
timeout: 5s
retries: 30
redis:
image: "valkey/valkey:8.1-alpine@sha256:0d27f0bca0249f61d060029a6aaf2e16b2c417d68d02a508e1dfb763fa2948b4"
restart: always
volumes:
- redis-data:/data
healthcheck:
test: ["CMD", "redis-cli", "--raw", "incr", "ping"]
interval: 5s
timeout: 5s
retries: 30
minio:
image: "minio/minio:RELEASE.2023-10-25T06-33-25Z"
command: server /data --console-address ":9001"
restart: always
volumes:
- minio-data:/data
ports:
- '127.0.0.1:9000:9000'
- '127.0.0.1:9001:9001'
healthcheck:
test:
[
"CMD-SHELL",
"curl -s -o /dev/null http://127.0.0.1:9000/minio/index.html",
]
interval: 5s
timeout: 30s
retries: 30
start_period: 10s
speckle-server:
image: speckle/speckle-server:latest
restart: always
healthcheck:
test:
- CMD
- /nodejs/bin/node
- -e
- "try { require('node:http').request({headers: {'Content-Type': 'application/json'}, port:3000, hostname:'127.0.0.1', path:'/readiness', method: 'GET', timeout: 2000 }, (res) => { body = ''; res.on('data', (chunk) => {body += chunk;}); res.on('end', () => {process.exit(Number(res.statusCode != 200 || body.toLowerCase().includes('error')));}); }).end(); } catch { process.exit(1); }"
interval: 10s
timeout: 10s
retries: 3
start_period: 90s
ports:
- "0.0.0.0:3000:3000"
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
minio:
condition: service_healthy
environment:
# TODO: Change this to the URL of the speckle server, as accessed from the network
CANONICAL_URL: "http://127.0.0.1:8080"
SPECKLE_AUTOMATE_URL: "http://127.0.0.1:3030"
FRONTEND_ORIGIN: "http://127.0.0.1:8081"
# TODO: Change thvolumes:
REDIS_URL: "redis://redis"
S3_ENDPOINT: "http://minio:9000"
S3_PUBLIC_ENDPOINT: 'http://127.0.0.1:9000'
S3_ACCESS_KEY: "minioadmin"
S3_SECRET_KEY: "minioadmin"
S3_BUCKET: "speckle-server"
S3_CREATE_BUCKET: "true"
FILE_SIZE_LIMIT_MB: 100
MAX_PROJECT_MODELS_PER_PAGE: 500
# TODO: Change this to a unique secret for this server
SESSION_SECRET: "TODO:ReplaceWithLongString"
STRATEGY_LOCAL: "true"
DEBUG: "speckle:*"
POSTGRES_URL: "postgres"
POSTGRES_USER: "speckle"
POSTGRES_PASSWORD: "speckle"
POSTGRES_DB: "speckle"
ENABLE_MP: "false"
LOG_PRETTY: "true"
FF_NEXT_GEN_FILE_IMPORTER_ENABLED: "true"
FF_LARGE_FILE_IMPORTS_ENABLED: "true"
networks:
default:
name: speckle-server
volumes:
postgres-data:
redis-data:
minio-data:
+6
View File
@@ -0,0 +1,6 @@
{
"sdk": {
"version": "8.0.400",
"rollForward": "latestMinor"
}
}
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

+356
View File
@@ -0,0 +1,356 @@
## Storage Size
1 million objects => 540mb ( based on ~= 4.2 million objects => 2.3GB not gzipped)
1 million objects => 127mb gzipped
4x reduction in space
## Local storage takeaways:
SQLite optimisations make a difference in insertion speed. Insertion speed does slow down on large tables (+1m rows).
Partioned tables (by, for example, the first two decimals of the hash) have slower but predictable insertion speed. Not sure if compromise is worth it?
## Even More Optimised single object table
Optimisations are:
- `PRAGMA journal_mode = MEMORY;`
- `PRAGMA synchronous = OFF;`
- `PRAGMA count_changes=OFF;`
- `PRAGMA temp_store=MEMORY;`
### Test 1
-------------------------------------------------
BufferedWriteTest: Wrote 100000 in 2286 ms -> 50000 objects per second
-------------------------------------------------
-------------------------------------------------
BulkWriteMany: Wrote 100000 in 1426 ms -> 100000 objects per second
-------------------------------------------------
### Test 2
-------------------------------------------------
BufferedWriteTest: Wrote 100000 in 3052 ms -> 33333.333333333336 objects per second
-------------------------------------------------
-------------------------------------------------
BulkWriteMany: Wrote 100000 in 2244 ms -> 50000 objects per second
-------------------------------------------------
### Test 3
-------------------------------------------------
BufferedWriteTest: Wrote 100000 in 4941 ms -> 25000 objects per second
-------------------------------------------------
-------------------------------------------------
BulkWriteMany: Wrote 100000 in 2555 ms -> 50000 objects per second
-------------------------------------------------
### Test 4
-------------------------------------------------
BufferedWriteTest: Wrote 100000 in 8022 ms -> 12500 objects per second
-------------------------------------------------
-------------------------------------------------
BulkWriteMany: Wrote 100000 in 3350 ms -> 33333.333333333336 objects per second
-------------------------------------------------
### Test 5
-------------------------------------------------
BufferedWriteTest: Wrote 100000 in 6602 ms -> 16666.666666666668 objects per second
-------------------------------------------------
-------------------------------------------------
BulkWriteMany: Wrote 100000 in 3445 ms -> 33333.333333333336 objects per second
-------------------------------------------------
### Test 5+: A couple of more rounds, pushing objs to 2.000k
-------------------------------------------------
BufferedWriteTest: Wrote 100000 in 7332 ms -> 14285.714285714286 objects per second
-------------------------------------------------
-------------------------------------------------
BulkWriteMany: Wrote 100000 in 7625 ms -> 14285.714285714286 objects per second
-------------------------------------------------
-------------------------------------------------
-------------------------------------------------
BufferedWriteTest: Wrote 100000 in 7539 ms -> 14285.714285714286 objects per second
-------------------------------------------------
-------------------------------------------------
BulkWriteMany: Wrote 100000 in 4249 ms -> 25000 objects per second
-------------------------------------------------
-------------------------------------------------
-------------------------------------------------
BufferedWriteTest: Wrote 100000 in 8300 ms -> 12500 objects per second
-------------------------------------------------
-------------------------------------------------
BulkWriteMany: Wrote 100000 in 7289 ms -> 14285.714285714286 objects per second
-------------------------------------------------
-------------------------------------------------
-------------------------------------------------
BufferedWriteTest: Wrote 100000 in 8668 ms -> 12500 objects per second
-------------------------------------------------
-------------------------------------------------
BulkWriteMany: Wrote 100000 in 8060 ms -> 12500 objects per second
-------------------------------------------------
Starting to save 100000 of objects
-------------------------------------------------
BufferedWriteTest: Wrote 100000 in 10228 ms -> 10000 objects per second
-------------------------------------------------
-------------------------------------------------
BulkWriteMany: Wrote 100000 in 11475 ms -> 9090.90909090909 objects per second
-------------------------------------------------
-------------------------------------------------
Starting to save 100000 of objects
-------------------------------------------------
BufferedWriteTest: Wrote 100000 in 12540 ms -> 8333.333333333334 objects per second
-------------------------------------------------
-------------------------------------------------
BulkWriteMany: Wrote 100000 in 7113 ms -> 14285.714285714286 objects per second
-------------------------------------------------
-------------------------------------------------
Starting to save 100000 of objects
-------------------------------------------------
BufferedWriteTest: Wrote 100000 in 17153 ms -> 5882.35294117647 objects per second
-------------------------------------------------
-------------------------------------------------
BulkWriteMany: Wrote 100000 in 5997 ms -> 20000 objects per second
-------------------------------------------------
-------------------------------------------------
Starting to save 100000 of objects
-------------------------------------------------
BufferedWriteTest: Wrote 100000 in 20841 ms -> 5000 objects per second
-------------------------------------------------
-------------------------------------------------
BulkWriteMany: Wrote 100000 in 9195 ms -> 11111.111111111111 objects per second
-------------------------------------------------
Starting to save 100000 of objects
-------------------------------------------------
BufferedWriteTest: Wrote 100000 in 13404 ms -> 7692.307692307692 objects per second
-------------------------------------------------
-------------------------------------------------
BulkWriteMany: Wrote 100000 in 7529 ms -> 14285.714285714286 objects per second
-------------------------------------------------
-------------------------------------------------
Starting to save 100000 of objects
-------------------------------------------------
BufferedWriteTest: Wrote 100000 in 19806 ms -> 5263.1578947368425 objects per second
-------------------------------------------------
-------------------------------------------------
BulkWriteMany: Wrote 100000 in 7318 ms -> 14285.714285714286 objects per second
-------------------------------------------------
-------------------------------------------------
Starting to save 100000 of objects
-------------------------------------------------
BufferedWriteTest: Wrote 100000 in 24612 ms -> 4166.666666666667 objects per second
-------------------------------------------------
-------------------------------------------------
BulkWriteMany: Wrote 100000 in 7410 ms -> 14285.714285714286 objects per second
-------------------------------------------------
-------------------------------------------------
Starting to save 100000 of objects
-------------------------------------------------
BufferedWriteTest: Wrote 100000 in 22257 ms -> 4545.454545454545 objects per second
-------------------------------------------------
-------------------------------------------------
BulkWriteMany: Wrote 100000 in 18699 ms -> 5555.555555555556 objects per second
-------------------------------------------------
-------------------------------------------------
Starting to save 100000 of objects
-------------------------------------------------
BufferedWriteTest: Wrote 100000 in 20947 ms -> 5000 objects per second
-------------------------------------------------
-------------------------------------------------
BulkWriteMany: Wrote 100000 in 14089 ms -> 7142.857142857143 objects per second
-------------------------------------------------
## Optimised single object table
Optimisations are: `PRAGMA journal_mode = MEMORY;` and `PRAGMA synchronous = OFF;`
### Test 1:
-------------------------------------------------
BufferedWriteTest: Wrote 100000 in 2267 ms -> 50000 objects per second
-------------------------------------------------
-------------------------------------------------
BulkWriteMany: Wrote 100000 in 1327 ms -> 100000 objects per second
-------------------------------------------------
### Test 2:
-------------------------------------------------
BufferedWriteTest: Wrote 100000 in 4532 ms -> 25000 objects per second
-------------------------------------------------
-------------------------------------------------
BulkWriteMany: Wrote 100000 in 2243 ms -> 50000 objects per second
-------------------------------------------------
### Test 3:
-------------------------------------------------
BufferedWriteTest: Wrote 100000 in 3768 ms -> 33333.333333333336 objects per second
-------------------------------------------------
-------------------------------------------------
BulkWriteMany: Wrote 100000 in 5295 ms -> 20000 objects per second
-------------------------------------------------
### Test 4:
-------------------------------------------------
BufferedWriteTest: Wrote 100000 in 4033 ms -> 25000 objects per second
-------------------------------------------------
-------------------------------------------------
BulkWriteMany: Wrote 100000 in 3126 ms -> 33333.333333333336 objects per second
-------------------------------------------------
### Test 5:
-------------------------------------------------
BufferedWriteTest: Wrote 100000 in 4432 ms -> 25000 objects per second
-------------------------------------------------
-------------------------------------------------
BulkWriteMany: Wrote 100000 in 3527 ms -> 33333.333333333336 objects per second
-------------------------------------------------
## Single object table
### Test 1:
-------------------------------------------------
BufferedWriteTest: Wrote 100000 in 11964 ms -> 9090.90909090909 objects per second
-------------------------------------------------
-------------------------------------------------
BulkWriteMany: Wrote 100000 in 6875 ms -> 16666.666666666668 objects per second
-------------------------------------------------
200k total in db
### Test 2:
-------------------------------------------------
BufferedWriteTest: Wrote 100000 in 21956 ms -> 4761.9047619047615 objects per second
-------------------------------------------------
-------------------------------------------------
BulkWriteMany: Wrote 100000 in 8904 ms -> 12500 objects per second
-------------------------------------------------
400k total in db
### Test 3:
-------------------------------------------------
BufferedWriteTest: Wrote 100000 in 25532 ms -> 4000 objects per second
-------------------------------------------------
-------------------------------------------------
BulkWriteMany: Wrote 100000 in 10124 ms -> 10000 objects per second
-------------------------------------------------
600k total in db
### Test 4:
-------------------------------------------------
BufferedWriteTest: Wrote 100000 in 26629 ms -> 3846.153846153846 objects per second
-------------------------------------------------
-------------------------------------------------
BulkWriteMany: Wrote 100000 in 10610 ms -> 10000 objects per second
-------------------------------------------------
800k total in db
### Test 5:
-------------------------------------------------
BufferedWriteTest: Wrote 100000 in 26956 ms -> 3846.153846153846 objects per second
-------------------------------------------------
-------------------------------------------------
BulkWriteMany: Wrote 100000 in 11007 ms -> 9090.90909090909 objects per second
-------------------------------------------------
1000k total in db
## Bucketed Object Table (256 individual tables for objects):
Pre-generate 256 tables, of form `objs${prefix}`, where prefix is the cartesian product of all the valid hex decimals (`0-9, a-f`).
### Test 1:
Forgot to copy paste.
200k total in db
### Test 2:
-------------------------------------------------
BufferedWriteTest: Wrote 100000 in 19096 ms -> 5263.1578947368425 objects per second
-------------------------------------------------
-------------------------------------------------
BulkWriteMany: Wrote 100000 in 7401 ms -> 14285.714285714286 objects per second
-------------------------------------------------
400k total in db
### Test 3:
-------------------------------------------------
BufferedWriteTest: Wrote 100000 in 22477 ms -> 4545.454545454545 objects per second
-------------------------------------------------
-------------------------------------------------
BulkWriteMany: Wrote 100000 in 8668 ms -> 12500 objects per second
-------------------------------------------------
600k total in db
### Test 4:
-------------------------------------------------
BufferedWriteTest: Wrote 100000 in 23438 ms -> 4347.826086956522 objects per second
-------------------------------------------------
-------------------------------------------------
BulkWriteMany: Wrote 100000 in 9288 ms -> 11111.111111111111 objects per second
-------------------------------------------------
800k total in db
### Test 5:
-------------------------------------------------
BufferedWriteTest: Wrote 100000 in 23735 ms -> 4347.826086956522 objects per second
-------------------------------------------------
-------------------------------------------------
BulkWriteMany: Wrote 100000 in 9944 ms -> 11111.111111111111 objects per second
-------------------------------------------------
1mil total in db
@@ -0,0 +1,61 @@
using System.Diagnostics;
using System.Text.Json;
using GraphQL;
using GraphQL.Client.Http;
using Speckle.Automate.Sdk.Schema;
using Speckle.InterfaceGenerator;
using Speckle.Sdk.Api;
using Speckle.Sdk.Credentials;
namespace Speckle.Automate.Sdk;
[GenerateAutoInterface(VisibilityModifier = "public")]
internal sealed class AutomationContextFactory(
IClientFactory clientFactory,
IAccountFactory accountFactory,
IOperations operations
) : IAutomationContextFactory
{
private static readonly JsonSerializerOptions s_jsonSerializerSettings = new()
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
};
/// <inheritdoc cref="Initialize(AutomationRunData, string)"/>
public async Task<IAutomationContext> Initialize(string automationRunData, string speckleToken)
{
var runData = JsonSerializer.Deserialize<AutomationRunData>(automationRunData, s_jsonSerializerSettings);
return await Initialize(runData, speckleToken).ConfigureAwait(false);
}
/// <inheritdoc cref="Initialize(AutomationRunData, Account)"/>
/// <exception cref="GraphQLHttpRequestException">Request failed on the HTTP layer (received a non-successful response code)</exception>
/// <exception cref="AggregateException"><inheritdoc cref="Speckle.Sdk.Api.GraphQL.GraphQLErrorHandler.EnsureGraphQLSuccess(IGraphQLResponse)"/></exception>
public async Task<IAutomationContext> Initialize(AutomationRunData automationRunData, string speckleToken)
{
Account account = await accountFactory
.CreateAccount(automationRunData.SpeckleServerUrl, speckleToken)
.ConfigureAwait(false);
return Initialize(automationRunData, account);
}
/// <summary>
/// Creates an <see cref="AutomationContext"/> from the provided data
/// </summary>
public IAutomationContext Initialize(AutomationRunData automationRunData, Account account)
{
IClient client = clientFactory.Create(account);
Stopwatch initTime = Stopwatch.StartNew();
return new AutomationContext(operations)
{
AutomationRunData = automationRunData,
SpeckleClient = client,
_speckleToken = account.token,
_initTime = initTime,
AutomationResult = new AutomationResult(),
};
}
}
@@ -0,0 +1,375 @@
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using GraphQL;
using Speckle.Automate.Sdk.Schema;
using Speckle.Automate.Sdk.Schema.Triggers;
using Speckle.InterfaceGenerator;
using Speckle.Newtonsoft.Json;
using Speckle.Sdk;
using Speckle.Sdk.Api;
using Speckle.Sdk.Api.GraphQL.Inputs;
using Speckle.Sdk.Api.GraphQL.Models;
using Speckle.Sdk.Common;
using Speckle.Sdk.Models;
using Version = Speckle.Sdk.Api.GraphQL.Models.Version;
namespace Speckle.Automate.Sdk;
[GenerateAutoInterface(VisibilityModifier = "public")]
internal sealed class AutomationContext(IOperations operations) : IAutomationContext
{
public AutomationRunData AutomationRunData { get; set; }
public string? ContextView
{
get => AutomationResult.ResultView;
private set => AutomationResult.ResultView = value;
}
public required IClient SpeckleClient { get; init; }
public required string _speckleToken { get; init; }
// added for performance measuring
public required Stopwatch _initTime { get; init; }
public required AutomationResult AutomationResult { get; init; }
public string RunStatus => AutomationResult.RunStatus;
public string? StatusMessage => AutomationResult.StatusMessage;
public TimeSpan Elapsed => _initTime.Elapsed;
/// <summary>
/// Receive version for automation.
/// </summary>
/// <returns> Commit object. </returns>
/// <exception cref="SpeckleException">Throws if commit object is null.</exception>
public async Task<Base> ReceiveVersion(CancellationToken cancellationToken = default)
{
// TODO: this is a quick hack to keep implementation consistency. Move to proper receive many versions
if (AutomationRunData.Triggers.First() is not VersionCreationTrigger trigger)
{
throw new SpeckleException("Processed automation run data without any triggers");
}
var versionId = trigger.Payload.VersionId;
var version = await SpeckleClient
.Version.Get(versionId, AutomationRunData.ProjectId, cancellationToken)
.ConfigureAwait(false);
if (version.referencedObject == null)
{
throw new SpeckleException(
"The requested speckle model version has exceeded workspace version history limits or the reference object is otherwise null"
);
}
Base? rootObject = await operations
.Receive2(
SpeckleClient.ServerUrl,
AutomationRunData.ProjectId,
version.referencedObject,
SpeckleClient.Account.token,
null,
cancellationToken
)
.ConfigureAwait(false);
Console.WriteLine($"It took {Elapsed.TotalSeconds} seconds to receive the speckle version {versionId}");
return rootObject;
}
/// <summary>
/// Creates new version in the project.
/// </summary>
/// <param name="rootObject">Object to send to project.</param>
/// <param name="model">The model to create the version under</param>
/// <param name="versionMessage">Version message.</param>
/// <param name="cancellationToken">Version message.</param>
/// <returns>Version id.</returns>
/// <exception cref="SpeckleException"> Throws if given model name is as same as with model name in automation run data.
/// The reason is to prevent circular run loop in automation.</exception>
public async Task<Version> CreateNewVersionInProject(
Base rootObject,
Model model,
string versionMessage = "",
CancellationToken cancellationToken = default
)
{
// Confirm target branch is not the same as source branch
foreach (var trigger in AutomationRunData.Triggers)
{
if (trigger.Payload.ModelId == model.id)
{
throw new SpeckleException(
$"""
The target model: {model.name} ({model.id}) cannot match the model
that triggered this automation:
{trigger.Payload.ModelId}
"""
);
}
}
var (rootObjectId, _) = await operations
.Send2(
SpeckleClient.ServerUrl,
AutomationRunData.ProjectId,
SpeckleClient.Account.token,
rootObject,
null,
cancellationToken
)
.ConfigureAwait(false);
var newVersion = await SpeckleClient
.Version.Create(
new CreateVersionInput(rootObjectId, model.id, AutomationRunData.ProjectId, versionMessage),
cancellationToken
)
.ConfigureAwait(false);
AutomationResult.ResultVersions.Add(newVersion.id);
return newVersion;
}
/// <summary>
/// Set context view for automation result view.
/// </summary>
/// <param name="resourceIds"> Resource contexts to bind into view.</param>
/// <param name="includeSourceModelVersion"> Whether bind source version into result view or not.</param>
/// <exception cref="SpeckleException"> Throws if there is no context to create result view.</exception>
[MemberNotNull(nameof(ContextView))]
[AutoInterfaceIgnore] //Ignore so we can explicitly add the MemberNotNull attibute to the interface method
public void SetContextView(IReadOnlyCollection<string>? resourceIds = null, bool includeSourceModelVersion = true)
{
List<string> linkResources = new();
if (includeSourceModelVersion)
{
foreach (var trigger in AutomationRunData.Triggers)
{
switch (trigger)
{
case VersionCreationTrigger versionCreationTrigger:
{
linkResources.Add($"{versionCreationTrigger.Payload.ModelId}@{versionCreationTrigger.Payload.VersionId}");
break;
}
default:
{
throw new SpeckleException($"Could not link resource specified by {trigger.TriggerType} trigger");
}
}
}
}
if (resourceIds is not null)
{
linkResources.AddRange(resourceIds);
}
if (linkResources.Count == 0)
{
throw new SpeckleException("We do not have enough resource ids to compose a context view");
}
ContextView = $"/projects/{AutomationRunData.ProjectId}/models/{string.Join(",", linkResources)}";
}
public async Task ReportRunStatus()
{
ObjectResults? objectResults = null;
if (RunStatus is "SUCCEEDED" or "FAILED")
{
objectResults = new ObjectResults
{
Version = 2,
Values = new ObjectResultValues
{
BlobIds = AutomationResult.Blobs,
ObjectResults = AutomationResult.ObjectResults,
},
};
}
//language=graphql
const string QUERY = """
mutation AutomateFunctionRunStatusReport($projectId: String!, $functionRunId: String!, $status: AutomateRunStatus!, $statusMessage: String, $results: JSONObject, $contextView: String) {
automateFunctionRunStatusReport(
input: {projectId: $projectId, functionRunId: $functionRunId, status: $status, statusMessage: $statusMessage, contextView: $contextView, results: $results}
)
}
""";
GraphQLRequest request = new()
{
Query = QUERY,
Variables = new
{
projectId = AutomationRunData.ProjectId,
functionRunId = AutomationRunData.FunctionRunId,
status = RunStatus,
statusMessage = AutomationResult.StatusMessage,
contextView = ContextView,
results = objectResults,
},
};
await SpeckleClient.ExecuteGraphQLRequest<Dictionary<string, object>>(request).ConfigureAwait(false);
}
/// <summary>
/// Stores result file in automation result. It will be available to download on Frontend if added.
/// </summary>
/// <param name="filePath"> File path to store.</param>
/// <exception cref="FileNotFoundException"> Throws if given file path is not exist.</exception>
/// <exception cref="SpeckleException"> Throws if upload requests return no result.</exception>
public async Task StoreFileResult(string filePath)
{
if (!File.Exists(filePath))
{
throw new FileNotFoundException("The given file path doesn't exist", fileName: filePath);
}
using MultipartFormDataContent formData = new();
FileStream fileStream = new(filePath, FileMode.Open, FileAccess.Read);
using StreamContent streamContent = new(fileStream);
formData.Add(streamContent, "files", Path.GetFileName(filePath));
HttpResponseMessage request = await SpeckleClient
.GQLClient.HttpClient.PostAsync(
new Uri(AutomationRunData.SpeckleServerUrl, $"api/stream/{AutomationRunData.ProjectId}/blob"),
formData
)
.ConfigureAwait(false);
request.EnsureSuccessStatusCode();
string responseString = await request.Content.ReadAsStringAsync().ConfigureAwait(false);
Console.WriteLine("RESPONSE - " + responseString);
BlobUploadResponse uploadResponse = JsonConvert.DeserializeObject<BlobUploadResponse>(responseString);
if (uploadResponse.UploadResults.Count != 1)
{
throw new SpeckleException("Expected one upload result.");
}
AutomationResult.Blobs.AddRange(uploadResponse.UploadResults.Select(r => r.BlobId));
}
private void MarkRun(AutomationStatus status, string? statusMessage)
{
double duration = Elapsed.TotalSeconds;
AutomationResult.StatusMessage = statusMessage;
string statusValue = AutomationStatusMapping.Get(status);
AutomationResult.RunStatus = statusValue;
AutomationResult.Elapsed = duration;
string msg = $"Automation run {statusValue} after {duration} seconds.";
if (statusMessage is not null)
{
msg += $"\n{statusMessage}";
}
Console.WriteLine(msg);
}
public void MarkRunFailed(string statusMessage) => MarkRun(AutomationStatus.Failed, statusMessage);
public void MarkRunException(string? statusMessage) => MarkRun(AutomationStatus.Exception, statusMessage);
public void MarkRunSuccess(string? statusMessage) => MarkRun(AutomationStatus.Succeeded, statusMessage);
/// <summary>
/// Add a new error case to the run results.
/// </summary>
/// <param name="category">A short tag for the error type.</param>
/// <param name="affectedObjects">A list of objects that are causing the result.</param>
/// <param name="message">Optional error message.</param>
/// <param name="metadata">User provided metadata key value pairs.</param>
/// <param name="visualOverrides">Case specific 3D visual overrides.</param>
/// <exception cref="ArgumentException">Throws if the provided <paramref name="affectedObjects"/> input is empty.</exception>
public void AttachErrorToObjects(
string category,
IReadOnlyCollection<Base> affectedObjects,
string? message = null,
Dictionary<string, object>? metadata = null,
Dictionary<string, object>? visualOverrides = null
) => AttachResultToObjects(ObjectResultLevel.Error, category, affectedObjects, message, metadata, visualOverrides);
/// <summary>
/// Add a new warning case to the run results.
/// </summary>
/// <inheritdoc cref="AttachErrorToObjects"/>
public void AttachWarningToObjects(
string category,
IReadOnlyCollection<Base> affectedObjects,
string? message = null,
Dictionary<string, object>? metadata = null,
Dictionary<string, object>? visualOverrides = null
) => AttachResultToObjects(ObjectResultLevel.Warning, category, affectedObjects, message, metadata, visualOverrides);
/// <summary>
/// Add a new info case to the run results.
/// </summary>
/// <inheritdoc cref="AttachErrorToObjects"/>
public void AttachInfoToObjects(
string category,
IReadOnlyCollection<Base> affectedObjects,
string? message = null,
Dictionary<string, object>? metadata = null,
Dictionary<string, object>? visualOverrides = null
) => AttachResultToObjects(ObjectResultLevel.Info, category, affectedObjects, message, metadata, visualOverrides);
/// <summary>
/// Add a new success case to the run results.
/// </summary>
/// <inheritdoc cref="AttachErrorToObjects"/>
public void AttachSuccessToObjects(
string category,
IReadOnlyCollection<Base> affectedObjects,
string? message = null,
Dictionary<string, object>? metadata = null,
Dictionary<string, object>? visualOverrides = null
) => AttachResultToObjects(ObjectResultLevel.Success, category, affectedObjects, message, metadata, visualOverrides);
/// <summary>
/// Add a new case to the run results.
/// </summary>
/// <param name="level">The level assigned to this result.</param>
/// <inheritdoc cref="AttachErrorToObjects"/>
public void AttachResultToObjects(
ObjectResultLevel level,
string category,
IReadOnlyCollection<Base> affectedObjects,
string? message = null,
Dictionary<string, object>? metadata = null,
Dictionary<string, object>? visualOverrides = null
)
{
if (affectedObjects.Count == 0)
{
throw new ArgumentException($"Need at least one affected object to report a(n) {level}");
}
string levelString = ObjectResultLevelMapping.Get(level);
Dictionary<string, string?> ids = affectedObjects.ToDictionary(
x => x.id.NotNull($"You can only attach {level} results to objects with an id"),
x => x.applicationId
);
Console.WriteLine($"Created new {levelString.ToUpper()} category: {category} caused by: {message}");
ResultCase resultCase = new()
{
Category = category,
Level = levelString,
ObjectAppIds = ids,
Message = message,
Metadata = metadata,
VisualOverrides = visualOverrides,
};
AutomationResult.ObjectResults.Add(resultCase);
}
}
public partial interface IAutomationContext
{
[MemberNotNull(nameof(ContextView))]
public void SetContextView(IReadOnlyCollection<string>? resourceIds = null, bool includeSourceModelVersion = true);
}
@@ -0,0 +1,7 @@
namespace Speckle.Automate.Sdk.DataAnnotations;
/// <summary>
/// If specified, the given function input will be redacted in all contexts.
/// </summary>
[AttributeUsage(AttributeTargets.All)]
public sealed class SecretAttribute : Attribute { }
+195
View File
@@ -0,0 +1,195 @@
using System.CommandLine;
using System.Diagnostics.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Schema;
using Newtonsoft.Json.Schema.Generation;
using Newtonsoft.Json.Serialization;
using Speckle.Automate.Sdk.DataAnnotations;
using Speckle.Automate.Sdk.Schema;
using Speckle.InterfaceGenerator;
using Speckle.Sdk;
namespace Speckle.Automate.Sdk;
/// <summary>
/// Provides mechanisms to execute any function that conforms to the AutomateFunction "interface"
/// </summary>
[GenerateAutoInterface(VisibilityModifier = "public")]
internal class AutomationRunner(IAutomationContextFactory contextFactory) : IAutomationRunner
{
[SuppressMessage("Design", "CA1031:Do not catch general exception types")]
public async Task<IAutomationContext> RunFunction<TInput>(
Func<IAutomationContext, TInput, Task> automateFunction,
AutomationRunData automationRunData,
string speckleToken,
TInput inputs
)
where TInput : struct
{
var automationContext = await contextFactory.Initialize(automationRunData, speckleToken).ConfigureAwait(false);
try
{
await automateFunction.Invoke(automationContext, inputs).ConfigureAwait(false);
if (automationContext.RunStatus is not ("FAILED" or "SUCCEEDED"))
{
automationContext.MarkRunSuccess(
"WARNING: Automate assumed a success status, but it was not marked as so by the function."
);
}
}
catch (Exception ex) when (!ex.IsFatal())
{
Console.WriteLine(ex.ToString());
automationContext.MarkRunException("Function error. Check the automation run logs for details.");
}
finally
{
if (automationContext.ContextView is null)
{
automationContext.SetContextView();
}
await automationContext.ReportRunStatus().ConfigureAwait(false);
}
return automationContext;
}
public async Task<IAutomationContext> RunFunction(
Func<IAutomationContext, Task> automateFunction,
AutomationRunData automationRunData,
string speckleToken
) =>
await RunFunction(
async (context, _) => await automateFunction(context).ConfigureAwait(false),
automationRunData,
speckleToken,
new Fake()
)
.ConfigureAwait(false);
private struct Fake { }
/// <summary>
/// Main entrypoint to execute an Automate function with no input data
/// </summary>
/// <param name="args">The command line arguments passed into the function by automate</param>
/// <param name="automateFunction">The automate function to execute</param>
/// <remarks>This should always be called in your own functions, as it contains the logic to trigger the function automatically.</remarks>
public async Task<int> Main(string[] args, Func<IAutomationContext, Task> automateFunction)
{
return await Main(
args,
async (IAutomationContext context, Fake _) => await automateFunction(context).ConfigureAwait(false)
)
.ConfigureAwait(false);
}
/// <summary>
/// Main entrypoint to execute an Automate function with input data of type <typeparamref name="TInput"/>.
/// </summary>
/// <param name="args">The command line arguments passed into the function by automate</param>
/// <param name="automateFunction">The automate function to execute</param>
/// <typeparam name="TInput">The provided input data</typeparam>
/// <remarks>This should always be called in your own functions, as it contains the logic to trigger the function automatically.</remarks>
public async Task<int> Main<TInput>(string[] args, Func<IAutomationContext, TInput, Task> automateFunction)
where TInput : struct
{
Argument<string> pathArg = new(name: "Input Path", description: "A file path to retrieve function inputs");
RootCommand rootCommand = new();
// a stupid hack to be able to exit with a specific integer exit code
// read more at https://github.com/dotnet/command-line-api/issues/1570
var exitCode = 0;
rootCommand.AddArgument(pathArg);
rootCommand.SetHandler(
async inputPath =>
{
try
{
FunctionRunData<TInput> data = FunctionRunDataParser.FromPath<TInput>(inputPath);
var context = await RunFunction(
automateFunction,
data.AutomationRunData,
data.SpeckleToken,
data.FunctionInputs
)
.ConfigureAwait(false);
if (context.RunStatus is "EXCEPTION")
{
exitCode = 1;
}
}
catch (Exception)
{
exitCode = 1;
throw;
}
},
pathArg
);
Argument<string> schemaFilePathArg = new(
name: "Function inputs file path",
description: "A token to talk to the Speckle server with"
);
Command generateSchemaCommand = new("generate-schema", "Generate JSON schema for the function inputs");
generateSchemaCommand.AddArgument(schemaFilePathArg);
generateSchemaCommand.SetHandler(
schemaFilePath =>
{
try
{
JSchemaGenerator generator = new() { ContractResolver = new CamelCasePropertyNamesContractResolver() };
generator.GenerationProviders.Add(new SpeckleSecretProvider());
JSchema schema = generator.Generate(typeof(TInput));
schema.ToString(SchemaVersion.Draft2019_09);
File.WriteAllText(schemaFilePath, schema.ToString());
}
catch (Exception)
{
exitCode = 1;
throw;
}
},
schemaFilePathArg
);
rootCommand.Add(generateSchemaCommand);
await rootCommand.InvokeAsync(args).ConfigureAwait(false);
// if we've gotten this far, the execution should technically be completed as expected
// thus exiting with 0 is the semantically correct thing to do
return exitCode;
}
}
internal sealed class SpeckleSecretProvider : JSchemaGenerationProvider
{
public override JSchema? GetSchema(JSchemaTypeGenerationContext context)
{
var attributes = context.MemberProperty?.AttributeProvider?.GetAttributes(false) ?? new List<Attribute>();
var isSecretString = attributes.Any(att => att is SecretAttribute);
if (isSecretString)
{
return CreateSchemaWithWriteOnly(context.ObjectType, context.Required);
}
return null;
}
private static JSchema CreateSchemaWithWriteOnly(Type type, Required required)
{
JSchemaGenerator generator = new();
JSchema schema = generator.Generate(type, required != Required.Always);
schema.WriteOnly = true;
return schema;
}
}
@@ -0,0 +1,12 @@
namespace Speckle.Automate.Sdk.Schema;
public class AutomationResult
{
public double Elapsed { get; set; }
public string? ResultView { get; set; }
public List<string> ResultVersions { get; set; } = new();
public List<string> Blobs { get; set; } = new();
public string RunStatus { get; set; } = AutomationStatusMapping.Get(AutomationStatus.Running);
public string? StatusMessage { get; set; }
public List<ResultCase> ObjectResults { get; set; } = new();
}
@@ -0,0 +1,28 @@
using System.Text.Json.Serialization;
using Speckle.Automate.Sdk.Schema.Triggers;
namespace Speckle.Automate.Sdk.Schema;
///<summary>
/// Values of the project, model and automation that triggered this function run.
///</summary>
public readonly struct AutomationRunData
{
[JsonRequired]
public required string ProjectId { get; init; }
[JsonRequired]
public required Uri SpeckleServerUrl { get; init; }
[JsonRequired]
public required string AutomationId { get; init; }
[JsonRequired]
public required string AutomationRunId { get; init; }
[JsonRequired]
public required string FunctionRunId { get; init; }
[JsonRequired]
public required List<VersionCreationTrigger> Triggers { get; init; }
}
@@ -0,0 +1,13 @@
namespace Speckle.Automate.Sdk.Schema;
///<summary>
/// Set the status of the automation.
///</summary>
public enum AutomationStatus
{
Initializing,
Running,
Failed,
Succeeded,
Exception,
}
@@ -0,0 +1,21 @@
namespace Speckle.Automate.Sdk.Schema;
public abstract class AutomationStatusMapping
{
private const string INITIALIZING = "INITIALIZING";
private const string RUNNING = "RUNNING";
private const string FAILED = "FAILED";
private const string SUCCEEDED = "SUCCEEDED";
private const string EXCEPTION = "EXCEPTION";
public static string Get(AutomationStatus status) =>
status switch
{
AutomationStatus.Running => RUNNING,
AutomationStatus.Failed => FAILED,
AutomationStatus.Succeeded => SUCCEEDED,
AutomationStatus.Initializing => INITIALIZING,
AutomationStatus.Exception => EXCEPTION,
_ => throw new ArgumentOutOfRangeException($"Not valid value for enum {status}"),
};
}
@@ -0,0 +1,6 @@
namespace Speckle.Automate.Sdk.Schema;
public readonly struct BlobUploadResponse
{
public required List<UploadResult> UploadResults { get; init; }
}
@@ -0,0 +1,18 @@
using System.Text.Json.Serialization;
namespace Speckle.Automate.Sdk.Schema;
/// <summary>
/// Required data to run a function.
/// </summary>
/// <typeparam name="T"> Type for <see cref="FunctionInputs"/>.</typeparam>
public sealed class FunctionRunData<T>
{
[JsonRequired]
public required string SpeckleToken { get; init; }
[JsonRequired]
public required AutomationRunData AutomationRunData { get; init; }
public required T? FunctionInputs { get; init; }
}
@@ -0,0 +1,52 @@
using System.Text.Json;
namespace Speckle.Automate.Sdk.Schema;
public static class FunctionRunDataParser
{
private static readonly JsonSerializerOptions s_jsonSerializerSettings = new()
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
};
/// <summary>
/// Function run data parser from json file path./>
/// </summary>
/// <param name="inputLocation"> Path to retrieve function run data.</param>
/// <typeparam name="T"> Type for function inputs.</typeparam>
/// <returns>The data to be able to run function.</returns>
/// <exception cref="JsonException">Json was not valid</exception>
/// <exception cref="FileNotFoundException"> Throws unless file exists.</exception>
public static FunctionRunData<T> FromPath<T>(string inputLocation)
{
string inputJsonString = ReadInputData(inputLocation);
//It's important to use System.Text.Json here. The template FunctionInputs are decorated with STJ attributes
FunctionRunData<T>? functionRunData = JsonSerializer.Deserialize<FunctionRunData<T>>(
inputJsonString,
s_jsonSerializerSettings
);
if (functionRunData is null)
{
throw new JsonException($"Function run data couldn't deserialized at {inputLocation}");
}
return functionRunData;
}
/// <summary>
/// Read text from file.
/// </summary>
/// <param name="inputLocation"> Path to check file is exist.</param>
/// <returns>Text in file.</returns>
/// <exception cref="FileNotFoundException"> Throws unless file exists.</exception>
private static string ReadInputData(string inputLocation)
{
if (!File.Exists(inputLocation))
{
throw new FileNotFoundException($"Cannot find the function inputs file at {inputLocation}");
}
return File.ReadAllText(inputLocation);
}
}
@@ -0,0 +1,9 @@
namespace Speckle.Automate.Sdk.Schema;
public enum ObjectResultLevel
{
Success,
Info,
Warning,
Error,
}
@@ -0,0 +1,19 @@
namespace Speckle.Automate.Sdk.Schema;
public abstract class ObjectResultLevelMapping
{
private const string SUCCESS = "SUCCESS";
private const string INFO = "INFO";
private const string WARNING = "WARNING";
private const string ERROR = "ERROR";
public static string Get(ObjectResultLevel level) =>
level switch
{
ObjectResultLevel.Error => ERROR,
ObjectResultLevel.Warning => WARNING,
ObjectResultLevel.Info => INFO,
ObjectResultLevel.Success => SUCCESS,
_ => throw new ArgumentOutOfRangeException($"Not valid value for enum {level}"),
};
}
@@ -0,0 +1,7 @@
namespace Speckle.Automate.Sdk.Schema;
public readonly struct ObjectResultValues
{
public required List<ResultCase> ObjectResults { get; init; }
public required List<string> BlobIds { get; init; }
}
@@ -0,0 +1,7 @@
namespace Speckle.Automate.Sdk.Schema;
public readonly struct ObjectResults
{
public int Version { get; init; }
public ObjectResultValues Values { get; init; }
}
@@ -0,0 +1,11 @@
namespace Speckle.Automate.Sdk.Schema;
public readonly struct ResultCase
{
public required string Category { get; init; }
public required string Level { get; init; }
public required Dictionary<string, string?> ObjectAppIds { get; init; }
public required string? Message { get; init; }
public required Dictionary<string, object>? Metadata { get; init; }
public required Dictionary<string, object>? VisualOverrides { get; init; }
}
@@ -0,0 +1,6 @@
namespace Speckle.Automate.Sdk.Schema.Triggers;
public abstract class AutomationRunTriggerBase
{
public required string TriggerType { get; init; }
}
@@ -0,0 +1,36 @@
using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization;
namespace Speckle.Automate.Sdk.Schema.Triggers;
/// <summary>
/// Represents a single version creation trigger for the automation run.
/// </summary>
public sealed class VersionCreationTrigger : AutomationRunTriggerBase
{
public const string VERSION_CREATION_TRIGGER_TYPE = "versionCreation";
[JsonRequired]
public required VersionCreationTriggerPayload Payload { get; init; }
public VersionCreationTrigger() { }
[SetsRequiredMembers]
public VersionCreationTrigger(string modelId, string versionId)
{
Payload = new() { ModelId = modelId, VersionId = versionId };
TriggerType = VERSION_CREATION_TRIGGER_TYPE;
}
}
/// <summary>
/// Represents the version creation trigger payload.
/// </summary>
public sealed record VersionCreationTriggerPayload
{
[JsonRequired]
public required string ModelId { get; init; }
[JsonRequired]
public required string VersionId { get; init; }
}
@@ -0,0 +1,8 @@
namespace Speckle.Automate.Sdk.Schema;
public readonly struct UploadResult
{
public required string BlobId { get; init; }
public required string FileName { get; init; }
public required int UploadStatus { get; init; }
}
@@ -0,0 +1,50 @@
using System.Reflection;
using Microsoft.Extensions.DependencyInjection;
using Speckle.Objects.Geometry;
using Speckle.Sdk;
using Speckle.Sdk.Models;
using Speckle.Sdk.Serialisation.V2;
namespace Speckle.Automate.Sdk;
public static class ServiceRegistration
{
/// <summary>
/// Sets-up the serviceCollection with all the services in Speckle.Automate.Sdk and Speckle.Sdk
/// </summary>
/// <param name="serviceCollection"></param>
/// <returns></returns>
public static IServiceCollection AddAutomateSdk(this IServiceCollection serviceCollection)
{
var executingAssembly = Assembly.GetExecutingAssembly().GetName();
var speckleAssembly = typeof(Base).Assembly.GetName();
AddAutomateSdk(
serviceCollection,
new SpeckleSdkOptions(
new(executingAssembly.FullName, "automatefunction"),
executingAssembly.Version?.ToString() ?? "Unknown",
speckleAssembly.Version?.ToString(),
[typeof(Base).Assembly, typeof(Point).Assembly]
)
);
return serviceCollection;
}
public static IServiceCollection AddAutomateSdk(
this IServiceCollection serviceCollection,
SpeckleSdkOptions speckleSdkOptions
)
{
serviceCollection.AddSpeckleSdk(speckleSdkOptions);
//Overwrite the SDK's default IDeserializeProcessFactory to ensure SQLite is not used to cache objects
serviceCollection.AddTransient<IDeserializeProcessFactory, DeserializeProcessFactoryNoCache>();
//Add automate assembly services
serviceCollection.AddTransient<IAutomationContextFactory, AutomationContextFactory>();
serviceCollection.AddTransient<IAutomationRunner, AutomationRunner>();
return serviceCollection;
}
}
@@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup Label="Compiler Properties">
<TargetFrameworks>netstandard2.0;net8.0</TargetFrameworks>
</PropertyGroup>
<PropertyGroup Label="Nugetspec Package Properties">
<PackageId>Speckle.Automate.Sdk</PackageId>
<Description>Speckle Automate SDK</Description>
<PackageTags>$(PackageTags) speckle automation</PackageTags>
</PropertyGroup>
<PropertyGroup Label="Nuget Package Properties">
<IsPackable>true</IsPackable>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>
<ItemGroup Label="Expose internals to test projects">
<InternalsVisibleTo Include="Speckle.Automate.Sdk.Tests.Integration" />
</ItemGroup>
<ItemGroup Label="Package References">
<PackageReference Include="Newtonsoft.Json.Schema" />
<PackageReference Include="System.CommandLine" NoWarn="NU5104" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0'">
<PackageReference Include="System.Text.Json" />
</ItemGroup>
<ItemGroup Label="Project References">
<ProjectReference Include="..\Speckle.Objects\Speckle.Objects.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,79 @@
using Speckle.Newtonsoft.Json;
using Speckle.Sdk;
namespace Speckle.Automate.Sdk.Test;
public class TestAppSettings
{
public string? SpeckleToken { get; set; }
public string? SpeckleServerUrl { get; set; }
public string? SpeckleProjectId { get; set; }
public string? SpeckleAutomationId { get; set; }
}
public static class TestAutomateEnvironment
{
public static TestAppSettings? AppSettings { get; private set; }
private static string GetEnvironmentVariable(string environmentVariableName)
{
var value = TryGetEnvironmentVariable(environmentVariableName);
if (value is null)
{
throw new SpeckleException($"Cannot run tests without a {environmentVariableName} environment variable");
}
return value;
}
private static string? TryGetEnvironmentVariable(string environmentVariableName)
{
return Environment.GetEnvironmentVariable(environmentVariableName);
}
private static TestAppSettings? GetAppSettings()
{
if (AppSettings != null)
{
return AppSettings;
}
var path = "./appsettings.json";
var json = File.ReadAllText(path);
var appSettings = JsonConvert.DeserializeObject<TestAppSettings>(json);
AppSettings = appSettings;
return AppSettings;
}
public static string GetSpeckleToken()
{
return GetAppSettings()?.SpeckleToken ?? GetEnvironmentVariable("SPECKLE_TOKEN");
}
public static Uri GetSpeckleServerUrl()
{
var urlString =
GetAppSettings()?.SpeckleServerUrl ?? TryGetEnvironmentVariable("SPECKLE_SERVER_URL") ?? "http://127.0.0.1:3000";
return new Uri(urlString);
}
public static string GetSpeckleProjectId()
{
return GetAppSettings()?.SpeckleProjectId ?? GetEnvironmentVariable("SPECKLE_PROJECT_ID");
}
public static string GetSpeckleAutomationId()
{
return GetAppSettings()?.SpeckleAutomationId ?? GetEnvironmentVariable("SPECKLE_AUTOMATION_ID");
}
public static void Clear()
{
AppSettings = null;
}
}
@@ -0,0 +1,90 @@
using GraphQL;
using Speckle.Automate.Sdk.Schema;
using Speckle.Automate.Sdk.Schema.Triggers;
using Speckle.Newtonsoft.Json;
using Speckle.Sdk.Api;
using Speckle.Sdk.Api.GraphQL.Models.Responses;
namespace Speckle.Automate.Sdk.Test;
internal class TestAutomationRun
{
[JsonRequired]
public required string AutomationRunId { get; init; }
[JsonRequired]
public required string FunctionRunId { get; init; }
[JsonRequired]
public required IReadOnlyList<TestAutomationRunTrigger> Triggers { get; init; }
}
internal class TestAutomationRunTrigger : AutomationRunTriggerBase
{
/// <remarks>This should really be a TestAutomationRunTriggerPayload, but right now, they look the samee</remarks>
public required VersionCreationTriggerPayload Payload { get; init; }
}
public static class TestAutomateUtils
{
public static async Task<AutomationRunData> CreateTestRun(
IClient speckleClient,
CancellationToken cancellationToken = default
)
{
//language=graphql
const string QUERY = """
mutation Mutation($projectId: ID!, $automationId: ID!) {
data:projectMutations {
data:automationMutations(projectId: $projectId) {
data:createTestAutomationRun(automationId: $automationId) {
automationRunId
functionRunId
triggers {
payload {
modelId
versionId
}
triggerType
}
}
}
}
}
""";
GraphQLRequest request = new(
query: QUERY,
variables: new
{
automationId = TestAutomateEnvironment.GetSpeckleAutomationId(),
projectId = TestAutomateEnvironment.GetSpeckleProjectId(),
}
);
var res = await speckleClient
.ExecuteGraphQLRequest<RequiredResponse<RequiredResponse<RequiredResponse<TestAutomationRun>>>>(
request,
cancellationToken
)
.ConfigureAwait(false);
var runData = res.data.data.data;
var triggerData = runData.Triggers[0].Payload;
string modelId = triggerData.ModelId;
string versionId = triggerData.VersionId;
var data = new AutomationRunData()
{
ProjectId = TestAutomateEnvironment.GetSpeckleProjectId(),
SpeckleServerUrl = TestAutomateEnvironment.GetSpeckleServerUrl(),
AutomationId = TestAutomateEnvironment.GetSpeckleAutomationId(),
AutomationRunId = runData.AutomationRunId,
FunctionRunId = runData.FunctionRunId,
Triggers = [new(modelId: modelId, versionId: versionId)],
};
return data;
}
}
+618
View File
@@ -0,0 +1,618 @@
{
"version": 2,
"dependencies": {
".NETStandard,Version=v2.0": {
"Microsoft.SourceLink.GitHub": {
"type": "Direct",
"requested": "[8.0.0, )",
"resolved": "8.0.0",
"contentHash": "G5q7OqtwIyGTkeIOAc3u2ZuV/kicQaec5EaRnc0pIeSnh9LUjj+PYQrJYBURvDt7twGl2PKA7nSN0kz1Zw5bnQ==",
"dependencies": {
"Microsoft.Build.Tasks.Git": "8.0.0",
"Microsoft.SourceLink.Common": "8.0.0"
}
},
"NETStandard.Library": {
"type": "Direct",
"requested": "[2.0.3, )",
"resolved": "2.0.3",
"contentHash": "st47PosZSHrjECdjeIzZQbzivYBJFv6P2nv4cj2ypdI204DO+vZ7l5raGMiX4eXMJ53RfOIg+/s4DHVZ54Nu2A==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0"
}
},
"Newtonsoft.Json.Schema": {
"type": "Direct",
"requested": "[4.0.1, )",
"resolved": "4.0.1",
"contentHash": "rbHUKp5WTIbqmLEeJ21nTTDGcfR0LA7bVMzm0bYc3yx6NFKiCIHzzvYbwA4Sqgs7+wNldc5nBlkbithWj8IZig==",
"dependencies": {
"Newtonsoft.Json": "13.0.3"
}
},
"PolySharp": {
"type": "Direct",
"requested": "[1.15.0, )",
"resolved": "1.15.0",
"contentHash": "FbU0El+EEjdpuIX4iDbeS7ki1uzpJPx8vbqOzEtqnl1GZeAGJfq+jCbxeJL2y0EPnUNk8dRnnqR2xnYXg9Tf+g=="
},
"Speckle.InterfaceGenerator": {
"type": "Direct",
"requested": "[0.9.6, )",
"resolved": "0.9.6",
"contentHash": "HKH7tYrYYlCK1ct483hgxERAdVdMtl7gUKW9ijWXxA1UsYR4Z+TrRHYmzZ9qmpu1NnTycSrp005NYM78GDKV1w=="
},
"System.CommandLine": {
"type": "Direct",
"requested": "[2.0.0-beta4.22272.1, )",
"resolved": "2.0.0-beta4.22272.1",
"contentHash": "1uqED/q2H0kKoLJ4+hI2iPSBSEdTuhfCYADeJrAqERmiGQ2NNacYKRNEQ+gFbU4glgVyK8rxI+ZOe1onEtr/Pg==",
"dependencies": {
"System.Memory": "4.5.4"
}
},
"System.Text.Json": {
"type": "Direct",
"requested": "[8.0.5, )",
"resolved": "8.0.5",
"contentHash": "0f1B50Ss7rqxXiaBJyzUu9bWFOO2/zSlifZ/UNMdiIpDYe4cY4LQQicP4nirK1OS31I43rn062UIJ1Q9bpmHpg==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "8.0.0",
"System.Buffers": "4.5.1",
"System.Memory": "4.5.5",
"System.Runtime.CompilerServices.Unsafe": "6.0.0",
"System.Text.Encodings.Web": "8.0.0",
"System.Threading.Tasks.Extensions": "4.5.4"
}
},
"GraphQL.Client.Abstractions": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "h7uzWFORHZ+CCjwr/ThAyXMr0DPpzEANDa4Uo54wqCQ+j7qUKwqYTgOrb1W40sqbvNaZm9v/X7It31SUw0maHA==",
"dependencies": {
"GraphQL.Primitives": "6.0.0"
}
},
"GraphQL.Client.Abstractions.Websocket": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "Nr9bPf8gIOvLuXpqEpqr9z9jslYFJOvd0feHth3/kPqeR3uMbjF5pjiwh4jxyMcxHdr8Pb6QiXkV3hsSyt0v7A==",
"dependencies": {
"GraphQL.Client.Abstractions": "6.0.0"
}
},
"GraphQL.Primitives": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "yg72rrYDapfsIUrul7aF6wwNnTJBOFvuA9VdDTQpPa8AlAriHbufeXYLBcodKjfUdkCnaiggX1U/nEP08Zb5GA=="
},
"Microsoft.Build.Tasks.Git": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ=="
},
"Microsoft.Data.Sqlite.Core": {
"type": "Transitive",
"resolved": "7.0.5",
"contentHash": "FTerRmQPqHrCrnoUzhBu+E+1DNGwyrAMLqHkAqOOOu5pGfyMOj8qQUBxI/gDtWtG11p49UxSfWmBzRNlwZqfUg==",
"dependencies": {
"SQLitePCLRaw.core": "2.1.4"
}
},
"Microsoft.Extensions.Configuration": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "nOP8R1mVb/6mZtm2qgAJXn/LFm/2kMjHDAg/QJLFG6CuWYJtaD3p1BwQhufBVvRzL9ceJ/xF0SQ0qsI2GkDQAA==",
"dependencies": {
"Microsoft.Extensions.Configuration.Abstractions": "2.2.0"
}
},
"Microsoft.Extensions.Configuration.Abstractions": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "65MrmXCziWaQFrI0UHkQbesrX5wTwf9XPjY5yFm/VkgJKFJ5gqvXRoXjIZcf2wLi5ZlwGz/oMYfyURVCWbM5iw==",
"dependencies": {
"Microsoft.Extensions.Primitives": "2.2.0"
}
},
"Microsoft.Extensions.Configuration.Binder": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "vJ9xvOZCnUAIHcGC3SU35r3HKmHTVIeHzo6u/qzlHAqD8m6xv92MLin4oJntTvkpKxVX3vI1GFFkIQtU3AdlsQ==",
"dependencies": {
"Microsoft.Extensions.Configuration": "2.2.0"
}
},
"Microsoft.Extensions.Logging.Abstractions": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "B2WqEox8o+4KUOpL7rZPyh6qYjik8tHi2tN8Z9jZkHzED8ElYgZa/h6K+xliB435SqUcWT290Fr2aa8BtZjn8A=="
},
"Microsoft.Extensions.Options": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "UpZLNLBpIZ0GTebShui7xXYh6DmBHjWM8NxGxZbdQh/bPZ5e6YswqI+bru6BnEL5eWiOdodsXtEz3FROcgi/qg==",
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
"Microsoft.Extensions.Primitives": "2.2.0",
"System.ComponentModel.Annotations": "4.5.0"
}
},
"Microsoft.Extensions.Primitives": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "azyQtqbm4fSaDzZHD/J+V6oWMFaf2tWP4WEGIYePLCMw3+b2RQdj9ybgbQyjCshcitQKQ4lEDOZjmSlTTrHxUg==",
"dependencies": {
"System.Memory": "4.5.1",
"System.Runtime.CompilerServices.Unsafe": "4.5.1"
}
},
"Microsoft.NETCore.Platforms": {
"type": "Transitive",
"resolved": "1.1.0",
"contentHash": "kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A=="
},
"Microsoft.NETCore.Targets": {
"type": "Transitive",
"resolved": "1.1.0",
"contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg=="
},
"Microsoft.SourceLink.Common": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
},
"Newtonsoft.Json": {
"type": "Transitive",
"resolved": "13.0.3",
"contentHash": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
"resolved": "2.1.4",
"contentHash": "EWI1olKDjFEBMJu0+3wuxwziIAdWDVMYLhuZ3Qs84rrz+DHwD00RzWPZCa+bLnHCf3oJwuFZIRsHT5p236QXww==",
"dependencies": {
"SQLitePCLRaw.lib.e_sqlite3": "2.1.4",
"SQLitePCLRaw.provider.e_sqlite3": "2.1.4"
}
},
"SQLitePCLRaw.core": {
"type": "Transitive",
"resolved": "2.1.4",
"contentHash": "inBjvSHo9UDKneGNzfUfDjK08JzlcIhn1+SP5Y3m6cgXpCxXKCJDy6Mka7LpgSV+UZmKSnC8rTwB0SQ0xKu5pA==",
"dependencies": {
"System.Memory": "4.5.3"
}
},
"SQLitePCLRaw.lib.e_sqlite3": {
"type": "Transitive",
"resolved": "2.1.4",
"contentHash": "2C9Q9eX7CPLveJA0rIhf9RXAvu+7nWZu1A2MdG6SD/NOu26TakGgL1nsbc0JAspGijFOo3HoN79xrx8a368fBg=="
},
"SQLitePCLRaw.provider.e_sqlite3": {
"type": "Transitive",
"resolved": "2.1.4",
"contentHash": "CSlb5dUp1FMIkez9Iv5EXzpeq7rHryVNqwJMWnpq87j9zWZexaEMdisDktMsnnrzKM6ahNrsTkjqNodTBPBxtQ==",
"dependencies": {
"SQLitePCLRaw.core": "2.1.4"
}
},
"System.Buffers": {
"type": "Transitive",
"resolved": "4.5.1",
"contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg=="
},
"System.ComponentModel.Annotations": {
"type": "Transitive",
"resolved": "4.5.0",
"contentHash": "UxYQ3FGUOtzJ7LfSdnYSFd7+oEv6M8NgUatatIN2HxNtDdlcvFAf+VIq4Of9cDMJEJC0aSRv/x898RYhB4Yppg=="
},
"System.Memory": {
"type": "Transitive",
"resolved": "4.5.5",
"contentHash": "XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw==",
"dependencies": {
"System.Buffers": "4.5.1",
"System.Numerics.Vectors": "4.4.0",
"System.Runtime.CompilerServices.Unsafe": "4.5.3"
}
},
"System.Numerics.Vectors": {
"type": "Transitive",
"resolved": "4.4.0",
"contentHash": "UiLzLW+Lw6HLed1Hcg+8jSRttrbuXv7DANVj0DkL9g6EnnzbL75EB7EWsw5uRbhxd/4YdG8li5XizGWepmG3PQ=="
},
"System.Reactive": {
"type": "Transitive",
"resolved": "5.0.0",
"contentHash": "erBZjkQHWL9jpasCE/0qKAryzVBJFxGHVBAvgRN1bzM0q2s1S4oYREEEL0Vb+1kA/6BKb5FjUZMp5VXmy+gzkQ==",
"dependencies": {
"System.Runtime.InteropServices.WindowsRuntime": "4.3.0",
"System.Threading.Tasks.Extensions": "4.5.4"
}
},
"System.Runtime": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0"
}
},
"System.Runtime.CompilerServices.Unsafe": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg=="
},
"System.Runtime.InteropServices.WindowsRuntime": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "J4GUi3xZQLUBasNwZnjrffN8i5wpHrBtZoLG+OhRyGo/+YunMRWWtwoMDlUAIdmX0uRfpHIBDSV6zyr3yf00TA==",
"dependencies": {
"System.Runtime": "4.3.0"
}
},
"System.Text.Encodings.Web": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "yev/k9GHAEGx2Rg3/tU6MQh4HGBXJs70y7j1LaM1i/ER9po+6nnQ6RRqTJn1E7Xu0fbIFK80Nh5EoODxrbxwBQ==",
"dependencies": {
"System.Buffers": "4.5.1",
"System.Memory": "4.5.5",
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
}
},
"System.Threading.Tasks.Extensions": {
"type": "Transitive",
"resolved": "4.5.4",
"contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==",
"dependencies": {
"System.Runtime.CompilerServices.Unsafe": "4.5.3"
}
},
"speckle.objects": {
"type": "Project",
"dependencies": {
"Speckle.Sdk": "[1.0.0, )"
}
},
"speckle.sdk": {
"type": "Project",
"dependencies": {
"GraphQL.Client": "[6.0.0, )",
"Microsoft.Bcl.AsyncInterfaces": "[5.0.0, )",
"Microsoft.CSharp": "[4.7.0, )",
"Microsoft.Data.Sqlite": "[7.0.5, )",
"Microsoft.Extensions.DependencyInjection.Abstractions": "[2.2.0, )",
"Microsoft.Extensions.Logging": "[2.2.0, )",
"Speckle.DoubleNumerics": "[4.1.0, )",
"Speckle.Newtonsoft.Json": "[13.0.2, )",
"Speckle.Sdk.Dependencies": "[1.0.0, )"
}
},
"speckle.sdk.dependencies": {
"type": "Project"
},
"GraphQL.Client": {
"type": "CentralTransitive",
"requested": "[6.0.0, )",
"resolved": "6.0.0",
"contentHash": "8yPNBbuVBpTptivyAlak4GZvbwbUcjeQTL4vN1HKHRuOykZ4r7l5fcLS6vpyPyLn0x8FsL31xbOIKyxbmR9rbA==",
"dependencies": {
"GraphQL.Client.Abstractions": "6.0.0",
"GraphQL.Client.Abstractions.Websocket": "6.0.0",
"System.Reactive": "5.0.0"
}
},
"Microsoft.Bcl.AsyncInterfaces": {
"type": "CentralTransitive",
"requested": "[5.0.0, )",
"resolved": "8.0.0",
"contentHash": "3WA9q9yVqJp222P3x1wYIGDAkpjAku0TMUaaQV22g6L67AI0LdOIrVS7Ht2vJfLHGSPVuqN94vIr15qn+HEkHw==",
"dependencies": {
"System.Threading.Tasks.Extensions": "4.5.4"
}
},
"Microsoft.CSharp": {
"type": "CentralTransitive",
"requested": "[4.7.0, )",
"resolved": "4.7.0",
"contentHash": "pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA=="
},
"Microsoft.Data.Sqlite": {
"type": "CentralTransitive",
"requested": "[7.0.5, )",
"resolved": "7.0.5",
"contentHash": "KGxbPeWsQMnmQy43DSBxAFtHz3l2JX8EWBSGUCvT3CuZ8KsuzbkqMIJMDOxWtG8eZSoCDI04aiVQjWuuV8HmSw==",
"dependencies": {
"Microsoft.Data.Sqlite.Core": "7.0.5",
"SQLitePCLRaw.bundle_e_sqlite3": "2.1.4"
}
},
"Microsoft.Extensions.DependencyInjection.Abstractions": {
"type": "CentralTransitive",
"requested": "[2.2.0, )",
"resolved": "2.2.0",
"contentHash": "f9hstgjVmr6rmrfGSpfsVOl2irKAgr1QjrSi3FgnS7kulxband50f2brRLwySAQTADPZeTdow0mpSMcoAdadCw=="
},
"Microsoft.Extensions.Logging": {
"type": "CentralTransitive",
"requested": "[2.2.0, )",
"resolved": "2.2.0",
"contentHash": "Nxqhadc9FCmFHzU+fz3oc8sFlE6IadViYg8dfUdGzJZ2JUxnCsRghBhhOWdM4B2zSZqEc+0BjliBh/oNdRZuig==",
"dependencies": {
"Microsoft.Extensions.Configuration.Binder": "2.2.0",
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
"Microsoft.Extensions.Logging.Abstractions": "2.2.0",
"Microsoft.Extensions.Options": "2.2.0"
}
},
"Speckle.DoubleNumerics": {
"type": "CentralTransitive",
"requested": "[4.1.0, )",
"resolved": "4.1.0",
"contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
},
"Speckle.Newtonsoft.Json": {
"type": "CentralTransitive",
"requested": "[13.0.2, )",
"resolved": "13.0.2",
"contentHash": "g1BejUZwax5PRfL6xHgLEK23sqHWOgOj9hE7RvfRRlN00AGt8GnPYt8HedSK7UB3HiRW8zCA9Pn0iiYxCK24BA=="
}
},
"net8.0": {
"Microsoft.SourceLink.GitHub": {
"type": "Direct",
"requested": "[8.0.0, )",
"resolved": "8.0.0",
"contentHash": "G5q7OqtwIyGTkeIOAc3u2ZuV/kicQaec5EaRnc0pIeSnh9LUjj+PYQrJYBURvDt7twGl2PKA7nSN0kz1Zw5bnQ==",
"dependencies": {
"Microsoft.Build.Tasks.Git": "8.0.0",
"Microsoft.SourceLink.Common": "8.0.0"
}
},
"Newtonsoft.Json.Schema": {
"type": "Direct",
"requested": "[4.0.1, )",
"resolved": "4.0.1",
"contentHash": "rbHUKp5WTIbqmLEeJ21nTTDGcfR0LA7bVMzm0bYc3yx6NFKiCIHzzvYbwA4Sqgs7+wNldc5nBlkbithWj8IZig==",
"dependencies": {
"Newtonsoft.Json": "13.0.3"
}
},
"PolySharp": {
"type": "Direct",
"requested": "[1.15.0, )",
"resolved": "1.15.0",
"contentHash": "FbU0El+EEjdpuIX4iDbeS7ki1uzpJPx8vbqOzEtqnl1GZeAGJfq+jCbxeJL2y0EPnUNk8dRnnqR2xnYXg9Tf+g=="
},
"Speckle.InterfaceGenerator": {
"type": "Direct",
"requested": "[0.9.6, )",
"resolved": "0.9.6",
"contentHash": "HKH7tYrYYlCK1ct483hgxERAdVdMtl7gUKW9ijWXxA1UsYR4Z+TrRHYmzZ9qmpu1NnTycSrp005NYM78GDKV1w=="
},
"System.CommandLine": {
"type": "Direct",
"requested": "[2.0.0-beta4.22272.1, )",
"resolved": "2.0.0-beta4.22272.1",
"contentHash": "1uqED/q2H0kKoLJ4+hI2iPSBSEdTuhfCYADeJrAqERmiGQ2NNacYKRNEQ+gFbU4glgVyK8rxI+ZOe1onEtr/Pg=="
},
"GraphQL.Client.Abstractions": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "h7uzWFORHZ+CCjwr/ThAyXMr0DPpzEANDa4Uo54wqCQ+j7qUKwqYTgOrb1W40sqbvNaZm9v/X7It31SUw0maHA==",
"dependencies": {
"GraphQL.Primitives": "6.0.0"
}
},
"GraphQL.Client.Abstractions.Websocket": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "Nr9bPf8gIOvLuXpqEpqr9z9jslYFJOvd0feHth3/kPqeR3uMbjF5pjiwh4jxyMcxHdr8Pb6QiXkV3hsSyt0v7A==",
"dependencies": {
"GraphQL.Client.Abstractions": "6.0.0"
}
},
"GraphQL.Primitives": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "yg72rrYDapfsIUrul7aF6wwNnTJBOFvuA9VdDTQpPa8AlAriHbufeXYLBcodKjfUdkCnaiggX1U/nEP08Zb5GA=="
},
"Microsoft.Build.Tasks.Git": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ=="
},
"Microsoft.Data.Sqlite.Core": {
"type": "Transitive",
"resolved": "7.0.5",
"contentHash": "FTerRmQPqHrCrnoUzhBu+E+1DNGwyrAMLqHkAqOOOu5pGfyMOj8qQUBxI/gDtWtG11p49UxSfWmBzRNlwZqfUg==",
"dependencies": {
"SQLitePCLRaw.core": "2.1.4"
}
},
"Microsoft.Extensions.Configuration": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "nOP8R1mVb/6mZtm2qgAJXn/LFm/2kMjHDAg/QJLFG6CuWYJtaD3p1BwQhufBVvRzL9ceJ/xF0SQ0qsI2GkDQAA==",
"dependencies": {
"Microsoft.Extensions.Configuration.Abstractions": "2.2.0"
}
},
"Microsoft.Extensions.Configuration.Abstractions": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "65MrmXCziWaQFrI0UHkQbesrX5wTwf9XPjY5yFm/VkgJKFJ5gqvXRoXjIZcf2wLi5ZlwGz/oMYfyURVCWbM5iw==",
"dependencies": {
"Microsoft.Extensions.Primitives": "2.2.0"
}
},
"Microsoft.Extensions.Configuration.Binder": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "vJ9xvOZCnUAIHcGC3SU35r3HKmHTVIeHzo6u/qzlHAqD8m6xv92MLin4oJntTvkpKxVX3vI1GFFkIQtU3AdlsQ==",
"dependencies": {
"Microsoft.Extensions.Configuration": "2.2.0"
}
},
"Microsoft.Extensions.Logging.Abstractions": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "B2WqEox8o+4KUOpL7rZPyh6qYjik8tHi2tN8Z9jZkHzED8ElYgZa/h6K+xliB435SqUcWT290Fr2aa8BtZjn8A=="
},
"Microsoft.Extensions.Options": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "UpZLNLBpIZ0GTebShui7xXYh6DmBHjWM8NxGxZbdQh/bPZ5e6YswqI+bru6BnEL5eWiOdodsXtEz3FROcgi/qg==",
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
"Microsoft.Extensions.Primitives": "2.2.0",
"System.ComponentModel.Annotations": "4.5.0"
}
},
"Microsoft.Extensions.Primitives": {
"type": "Transitive",
"resolved": "2.2.0",
"contentHash": "azyQtqbm4fSaDzZHD/J+V6oWMFaf2tWP4WEGIYePLCMw3+b2RQdj9ybgbQyjCshcitQKQ4lEDOZjmSlTTrHxUg==",
"dependencies": {
"System.Memory": "4.5.1",
"System.Runtime.CompilerServices.Unsafe": "4.5.1"
}
},
"Microsoft.SourceLink.Common": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
},
"Newtonsoft.Json": {
"type": "Transitive",
"resolved": "13.0.3",
"contentHash": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ=="
},
"SQLitePCLRaw.bundle_e_sqlite3": {
"type": "Transitive",
"resolved": "2.1.4",
"contentHash": "EWI1olKDjFEBMJu0+3wuxwziIAdWDVMYLhuZ3Qs84rrz+DHwD00RzWPZCa+bLnHCf3oJwuFZIRsHT5p236QXww==",
"dependencies": {
"SQLitePCLRaw.lib.e_sqlite3": "2.1.4",
"SQLitePCLRaw.provider.e_sqlite3": "2.1.4"
}
},
"SQLitePCLRaw.core": {
"type": "Transitive",
"resolved": "2.1.4",
"contentHash": "inBjvSHo9UDKneGNzfUfDjK08JzlcIhn1+SP5Y3m6cgXpCxXKCJDy6Mka7LpgSV+UZmKSnC8rTwB0SQ0xKu5pA==",
"dependencies": {
"System.Memory": "4.5.3"
}
},
"SQLitePCLRaw.lib.e_sqlite3": {
"type": "Transitive",
"resolved": "2.1.4",
"contentHash": "2C9Q9eX7CPLveJA0rIhf9RXAvu+7nWZu1A2MdG6SD/NOu26TakGgL1nsbc0JAspGijFOo3HoN79xrx8a368fBg=="
},
"SQLitePCLRaw.provider.e_sqlite3": {
"type": "Transitive",
"resolved": "2.1.4",
"contentHash": "CSlb5dUp1FMIkez9Iv5EXzpeq7rHryVNqwJMWnpq87j9zWZexaEMdisDktMsnnrzKM6ahNrsTkjqNodTBPBxtQ==",
"dependencies": {
"SQLitePCLRaw.core": "2.1.4"
}
},
"System.ComponentModel.Annotations": {
"type": "Transitive",
"resolved": "4.5.0",
"contentHash": "UxYQ3FGUOtzJ7LfSdnYSFd7+oEv6M8NgUatatIN2HxNtDdlcvFAf+VIq4Of9cDMJEJC0aSRv/x898RYhB4Yppg=="
},
"System.Memory": {
"type": "Transitive",
"resolved": "4.5.3",
"contentHash": "3oDzvc/zzetpTKWMShs1AADwZjQ/36HnsufHRPcOjyRAAMLDlu2iD33MBI2opxnezcVUtXyqDXXjoFMOU9c7SA=="
},
"System.Reactive": {
"type": "Transitive",
"resolved": "5.0.0",
"contentHash": "erBZjkQHWL9jpasCE/0qKAryzVBJFxGHVBAvgRN1bzM0q2s1S4oYREEEL0Vb+1kA/6BKb5FjUZMp5VXmy+gzkQ=="
},
"System.Runtime.CompilerServices.Unsafe": {
"type": "Transitive",
"resolved": "4.5.1",
"contentHash": "Zh8t8oqolRaFa9vmOZfdQm/qKejdqz0J9kr7o2Fu0vPeoH3BL1EOXipKWwkWtLT1JPzjByrF19fGuFlNbmPpiw=="
},
"speckle.objects": {
"type": "Project",
"dependencies": {
"Speckle.Sdk": "[1.0.0, )"
}
},
"speckle.sdk": {
"type": "Project",
"dependencies": {
"GraphQL.Client": "[6.0.0, )",
"Microsoft.Data.Sqlite": "[7.0.5, )",
"Microsoft.Extensions.DependencyInjection.Abstractions": "[2.2.0, )",
"Microsoft.Extensions.Logging": "[2.2.0, )",
"Speckle.DoubleNumerics": "[4.1.0, )",
"Speckle.Newtonsoft.Json": "[13.0.2, )",
"Speckle.Sdk.Dependencies": "[1.0.0, )"
}
},
"speckle.sdk.dependencies": {
"type": "Project"
},
"GraphQL.Client": {
"type": "CentralTransitive",
"requested": "[6.0.0, )",
"resolved": "6.0.0",
"contentHash": "8yPNBbuVBpTptivyAlak4GZvbwbUcjeQTL4vN1HKHRuOykZ4r7l5fcLS6vpyPyLn0x8FsL31xbOIKyxbmR9rbA==",
"dependencies": {
"GraphQL.Client.Abstractions": "6.0.0",
"GraphQL.Client.Abstractions.Websocket": "6.0.0",
"System.Reactive": "5.0.0"
}
},
"Microsoft.Data.Sqlite": {
"type": "CentralTransitive",
"requested": "[7.0.5, )",
"resolved": "7.0.5",
"contentHash": "KGxbPeWsQMnmQy43DSBxAFtHz3l2JX8EWBSGUCvT3CuZ8KsuzbkqMIJMDOxWtG8eZSoCDI04aiVQjWuuV8HmSw==",
"dependencies": {
"Microsoft.Data.Sqlite.Core": "7.0.5",
"SQLitePCLRaw.bundle_e_sqlite3": "2.1.4"
}
},
"Microsoft.Extensions.DependencyInjection.Abstractions": {
"type": "CentralTransitive",
"requested": "[2.2.0, )",
"resolved": "2.2.0",
"contentHash": "f9hstgjVmr6rmrfGSpfsVOl2irKAgr1QjrSi3FgnS7kulxband50f2brRLwySAQTADPZeTdow0mpSMcoAdadCw=="
},
"Microsoft.Extensions.Logging": {
"type": "CentralTransitive",
"requested": "[2.2.0, )",
"resolved": "2.2.0",
"contentHash": "Nxqhadc9FCmFHzU+fz3oc8sFlE6IadViYg8dfUdGzJZ2JUxnCsRghBhhOWdM4B2zSZqEc+0BjliBh/oNdRZuig==",
"dependencies": {
"Microsoft.Extensions.Configuration.Binder": "2.2.0",
"Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0",
"Microsoft.Extensions.Logging.Abstractions": "2.2.0",
"Microsoft.Extensions.Options": "2.2.0"
}
},
"Speckle.DoubleNumerics": {
"type": "CentralTransitive",
"requested": "[4.1.0, )",
"resolved": "4.1.0",
"contentHash": "20DtS+FsDRsOD9+AU3TwNFZ0qrKo5f6f7B5ZR9wStsIHHHC9k7DpjbCvuNtmnSjx54MD+TJC7wV2f5iyGVPj1A=="
},
"Speckle.Newtonsoft.Json": {
"type": "CentralTransitive",
"requested": "[13.0.2, )",
"resolved": "13.0.2",
"contentHash": "g1BejUZwax5PRfL6xHgLEK23sqHWOgOj9hE7RvfRRlN00AGt8GnPYt8HedSK7UB3HiRW8zCA9Pn0iiYxCK24BA=="
}
}
}
}
+10
View File
@@ -0,0 +1,10 @@
[*.{cs,vb}]
# Name properties with camelCase
dotnet_naming_rule.properties_should_be_camel_case.severity = none
dotnet_naming_rule.properties_should_be_camel_case.symbols = properties
dotnet_naming_rule.properties_should_be_camel_case.style = property_style
dotnet_naming_symbols.properties.applicable_kinds = property
dotnet_naming_style.property_style.capitalization = camel_case
+68
View File
@@ -0,0 +1,68 @@
using Speckle.Objects.Geometry;
using Speckle.Sdk.Models;
namespace Speckle.Objects.Annotation;
/// <summary>
/// Text class for representation in the viewer
/// </summary>
[SpeckleType("Objects.Annotation.Text")]
public class Text : Base
{
/// <summary>
/// Plain text, without formatting
/// </summary>
public required string value { get; set; }
/// <summary>
/// Height in linear units or pixels (if Units.None)
/// </summary>
public required double height { get; set; }
/// <summary>
/// Units will be 'Units.None' if the text size is defined in pixels (stays the same size
/// independently of zooming the model). Default height in pixels is 17px (used for Viewer measurements)
/// </summary>
public required string units { get; set; }
/// <summary>
/// If true, the text is oriented to face the screen (camera-aligned).
/// </summary>
public required bool screenOriented { get; set; }
/// <summary>
/// Horizontal alignment: Left, Center or Right
/// </summary>
public AlignmentHorizontal alignmentH { get; set; }
/// <summary>
/// Vertical alignment: Top, Center or Bottom
/// </summary>
public AlignmentVertical alignmentV { get; set; }
/// <summary>
/// Plane axis vectors will be ignored if screenOriented is true
/// </summary>
public required Plane plane { get; set; }
/// <summary>
/// Maximum width of the text field (in 'units').
/// Text will be split into lines (wrapped) to fit into the width.
/// null, if text should not be wrapped.
/// </summary>
public double? maxWidth { get; set; }
}
public enum AlignmentHorizontal
{
Left,
Center,
Right,
}
public enum AlignmentVertical
{
Top,
Center,
Bottom,
}
+16
View File
@@ -0,0 +1,16 @@
using Speckle.Sdk.Models;
namespace Speckle.Objects.Data;
/// <summary>
/// Represents a ArcGIS.Core.CoreObjectsBase object in ArcGIS
/// </summary>
[SpeckleType("Objects.Data.ArcgisObject")]
public class ArcgisObject : DataObject, IGisObject
{
public required string type { get; set; }
public required string units { get; set; }
IReadOnlyList<Base> IDisplayValue<IReadOnlyList<Base>>.displayValue => displayValue;
}
@@ -0,0 +1,19 @@
using Speckle.Sdk.Models;
namespace Speckle.Objects.Data;
/// <summary>
/// Represents a base class object in Archicad
/// </summary>
[SpeckleType("Objects.Data.ArchicadObject")]
public class ArchicadObject : DataObject, IArchicadObject
{
public required string type { get; set; }
public required string level { get; set; }
[DetachProperty]
public required List<ArchicadObject> elements { get; set; }
IReadOnlyList<IArchicadObject> IArchicadObject.elements => elements;
}
+27
View File
@@ -0,0 +1,27 @@
using Speckle.Sdk.Models;
namespace Speckle.Objects.Data;
/// <summary>
/// Represents an Autodesk.Civil.DatabaseServices.Entity object in Civil3d
/// </summary>
[SpeckleType("Objects.Data.Civil3dObject")]
public class Civil3dObject : DataObject, ICivilObject
{
public required string type { get; set; }
/// <summary>
/// Curves representing the base curve of an entity
/// </summary>
public required List<ICurve>? baseCurves { get; set; }
/// <summary>
/// Children objects, eg profiles, this civil entity may contain.
/// </summary>
[DetachProperty]
public required List<Base> elements { get; set; }
public required string units { get; set; }
IReadOnlyList<Base> ICivilObject.elements => elements;
}
+16
View File
@@ -0,0 +1,16 @@
using Speckle.Sdk.Models;
namespace Speckle.Objects.Data;
[SpeckleType("Objects.Data.DataObject")]
public class DataObject : Base, IDataObject
{
public required string name { get; set; }
[DetachProperty]
public required List<Base> displayValue { get; set; }
public required Dictionary<string, object?> properties { get; set; }
IReadOnlyList<Base> IDisplayValue<IReadOnlyList<Base>>.displayValue => displayValue;
}
+24
View File
@@ -0,0 +1,24 @@
using Speckle.Sdk.Models;
namespace Speckle.Objects.Data;
/// <summary>
/// Represents a wrapper object in ETABS
/// </summary>
[SpeckleType("Objects.Data.EtabsObject")]
public class EtabsObject : DataObject, ICsiObject
{
public required string type { get; set; }
/// <summary>
/// Children objects, eg joints, this etabs object may contain.
/// </summary>
[DetachProperty]
public required List<EtabsObject> elements { get; set; }
public required string units { get; set; }
IReadOnlyList<ICsiObject> ICsiObject.elements => elements;
IReadOnlyList<Base> IDisplayValue<IReadOnlyList<Base>>.displayValue => displayValue;
}
@@ -0,0 +1,14 @@
using Speckle.Sdk.Models;
namespace Speckle.Objects.Data;
/// <summary>
/// Represents a "first selectable ancestor" Navisworks.ModelItem object in Navisworks
/// </summary>
[SpeckleType("Objects.Data.NavisworksObject")]
public class NavisworksObject : DataObject, INavisworksObject
{
public required string units { get; set; }
IReadOnlyList<Base> IDisplayValue<IReadOnlyList<Base>>.displayValue => displayValue;
}
+36
View File
@@ -0,0 +1,36 @@
using Speckle.Sdk.Models;
namespace Speckle.Objects.Data;
/// <summary>
/// Represents an Autodesk.Revit.DB.Element object in Revit
/// </summary>
[SpeckleType("Objects.Data.RevitObject")]
public class RevitObject : DataObject, IRevitObject
{
public required string type { get; set; }
public required string family { get; set; }
public required string category { get; set; }
/// <summary>
/// The level constraint of the object.
/// For objects constrained by multiple levels, this represents the base constraint.
/// For objects with no level constraint, this should be null.
/// </summary>
public required string? level { get; set; }
/// <summary>
/// A Curve or Point object representing the location of a Revit element.
/// </summary>
public required Base? location { get; set; }
/// <summary>
/// Children objects, eg hosted elements, this RevitObject may contain.
/// </summary>
[DetachProperty]
public required List<RevitObject> elements { get; set; }
public required string units { get; set; }
IReadOnlyList<IRevitObject> IRevitObject.elements => elements;
}
+24
View File
@@ -0,0 +1,24 @@
using Speckle.Sdk.Models;
namespace Speckle.Objects.Data;
/// <summary>
/// Represents an Tekla.Structures.Model.ModelObject object in Tekla Structures
/// </summary>
[SpeckleType("Objects.Data.TeklaObject")]
public class TeklaObject : DataObject, ITeklaObject
{
public required string type { get; set; }
/// <summary>
/// Children objects, eg profiles, this tekla modelobject may contain.
/// </summary>
[DetachProperty]
public required List<TeklaObject> elements { get; set; }
public required string units { get; set; }
IReadOnlyList<ITeklaObject> ITeklaObject.elements => elements;
IReadOnlyList<Base> IDisplayValue<IReadOnlyList<Base>>.displayValue => displayValue;
}
@@ -0,0 +1,18 @@
using Speckle.Sdk.Models;
namespace Speckle.Objects.Deprecated;
[SpeckleType("Objects.Deprecated.LegacyV2")]
[DeprecatedSpeckleType("Objects.Other.BlockInstance")]
[DeprecatedSpeckleType("Objects.Other.Revit.RevitInstance")]
[DeprecatedSpeckleType("Objects.BuiltElements.View")]
[DeprecatedSpeckleType("Objects.BuiltElements.GridLine")]
[DeprecatedSpeckleType("Objects.Other.BlockDefinition")]
[DeprecatedSpeckleType("Objects.Other.DisplayStyle")]
[DeprecatedSpeckleType("Objects.Other.Material")]
[DeprecatedSpeckleType("Objects.Other.MaterialQuantity")]
[DeprecatedSpeckleType("Objects.Other.Revit.RevitMaterial")]
[DeprecatedSpeckleType("Objects.BuiltElements.Revit.Parameter")]
[DeprecatedSpeckleType("Objects.BuiltElements.Revit.Curve.ModelCurve")]
[DeprecatedSpeckleType("Objects.BuiltElements.Revit.DirectShape")]
public class LegacyV2 : Base { }
@@ -0,0 +1,103 @@
using Speckle.Objects.Geometry;
namespace Speckle.Objects;
public static class CurveTypeEncoding
{
public const double Arc = 0;
public const double Circle = 1;
public const double Curve = 2;
public const double Ellipse = 3;
public const double Line = 4;
public const double Polyline = 5;
public const double PolyCurve = 6;
}
/// <summary>
/// This class is a helper class for Brep curve encoding!!
/// </summary>
public static class CurveArrayEncodingExtensions
{
public static List<double> ToArray(IReadOnlyCollection<ICurve> curves)
{
var list = new List<double>();
foreach (var curve in curves)
{
switch (curve)
{
case Arc a:
list.AddRange(a.ToList());
break;
case Circle c:
list.AddRange(c.ToList());
break;
case Curve c:
list.AddRange(c.ToList());
break;
case Ellipse e:
list.AddRange(e.ToList());
break;
case Line l:
list.AddRange(l.ToList());
break;
case Polycurve p:
list.AddRange(p.ToList());
break;
case Polyline p:
list.AddRange(p.ToList());
break;
default:
throw new ArgumentOutOfRangeException(nameof(curves), $"Unkown curve type: {curve.GetType()}.");
}
}
return list;
}
public static List<ICurve> FromArray(List<double> list)
{
var curves = new List<ICurve>();
if (list.Count == 0)
{
return curves;
}
var done = false;
var currentIndex = 0;
while (!done)
{
var itemLength = (int)list[currentIndex];
var item = list.GetRange(currentIndex, itemLength + 1);
switch (item[1])
{
case CurveTypeEncoding.Arc:
curves.Add(Arc.FromList(item));
break;
case CurveTypeEncoding.Circle:
curves.Add(Circle.FromList(item));
break;
case CurveTypeEncoding.Curve:
curves.Add(Curve.FromList(item));
break;
case CurveTypeEncoding.Ellipse:
curves.Add(Ellipse.FromList(item));
break;
case CurveTypeEncoding.Line:
curves.Add(Line.FromList(item));
break;
case CurveTypeEncoding.Polyline:
curves.Add(Polyline.FromList(item));
break;
case CurveTypeEncoding.PolyCurve:
curves.Add(Polycurve.FromList(item));
break;
}
currentIndex += itemLength + 1;
done = currentIndex >= list.Count;
}
return curves;
}
}
+165
View File
@@ -0,0 +1,165 @@
using Speckle.Newtonsoft.Json;
using Speckle.Objects.Other;
using Speckle.Objects.Primitive;
using Speckle.Sdk.Common;
using Speckle.Sdk.Models;
namespace Speckle.Objects.Geometry;
/// <summary>
/// Represents a sub-curve of a three-dimensional circle.
/// </summary>
[SpeckleType("Objects.Geometry.Arc")]
public class Arc : Base, IHasBoundingBox, ICurve, ITransformable<Arc>
{
/// <summary>
/// Gets or sets the plane of the <see cref="Arc"/>.
/// The plane origin is the <see cref="Arc"/> center.
/// The plane normal indicates the handedness of the <see cref="Arc"/> such that direction from <see cref="startPoint"/> to <see cref="endPoint"/> is counterclockwise.
/// </summary>
public required Plane plane { get; set; }
/// <summary>
/// The start <see cref="Point"/> of the <see cref="Arc"/>
/// </summary>
public required Point startPoint { get; set; }
/// <summary>
/// Gets or sets the point at 0.5 length.
/// </summary>
public required Point midPoint { get; set; }
/// <summary>
/// The end <see cref="Point"/> of the <see cref="Arc"/>
/// </summary>
public required Point endPoint { get; set; }
/// <summary>
/// The radius of the <see cref="Arc"/>
/// </summary>
public double radius => Point.Distance(plane.origin, startPoint);
/// <summary>
/// OBSOLETE - This is just here for backwards compatibility.
/// </summary>
[JsonIgnore, Obsolete("start angle should be calculated from arc startpoint and plane if needed", true)]
public double? startAngle { get; set; }
/// <summary>
/// OBSOLETE - This is just here for backwards compatibility.
/// </summary>
[JsonIgnore, Obsolete("end angle should be calculated from arc endpoint and plane if needed", true)]
public double? endAngle { get; set; }
/// <summary>
/// OBSOLETE - This is just here for backwards compatibility.
/// </summary>
[JsonIgnore, Obsolete("Refer to measure instead", true)]
public double angleRadians { get; set; }
/// <summary>
/// The measure of the <see cref="Arc"/> in radians.
/// Calculated using the arc addition postulate using the <see cref="midPoint"/>.
/// </summary>
public double measure =>
(2 * Math.Asin(Point.Distance(startPoint, midPoint) / (2 * radius)))
+ (2 * Math.Asin(Point.Distance(midPoint, endPoint) / (2 * radius)));
/// <summary>
/// The units this object was specified in.
/// </summary>
public required string units { get; set; }
/// <inheritdoc/>
public Interval domain { get; set; } = new() { start = 0, end = 0 };
/// <summary>
/// The length of the <see cref="Arc"/>
/// </summary>
public double length => radius * measure;
/// <summary>
/// OBSOLETE - This is just here for backwards compatibility.
/// </summary>
[JsonIgnore, Obsolete("Area property does not belong on an arc", true)]
public double area { get; set; }
/// <inheritdoc/>
public Box? bbox { get; set; }
/// <inheritdoc/>
public bool TransformTo(Transform transform, out Arc transformed)
{
startPoint.TransformTo(transform, out Point transformedStartPoint);
midPoint.TransformTo(transform, out Point transformedMidpoint);
endPoint.TransformTo(transform, out Point transformedEndPoint);
plane.TransformTo(transform, out Plane pln);
Arc arc = new()
{
startPoint = transformedStartPoint,
endPoint = transformedEndPoint,
midPoint = transformedMidpoint,
plane = pln,
domain = domain,
units = units,
};
transformed = arc;
return true;
}
/// <inheritdoc/>
public bool TransformTo(Transform transform, out ITransformable transformed)
{
var res = TransformTo(transform, out Arc arc);
transformed = arc;
return res;
}
/// <summary>
/// Creates a flat list with the values of the <see cref="Arc"/>
/// This is only used for serialisation purposes.
/// </summary>
/// <returns>A list of numbers representing the <see cref="Arc"/>'s value</returns>
public List<double> ToList()
{
var list = new List<double>();
list.Add(radius);
list.Add(0); // Backwards compatibility: start angle
list.Add(0); // Backwards compatibility: end angle
list.Add(measure);
list.Add(domain?.start ?? 0);
list.Add(domain?.end ?? 0);
list.AddRange(plane.ToList());
list.AddRange(startPoint.ToList());
list.AddRange(midPoint.ToList());
list.AddRange(endPoint.ToList());
list.Add(Units.GetEncodingFromUnit(units));
list.Insert(0, CurveTypeEncoding.Arc);
list.Insert(0, list.Count);
return list;
}
/// <summary>
/// Creates a new <see cref="Arc"/> instance based on a flat list of numerical values.
/// This is only used for deserialisation purposes.
/// </summary>
/// <remarks>The input list should be the result of having called <see cref="Arc.ToList"/></remarks>
/// <param name="list">A list of numbers</param>
/// <returns>A new <see cref="Arc"/> with the values assigned from the list.</returns>
public static Arc FromList(List<double> list)
{
string units = Units.GetUnitFromEncoding(list[^1]);
Arc arc = new()
{
domain = new Interval { start = list[6], end = list[7] },
units = units,
plane = Plane.FromList(list.GetRange(8, 13)),
startPoint = Point.FromList(list.GetRange(21, 3), units),
midPoint = Point.FromList(list.GetRange(24, 3), units),
endPoint = Point.FromList(list.GetRange(27, 3), units),
};
arc.plane.units = arc.units;
return arc;
}
}
@@ -0,0 +1,81 @@
using Speckle.Sdk.Models;
namespace Speckle.Objects.Geometry.Autocad;
/// <summary>
/// A curve that is comprised of line, arc and/or curve segments, representing the Autocad Polyline, Polyline2d, and Polyline3d classes.
/// </summary>
/// <remarks>
/// <see cref="AutocadPolyType.Light"/> and <see cref="AutocadPolyType.Simple2d"/> types will have only <see cref="Line"/>s and <see cref="Arc"/>s in <see cref="Polycurve.segments"/>.
/// <see cref="AutocadPolyType.Simple3d"/> type will have only <see cref="Line"/>s in <see cref="Polycurve.segments"/>.
/// <see cref="AutocadPolyType.FitCurve2d"/> type will only have <see cref="Arc"/>s in <see cref="Polycurve.segments"/>.
/// <see cref="AutocadPolyType.CubicSpline2d"/>, <see cref="AutocadPolyType.CubicSpline3d"/>, <see cref="AutocadPolyType.QuadSpline2d"/>, and <see cref="AutocadPolyType.QuadSpline3d"/> types will have only a single <see cref="Curve"/>s in <see cref="Polycurve.segments"/>.
/// </remarks>
[SpeckleType("Objects.Geometry.Autocad.AutocadPolycurve")]
public class AutocadPolycurve : Polycurve
{
/// <summary>
/// Gets or sets the raw coordinates of the vertices.
/// </summary>
/// <remarks>
/// For <see cref="AutocadPolyType.Light"/> Polylines, these are xy coordinates in the Object Coordinate System (OCS)/>.
/// For Polyline2d and Polyline3d types, these are xyz coordinates in the Global Coordinate System. fml.
/// </remarks>
[DetachProperty, Chunkable(31250)]
public required List<double> value { get; set; }
/// <summary>
/// The bulge factor at each vertex. Should be null for Polyline3d.
/// </summary>
/// <remarks>
/// The bulge factor is used to indicate how much of an arc segment is present at this vertex.
/// The bulge factor is the tangent of one fourth the included angle for an arc segment,
/// made negative if the arc goes clockwise from the start point to the endpoint.
/// A bulge of 0 indicates a straight segment, and a bulge of 1 is a semicircle.
/// </remarks>
public required List<double>? bulges { get; set; }
/// <summary>
/// The tangent in radians at each vertex. Should be null for Polyline and Polyline3d.
/// </summary>
public required List<double?>? tangents { get; set; }
/// <summary>
/// The normal of the plane of the Autocad Polyline or Polyline2d. Should be null for Polyline3d.
/// </summary>
public required Vector? normal { get; set; }
/// <summary>
/// The distance from the plane to the origin of the Autocad Polyline or Polyline2d. Should be null for Polyline3d.
/// </summary>
public double? elevation { get; set; }
public required AutocadPolyType polyType { get; set; }
}
/// <summary>
/// Represents the type of a Autocad Polyline.
/// </summary>
public enum AutocadPolyType
{
/// Polyline type is not known
Unknown,
/// Polyline type is the Autocad Polyline class
Light,
Simple2d,
Simple3d,
/// The Autocad Polyline2d fit curve poly type. Constructed with pairs of arcs with continuous tangents.
FitCurve2d,
CubicSpline2d,
CubicSpline3d,
QuadSpline2d,
QuadSpline3d,
}
+57
View File
@@ -0,0 +1,57 @@
using Speckle.Newtonsoft.Json;
using Speckle.Objects.Primitive;
using Speckle.Sdk.Common;
using Speckle.Sdk.Models;
namespace Speckle.Objects.Geometry;
/// <summary>
/// Represents a 3-dimensional box oriented on a plane.
/// </summary>
[SpeckleType("Objects.Geometry.Box")]
public class Box : Base, IHasVolume, IHasArea, IHasBoundingBox
{
[JsonIgnore, Obsolete("Use plane property instead", true)]
public Plane basePlane
{
get => plane;
set => plane = value;
}
/// <summary>
/// Gets or sets the plane that defines the orientation of the <see cref="Box"/>
/// </summary>
public required Plane plane { get; set; }
/// <summary>
/// Gets or sets the <see cref="Interval"/> that defines the min and max coordinate in the X direction
/// </summary>
public required Interval xSize { get; set; }
/// <summary>
/// Gets or sets the <see cref="Interval"/> that defines the min and max coordinate in the Y direction
/// </summary>
public required Interval ySize { get; set; }
/// <summary>
/// Gets or sets the <see cref="Interval"/> that defines the min and max coordinate in the Y direction
/// </summary>
public required Interval zSize { get; set; }
/// <summary>
/// The units this object's coordinates are in.
/// </summary>
/// <remarks>
/// This should be one of <see cref="Units"/>
/// </remarks>
public required string units { get; set; }
/// <inheritdoc/>
public double area => 2 * (xSize.Length * ySize.Length + xSize.Length * zSize.Length + ySize.Length * zSize.Length);
[JsonIgnore, Obsolete("Boxs should not have a bounding box", true)]
public Box? bbox { get; }
/// <inheritdoc/>
public double volume => xSize.Length * ySize.Length * zSize.Length;
}
+740
View File
@@ -0,0 +1,740 @@
using System.Runtime.Serialization;
using Speckle.Newtonsoft.Json;
using Speckle.Objects.Other;
using Speckle.Objects.Primitive;
using Speckle.Sdk.Common;
using Speckle.Sdk.Models;
namespace Speckle.Objects.Geometry;
/// <summary>
/// Represents a "Boundary Representation" Solid
/// </summary>
[SpeckleType("Objects.Geometry.Brep")]
public class Brep : Base, IHasArea, IHasVolume, IHasBoundingBox, ITransformable<Brep>, IDisplayValue<List<Mesh>>
{
/// <summary>
/// The unit's this object's coordinates are in.
/// </summary>
/// <remarks>
/// This should be one of <see cref="Units"/>
/// </remarks>
public required string units { get; set; }
/// <summary>
/// Gets or sets the list of surfaces in this <see cref="Brep"/> instance.
/// </summary>
[JsonIgnore]
public required List<Surface> Surfaces { get; set; }
/// <summary>
/// Gets or sets the flat list of numbers representing the <see cref="Brep"/>'s surfaces.
/// </summary>
[DetachProperty, Chunkable(31250)]
public List<double> SurfacesValue
{
get
{
var list = new List<double>();
foreach (var srf in Surfaces)
{
list.AddRange(srf.ToList());
}
return list;
}
set
{
if (value == null)
{
return;
}
var list = new List<Surface>();
var done = false;
var currentIndex = 0;
while (!done)
{
var len = (int)value[currentIndex];
list.Add(Surface.FromList(value.GetRange(currentIndex + 1, len)));
currentIndex += len + 1;
done = currentIndex >= value.Count;
}
Surfaces = list;
}
}
/// <summary>
/// Gets or sets the list of 3-dimensional curves in this <see cref="Brep"/> instance.
/// </summary>
[JsonIgnore]
public required List<ICurve> Curve3D { get; set; }
/// <summary>
/// Gets or sets the flat list of numbers representing the <see cref="Brep"/>'s 3D curves.
/// </summary>
/// <remarks>
/// This is only used for the <see cref="Brep"/> class serialisation/deserialisation. You should use <see cref="Brep.Curve3D"/> instead.
/// </remarks>
[DetachProperty, Chunkable(31250)]
public List<double> Curve3DValues
{
get => CurveArrayEncodingExtensions.ToArray(Curve3D);
set
{
if (value != null)
{
Curve3D = CurveArrayEncodingExtensions.FromArray(value);
}
}
}
/// <summary>
/// Gets or sets the list of 2-dimensional UV curves in this <see cref="Brep"/> instance.
/// </summary>
[JsonIgnore]
public required List<ICurve> Curve2D { get; set; }
/// <summary>
/// Gets or sets the flat list of numbers representing the <see cref="Brep"/>'s 2D curves.
/// </summary>
/// <remarks>
/// This is only used for the <see cref="Brep"/> class serialisation/deserialisation. You should use <see cref="Brep.Curve2D"/> instead.
/// </remarks>
[DetachProperty, Chunkable(31250)]
public List<double> Curve2DValues
{
get => CurveArrayEncodingExtensions.ToArray(Curve2D);
set
{
if (value != null)
{
Curve2D = CurveArrayEncodingExtensions.FromArray(value);
}
}
}
/// <summary>
/// Gets or sets the list of vertices in this <see cref="Brep"/> instance.
/// </summary>
[JsonIgnore]
public required List<Point> Vertices { get; set; }
/// <summary>
/// Gets or sets the flat list of numbers representing the <see cref="Brep"/>'s vertices.
/// </summary>
/// <remarks>
/// This is only used for the <see cref="Brep"/> class serialisation/deserialisation. You should use <see cref="Brep.Vertices"/> instead.
/// </remarks>
[DetachProperty, Chunkable(31250)]
public List<double> VerticesValue
{
get
{
var list = new List<double>((Vertices.Count * 3) + 1);
list.Add(Units.GetEncodingFromUnit(units));
foreach (var vertex in Vertices)
{
list.AddRange(vertex.ToList());
}
return list;
}
set
{
if (value != null)
{
var units = value.Count % 3 == 0 ? Units.None : Units.GetUnitFromEncoding(value[0]);
Vertices = new(value.Count / 3);
for (int i = value.Count % 3 == 0 ? 0 : 1; i < value.Count; i += 3)
{
Vertices.Add(new Point(value[i], value[i + 1], value[i + 2], units));
}
}
}
}
/// <summary>
/// Gets or sets the list of edges in this <see cref="Brep"/> instance.
/// </summary>
[JsonIgnore]
public required List<BrepEdge> Edges { get; set; }
/// <summary>
/// Gets or sets the flat list of numbers representing the <see cref="Brep"/>'s edges.
/// </summary>
/// <remarks>
/// This is only used for the <see cref="Brep"/> class serialisation/deserialisation. You should use <see cref="Brep.Edges"/> instead.
/// </remarks>
[DetachProperty, Chunkable(62500)]
public List<double?> EdgesValue
{
get =>
Edges
.SelectMany(e =>
{
var ints = new List<double?>();
ints.Add(e.Curve3dIndex);
ints.Add(e.StartIndex);
ints.Add(e.EndIndex);
ints.Add(Convert.ToInt32(e.ProxyCurveIsReversed));
ints.Add(e.Domain.start);
ints.Add(e.Domain.end);
ints.AddRange(e.TrimIndices.Select(Convert.ToDouble).Cast<double?>());
return ints.Prepend(ints.Count);
})
.ToList();
set
{
Edges = new List<BrepEdge>();
if (value == null || value.Count == 0)
{
return;
}
var i = 0;
while (i < value.Count)
{
int n = Convert.ToInt32(value[i]);
var loopValues = value.GetRange(i + 1, n);
var curve3dIndex = Convert.ToInt32(loopValues[0]);
var startIndex = Convert.ToInt32(loopValues[1]);
var endIndex = Convert.ToInt32(loopValues[2]);
var proxyReversed = Convert.ToBoolean(loopValues[3]);
var domainStart = loopValues[4];
var domainEnd = loopValues[5];
Interval domain =
domainStart.HasValue && domainEnd.HasValue
? new() { start = domainStart.Value, end = domainEnd.Value }
: Interval.UnitInterval;
var trimIndices = loopValues.GetRange(6, loopValues.Count - 6).Select(d => Convert.ToInt32(d)).ToArray();
var edge = new BrepEdge
{
Brep = this,
Curve3dIndex = curve3dIndex,
TrimIndices = trimIndices,
StartIndex = startIndex,
EndIndex = endIndex,
ProxyCurveIsReversed = proxyReversed,
Domain = domain,
};
Edges.Add(edge);
i += n + 1;
}
}
}
/// <summary>
/// Gets or sets the list of closed UV loops in this <see cref="Brep"/> instance.
/// </summary>
[JsonIgnore]
public required List<BrepLoop> Loops { get; set; }
/// <summary>
/// Gets or sets the flat list of numbers representing the <see cref="Brep"/>'s loops.
/// </summary>
/// <remarks>
/// This is only used for the <see cref="Brep"/> class serialisation/deserialisation. You should use <see cref="Brep.Loops"/> instead.
/// </remarks>
[DetachProperty, Chunkable(62500)]
public List<int> LoopsValue
{
get =>
Loops
.SelectMany(l =>
{
var ints = new List<int>();
ints.Add(l.FaceIndex);
ints.Add((int)l.Type);
ints.AddRange(l.TrimIndices);
return ints.Prepend(ints.Count);
})
.ToList();
set
{
Loops = new List<BrepLoop>();
if (value == null || value.Count == 0)
{
return;
}
var i = 0;
while (i < value.Count)
{
int n = value[i];
var loopValues = value.GetRange(i + 1, n);
var faceIndex = loopValues[0];
var type = (BrepLoopType)loopValues[1];
var trimIndices = loopValues.GetRange(2, loopValues.Count - 2);
var loop = new BrepLoop
{
Brep = this,
FaceIndex = faceIndex,
TrimIndices = trimIndices,
Type = type,
};
Loops.Add(loop);
i += n + 1;
}
}
}
/// <summary>
/// Gets or sets the list of UV trim segments for each surface in this <see cref="Brep"/> instance.
/// </summary>
[JsonIgnore]
public required List<BrepTrim> Trims { get; set; }
/// <summary>
/// Gets or sets the flat list of numbers representing the <see cref="Brep"/>'s trims.
/// </summary>
/// <remarks>
/// This is only used for the <see cref="Brep"/> class serialisation/deserialisation. You should use <see cref="Brep.Trims"/> instead.
/// </remarks>
[DetachProperty, Chunkable(62500)]
public List<int> TrimsValue
{
get
{
List<int> list = new(Trims.Count * TRIMS_ENCODING_LENGTH);
foreach (var trim in Trims)
{
list.Add(trim.EdgeIndex);
list.Add(trim.StartIndex);
list.Add(trim.EndIndex);
list.Add(trim.FaceIndex);
list.Add(trim.LoopIndex);
list.Add(trim.CurveIndex);
list.Add(trim.IsoStatus);
list.Add((int)trim.TrimType);
list.Add(trim.IsReversed ? 1 : 0);
}
return list;
}
set
{
if (value == null)
{
return;
}
var list = new List<BrepTrim>(value.Count / TRIMS_ENCODING_LENGTH);
for (int i = 0; i < value.Count; i += TRIMS_ENCODING_LENGTH)
{
var trim = new BrepTrim
{
Brep = this,
EdgeIndex = value[i],
StartIndex = value[i + 1],
EndIndex = value[i + 2],
FaceIndex = value[i + 3],
LoopIndex = value[i + 4],
CurveIndex = value[i + 5],
IsoStatus = value[i + 6],
TrimType = (BrepTrimType)value[i + 7],
IsReversed = value[i + 8] == 1,
Domain = Interval.UnitInterval, //TODO: This is a problem, see CXPLA-28
};
list.Add(trim);
}
Trims = list;
}
}
private const int TRIMS_ENCODING_LENGTH = 9;
/// <summary>
/// Gets or sets the list of faces in this <see cref="Brep"/> instance.
/// </summary>
[JsonIgnore]
public required List<BrepFace> Faces { get; set; }
/// <summary>
/// Gets or sets the flat list of numbers representing the <see cref="Brep"/>'s faces.
/// </summary>
/// <remarks>
/// This is only used for the <see cref="Brep"/> class serialisation/deserialisation. You should use <see cref="Brep.Faces"/> instead.
/// </remarks>
[DetachProperty, Chunkable(62500)]
public List<int> FacesValue
{
get =>
Faces
.SelectMany(f =>
{
var ints = new List<int>();
ints.Add(f.SurfaceIndex);
ints.Add(f.OuterLoopIndex);
ints.Add(f.OrientationReversed ? 1 : 0);
ints.AddRange(f.LoopIndices);
return ints.Prepend(ints.Count);
})
.ToList();
set
{
if (value == null || value.Count == 0)
{
return;
}
Faces = new List<BrepFace>();
var i = 0;
while (i < value.Count)
{
int n = value[i];
var faceValues = value.GetRange(i + 1, n);
var surfIndex = faceValues[0];
var outerLoopIndex = faceValues[1];
var orientationIsReversed = faceValues[2] == 1;
var loopIndices = faceValues.GetRange(3, faceValues.Count - 3);
var face = new BrepFace
{
Brep = this,
SurfaceIndex = surfIndex,
LoopIndices = loopIndices,
OuterLoopIndex = outerLoopIndex,
OrientationReversed = orientationIsReversed,
};
Faces.Add(face);
i += n + 1;
}
}
}
/// <summary>
/// Gets or sets if this <see cref="Brep"/> instance is closed or not.
/// </summary>
public required bool IsClosed { get; set; }
/// <summary>
/// Gets or sets the list of surfaces in this <see cref="Brep"/> instance.
/// </summary>
public required BrepOrientation Orientation { get; set; }
/// <inheritdoc/>
[DetachProperty]
public required List<Mesh> displayValue { get; set; }
/// <inheritdoc/>
public double area { get; set; }
/// <inheritdoc/>
public Box? bbox { get; set; }
/// <inheritdoc/>
public double volume { get; set; }
/// <inheritdoc/>
public bool TransformTo(Transform transform, out Brep transformed)
{
// transform display values
var displayValues = new List<Mesh>(displayValue.Count);
foreach (Mesh v in displayValue)
{
v.TransformTo(transform, out Mesh mesh);
displayValues.Add(mesh);
}
// transform surfaces
var surfaces = new List<Surface>(Surfaces.Count);
foreach (var srf in Surfaces)
{
srf.TransformTo(transform, out Surface surface);
surfaces.Add(surface);
}
// transform curve3d
var success3D = true;
var transformedCurve3D = new List<ICurve>();
foreach (var curve in Curve3D)
{
if (curve is ITransformable c)
{
c.TransformTo(transform, out ITransformable tc);
transformedCurve3D.Add((ICurve)tc);
}
else
{
success3D = false;
}
}
// transform vertices
var transformedVertices = new List<Point>(Vertices.Count);
foreach (var vertex in Vertices)
{
vertex.TransformTo(transform, out Point transformedVertex);
transformedVertices.Add(transformedVertex);
}
transformed = new Brep
{
units = units,
displayValue = displayValues,
Surfaces = surfaces,
Curve3D = transformedCurve3D,
Curve2D = new List<ICurve>(Curve2D),
Vertices = transformedVertices,
Edges = new List<BrepEdge>(Edges.Count),
Loops = new List<BrepLoop>(Loops.Count),
Trims = new List<BrepTrim>(Trims.Count),
Faces = new List<BrepFace>(Faces.Count),
IsClosed = IsClosed,
Orientation = Orientation,
applicationId = applicationId ?? id,
};
foreach (var e in Edges)
{
transformed.Edges.Add(
new BrepEdge
{
Brep = transformed,
Curve3dIndex = e.Curve3dIndex,
TrimIndices = e.TrimIndices,
StartIndex = e.StartIndex,
EndIndex = e.EndIndex,
ProxyCurveIsReversed = e.ProxyCurveIsReversed,
Domain = e.Domain,
}
);
}
foreach (var l in Loops)
{
transformed.Loops.Add(
new BrepLoop
{
Brep = transformed,
FaceIndex = l.FaceIndex,
TrimIndices = l.TrimIndices,
Type = l.Type,
}
);
}
foreach (var t in Trims)
{
transformed.Trims.Add(
new BrepTrim
{
Brep = transformed,
EdgeIndex = t.EdgeIndex,
FaceIndex = t.FaceIndex,
LoopIndex = t.LoopIndex,
CurveIndex = t.CurveIndex,
IsoStatus = t.IsoStatus,
TrimType = t.TrimType,
IsReversed = t.IsReversed,
StartIndex = t.StartIndex,
EndIndex = t.EndIndex,
Domain = null!,
}
);
}
foreach (var f in Faces)
{
transformed.Faces.Add(
new BrepFace
{
Brep = transformed,
SurfaceIndex = f.SurfaceIndex,
LoopIndices = f.LoopIndices,
OuterLoopIndex = f.OuterLoopIndex,
OrientationReversed = f.OrientationReversed,
}
);
}
return success3D;
}
/// <inheritdoc/>
public bool TransformTo(Transform transform, out ITransformable transformed)
{
var res = TransformTo(transform, out Brep brep);
transformed = brep;
return res;
}
[OnDeserialized]
internal void OnDeserialized(StreamingContext context)
{
Surfaces.ForEach(s => s.units = units);
for (var i = 0; i < Edges.Count; i++)
{
var e = Edges[i];
var existing = e;
lock (existing)
{
if (e.Brep != null)
{
e = new BrepEdge
{
Brep = this,
Curve3dIndex = e.Curve3dIndex,
TrimIndices = e.TrimIndices,
StartIndex = e.StartIndex,
EndIndex = e.EndIndex,
ProxyCurveIsReversed = e.ProxyCurveIsReversed,
Domain = e.Domain,
};
Edges[i] = e;
}
else
{
e.Brep = this;
}
}
}
for (var i = 0; i < Loops.Count; i++)
{
var l = Loops[i];
var existingLoop = l;
lock (existingLoop)
{
if (l.Brep != null)
{
l = new BrepLoop
{
Brep = this,
FaceIndex = l.FaceIndex,
TrimIndices = l.TrimIndices,
Type = l.Type,
};
Loops[i] = l;
}
else
{
l.Brep = this;
}
}
}
for (var i = 0; i < Trims.Count; i++)
{
var t = Trims[i];
var existingTrim = t;
lock (existingTrim)
{
if (t.Brep != null)
{
t = new BrepTrim
{
Brep = this,
EdgeIndex = t.EdgeIndex,
LoopIndex = t.LoopIndex,
CurveIndex = t.CurveIndex,
IsoStatus = t.IsoStatus,
TrimType = t.TrimType,
IsReversed = t.IsReversed,
StartIndex = t.StartIndex,
EndIndex = t.EndIndex,
FaceIndex = t.FaceIndex,
Domain = Interval.UnitInterval, //TODO: This is a problem, see CXPLA-28
};
Trims[i] = t;
}
else
{
t.Brep = this;
}
}
}
for (var i = 0; i < Faces.Count; i++)
{
var f = Faces[i];
var existingFace = f;
lock (existingFace)
{
if (f.Brep != null)
{
f = new BrepFace
{
Brep = this,
SurfaceIndex = f.SurfaceIndex,
LoopIndices = f.LoopIndices,
OuterLoopIndex = f.OuterLoopIndex,
OrientationReversed = f.OrientationReversed,
};
Faces[i] = f;
}
else
{
f.Brep = this;
}
}
}
}
}
/// <summary>
/// Represents the orientation of a <see cref="Brep"/>
/// </summary>
public enum BrepOrientation
{
/// Brep has no specific orientation
None = 0,
/// Brep faces inward
Inward = -1,
/// Brep faces outward
Outward = 1,
/// Orientation is not known
Unknown = 2,
}
/// <summary>
/// Represents the type of a loop in a <see cref="Brep"/>'s face.
/// </summary>
public enum BrepLoopType
{
/// Loop type is not known
Unknown,
/// Loop is the outer loop of a face
Outer,
/// Loop is an inner loop of a face
Inner,
/// Loop is a closed curve with no area.
Slit,
/// Loop represents a curve on a surface
CurveOnSurface,
/// Loop is collapsed to a point.
PointOnSurface,
}
/// <summary>
/// Represents the type of a trim in a <see cref="Brep"/>'s loop.
/// </summary>
public enum BrepTrimType
{
Unknown,
Boundary,
Mated,
Seam,
Singular,
CurveOnSurface,
PointOnSurface,
Slit,
}
+36
View File
@@ -0,0 +1,36 @@
using Speckle.Newtonsoft.Json;
using Speckle.Objects.Primitive;
using Speckle.Sdk.Models;
namespace Speckle.Objects.Geometry;
/// <summary>
/// Represents an edge of the <see cref="Brep"/>.
/// </summary>
[SpeckleType("Objects.Geometry.BrepEdge")]
public class BrepEdge : Base
{
[JsonIgnore]
public required Brep Brep { get; set; }
public required int Curve3dIndex { get; set; }
public required int[] TrimIndices { get; set; }
public required int StartIndex { get; set; }
public required int EndIndex { get; set; }
public required bool ProxyCurveIsReversed { get; set; }
public required Interval Domain { get; set; }
[JsonIgnore]
public Point StartVertex => Brep.Vertices[StartIndex];
[JsonIgnore]
public Point EndVertex => Brep.Vertices[EndIndex];
[JsonIgnore]
public IEnumerable<BrepTrim> Trims => TrimIndices.Select(i => Brep.Trims[i]);
[JsonIgnore]
public ICurve Curve => Brep.Curve3D[Curve3dIndex];
}
+28
View File
@@ -0,0 +1,28 @@
using Speckle.Newtonsoft.Json;
using Speckle.Sdk.Models;
namespace Speckle.Objects.Geometry;
/// <summary>
/// Represents a face on a <see cref="Brep"/>
/// </summary>
[SpeckleType("Objects.Geometry.BrepFace")]
public class BrepFace : Base
{
[JsonIgnore]
public required Brep Brep { get; set; }
public required int SurfaceIndex { get; set; }
public required List<int> LoopIndices { get; set; }
public required int OuterLoopIndex { get; set; }
public required bool OrientationReversed { get; set; }
[JsonIgnore]
public BrepLoop OuterLoop => Brep.Loops[OuterLoopIndex];
[JsonIgnore]
public Surface Surface => Brep.Surfaces[SurfaceIndex];
[JsonIgnore]
public List<BrepLoop> Loops => LoopIndices.Select(i => Brep.Loops[i]).ToList();
}
+24
View File
@@ -0,0 +1,24 @@
using Speckle.Newtonsoft.Json;
using Speckle.Sdk.Models;
namespace Speckle.Objects.Geometry;
/// <summary>
/// Represents a UV Trim Closed Loop on one of the <see cref="Brep"/>'s surfaces.
/// </summary>
[SpeckleType("Objects.Geometry.BrepLoop")]
public class BrepLoop : Base
{
[JsonIgnore]
public required Brep Brep { get; set; }
public required int FaceIndex { get; set; }
public required List<int> TrimIndices { get; set; }
public required BrepLoopType Type { get; set; }
[JsonIgnore]
public BrepFace Face => Brep.Faces[FaceIndex];
[JsonIgnore]
public List<BrepTrim> Trims => TrimIndices.Select(i => Brep.Trims[i]).ToList();
}
+38
View File
@@ -0,0 +1,38 @@
using Speckle.Newtonsoft.Json;
using Speckle.Objects.Primitive;
using Speckle.Sdk.Models;
namespace Speckle.Objects.Geometry;
/// <summary>
/// Represents a UV Trim curve for one of the <see cref="Brep"/>'s surfaces.
/// </summary>
[SpeckleType("Objects.Geometry.BrepTrim")]
public class BrepTrim : Base
{
[JsonIgnore]
public required Brep Brep { get; set; }
public required int EdgeIndex { get; set; }
public required int StartIndex { get; set; }
public required int EndIndex { get; set; }
public required int FaceIndex { get; set; }
public required int LoopIndex { get; set; }
public required int CurveIndex { get; set; }
public required int IsoStatus { get; set; }
public required BrepTrimType TrimType { get; set; }
public required bool IsReversed { get; set; }
public required Interval Domain { get; set; }
[JsonIgnore]
public BrepFace Face => Brep.Faces[FaceIndex];
[JsonIgnore]
public BrepLoop Loop => Brep.Loops[LoopIndex];
[JsonIgnore]
public BrepEdge? Edge => EdgeIndex != -1 ? Brep.Edges[EdgeIndex] : null;
[JsonIgnore]
public ICurve Curve2d => Brep.Curve2D[CurveIndex];
}
+33
View File
@@ -0,0 +1,33 @@
using Speckle.Objects.Other;
using Speckle.Sdk.Models;
namespace Speckle.Objects.Geometry;
public interface IRawEncodedObject
{
public RawEncoding encodedValue { get; set; }
}
public abstract class RawEncodedObject : Base, IDisplayValue<List<Mesh>>, IRawEncodedObject, IHasArea, IHasVolume
{
[DetachProperty]
public required List<Mesh> displayValue { get; set; }
[DetachProperty]
public required RawEncoding encodedValue { get; set; }
public required string units { get; set; }
public double area { get; set; }
public double volume { get; set; }
}
[SpeckleType("Objects.Geometry.BrepX")]
public class BrepX : RawEncodedObject;
[SpeckleType("Objects.Geometry.ExtrusionX")]
public class ExtrusionX : RawEncodedObject;
[SpeckleType("Objects.Geometry.SubDX")]
public class SubDX : RawEncodedObject;
+82
View File
@@ -0,0 +1,82 @@
using Speckle.Objects.Primitive;
using Speckle.Sdk.Common;
using Speckle.Sdk.Models;
namespace Speckle.Objects.Geometry;
/// <summary>
/// Represents a circular curve based on a base <see cref="Plane"/> and a <see cref="double"/> as radius.
/// </summary>
/// <remarks>
/// These circles are expected to be full (untrimmed) circles.
/// For trimmed circles, convert them as <see cref="Arc"/>s instead
/// </remarks>
[SpeckleType("Objects.Geometry.Circle")]
public class Circle : Base, ICurve, IHasArea, IHasBoundingBox
{
/// <summary>
/// The radius of the circle
/// </summary>
public required double radius { get; set; }
/// <summary>
/// The <see cref="Plane"/> the circle lies in.
/// </summary>
public required Plane plane { get; set; }
/// <summary>
/// The units this object was modeled in.
/// </summary>
public required string units { get; set; }
/// <inheritdoc/>
public Interval domain { get; set; } = Interval.UnitInterval;
/// <inheritdoc/>
public double length => 2 * Math.PI * radius;
//public Point center { get; set; }
/// <inheritdoc/>
public double area => Math.PI * radius * radius;
/// <inheritdoc/>
public Box? bbox { get; set; }
/// <summary>
/// Returns the coordinates of this <see cref="Circle"/> as a list of numbers
/// </summary>
/// <returns>A list of values representing the <see cref="Circle"/></returns>
public List<double> ToList()
{
var list = new List<double>();
list.Add(radius);
list.Add(domain.start);
list.Add(domain.end);
list.AddRange(plane.ToList());
list.Add(Units.GetEncodingFromUnit(units));
list.Insert(0, CurveTypeEncoding.Circle);
list.Insert(0, list.Count);
return list;
}
/// <summary>
/// Creates a new <see cref="Circle"/> based on a list of coordinates and the unit they're drawn in.
/// </summary>
/// <param name="list">The list of values representing this <see cref="Circle"/></param>
/// <returns>A new <see cref="Circle"/> with the provided values.</returns>
public static Circle FromList(List<double> list)
{
var circle = new Circle
{
radius = list[2],
domain = new Interval { start = list[3], end = list[4] },
plane = Plane.FromList(list.GetRange(5, 13)),
units = Units.GetUnitFromEncoding(list[^1]),
};
return circle;
}
}
@@ -0,0 +1,72 @@
using System.Diagnostics.CodeAnalysis;
using Speckle.Newtonsoft.Json;
using Speckle.Objects.Other;
using Speckle.Sdk.Models;
namespace Speckle.Objects.Geometry;
[SpeckleType("Objects.Geometry.ControlPoint")]
public class ControlPoint : Point, ITransformable<ControlPoint>
{
public ControlPoint() { }
[SetsRequiredMembers]
public ControlPoint(double x, double y, double z, double w, string units, string? applicationId = null)
: base(x, y, z, units, applicationId)
{
weight = w;
}
public required double weight { get; set; }
/// <summary>
/// OBSOLETE - This is just here for backwards compatibility.
/// </summary>
[
JsonProperty(NullValueHandling = NullValueHandling.Ignore),
Obsolete("Access coordinates using XYZ and weight fields", true)
]
private new List<double> value
{
#pragma warning disable CS8603 // Possible null reference return. Reason: obsolete.
get => null;
#pragma warning restore CS8603 // Possible null reference return. Reason: obsolete.
set
{
x = value[0];
y = value[1];
z = value[2];
weight = value.Count > 3 ? value[3] : 1;
}
}
public bool TransformTo(Transform transform, out ControlPoint transformed)
{
TransformTo(transform, out Point transformedPoint);
transformed = new ControlPoint(
transformedPoint.x,
transformedPoint.y,
transformedPoint.z,
weight,
units,
applicationId
);
return true;
}
public override string ToString()
{
return $"{{{x},{y},{z},{weight}}}";
}
public void Deconstruct(out double x, out double y, out double z, out double weight)
{
Deconstruct(out x, out y, out z, out weight, out _);
}
public void Deconstruct(out double x, out double y, out double z, out double weight, out string? units)
{
Deconstruct(out x, out y, out z, out units);
weight = this.weight;
}
}
+190
View File
@@ -0,0 +1,190 @@
using Speckle.Objects.Other;
using Speckle.Objects.Primitive;
using Speckle.Sdk;
using Speckle.Sdk.Common;
using Speckle.Sdk.Models;
namespace Speckle.Objects.Geometry;
[SpeckleType("Objects.Geometry.Curve")]
public class Curve : Base, ICurve, IHasBoundingBox, IHasArea, ITransformable<Curve>, IDisplayValue<Polyline>
{
public required int degree { get; set; }
public required bool periodic { get; set; }
/// <summary>
/// "True" if weights differ, "False" if weights are the same.
/// </summary>
public required bool rational { get; set; }
[DetachProperty, Chunkable(31250)]
public required List<double> points { get; set; }
/// <summary>
/// Gets or sets the weights for this <see cref="Curve"/>. Use a default value of 1 for unweighted points.
/// </summary>
[DetachProperty, Chunkable(31250)]
public required List<double> weights { get; set; }
/// <summary>
/// Gets or sets the knots for this <see cref="Curve"/>. Count should be equal to <see cref="points"/> count + <see cref="degree"/> + 1.
/// </summary>
[DetachProperty, Chunkable(31250)]
public required List<double> knots { get; set; }
public required bool closed { get; set; }
/// <summary>
/// The units this object was specified in.
/// </summary>
public required string units { get; set; }
/// <inheritdoc/>
public Interval domain { get; set; } = Interval.UnitInterval;
/// <inheritdoc/>
public double length { get; set; }
/// <inheritdoc/>
[DetachProperty]
public required Polyline displayValue { get; set; }
/// <inheritdoc/>
public double area { get; set; }
/// <inheritdoc/>
public Box? bbox { get; set; }
/// <inheritdoc/>
public bool TransformTo(Transform transform, out Curve transformed)
{
// transform points
var transformedPoints = new List<Point>();
foreach (var point in GetPoints())
{
point.TransformTo(transform, out Point transformedPoint);
transformedPoints.Add(transformedPoint);
}
var result = displayValue.TransformTo(transform, out ITransformable polyline);
transformed = new Curve
{
degree = degree,
periodic = periodic,
rational = rational,
points = transformedPoints.SelectMany(o => o.ToList()).ToList(),
weights = weights,
knots = knots,
displayValue = (Polyline)polyline,
closed = closed,
units = units,
applicationId = applicationId,
domain = domain != null ? new Interval { start = domain.start, end = domain.end } : Interval.UnitInterval,
};
return result;
}
/// <inheritdoc/>
public bool TransformTo(Transform transform, out ITransformable transformed)
{
var res = TransformTo(transform, out Curve curve);
transformed = curve;
return res;
}
/// <returns><see cref="points"/> as list of <see cref="Point"/>s</returns>
/// <exception cref="SpeckleException">when list is malformed</exception>
public List<Point> GetPoints()
{
if (points.Count % 3 != 0)
{
throw new SpeckleException(
$"{nameof(Curve)}.{nameof(points)} list is malformed: expected length to be multiple of 3"
);
}
var pts = new List<Point>(points.Count / 3);
for (int i = 2; i < points.Count; i += 3)
{
pts.Add(new Point(points[i - 2], points[i - 1], points[i], units));
}
return pts;
}
/// <summary>
/// Returns the values of this <see cref="Curve"/> as a list of numbers.
/// </summary>
/// <returns>A list of values representing the <see cref="Curve"/></returns>
/// <remarks>
/// This is currently only used for encoding optimization in curves in breps!
/// </remarks>
public List<double> ToList()
{
var list = new List<double>();
var curve = this;
list.Add(curve.degree); // 0
list.Add(curve.periodic ? 1 : 0); // 1
list.Add(curve.rational ? 1 : 0); // 2
list.Add(curve.closed ? 1 : 0); // 3
list.Add(curve.domain?.start ?? 0); // 4
list.Add(curve.domain?.end ?? 1); // 5
list.Add(curve.points.Count); // 6
list.Add(curve.weights.Count); // 7
list.Add(curve.knots.Count); // 8
list.AddRange(curve.points); // 9 onwards
list.AddRange(curve.weights);
list.AddRange(curve.knots);
list.Add(Units.GetEncodingFromUnit(units));
list.Insert(0, CurveTypeEncoding.Curve);
list.Insert(0, list.Count);
return list;
}
/// <summary>
/// Creates a new <see cref="Curve"/> based on a list of coordinates and the unit they're drawn in.
/// </summary>
/// <param name="list">The list of values representing this <see cref="Curve"/></param>
/// <returns>A new <see cref="Curve"/> with the provided values.</returns>
/// <remarks>
/// This is currently being used only for deserialization of Brep curves!
/// </remarks>
public static Curve FromList(List<double> list)
{
if ((int)list[0] != list.Count - 1)
{
throw new ArgumentException($"Incorrect length. Expected {list[0]}, got {list.Count}", nameof(list));
}
if (list[1] != CurveTypeEncoding.Curve)
{
throw new ArgumentException($"Wrong curve type. Expected {CurveTypeEncoding.Curve}, got {list[1]}", nameof(list));
}
var pointsCount = (int)list[8];
var weightsCount = (int)list[9];
var knotsCount = (int)list[10];
string units = Units.GetUnitFromEncoding(list[^1]);
var curve = new Curve
{
degree = (int)list[2],
periodic = (int)list[3] == 1,
rational = (int)list[4] == 1,
closed = (int)list[5] == 1,
domain = new Interval { start = list[6], end = list[7] },
displayValue = new Polyline { value = new(), units = units }, // this is unique to breps, so we do not create curves with null displayValues
points = list.GetRange(11, pointsCount),
weights = list.GetRange(11 + pointsCount, weightsCount),
knots = list.GetRange(11 + pointsCount + weightsCount, knotsCount),
units = units,
};
return curve;
}
}
+76
View File
@@ -0,0 +1,76 @@
using Speckle.Objects.Primitive;
using Speckle.Sdk.Common;
using Speckle.Sdk.Models;
namespace Speckle.Objects.Geometry;
[SpeckleType("Objects.Geometry.Ellipse")]
public class Ellipse : Base, ICurve, IHasArea
{
/// <summary>
/// Gets or sets the first radius of the <see cref="Ellipse"/>. This is usually the major radius.
/// </summary>
public required double firstRadius { get; set; }
/// <summary>
/// Gets or sets the second radius of the <see cref="Ellipse"/>. This is usually the minor radius.
/// </summary>
public required double secondRadius { get; set; }
/// <summary>
/// Gets or sets the plane to draw this ellipse in.
/// </summary>
public required Plane plane { get; set; }
/// <summary>
/// Gets or set the domain interval to trim this <see cref="Ellipse"/> with.
/// </summary>
public Interval? trimDomain { get; set; }
/// <inheritdoc />
public Box? bbox { get; set; }
public required string units { get; set; }
/// <summary>
/// Gets or sets the domain interval for this <see cref="Ellipse"/>.
/// </summary>
public required Interval domain { get; set; }
/// <inheritdoc />
public double length { get; set; }
//public Point center { get; set; }
/// <inheritdoc />
public double area { get; set; }
public List<double> ToList()
{
var list = new List<double>();
list.Add(firstRadius);
list.Add(secondRadius);
list.Add(domain.start);
list.Add(domain.end);
list.AddRange(plane.ToList());
list.Add(Units.GetEncodingFromUnit(units));
list.Insert(0, CurveTypeEncoding.Ellipse);
list.Insert(0, list.Count);
return list;
}
public static Ellipse FromList(List<double> list)
{
var ellipse = new Ellipse
{
firstRadius = list[2],
secondRadius = list[3],
domain = new Interval { start = list[4], end = list[5] },
plane = Plane.FromList(list.GetRange(6, 13)),
units = Units.GetUnitFromEncoding(list[^1]),
};
return ellipse;
}
}
+122
View File
@@ -0,0 +1,122 @@
using System.Diagnostics.CodeAnalysis;
using Speckle.Newtonsoft.Json;
using Speckle.Objects.Other;
using Speckle.Objects.Primitive;
using Speckle.Sdk.Common;
using Speckle.Sdk.Models;
namespace Speckle.Objects.Geometry;
[SpeckleType("Objects.Geometry.Line")]
public class Line : Base, ICurve, IHasBoundingBox, ITransformable<Line>
{
public Line() { }
/// <param name="coordinates"></param>
/// <param name="units"></param>
/// <param name="applicationId"></param>
/// <exception cref="ArgumentException"><paramref name="coordinates"/> must have a length of 6</exception>
[SetsRequiredMembers]
public Line(IList<double> coordinates, string units, string? applicationId = null)
{
if (coordinates.Count < 6)
{
throw new ArgumentException("Line from coordinate array requires 6 coordinates.", nameof(coordinates));
}
start = new Point(coordinates[0], coordinates[1], coordinates[2], units, applicationId);
end = new Point(coordinates[3], coordinates[4], coordinates[5], units, applicationId);
this.units = units;
this.applicationId = applicationId;
}
/// <summary>
/// OBSOLETE - This is just here for backwards compatibility.
/// You should not use this for anything.
/// </summary>
[JsonIgnore, Obsolete("Area should not be on the line class", true)]
public double area => 0;
public required string units { get; set; }
public required Point start { get; set; }
public required Point end { get; set; }
public Interval domain { get; set; } = Interval.UnitInterval;
public double length => Point.Distance(start, end);
public Box? bbox { get; set; }
public bool TransformTo(Transform transform, out Line transformed)
{
start.TransformTo(transform, out Point transformedStart);
end.TransformTo(transform, out Point transformedEnd);
transformed = new Line
{
start = transformedStart,
end = transformedEnd,
applicationId = applicationId,
units = units,
domain = new() { start = domain.start, end = domain.end },
};
return true;
}
public bool TransformTo(Transform transform, out ITransformable transformed)
{
var res = TransformTo(transform, out Line line);
transformed = line;
return res;
}
public List<double> ToList()
{
var list = new List<double>();
list.AddRange(start.ToList());
list.AddRange(end.ToList());
list.Add(domain?.start ?? 0);
list.Add(domain?.end ?? 1);
list.Add(Units.GetEncodingFromUnit(units));
list.Insert(0, CurveTypeEncoding.Line);
list.Insert(0, list.Count);
return list;
}
public static Line FromList(IReadOnlyList<double> list)
{
var units = Units.GetUnitFromEncoding(list[^1]);
var startPt = new Point(list[2], list[3], list[4], units);
var endPt = new Point(list[5], list[6], list[7], units);
var line = new Line
{
start = startPt,
end = endPt,
units = units,
domain = new Interval { start = list[8], end = list[9] },
};
return line;
}
/// <summary>
/// OBSOLETE - This is just here for backwards compatibility.
/// You should not use this for anything. Access coordinates using start and end point.
/// </summary>
[
JsonProperty(NullValueHandling = NullValueHandling.Ignore),
Obsolete("Access coordinates using start and end point", true)
]
public List<double>? value
{
get => null;
set
{
if (value == null)
{
return;
}
start = new Point(value[0], value[1], value[2], Units.Meters);
end = new Point(value[3], value[4], value[5], Units.Meters);
}
}
}
+169
View File
@@ -0,0 +1,169 @@
using System.Diagnostics.Contracts;
using Speckle.Newtonsoft.Json;
using Speckle.Objects.Other;
using Speckle.Objects.Utils;
using Speckle.Sdk;
using Speckle.Sdk.Common;
using Speckle.Sdk.Models;
namespace Speckle.Objects.Geometry;
/// <remarks><a href="https://speckle.notion.site/Objects-Geometry-Mesh-9b0bf5ab92bf42f58bf2fe3922d2efca">More docs on notion</a></remarks>
[SpeckleType("Objects.Geometry.Mesh")]
public class Mesh : Base, IHasBoundingBox, IHasVolume, IHasArea, ITransformable<Mesh>
{
/// <summary>
/// Flat list of vertex data (flat <c>x,y,z,x,y,z...</c> list)
/// </summary>
[DetachProperty, Chunkable(31250)]
public required List<double> vertices { get; set; }
/// <summary>
/// Flat list of face data<br/>
/// Each face starts with the length of the face (e.g. 3 in the case of triangles), followed by that many indices
/// </summary>
/// <remarks>
/// N-gons are supported, but large values of n (> ~50) tend to cause significant performance problems for consumers (e.g. HostApps and <see cref="MeshTriangulationHelper"/>.
/// </remarks>
/// <example>
/// <code>[
/// 3, 0, 1, 2, //first face, a triangle (3-gon)
/// 4, 1, 2, 3, 4, //second face, a quad (4-gon)
/// 6, 4, 5, 6, 7, 8, 9, //third face, an n-gon (6-gon)
/// ];</code></example>
[DetachProperty, Chunkable(62500)]
public required List<int> faces { get; set; }
/// <summary>Vertex colors as ARGB <see cref="int"/>s</summary>
/// <remarks>Expected that there are either 1 color per vertex, or an empty <see cref="List{T}"/></remarks>
[DetachProperty, Chunkable(62500)]
public List<int> colors { get; set; } = new();
/// <summary>Flat list of texture coordinates (flat <c>u,v,u,v,u,v...</c> list)</summary>
/// <remarks>Expected that there are either 1 texture coordinate per vertex, or an empty <see cref="List{T}"/></remarks>
[DetachProperty, Chunkable(31250)]
public List<double> textureCoordinates { get; set; } = new();
/// <summary>
/// <summary>Flat list of vertex normal data (flat <c>x,y,z,x,y,z...</c> list)</summary>
/// <remarks>Expected that there are either 1 texture coordinate per vertex, or an empty <see cref="List{T}"/></remarks>
/// </summary>
[DetachProperty, Chunkable(31250)]
public List<double> vertexNormals { get; set; } = new();
/// <summary>
/// The unit's this <see cref="Mesh"/> is in.
/// This should be one of <see cref="Units"/>
/// </summary>
public required string units { get; set; }
/// <inheritdoc/>
public double area { get; set; }
/// <inheritdoc/>
public Box? bbox { get; set; }
/// <inheritdoc/>
public double volume { get; set; }
/// <inheritdoc/>
public bool Transform(Transform transform)
{
// transform vertices
vertices = GetPoints()
.SelectMany(vertex =>
{
vertex.TransformTo(transform, out Point transformedVertex);
return transformedVertex.ToList();
})
.ToList();
return true;
}
/// <inheritdoc/>
public bool TransformTo(Transform transform, out Mesh transformed)
{
// transform vertices
var transformedVertices = new List<Point>();
foreach (var vertex in GetPoints())
{
vertex.TransformTo(transform, out Point transformedVertex);
transformedVertices.Add(transformedVertex);
}
transformed = new Mesh
{
vertices = transformedVertices.SelectMany(o => o.ToList()).ToList(),
textureCoordinates = textureCoordinates,
applicationId = applicationId ?? id,
faces = faces,
colors = colors,
units = units,
};
transformed["renderMaterial"] = this["renderMaterial"];
return true;
}
/// <inheritdoc/>
public bool TransformTo(Transform transform, out ITransformable transformed)
{
var res = TransformTo(transform, out Mesh brep);
transformed = brep;
return res;
}
[JsonIgnore]
public int VerticesCount => vertices.Count / 3;
[JsonIgnore]
public int TextureCoordinatesCount => textureCoordinates.Count / 2;
/// <summary>
/// Gets a vertex as a <see cref="Point"/> by <paramref name="index"/>
/// </summary>
/// <param name="index">The index of the vertex</param>
/// <returns>Vertex as a <see cref="Point"/></returns>
/// <remarks>It is usually recommended to instead consume the <see cref="vertices"/> list manually for better performance</remarks>
[Pure]
public Point GetPoint(int index)
{
index *= 3;
return new Point(vertices[index], vertices[index + 1], vertices[index + 2], units, applicationId);
}
/// <returns><see cref="vertices"/> as list of <see cref="Point"/>s</returns>
/// <exception cref="SpeckleException">when list is malformed</exception>
/// <remarks>It is usually recommended to instead consume the <see cref="vertices"/> list manually for better performance</remarks>
[Pure]
public List<Point> GetPoints()
{
if (vertices.Count % 3 != 0)
{
throw new SpeckleException(
$"{nameof(Mesh)}.{nameof(vertices)} list is malformed: expected length to be multiple of 3"
);
}
var pts = new List<Point>(vertices.Count / 3);
for (int i = 2; i < vertices.Count; i += 3)
{
pts.Add(new Point(vertices[i - 2], vertices[i - 1], vertices[i], units));
}
return pts;
}
/// <summary>
/// Gets a texture coordinate as a <see cref="ValueTuple{T1, T2}"/> by <paramref name="index"/>
/// </summary>
/// <param name="index">The index of the texture coordinate</param>
/// <returns>Texture coordinate as a <see cref="ValueTuple{T1, T2}"/></returns>
[Pure]
public (double, double) GetTextureCoordinate(int index)
{
index *= 2;
return (textureCoordinates[index], textureCoordinates[index + 1]);
}
}
+103
View File
@@ -0,0 +1,103 @@
using Speckle.Objects.Other;
using Speckle.Sdk.Common;
using Speckle.Sdk.Models;
namespace Speckle.Objects.Geometry;
/// <summary>
/// A 3-dimensional Plane consisting of an origin <see cref="Point"/>, and 3 <see cref="Vector"/> as its X, Y and Z axis.
/// </summary>
[SpeckleType("Objects.Geometry.Plane")]
public class Plane : Base, ITransformable<Plane>
{
/// <summary>
/// The <see cref="Plane"/>s origin point.
/// </summary>
public required Point origin { get; set; }
/// <summary>
/// The <see cref="Plane"/>s Z axis.
/// </summary>
public required Vector normal { get; set; }
/// <summary>
/// The <see cref="Plane"/>s X axis.
/// </summary>
public required Vector xdir { get; set; }
/// <summary>
/// The <see cref="Plane"/>s Y axis.
/// </summary>
public required Vector ydir { get; set; }
/// <summary>
/// The unit's this <see cref="Plane"/> is in.
/// This should be one of <see cref="Units"/>
/// </summary>
public required string units { get; set; }
/// <inheritdoc/>
public bool TransformTo(Transform transform, out Plane transformed)
{
origin.TransformTo(transform, out Point transformedOrigin);
normal.TransformTo(transform, out Vector transformedNormal);
xdir.TransformTo(transform, out Vector transformedXdir);
ydir.TransformTo(transform, out Vector transformedYdir);
transformed = new Plane
{
origin = transformedOrigin,
normal = transformedNormal,
xdir = transformedXdir,
ydir = transformedYdir,
applicationId = applicationId,
units = units,
};
return true;
}
/// <inheritdoc/>
public bool TransformTo(Transform transform, out ITransformable transformed)
{
var res = TransformTo(transform, out Plane plane);
transformed = plane;
return res;
}
/// <summary>
/// Returns the values of this <see cref="Plane"/> as a list of numbers
/// </summary>
/// <returns>A list of values representing the Plane.</returns>
public List<double> ToList()
{
var list = new List<double>();
list.AddRange(origin.ToList());
list.AddRange(normal.ToList());
list.AddRange(xdir.ToList());
list.AddRange(ydir.ToList());
list.Add(Units.GetEncodingFromUnit(units));
return list;
}
/// <summary>
/// Creates a new <see cref="Plane"/> based on a list of values and the unit they're drawn in.
/// </summary>
/// <param name="list">The list of values representing this plane</param>
/// <returns>A new <see cref="Plane"/> with the provided values.</returns>
public static Plane FromList(IReadOnlyList<double> list)
{
var units = Units.GetUnitFromEncoding(list[^1]);
var plane = new Plane
{
origin = new Point(list[0], list[1], list[2], units),
normal = new Vector(list[3], list[4], list[5], units),
xdir = new Vector(list[6], list[7], list[8], units),
ydir = new Vector(list[9], list[10], list[11], units),
units = units,
};
return plane;
}
}
+247
View File
@@ -0,0 +1,247 @@
using System.Diagnostics.CodeAnalysis;
using Speckle.Newtonsoft.Json;
using Speckle.Objects.Other;
using Speckle.Sdk.Common;
using Speckle.Sdk.Models;
namespace Speckle.Objects.Geometry;
/// <summary>
/// A 3-dimensional point
/// </summary>
/// <remarks>
/// TODO: The Point class does not override the Equality operator, which means that there may be cases where `Equals` is used instead of `==`, as the comparison will be done by reference, not value.
/// </remarks>
[SpeckleType("Objects.Geometry.Point")]
public class Point : Base, ITransformable<Point>, IEquatable<Point>
{
/// <inheritdoc/>
public Point() { }
/// <summary>
/// Constructs a new <see cref="Point"/> from a set of coordinates and it's units.
/// </summary>
/// <param name="x">The x coordinate</param>
/// <param name="y">The y coordinate</param>
/// <param name="z">The z coordinate</param>
/// <param name="units">The units of the point's coordinates. Defaults to Meters. </param>
/// <param name="applicationId">The object's unique application ID</param>
[SetsRequiredMembers]
public Point(double x, double y, double z, string units, string? applicationId = null)
{
this.x = x;
this.y = y;
this.z = z;
this.applicationId = applicationId;
this.units = units;
}
/// <summary>
/// The x coordinate of the point.
/// </summary>
public required double x { get; set; }
/// <summary>
/// The y coordinate of the point.
/// </summary>
public required double y { get; set; }
/// <summary>
/// The z coordinate of the point.
/// </summary>
public required double z { get; set; }
/// <summary>
/// The units this <see cref="Point"/> is in.
/// This should be one of the units specified in <see cref="Units"/>
/// </summary>
public required string units { get; set; }
/// <inheritdoc/>
public bool TransformTo(Transform transform, out Point transformed)
{
var matrix = transform.matrix;
var unitFactor = Units.GetConversionFactor(transform.units, units); // applied to translation vector
var divisor = matrix.M41 + matrix.M42 + matrix.M43 + unitFactor * matrix.M44;
var x = (this.x * matrix.M11 + this.y * matrix.M12 + this.z * matrix.M13 + unitFactor * matrix.M14) / divisor;
var y = (this.x * matrix.M21 + this.y * matrix.M22 + this.z * matrix.M23 + unitFactor * matrix.M24) / divisor;
var z = (this.x * matrix.M31 + this.y * matrix.M32 + this.z * matrix.M33 + unitFactor * matrix.M34) / divisor;
transformed = new Point(x, y, z, units, applicationId);
return true;
}
/// <inheritdoc/>
public bool TransformTo(Transform transform, out ITransformable transformed)
{
var res = TransformTo(transform, out Point pt);
transformed = pt;
return res;
}
/// <summary>
/// Returns the coordinates of this <see cref="Point"/> as a list of numbers
/// </summary>
/// <returns>A list of coordinates {x, y, z} </returns>
public List<double> ToList()
{
return new List<double> { x, y, z };
}
public Vector ToVector()
{
return new Vector(x, y, z, units, applicationId);
}
/// <summary>
/// Creates a new <see cref="Point"/> based on a list of coordinates and the unit they're drawn in.
/// </summary>
/// <param name="list">The list of coordinates {x, y, z}</param>
/// <param name="units">The units the coordinates are in</param>
/// <returns>A new <see cref="Point"/> with the provided coordinates.</returns>
public static Point FromList(IList<double> list, string units)
{
return new Point(list[0], list[1], list[2], units);
}
/// <summary>
/// Deconstructs a <see cref="Point"/> into it's coordinates and units
/// </summary>
/// <param name="x">The x coordinate</param>
/// <param name="y">The y coordinate</param>
/// <param name="z">The z coordinate</param>
/// <param name="units">The units the point's coordinates are in.</param>
public void Deconstruct(out double x, out double y, out double z, out string? units)
{
Deconstruct(out x, out y, out z);
units = this.units;
}
/// <summary>
/// Deconstructs a <see cref="Point"/> into it's coordinates and units
/// </summary>
/// <param name="x">The x coordinate</param>
/// <param name="y">The y coordinate</param>
/// <param name="z">The z coordinate</param>
public void Deconstruct(out double x, out double y, out double z)
{
x = this.x;
y = this.y;
z = this.z;
}
public static Point operator +(Point point1, Point point2) =>
new(point1.x + point2.x, point1.y + point2.y, point1.z + point2.z, point1.units);
public static Point operator -(Point point1, Point point2) =>
new(point1.x - point2.x, point1.y - point2.y, point1.z - point2.z, point1.units);
public static Point operator *(Point point1, Point point2) =>
new(point1.x * point2.x, point1.y * point2.y, point1.z * point2.z, point1.units);
public static Point operator *(Point point, double val) =>
new(point.x * val, point.y * val, point.z * val, point.units);
public static Point operator /(Point point, double val) =>
new(point.x / val, point.y / val, point.z / val, point.units);
public static bool operator ==(Point? point1, Point? point2)
{
if (point1 is null && point2 is null)
{
return true;
}
else if (point1 is null || point2 is null)
{
return false;
}
return point1.units == point2.units && point1.x == point2.x && point1.y == point2.y && point1.z == point2.z;
}
public static bool operator !=(Point? point1, Point? point2) => !(point1 == point2);
/// <summary>
/// Computes a point equidistant from two points.
/// </summary>
/// <param name="point1">First point.</param>
/// <param name="point2">Second point.</param>
/// <returns>A point at the same distance from <paramref name="point1"/> and <paramref name="point2"/></returns>
public static Point Midpoint(Point point1, Point point2)
{
return new Point(
0.5 * (point1.x + point2.x),
0.5 * (point1.y + point2.y),
0.5 * (point1.z + point2.z),
point1.units
);
}
/// <summary>
/// Computes the distance between two points
/// </summary>
/// <param name="point1">First point.</param>
/// <param name="point2">Second point.</param>
/// <returns>The distance from <paramref name="point1"/> to <paramref name="point2"/></returns>
public static double Distance(Point point1, Point point2)
{
return Math.Sqrt(
Math.Pow(point1.x - point2.x, 2) + Math.Pow(point1.y - point2.y, 2) + Math.Pow(point1.z - point2.z, 2)
);
}
/// <summary>
/// Computes the distance between two points.
/// </summary>
/// <param name="point">point for distance measurement</param>
/// <returns>The length of the line between this and the other point</returns>
public double DistanceTo(Point point)
{
return Math.Sqrt(Math.Pow(x - point.x, 2) + Math.Pow(y - point.y, 2) + Math.Pow(z - point.z, 2));
}
public bool Equals(Point? other) => this == other;
public override bool Equals(object? obj)
{
if (ReferenceEquals(this, obj))
{
return true;
}
if (obj is Point p)
{
return this == p;
}
return false;
}
public override int GetHashCode()
{
#if NETSTANDARD2_0
return HashCode.Of(units).And(x).And(y).And(y);
#else
return HashCode.Combine(units, x, y, z);
#endif
}
[Obsolete($"Use {nameof(Vector.ToPoint)}", true)]
public Point(Vector _) { }
/// <summary>
/// Gets or sets the coordinates of the <see cref="Point"/>
/// </summary>
[JsonProperty(NullValueHandling = NullValueHandling.Ignore), Obsolete("Use x,y,z properties instead", true)]
public List<double> value
{
get => null!;
set
{
x = value[0];
y = value[1];
z = value.Count > 2 ? value[2] : 0;
}
}
}
@@ -0,0 +1,91 @@
using Speckle.Objects.Other;
using Speckle.Sdk;
using Speckle.Sdk.Common;
using Speckle.Sdk.Models;
namespace Speckle.Objects.Geometry;
/// <summary>
/// A collection of points, with color and size support.
/// </summary>
[SpeckleType("Objects.Geometry.Pointcloud")]
public class Pointcloud : Base, IHasBoundingBox, ITransformable<Pointcloud>
{
/// <summary>
/// Gets or sets the list of points of this <see cref="Pointcloud"/>, stored as a flat list of coordinates [x1,y1,z1,x2,y2,...]
/// </summary>
[DetachProperty, Chunkable(31250)]
public required List<double> points { get; set; }
/// <summary>
/// Gets or sets the list of colors of this <see cref="Pointcloud"/>'s points., stored as ARGB <see cref="int"/>s.
/// </summary>
[DetachProperty, Chunkable(62500)]
public List<int> colors { get; set; } = new();
/// <summary>
/// Gets or sets the list of sizes of this <see cref="Pointcloud"/>'s points.
/// </summary>
[DetachProperty, Chunkable(62500)]
public List<double> sizes { get; set; } = new();
/// <summary>
/// The unit's this <see cref="Pointcloud"/> is in.
/// This should be one of <see cref="Units"/>
/// </summary>
public required string units { get; set; }
/// <inheritdoc/>
public Box? bbox { get; set; }
/// <inheritdoc/>
public bool TransformTo(Transform transform, out Pointcloud transformed)
{
// transform points
var transformedPoints = new List<Point>();
foreach (var point in GetPoints())
{
point.TransformTo(transform, out Point transformedPoint);
transformedPoints.Add(transformedPoint);
}
transformed = new Pointcloud
{
units = units,
points = transformedPoints.SelectMany(o => o.ToList()).ToList(),
colors = colors,
sizes = sizes,
applicationId = applicationId,
};
return true;
}
/// <inheritdoc/>
public bool TransformTo(Transform transform, out ITransformable transformed)
{
var res = TransformTo(transform, out Pointcloud pc);
transformed = pc;
return res;
}
/// <returns><see cref="points"/> as list of <see cref="Point"/>s</returns>
/// <exception cref="SpeckleException">when list is malformed</exception>
public List<Point> GetPoints()
{
if (points.Count % 3 != 0)
{
throw new SpeckleException(
$"{nameof(Pointcloud)}.{nameof(points)} list is malformed: expected length to be multiple of 3"
);
}
var pts = new List<Point>(points.Count / 3);
for (int i = 2; i < points.Count; i += 3)
{
pts.Add(new Point(points[i - 2], points[i - 1], points[i], units));
}
return pts;
}
}
+159
View File
@@ -0,0 +1,159 @@
using Speckle.Objects.Other;
using Speckle.Objects.Primitive;
using Speckle.Sdk.Common;
using Speckle.Sdk.Models;
namespace Speckle.Objects.Geometry;
/// <summary>
/// A curve that is comprised of multiple curves connected.
/// </summary>
[SpeckleType("Objects.Geometry.Polycurve")]
public class Polycurve : Base, ICurve, IHasArea, IHasBoundingBox, ITransformable
{
/// <summary>
/// Gets or sets the list of segments that comprise this <see cref="Polycurve"/>
/// </summary>
public required List<ICurve> segments { get; set; }
/// <summary>
/// Gets or sets a Boolean value indicating if the <see cref="Polycurve"/> is closed
/// (i.e. The start point of the first segment and the end point of the last segment coincide.)
/// </summary>
public bool closed { get; set; }
/// <summary>
/// The unit's this <see cref="Polycurve"/> is in.
/// This should be one of <see cref="Units"/>
/// </summary>
public required string units { get; set; }
/// <summary>
/// The internal domain of this curve.
/// </summary>
public Interval domain { get; set; } = Interval.UnitInterval;
/// <inheritdoc/>
public double length { get; set; }
/// <inheritdoc/>
public double area { get; set; }
/// <inheritdoc/>
public Box? bbox { get; set; }
/// <inheritdoc/>
public bool TransformTo(Transform transform, out ITransformable polycurve)
{
// transform segments
var success = true;
var transformed = new List<ICurve>();
foreach (var curve in segments)
{
if (curve is ITransformable c)
{
c.TransformTo(transform, out ITransformable tc);
transformed.Add((ICurve)tc);
}
else
{
success = false;
}
}
polycurve = new Polycurve
{
segments = transformed,
applicationId = applicationId,
closed = closed,
units = units,
};
return success;
}
/// <summary>
/// Constructs a new <see cref="Polycurve"/> instance from an existing <see cref="Polyline"/> curve.
/// </summary>
/// <param name="polyline">The polyline to be used when constructing the <see cref="Polycurve"/></param>
/// <returns>A <see cref="Polycurve"/> with the same shape as the provided polyline.</returns>
public static implicit operator Polycurve(Polyline polyline)
{
Polycurve polycurve = new()
{
segments = new(),
units = polyline.units,
area = polyline.area,
domain = polyline.domain,
closed = polyline.closed,
bbox = polyline.bbox,
length = polyline.length,
};
var points = polyline.GetPoints();
for (var i = 0; i < points.Count - 1; i++)
{
var line = new Line
{
start = points[i],
end = points[i + 1],
units = polyline.units,
};
polycurve.segments.Add(line);
}
if (polyline.closed)
{
var line = new Line
{
start = points[^1],
end = points[0],
units = polyline.units,
};
polycurve.segments.Add(line);
}
return polycurve;
}
/// <summary>
/// Returns the values of this <see cref="Polycurve"/> as a list of numbers
/// </summary>
/// <returns>A list of values representing the polycurve.</returns>
public List<double> ToList()
{
var list = new List<double>();
list.Add(closed ? 1 : 0);
list.Add(domain.start);
list.Add(domain.end);
var crvs = CurveArrayEncodingExtensions.ToArray(segments);
list.Add(crvs.Count);
list.AddRange(crvs);
list.Add(Units.GetEncodingFromUnit(units));
list.Insert(0, CurveTypeEncoding.PolyCurve);
list.Insert(0, list.Count);
return list;
}
/// <summary>
/// Creates a new <see cref="Polycurve"/> based on a list of coordinates and the unit they're drawn in.
/// </summary>
/// <param name="list">The list of values representing this polycurve</param>
/// <returns>A new <see cref="Polycurve"/> with the provided values.</returns>
public static Polycurve FromList(List<double> list)
{
var temp = list.GetRange(6, (int)list[5]);
var polycurve = new Polycurve
{
segments = CurveArrayEncodingExtensions.FromArray(temp),
closed = (int)list[2] == 1,
domain = new Interval { start = list[3], end = list[4] },
units = Units.GetUnitFromEncoding(list[^1]),
};
return polycurve;
}
}
+124
View File
@@ -0,0 +1,124 @@
using Speckle.Objects.Other;
using Speckle.Objects.Primitive;
using Speckle.Sdk;
using Speckle.Sdk.Common;
using Speckle.Sdk.Models;
namespace Speckle.Objects.Geometry;
/// <summary>
/// A polyline curve, defined by a set of vertices.
/// </summary>
[SpeckleType("Objects.Geometry.Polyline")]
public class Polyline : Base, ICurve, IHasArea, IHasBoundingBox, ITransformable
{
/// <summary>
/// Gets or sets the raw coordinates that define this polyline. Use GetPoints instead to access this data as <see cref="Point"/> instances instead.
/// </summary>
[DetachProperty, Chunkable(31250)]
public required List<double> value { get; set; }
/// <remarks>
/// If true, do not add the last point to the value list. Polyline first and last points should be unique.
/// </remarks>
public bool closed { get; set; }
/// <summary>
/// The unit's this <see cref="Polyline"/> is in.
/// This should be one of <see cref="Units"/>
/// </summary>
public required string units { get; set; }
/// <summary>
/// The internal domain of this curve.
/// </summary>
public Interval domain { get; set; } = Interval.UnitInterval;
/// <inheritdoc/>
public double length { get; set; }
/// <inheritdoc/>
public double area { get; set; }
/// <inheritdoc/>
public Box? bbox { get; set; }
/// <inheritdoc/>
public bool TransformTo(Transform transform, out ITransformable transformed)
{
// transform points
var transformedPoints = new List<Point>();
foreach (var point in GetPoints())
{
point.TransformTo(transform, out Point transformedPoint);
transformedPoints.Add(transformedPoint);
}
transformed = new Polyline
{
value = transformedPoints.SelectMany(o => o.ToList()).ToList(),
closed = closed,
applicationId = applicationId,
units = units,
};
return true;
}
///<remarks>This function may be suboptimal for performance for polylines with many points</remarks>
/// <returns><see cref="value"/> as List of <see cref="Point"/>s</returns>
/// <exception cref="SpeckleException">when list is malformed</exception>
public List<Point> GetPoints()
{
if (value.Count % 3 != 0)
{
throw new SpeckleException(
$"{nameof(Polyline)}.{nameof(value)} list is malformed: expected length to be multiple of 3"
);
}
var pts = new List<Point>(value.Count / 3);
for (int i = 2; i < value.Count; i += 3)
{
pts.Add(new Point(value[i - 2], value[i - 1], value[i], units));
}
return pts;
}
/// <summary>
/// Returns the values of this <see cref="Polyline"/> as a list of numbers
/// </summary>
/// <returns>A list of values representing the polyline.</returns>
public List<double> ToList()
{
var list = new List<double>();
list.Add(closed ? 1 : 0); // 2
list.Add(domain?.start ?? 0); // 3
list.Add(domain?.end ?? 1); // 4
list.Add(value.Count); // 5
list.AddRange(value); // 6 onwards
list.Add(Units.GetEncodingFromUnit(units));
list.Insert(0, CurveTypeEncoding.Polyline); // 1
list.Insert(0, list.Count); // 0
return list;
}
/// <summary>
/// Creates a new <see cref="Polyline"/> based on a list of coordinates and the unit they're drawn in.
/// </summary>
/// <param name="list">The list of values representing this polyline</param>
/// <returns>A new <see cref="Polyline"/> with the provided values.</returns>
public static Polyline FromList(List<double> list)
{
int pointCount = (int)list[5];
return new()
{
closed = (int)list[2] == 1,
domain = new Interval { start = list[3], end = list[4] },
value = list.GetRange(6, pointCount),
units = Units.GetUnitFromEncoding(list[^1]),
};
}
}
@@ -0,0 +1,25 @@
namespace Speckle.Objects.Geometry;
public static class PolylineExtensions
{
public static IEnumerable<Line> EnumerateAsLines(this Polyline polyline)
{
List<Point> points = polyline.GetPoints();
if (points.Count == 0)
{
yield break;
}
Point previousPoint = points[0];
for (int i = 1; i < points.Count; i++)
{
yield return new Line()
{
start = previousPoint,
end = points[i],
units = polyline.units,
};
previousPoint = points[i];
}
}
}
+97
View File
@@ -0,0 +1,97 @@
using Speckle.Objects.Other;
using Speckle.Sdk.Common;
using Speckle.Sdk.Models;
namespace Speckle.Objects.Geometry;
/// <summary>
/// Flat polygon, defined by an outer boundary and inner loops.
/// </summary>
[SpeckleType("Objects.Geometry.Region")]
public class Region : Base, IHasArea, IHasBoundingBox, ITransformable, IDisplayValue<List<Mesh>>
{
/// <summary>
/// Boundary of a region.
/// Should be a planar, closed, non-self-intersecting ICurve.
/// </summary>
public required ICurve boundary { get; set; }
/// <summary>
/// Loops (voids) in the region.
/// Each loop should be planar, closed, non-self-intersecting ICurve, located inside the boundary.
/// The loops should not intersect or touch each other.
/// </summary>
public required List<ICurve> innerLoops { get; set; } = new();
/// <summary>
/// The units of object's coordinates.
/// This should be one of <see cref="Units"/>
/// </summary>
public required string units { get; set; }
/// <summary>
/// Indication whether the region is just a geometry (false) or has a hatch pattern (true).
/// It's a distinction for receiving in apps that support both Region and Hatch (aka region with hatch pattern)
/// </summary>
public required bool hasHatchPattern { get; set; }
/// <inheritdoc/>
public double area { get; set; }
/// <inheritdoc/>
public Box? bbox { get; set; }
/// <inheritdoc/>
[DetachProperty]
public List<Mesh> displayValue { get; set; } = new();
/// <inheritdoc/>
public bool TransformTo(Transform transform, out ITransformable transformed)
{
// assign self to the returned object, in case transformation fails
transformed = this;
// transform boundary
if (boundary is ITransformable boundaryTransformable)
{
boundaryTransformable.TransformTo(transform, out ITransformable transformedBoundaryResult);
var transformedBoundary = (ICurve)transformedBoundaryResult;
// transform inner loops
var transformedLoops = new List<ICurve>();
foreach (var loop in innerLoops)
{
if (loop is ITransformable loopTransformable)
{
loopTransformable.TransformTo(transform, out ITransformable transformedLoop);
transformedLoops.Add((ICurve)transformedLoop);
}
else
{
return false;
}
}
// transform display meshes
var transformedMeshes = new List<Mesh>();
foreach (var mesh in displayValue)
{
mesh.TransformTo(transform, out ITransformable transformedMesh);
transformedMeshes.Add((Mesh)transformedMesh);
}
// if boundary and loops transformations succeeded
transformed = new Region
{
boundary = transformedBoundary,
innerLoops = transformedLoops,
hasHatchPattern = hasHatchPattern,
displayValue = transformedMeshes,
units = units,
};
return true;
}
return false;
}
}
+42
View File
@@ -0,0 +1,42 @@
using Speckle.Objects.Primitive;
using Speckle.Sdk.Common;
using Speckle.Sdk.Models;
namespace Speckle.Objects.Geometry;
public enum SpiralType
{
Biquadratic,
BiquadraticParabola,
Bloss,
Clothoid,
Cosine,
Cubic,
CubicParabola,
Radioid,
Sinusoid,
Unknown,
}
[SpeckleType("Objects.Geometry.Spiral")]
public class Spiral : Base, ICurve, IHasBoundingBox, IDisplayValue<Polyline>
{
public required Point startPoint { get; set; }
public required Point endPoint { get; set; }
public required Plane plane { get; set; } // plane with origin at spiral center
public required double turns { get; set; } // total angle of spiral. positive is counterclockwise, negative is clockwise
public required Vector pitchAxis { get; set; } = new(0, 0, 0, Units.None);
public required double pitch { get; set; }
public required SpiralType spiralType { get; set; }
public required string units { get; set; }
public required double length { get; set; }
public required Interval domain { get; set; }
[DetachProperty]
public required Polyline displayValue { get; set; }
public Box? bbox { get; set; }
}
+255
View File
@@ -0,0 +1,255 @@
using System.Diagnostics.CodeAnalysis;
using Speckle.Objects.Other;
using Speckle.Objects.Primitive;
using Speckle.Sdk.Common;
using Speckle.Sdk.Models;
namespace Speckle.Objects.Geometry;
/// <summary>
/// A Surface in NURBS form.
/// </summary>
[SpeckleType("Objects.Geometry.Surface")]
public class Surface : Base, IHasBoundingBox, IHasArea, ITransformable<Surface>
{
[Obsolete("Constructor should only be used by serializer, use one of the other constructors instead")]
public Surface()
{
pointData = [];
}
public Surface(List<List<ControlPoint>> controlPoints)
{
SetControlPoints(controlPoints);
}
public Surface(IList<double> pointData, int countU, int countV)
{
this.pointData = pointData;
this.countU = countU;
this.countV = countV;
}
/// <summary>
/// The degree of the surface in the U direction
/// </summary>
public required int degreeU { get; set; }
/// <summary>
/// The degree of the surface in the V direction
/// </summary>
public required int degreeV { get; set; }
/// <summary>
/// Determines if the <see cref="Surface"/> is rational.
/// </summary>
public required bool rational { get; set; }
/// <summary>
/// The raw data of the surface's control points. Use <see cref="GetControlPoints"/> or <see cref="SetControlPoints"/> instead of accessing this directly.
/// </summary>
public IList<double> pointData { get; set; }
/// <summary>
/// The number of control points in the U direction
/// </summary>
public int countU { get; set; }
/// <summary>
/// The number of control points in the V direction
/// </summary>
public int countV { get; set; }
/// <summary>
/// The knot vector in the U direction
/// </summary>
public required List<double> knotsU { get; set; }
/// <summary>
/// The knot vector in the V direction
/// </summary>
public required List<double> knotsV { get; set; }
/// <summary>
/// The surface's domain in the U direction
/// </summary>
public required Interval domainU { get; set; }
/// <summary>
/// The surface's domain in the V direction
/// </summary>
public required Interval domainV { get; set; }
/// <summary>
/// Determines if a surface is closed around the <see cref="domainU"/>.
/// </summary>
public required bool closedU { get; set; }
/// <summary>
/// Determines if a surface is closed around the <see cref="domainV"/>
/// </summary>
public required bool closedV { get; set; }
/// <summary>
/// The unit's this <see cref="Surface"/> is in.
/// This should be one of <see cref="Units"/>
/// </summary>
public required string units { get; set; }
/// <inheritdoc/>
public double area { get; set; }
/// <inheritdoc/>
public Box? bbox { get; set; }
/// <inheritdoc/>
public bool TransformTo(Transform transform, out Surface transformed)
{
var ptMatrix = GetControlPoints();
foreach (var ctrlPts in ptMatrix)
{
for (int i = 0; i < ctrlPts.Count; i++)
{
ctrlPts[i].TransformTo(transform, out var tPt);
ctrlPts[i] = tPt;
}
}
transformed = new Surface(ptMatrix)
{
degreeU = degreeU,
degreeV = degreeV,
countU = countU,
countV = countV,
rational = rational,
closedU = closedU,
closedV = closedV,
domainU = domainU,
domainV = domainV,
knotsU = knotsU,
knotsV = knotsV,
units = units,
};
return true;
}
/// <inheritdoc/>
public bool TransformTo(Transform transform, out ITransformable transformed)
{
var res = TransformTo(transform, out Surface surface);
transformed = surface;
return res;
}
/// <summary>
/// Gets the control points of this s<see cref="Surface"/>
/// </summary>
/// <returns>A 2-dimensional array representing this <see cref="Surface"/>s control points.</returns>
/// <remarks>The ControlPoints will be ordered following directions "[u][v]"</remarks>
public List<List<ControlPoint>> GetControlPoints()
{
var matrix = new List<List<ControlPoint>>();
for (var i = 0; i < countU; i++)
{
matrix.Add(new List<ControlPoint>());
}
for (var i = 0; i < pointData.Count; i += 4)
{
var uIndex = i / (countV * 4);
matrix[uIndex].Add(new ControlPoint(pointData[i], pointData[i + 1], pointData[i + 2], pointData[i + 3], units));
}
return matrix;
}
/// <summary>
/// Sets the control points of this <see cref="Surface"/>.
/// </summary>
/// <param name="value">A 2-dimensional array of <see cref="ControlPoint"/> instances.</param>
/// <remarks>The <paramref name="value"/> must be ordered following directions "[u][v]"</remarks>
[MemberNotNull(nameof(pointData))]
[MemberNotNull(nameof(countU))]
[MemberNotNull(nameof(countV))]
public void SetControlPoints(List<List<ControlPoint>> value)
{
List<double> data = new();
countU = value.Count;
countV = value[0].Count;
value.ForEach(row =>
row.ForEach(pt =>
{
data.Add(pt.x);
data.Add(pt.y);
data.Add(pt.z);
data.Add(pt.weight);
})
);
pointData = data;
}
/// <summary>
/// Returns the coordinates of this <see cref="Surface"/> as a list of numbers
/// </summary>
/// <returns>A list of values representing the surface</returns>
public List<double> ToList()
{
var list = new List<double>();
list.Add(degreeU);
list.Add(degreeV);
list.Add(countU);
list.Add(countV);
list.Add(rational ? 1 : 0);
list.Add(closedU ? 1 : 0);
list.Add(closedV ? 1 : 0);
list.Add(domainU.start); // 7
list.Add(domainU.end);
list.Add(domainV.start);
list.Add(domainV.end); // [0] 10
list.Add(pointData.Count); // 11
list.Add(knotsU.Count); // 12
list.Add(knotsV.Count); // 13
list.AddRange(pointData);
list.AddRange(knotsU);
list.AddRange(knotsV);
list.Add(Units.GetEncodingFromUnit(units));
list.Insert(0, list.Count);
return list;
}
/// <summary>
/// Creates a new <see cref="Surface"/> based on a list of coordinates and the unit they're drawn in.
/// </summary>
/// <param name="list">The list of values representing this surface</param>
/// <returns>A new <see cref="Surface"/> with the provided values.</returns>
public static Surface FromList(List<double> list)
{
var pointCount = (int)list[11];
var knotsUCount = (int)list[12];
var knotsVCount = (int)list[13];
var countU = (int)list[2];
var countV = (int)list[3];
var pointData = list.GetRange(14, pointCount);
var u = list[^1];
return new Surface(pointData, countU, countV)
{
degreeU = (int)list[0],
degreeV = (int)list[1],
rational = list[4] == 1,
closedU = list[5] == 1,
closedV = list[6] == 1,
domainU = new Interval { start = list[7], end = list[8] },
domainV = new Interval { start = list[9], end = list[10] },
knotsU = list.GetRange(14 + pointCount, knotsUCount),
knotsV = list.GetRange(14 + pointCount + knotsUCount, knotsVCount),
units = Units.GetUnitFromEncoding(u),
};
}
}
+216
View File
@@ -0,0 +1,216 @@
using System.Diagnostics.CodeAnalysis;
using Speckle.Newtonsoft.Json;
using Speckle.Objects.Other;
using Speckle.Sdk.Common;
using Speckle.Sdk.Models;
namespace Speckle.Objects.Geometry;
/// <summary>
/// A 3-dimensional vector
/// </summary>
[SpeckleType("Objects.Geometry.Vector")]
public class Vector : Base, IHasBoundingBox, ITransformable<Vector>
{
/// <inheritdoc/>
public Vector() { }
/// <summary>
/// Constructs a new 2D <see cref="Vector"/> from it's X and Y coordinates.
/// </summary>
/// <param name="x">The x coordinate of the vector</param>
/// <param name="y">The y coordinate of the vector</param>
/// <param name="units">The units the coordinates are in.</param>
/// <param name="applicationId">The unique application ID of the object.</param>
[SetsRequiredMembers]
public Vector(double x, double y, double z, string units, string? applicationId = null)
{
this.x = x;
this.y = y;
this.z = z;
this.applicationId = applicationId;
this.units = units;
}
/// <summary>
/// The unit's this <see cref="Vector"/> is in.
/// This should be one of <see cref="Units"/>
/// </summary>
public required string units { get; set; }
/// <summary>
/// The x coordinate of the vector.
/// </summary>
public required double x { get; set; }
/// <summary>
/// The y coordinate of the vector.
/// </summary>
public required double y { get; set; }
/// <summary>
/// The z coordinate of the vector.
/// </summary>
public required double z { get; set; }
/// <summary>
/// Gets the Euclidean length of this vector.
/// </summary>
/// <returns>Length of the vector.</returns>
[JsonIgnore]
public double Length => Math.Sqrt(DotProduct(this, this));
/// <inheritdoc/>
public Box? bbox { get; set; }
/// <inheritdoc/>
public bool TransformTo(Transform transform, out Vector transformed)
{
var m = transform.matrix;
var tX = x * m.M11 + y * m.M12 + z * m.M13;
var tY = x * m.M21 + y * m.M22 + z * m.M23;
var tZ = x * m.M31 + y * m.M32 + z * m.M33;
transformed = new Vector(tX, tY, tZ, units, applicationId);
return true;
}
/// <inheritdoc/>
public bool TransformTo(Transform transform, out ITransformable transformed)
{
_ = TransformTo(transform, out Vector vec);
transformed = vec;
return true;
}
/// <summary>
/// Returns the coordinates of this <see cref="Vector"/> as a list of numbers
/// </summary>
/// <returns>A list of coordinates {x, y, z} </returns>
public List<double> ToList() => [x, y, z];
public Point ToPoint() => new(x, y, z, units, applicationId);
/// <summary>
/// Creates a new vector based on a list of coordinates and the unit they're drawn in.
/// </summary>
/// <param name="list">The list of coordinates {x, y, z}</param>
/// <param name="units">The units the coordinates are in</param>
/// <returns>A new <see cref="Vector"/> with the provided coordinates.</returns>
public static Vector FromList(IReadOnlyList<double> list, string units)
{
return new Vector(list[0], list[1], list[2], units);
}
/// <summary>
/// Divides a vector by a numerical value. This will divide each coordinate by the provided value.
/// </summary>
/// <param name="vector">The vector to divide</param>
/// <param name="val">The value to divide by</param>
/// <returns>The resulting <see cref="Vector"/></returns>
public static Vector operator /(Vector vector, double val) =>
new(vector.x / val, vector.y / val, vector.z / val, vector.units);
/// <summary>
/// Multiplies a vector by a numerical value. This will multiply each coordinate by the provided value.
/// </summary>
/// <param name="vector">The vector to multiply</param>
/// <param name="val">The value to multiply by</param>
/// <returns>The resulting <see cref="Vector"/></returns>
public static Vector operator *(Vector vector, double val) =>
new(vector.x * val, vector.y * val, vector.z * val, vector.units);
/// <summary>
/// Adds two vectors by adding each of their coordinates.
/// </summary>
/// <param name="vector1">The first vector</param>
/// <param name="vector2">The second vector</param>
/// <returns>The resulting <see cref="Vector"/></returns>
public static Vector operator +(Vector vector1, Vector vector2) =>
new(vector1.x + vector2.x, vector1.y + vector2.y, vector1.z + vector2.z, vector1.units);
/// <summary>
/// Subtracts two vectors by subtracting each of their coordinates.
/// </summary>
/// <param name="vector1">The first vector</param>
/// <param name="vector2">The second vector</param>
/// <returns>The resulting <see cref="Vector"/></returns>
public static Vector operator -(Vector vector1, Vector vector2) =>
new(vector1.x - vector2.x, vector1.y - vector2.y, vector1.z - vector2.z, vector1.units);
/// <summary>
/// Gets the scalar product (dot product) of two given vectors
/// Dot product = u1*v1 + u2*v2 + u3*v3.
/// </summary>
/// <param name="u">First vector.</param>
/// <param name="v">Second vector.</param>
/// <returns>Numerical value of the dot product.</returns>
public static double DotProduct(Vector u, Vector v)
{
return u.x * v.x + u.y * v.y + u.z * v.z;
}
/// <summary>
/// Computes the vector product (cross product) of two given vectors
/// Cross product = { u2 * v3 - u3 * v2; u3 * v1 - u1 * v3; u1 * v2 - u2 * v1 }.
/// </summary>
/// <param name="u">First vector.</param>
/// <param name="v">Second vector.</param>
/// <returns>Vector result of the cross product.</returns>
public static Vector CrossProduct(Vector u, Vector v)
{
if (u.units != v.units && u.units != Units.None && v.units != Units.None)
{
throw new ArgumentException("Cannot perform cross product on two vectors with different unit systems");
}
var x = u.y * v.z - u.z * v.y;
var y = u.z * v.x - u.x * v.z;
var z = u.x * v.y - u.y * v.x;
return new Vector(x, y, z, units: u.units);
}
/// <summary>
/// Compute and return a unit vector from this vector
/// </summary>
/// <returns>a normalized unit vector</returns>
public void Normalize()
{
var length = Length;
x /= length;
y /= length;
z /= length;
}
/// <summary>
/// Inverses the direction of the vector, equivalent to multiplying by -1
/// </summary>
/// <returns>A pointing in the opposite direction</returns>
public Vector Negate()
{
x *= -1;
y *= -1;
z *= -1;
return this;
}
/// <summary>
/// Gets or sets the coordinates of the vector
/// </summary>
[
JsonProperty(NullValueHandling = NullValueHandling.Ignore),
Obsolete("Use X,Y,Z fields to access coordinates instead", true)
]
public List<double> value
{
#pragma warning disable CS8603 // Possible null reference return.
get => null;
#pragma warning restore CS8603 // Possible null reference return.
set
{
x = value[0];
y = value[1];
z = value.Count > 2 ? value[2] : 0;
}
}
}
+182
View File
@@ -0,0 +1,182 @@
using Speckle.Objects.Geometry;
using Speckle.Objects.Other;
using Speckle.Objects.Primitive;
using Speckle.Sdk.Models;
namespace Speckle.Objects;
#region Generic interfaces.
/// <summary>
/// Represents an object that has a <see cref="IHasBoundingBox.bbox"/>
/// </summary>
public interface IHasBoundingBox : ISpeckleObject
{
/// <summary>
/// The bounding box containing the object.
/// </summary>
Box? bbox { get; }
}
/// <summary>
/// Represents a <see cref="Base"/> object that has <see cref="IHasArea.area"/>
/// </summary>
public interface IHasArea : ISpeckleObject
{
/// <summary>
/// The area of the object
/// </summary>
double area { get; }
}
/// <summary>
/// Represents an object that has <see cref="IHasVolume.volume"/>
/// </summary>
public interface IHasVolume : ISpeckleObject
{
/// <summary>
/// The volume of the object
/// </summary>
double volume { get; }
}
/// <summary>
/// Represents
/// </summary>
public interface ICurve : ISpeckleObject
{
/// <summary>
/// The length of the curve.
/// </summary>
double length { get; }
/// <summary>
/// The numerical domain driving the curve's internal parametrization.
/// </summary>
Interval domain { get; }
string units { get; }
}
/// <summary>
/// Generic Interface for transformable objects.
/// </summary>
/// <typeparam name="T">The type of object to support transformations.</typeparam>
public interface ITransformable<T> : ITransformable
where T : ITransformable<T>
{
/// <inheritdoc cref="ITransformable.TransformTo"/>
bool TransformTo(Transform transform, out T transformed);
}
/// <summary>
/// Interface for transformable objects where the type may not be known on convert (eg ICurve implementations)
/// </summary>
public interface ITransformable : ISpeckleObject
{
/// <summary>
/// Returns a copy of the object with it's coordinates transformed by the provided <paramref name="transform"/>
/// </summary>
/// <param name="transform">The <see cref="Transform"/> to be applied.</param>
/// <param name="transformed">The transformed copy of the object.</param>
/// <returns>True if the transform operation was successful, false otherwise.</returns>
bool TransformTo(Transform transform, out ITransformable transformed);
}
/// <summary>
/// Specifies displayable <see cref="Base"/> simple geometries to be used as a fallback
/// if a displayable form cannot be converted.
/// </summary>
/// <example>
/// <see cref="Base"/> objects that represent conceptual / abstract / mathematically derived geometry
/// can use <see cref="displayValue"/> to be used in case the object lacks a natively displayable form.
/// (e.g <see cref="Spiral"/>)
/// </example>
/// <typeparam name="T">
/// Type of display value.
/// Expected to be either a <see cref="Base"/> type or a <see cref="List{T}"/> of <see cref="Base"/>s,
/// Should be constrained to types of <see cref="Point"/>, <see cref="Line"/>, <see cref="Mesh"/> or <see cref="Polyline"/>.
/// </typeparam>
public interface IDisplayValue<out T> : ISpeckleObject
{
/// <summary>
/// <see cref="displayValue"/> <see cref="Base"/>(s) will be used to display this <see cref="Base"/>
/// if a native displayable object cannot be converted.
/// </summary>
T displayValue { get; }
}
#endregion
#region Data objects
/// <summary>
/// Specifies properties on objects to be used for data-based workflows
/// </summary>
public interface IProperties : ISpeckleObject
{
Dictionary<string, object?> properties { get; }
}
public interface IDataObject : IProperties, IDisplayValue<IReadOnlyList<Base>>
{
/// <summary>
/// The name of the object, primarily used to decorate the object for consumption in frontend and other apps
/// </summary>
string name { get; }
}
public interface IRevitObject : IDataObject
{
string type { get; }
string family { get; }
string category { get; }
Base? location { get; }
IReadOnlyList<IRevitObject> elements { get; }
}
public interface ICivilObject : IDataObject
{
string type { get; }
List<ICurve>? baseCurves { get; }
IReadOnlyList<Base> elements { get; }
}
public interface ITeklaObject : IDataObject
{
string type { get; }
IReadOnlyList<ITeklaObject> elements { get; }
}
public interface ICsiObject : IDataObject
{
string type { get; }
IReadOnlyList<ICsiObject> elements { get; }
}
public interface IGisObject : IDataObject
{
string type { get; }
}
public interface IArchicadObject : IDataObject
{
string type { get; }
string level { get; }
IReadOnlyList<IArchicadObject> elements { get; }
}
public interface INavisworksObject : IDataObject { }
#endregion
+20
View File
@@ -0,0 +1,20 @@
using Speckle.Objects.Data;
using Speckle.Sdk.Models;
using Speckle.Sdk.Models.Proxies;
namespace Speckle.Objects.Other;
/// <summary>
/// Proxy for levels as DataObject value.
/// <remarks> These proxy lives in Objects library because it depends on DataObject</remarks>
/// </summary>
[SpeckleType("Objects.Other.LevelProxy")]
public class LevelProxy : Base, IProxyCollection
{
/// <summary>
/// The list of application ids of objects that use this level
/// </summary>
public required List<string> objects { get; set; }
public required DataObject value { get; set; }
}
+23
View File
@@ -0,0 +1,23 @@
using Speckle.Sdk.Models;
namespace Speckle.Objects.Other;
/// <summary>
/// Keeps track of a raw-encoded object in a native supported format. see <see cref="RawEncodingFormats"/>
/// </summary>
[SpeckleType("Objects.Other.RawEncoding")]
public class RawEncoding : Base // note: at this stage, since we're using this for extrusions and subds the name doesn't make sense anymore
{
public required string format { get; set; }
public required string contents { get; set; }
public RawEncoding() { }
}
/// <summary>
/// Supported encoding types "strongly" typed strings. This needs to match the extension of the file format.
/// </summary>
public static class RawEncodingFormats
{
public const string RHINO_3DM = "3dm";
}
@@ -0,0 +1,40 @@
using System.Drawing;
using Speckle.Newtonsoft.Json;
using Speckle.Sdk.Models;
namespace Speckle.Objects.Other;
/// <summary>
/// Minimal physically based material DTO class. Based on references from
/// https://threejs.org/docs/index.html#api/en/materials/MeshStandardMaterial
/// Theoretically has equivalents in Unity and Unreal.
///
/// See: https://docs.unrealengine.com/en-US/RenderingAndGraphics/Materials/PhysicallyBased/index.html
/// And: https://blogs.unity3d.com/2014/10/29/physically-based-shading-in-unity-5-a-primer/
/// </summary>
[SpeckleType("Objects.Other.RenderMaterial")]
public class RenderMaterial : Base
{
public required string name { get; set; }
public double opacity { get; set; } = 1;
public double metalness { get; set; }
public double roughness { get; set; } = 1;
public required int diffuse { get; set; } = Color.LightGray.ToArgb();
public int emissive { get; set; } = Color.Black.ToArgb();
[JsonIgnore]
public Color diffuseColor
{
get => Color.FromArgb(diffuse);
set => diffuse = value.ToArgb();
}
[JsonIgnore]
public Color emissiveColor
{
get => Color.FromArgb(emissive);
set => diffuse = value.ToArgb();
}
}
@@ -0,0 +1,22 @@
using Speckle.Sdk.Models;
using Speckle.Sdk.Models.Proxies;
namespace Speckle.Objects.Other;
/// <summary>
/// Used to store render material to object relationships in root collections
/// <remarks> These proxy lives in Objects library because it depends on RenderMaterial</remarks>
/// </summary>
[SpeckleType("Objects.Other.RenderMaterialProxy")]
public class RenderMaterialProxy : Base, IProxyCollection
{
/// <summary>
/// The list of application ids of objects that use this render material
/// </summary>
public required List<string> objects { get; set; }
/// <summary>
/// The render material used by <see cref="objects"/>
/// </summary>
public required RenderMaterial value { get; set; }
}

Some files were not shown because too many files have changed in this diff Show More