mirror of
https://github.com/immich-app/immich.git
synced 2026-05-17 13:02:14 -04:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 942c53d9fe |
@@ -16,7 +16,7 @@ services:
|
||||
- ${UPLOAD_LOCATION:-upload-devcontainer-volume}${UPLOAD_LOCATION:+/photos}:/data
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
- pnpm_store_server:/buildcache/pnpm-store
|
||||
- ../packages/plugin-core:/build/plugins/immich-plugin-core
|
||||
- ../packages/plugins:/build/corePlugin
|
||||
immich-web:
|
||||
env_file: !reset []
|
||||
immich-machine-learning:
|
||||
|
||||
@@ -7,7 +7,7 @@ on:
|
||||
required: false
|
||||
type: string
|
||||
environment:
|
||||
description: 'Target environment'
|
||||
description: 'Target environment (development, rc, or production)'
|
||||
required: true
|
||||
default: 'development'
|
||||
type: string
|
||||
@@ -116,6 +116,7 @@ jobs:
|
||||
~/.gradle/wrapper
|
||||
~/.android/sdk
|
||||
mobile/android/.gradle
|
||||
mobile/.dart_tool
|
||||
key: build-mobile-gradle-${{ runner.os }}-main
|
||||
|
||||
- name: Setup Android SDK
|
||||
@@ -188,6 +189,7 @@ jobs:
|
||||
~/.gradle/wrapper
|
||||
~/.android/sdk
|
||||
mobile/android/.gradle
|
||||
mobile/.dart_tool
|
||||
key: ${{ steps.cache-gradle-restore.outputs.cache-primary-key }}
|
||||
|
||||
build-sign-ios:
|
||||
@@ -296,10 +298,12 @@ jobs:
|
||||
run: |
|
||||
# Only upload to TestFlight on main branch
|
||||
if [[ "$GITHUB_REF" == "refs/heads/main" ]]; then
|
||||
if [[ "$ENVIRONMENT" == "development" ]]; then
|
||||
bundle exec fastlane gha_testflight_dev
|
||||
else
|
||||
if [[ "$ENVIRONMENT" == "rc" ]]; then
|
||||
bundle exec fastlane gha_testflight_rc
|
||||
elif [[ "$ENVIRONMENT" == "production" ]]; then
|
||||
bundle exec fastlane gha_release_prod
|
||||
elif [[ "$ENVIRONMENT" == "development" ]]; then
|
||||
bundle exec fastlane gha_testflight_dev
|
||||
fi
|
||||
else
|
||||
# Build only, no TestFlight upload for non-main branches
|
||||
|
||||
+14
-10
@@ -62,6 +62,9 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ./server
|
||||
steps:
|
||||
- id: token
|
||||
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||
@@ -81,7 +84,7 @@ jobs:
|
||||
github_token: ${{ steps.token.outputs.token }}
|
||||
|
||||
- name: Run ci-unit
|
||||
run: mise run //server:ci-unit
|
||||
run: mise run ci-unit
|
||||
|
||||
cli-unit-tests:
|
||||
name: Unit Test CLI
|
||||
@@ -377,7 +380,7 @@ jobs:
|
||||
cache-dependency-path: '**/pnpm-lock.yaml'
|
||||
|
||||
- name: Setup packages
|
||||
run: pnpm --filter @immich/sdk --filter @immich/cli install --frozen-lockfile && pnpm --filter @immich/sdk --filter @immich/cli build
|
||||
run: pnpm --filter "@immich/*" install --frozen-lockfile && pnpm --filter "@immich/*" build
|
||||
|
||||
- name: Run setup web
|
||||
run: pnpm install --frozen-lockfile && pnpm exec svelte-kit sync
|
||||
@@ -675,6 +678,7 @@ jobs:
|
||||
|
||||
- name: Install server dependencies
|
||||
run: SHARP_IGNORE_GLOBAL_LIBVIPS=true pnpm --filter immich install --frozen-lockfile
|
||||
|
||||
- name: Run API generation
|
||||
run: mise //:open-api
|
||||
working-directory: open-api
|
||||
@@ -713,6 +717,9 @@ jobs:
|
||||
--health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
|
||||
ports:
|
||||
- 5432:5432
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ./server
|
||||
steps:
|
||||
- id: token
|
||||
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||
@@ -734,21 +741,18 @@ jobs:
|
||||
- name: Install server dependencies
|
||||
run: SHARP_IGNORE_GLOBAL_LIBVIPS=true pnpm install --frozen-lockfile
|
||||
|
||||
- name: Build plugins
|
||||
run: mise //:plugins
|
||||
|
||||
- name: Build the app
|
||||
run: mise //server:build
|
||||
run: pnpm build
|
||||
|
||||
- name: Run existing migrations
|
||||
run: pnpm --filter immich migrations:run
|
||||
run: pnpm migrations:run
|
||||
|
||||
- name: Test npm run schema:reset command works
|
||||
run: pnpm --filter immich schema:reset
|
||||
run: pnpm schema:reset
|
||||
|
||||
- name: Generate new migrations
|
||||
continue-on-error: true
|
||||
run: pnpm --filter migrations:generate src/TestMigration
|
||||
run: pnpm migrations:generate src/TestMigration
|
||||
|
||||
- name: Find file changes
|
||||
uses: tj-actions/verify-changed-files@a1c6acee9df209257a246f2cc6ae8cb6581c1edf # v20.0.4
|
||||
@@ -764,7 +768,7 @@ jobs:
|
||||
run: |
|
||||
echo "ERROR: Generated migration files not up to date!"
|
||||
echo "Changed files: ${CHANGED_FILES}"
|
||||
cat ./server/src/*-TestMigration.ts
|
||||
cat ./src/*-TestMigration.ts
|
||||
exit 1
|
||||
|
||||
- name: Run SQL generation
|
||||
|
||||
@@ -74,7 +74,7 @@ services:
|
||||
- ${UPLOAD_LOCATION}/photos:/data
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
- pnpm_store_server:/buildcache/pnpm-store
|
||||
- ../packages/plugin-core:/build/plugins/immich-plugin-core
|
||||
- ../packages/plugins:/build/corePlugin
|
||||
env_file:
|
||||
- .env
|
||||
environment:
|
||||
|
||||
@@ -18,7 +18,7 @@ make e2e
|
||||
Before you can run the tests, you need to run the following commands _once_:
|
||||
|
||||
- `pnpm install`
|
||||
- `pnpm --filter @immich/sdk --filter @immich/cli build`
|
||||
- `pnpm --filter "@immich/*" build`
|
||||
- `mise //:open-api`
|
||||
|
||||
Once the test environment is running, the e2e tests can be run via:
|
||||
|
||||
@@ -52,7 +52,7 @@ Scroll to the bottom of the "**Details**" section and find the `IP Address` list
|
||||
|
||||
## Step 4 - Configure Firewall Settings
|
||||
|
||||
Once your project completes the build process, your containers will start. In order to be able to access Immich from your browser, you need to configure the firewall settings for your Synology NAS to allow communication between the Immich containers.
|
||||
Once your project completes the build process, your containers will start. In order to be able to access Immich from your browser, you need to configure the firewall settings for your Synology NAS.
|
||||
|
||||
Open "**Control Panel**" on your Synology NAS, and select "**Security**". Navigate to "**Firewall**"
|
||||
|
||||
@@ -74,7 +74,6 @@ Read the [Post Installation](/install/post-install.mdx) steps and [upgrade instr
|
||||
|
||||
<details>
|
||||
<summary>Updating Immich using Container Manager</summary>
|
||||
|
||||
Check the post installation and upgrade instructions at the links above before proceeding with this section.
|
||||
|
||||
## Step 1. Backup
|
||||
@@ -111,7 +110,7 @@ Go to **Project**, select **Action** then **Build**. This will download, unpack,
|
||||
|
||||
## Step 5. Update firewall rule
|
||||
|
||||
Without a fixed subnet, the default behavior is to automatically start the containers once installed. If `immich_server` runs for a few seconds and then stops, it may be because the firewall rule no longer matches the server IP address.
|
||||
The default behavior is to automatically start the containers once installed. If `immich_server` runs for a few seconds and then stops, it may be because the firewall rule no longer matches the server IP address.
|
||||
|
||||
Go to the **Container** section. Click on `immich_server` and scroll down on **General** to find the IP address.
|
||||

|
||||
@@ -124,67 +123,4 @@ In this example, the IP addresses mismatch and the firewall rule needs to be edi
|
||||
|
||||

|
||||
|
||||
To prevent future firewall issues, you may set a fixed subnet. [See Set Fixed Subnet](#set-fixed-subnet) for instructions.
|
||||
|
||||
</details>
|
||||
|
||||
<details id="set-fixed-subnet">
|
||||
<summary>Set Fixed Subnet</summary>
|
||||
|
||||
Docker by default assigns dynamic subnets to bridge networks which can change when rebuilding containers and can cause firewall rules to break. To avoid this, define a fixed subnet in your `docker-compose.yml`:
|
||||
|
||||
## Step 1. Determine current subnet
|
||||
|
||||
Go to the **Container** section. Click on `immich_server` and scroll down on **General** to find the IP address.
|
||||

|
||||
|
||||
## Step 2. Add network configuration
|
||||
|
||||
Add the following network configuration at the end of your `docker-compose.yml` file:
|
||||
|
||||
```yaml
|
||||
networks:
|
||||
immich-network:
|
||||
driver: bridge
|
||||
ipam:
|
||||
config:
|
||||
- subnet: 172.20.0.0/16
|
||||
gateway: 172.20.0.1
|
||||
```
|
||||
|
||||
If your docker container is running on a different subnet then update accordingly.
|
||||
|
||||
## Step 3. Add network to each service
|
||||
|
||||
Add the network to each service (immich-server, immich-machine-learning, redis, database):
|
||||
|
||||
```yaml
|
||||
services:
|
||||
immich-server:
|
||||
# other config options
|
||||
networks:
|
||||
- immich-network
|
||||
|
||||
immich-machine-learning:
|
||||
# other config options
|
||||
networks:
|
||||
- immich-network
|
||||
|
||||
redis:
|
||||
# other config options
|
||||
networks:
|
||||
- immich-network
|
||||
|
||||
database:
|
||||
# other config options
|
||||
networks:
|
||||
- immich-network
|
||||
```
|
||||
|
||||
Save your changes. Synology will ask if you want to save changes only or rebuild containers. Select rebuild containers.
|
||||
|
||||
## Step 4. Update Firewall Rules, if necessary
|
||||
|
||||
If your firewall rules were not already set for this subnet, the firewall rules will need to be updated. See [Step 4 - Configure Firewall Settings](#step-4---configure-firewall-settings).
|
||||
|
||||
</details>
|
||||
|
||||
+7
-13
@@ -22,12 +22,13 @@
|
||||
"add_birthday": "Add a birthday",
|
||||
"add_endpoint": "Add endpoint",
|
||||
"add_exclusion_pattern": "Add exclusion pattern",
|
||||
"add_filter": "Add filter",
|
||||
"add_filter_description": "Click to add a filter condition",
|
||||
"add_location": "Add location",
|
||||
"add_more_users": "Add more users",
|
||||
"add_partner": "Add partner",
|
||||
"add_path": "Add path",
|
||||
"add_photos": "Add photos",
|
||||
"add_step": "Add step",
|
||||
"add_tag": "Add tag",
|
||||
"add_to": "Add to…",
|
||||
"add_to_album": "Add to album",
|
||||
@@ -41,6 +42,7 @@
|
||||
"add_to_shared_album": "Add to shared album",
|
||||
"add_upload_to_stack": "Add upload to stack",
|
||||
"add_url": "Add URL",
|
||||
"add_workflow_step": "Add workflow step",
|
||||
"added_to_archive": "Added to archive",
|
||||
"added_to_favorites": "Added to favorites",
|
||||
"added_to_favorites_count": "Added {count, number} to favorites",
|
||||
@@ -731,7 +733,6 @@
|
||||
"cannot_update_the_description": "Cannot update the description",
|
||||
"cast": "Cast",
|
||||
"cast_description": "Configure available cast destinations",
|
||||
"change": "Change",
|
||||
"change_date": "Change date",
|
||||
"change_description": "Change description",
|
||||
"change_display_order": "Change display order",
|
||||
@@ -760,7 +761,6 @@
|
||||
"check_corrupt_asset_backup_description": "Run this check only over Wi-Fi and once all assets have been backed-up. The procedure might take a few minutes.",
|
||||
"check_logs": "Check Logs",
|
||||
"checksum": "Checksum",
|
||||
"choose": "Choose",
|
||||
"choose_matching_people_to_merge": "Choose matching people to merge",
|
||||
"city": "City",
|
||||
"cleanup_confirm_description": "Immich found {count} assets (created before {date}) safely backed up to the server. Remove the local copies from this device?",
|
||||
@@ -809,7 +809,6 @@
|
||||
"comments_are_disabled": "Comments are disabled",
|
||||
"common_create_new_album": "Create new album",
|
||||
"completed": "Completed",
|
||||
"configuration": "Configuration",
|
||||
"confirm": "Confirm",
|
||||
"confirm_admin_password": "Confirm Admin Password",
|
||||
"confirm_delete_face": "Are you sure you want to delete {name} face from the asset?",
|
||||
@@ -1629,6 +1628,7 @@
|
||||
"next": "Next",
|
||||
"next_memory": "Next memory",
|
||||
"no": "No",
|
||||
"no_actions_added": "No actions added yet",
|
||||
"no_albums_found": "No albums found",
|
||||
"no_albums_message": "Create an album to organize your photos and videos",
|
||||
"no_albums_with_name_yet": "It looks like you do not have any albums with this name yet.",
|
||||
@@ -1645,6 +1645,7 @@
|
||||
"no_exif_info_available": "No exif info available",
|
||||
"no_explore_results_message": "Upload more photos to explore your collection.",
|
||||
"no_favorites_message": "Add favorites to quickly find your best pictures and videos",
|
||||
"no_filters_added": "No filters added yet",
|
||||
"no_libraries_message": "Create an external library to view your photos and videos",
|
||||
"no_local_assets_found": "No local assets found with this checksum",
|
||||
"no_location_set": "No location set",
|
||||
@@ -1657,7 +1658,6 @@
|
||||
"no_results": "No results",
|
||||
"no_results_description": "Try a synonym or more general keyword",
|
||||
"no_shared_albums_message": "Create an album to share photos and videos with people in your network",
|
||||
"no_steps": "No steps added yet",
|
||||
"no_uploads_in_progress": "No uploads in progress",
|
||||
"none": "None",
|
||||
"not_allowed": "Not allowed",
|
||||
@@ -1794,8 +1794,6 @@
|
||||
"play_original_video_setting_description": "Prefer playback of original videos rather than transcoded videos. If original asset is not compatible it may not playback correctly.",
|
||||
"play_transcoded_video": "Play transcoded video",
|
||||
"please_auth_to_access": "Please authenticate to access",
|
||||
"plugin_method_filter_type": "Filter",
|
||||
"plugin_method_filter_type_description": "This method can filter events and conditionally prevent subsequent steps from running",
|
||||
"port": "Port",
|
||||
"preferences_settings_subtitle": "Manage the app's preferences",
|
||||
"preferences_settings_title": "Preferences",
|
||||
@@ -2238,10 +2236,6 @@
|
||||
"start_date_before_end_date": "Start date must be before end date",
|
||||
"state": "State",
|
||||
"status": "Status",
|
||||
"step_delete": "Delete step",
|
||||
"step_delete_confirm": "Are you sure you want to delete this step?",
|
||||
"step_details": "Step details",
|
||||
"steps": "Steps",
|
||||
"stop_casting": "Stop casting",
|
||||
"stop_motion_photo": "Stop Motion Photo",
|
||||
"stop_photo_sharing": "Stop sharing your photos?",
|
||||
@@ -2335,7 +2329,7 @@
|
||||
"trash_page_title": "Trash ({count})",
|
||||
"trashed_items_will_be_permanently_deleted_after": "Trashed items will be permanently deleted after {days, plural, one {# day} other {# days}}.",
|
||||
"trigger": "Trigger",
|
||||
"trigger_asset_uploaded": "Asset Upload",
|
||||
"trigger_asset_uploaded": "Asset Uploaded",
|
||||
"trigger_asset_uploaded_description": "Triggered when a new asset is uploaded",
|
||||
"trigger_description": "An event that kicks off the workflow",
|
||||
"trigger_person_recognized": "Person Recognized",
|
||||
@@ -2375,6 +2369,7 @@
|
||||
"unsupported_field_type": "Unsupported field type",
|
||||
"unsupported_file_type": "File {file} can't be uploaded because its file type {type} is not supported.",
|
||||
"untagged": "Untagged",
|
||||
"untitled_workflow": "Untitled workflow",
|
||||
"up_next": "Up next",
|
||||
"update_location_action_prompt": "Update the location of {count} selected assets with:",
|
||||
"updated_at": "Updated",
|
||||
@@ -2466,7 +2461,6 @@
|
||||
"welcome_to_immich": "Welcome to Immich",
|
||||
"width": "Width",
|
||||
"wifi_name": "Wi-Fi Name",
|
||||
"workflow": "Workflow",
|
||||
"workflow_delete_prompt": "Are you sure you want to delete this workflow?",
|
||||
"workflow_deleted": "Workflow deleted",
|
||||
"workflow_description": "Workflow description",
|
||||
|
||||
@@ -2,7 +2,7 @@ experimental_monorepo_root = true
|
||||
|
||||
[monorepo]
|
||||
config_roots = [
|
||||
"packages/plugin-core",
|
||||
"packages/plugins",
|
||||
"server",
|
||||
"packages/cli",
|
||||
"deployment",
|
||||
@@ -22,9 +22,6 @@ terragrunt = "1.0.3"
|
||||
opentofu = "1.11.6"
|
||||
java = "21.0.2"
|
||||
"npm:oazapfts" = "7.5.0"
|
||||
"github:extism/cli" = "1.6.3"
|
||||
"github:webassembly/binaryen" = "version_124"
|
||||
"github:extism/js-pdk" = "1.6.0"
|
||||
|
||||
[tools."github:CQLabs/homebrew-dcm"]
|
||||
version = "1.37.0"
|
||||
@@ -44,12 +41,6 @@ macos-arm64 = { asset_pattern = "jellyfin-ffmpeg_*_portable_macarm64-gpl.tar.xz"
|
||||
experimental = true
|
||||
pin = true
|
||||
|
||||
[tasks.plugins]
|
||||
run = [
|
||||
"pnpm --filter @immich/plugin-sdk --filter @immich/plugin-core install --frozen-lockfile",
|
||||
"pnpm --filter @immich/plugin-sdk --filter @immich/plugin-core build"
|
||||
]
|
||||
|
||||
[tasks.open-api-typescript]
|
||||
run = [
|
||||
"oazapfts --optimistic --argumentStyle=object --useEnumType --allSchemas open-api/immich-openapi-specs.json packages/sdk/src/fetch-client.ts",
|
||||
@@ -64,8 +55,6 @@ run = "bash ./bin/generate-dart-sdk.sh"
|
||||
[tasks.open-api]
|
||||
env = { SHARP_IGNORE_GLOBAL_LIBVIPS = true }
|
||||
run = [
|
||||
{ task = "//:plugins" },
|
||||
{ task = "//server:build" },
|
||||
{ task = "//server:install" },
|
||||
{ task = "//server:build" },
|
||||
{ task = "//server:sync-open-api" },
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
default_platform(:android)
|
||||
|
||||
platform :android do
|
||||
desc "Build Android and Release Testing"
|
||||
lane :beta do
|
||||
desc "Build and Release Android RC to Open Testing"
|
||||
lane :rc do
|
||||
gradle(
|
||||
task: 'bundle',
|
||||
build_type: 'Release',
|
||||
|
||||
@@ -169,6 +169,37 @@ end
|
||||
)
|
||||
end
|
||||
|
||||
desc "iOS RC Build to public TestFlight"
|
||||
lane :gha_testflight_rc do
|
||||
api_key = get_api_key
|
||||
|
||||
sigh(api_key: api_key, app_identifier: DEV_BUNDLE_ID, force: true)
|
||||
main_profile_name = lane_context[SharedValues::SIGH_NAME]
|
||||
|
||||
sigh(api_key: api_key, app_identifier: "#{DEV_BUNDLE_ID}.ShareExtension", force: true)
|
||||
share_profile_name = lane_context[SharedValues::SIGH_NAME]
|
||||
|
||||
sigh(api_key: api_key, app_identifier: "#{DEV_BUNDLE_ID}.Widget", force: true)
|
||||
widget_profile_name = lane_context[SharedValues::SIGH_NAME]
|
||||
|
||||
configure_code_signing(
|
||||
base_bundle_id: DEV_BUNDLE_ID,
|
||||
profile_name_main: main_profile_name,
|
||||
profile_name_share: share_profile_name,
|
||||
profile_name_widget: widget_profile_name
|
||||
)
|
||||
|
||||
build_and_upload(
|
||||
api_key: api_key,
|
||||
base_bundle_id: DEV_BUNDLE_ID,
|
||||
version_number: get_version_from_pubspec.split('-').first,
|
||||
distribute_external: true,
|
||||
profile_name_main: main_profile_name,
|
||||
profile_name_share: share_profile_name,
|
||||
profile_name_widget: widget_profile_name
|
||||
)
|
||||
end
|
||||
|
||||
desc "iOS Release to TestFlight"
|
||||
lane :gha_release_prod do
|
||||
api_key = get_api_key
|
||||
|
||||
@@ -11,7 +11,6 @@ class RemoteAsset extends BaseAsset {
|
||||
final String ownerId;
|
||||
final String? stackId;
|
||||
final DateTime? uploadedAt;
|
||||
final DateTime? deletedAt;
|
||||
|
||||
const RemoteAsset({
|
||||
required this.id,
|
||||
@@ -32,7 +31,6 @@ class RemoteAsset extends BaseAsset {
|
||||
super.livePhotoVideoId,
|
||||
this.stackId,
|
||||
required super.isEdited,
|
||||
this.deletedAt,
|
||||
}) : localAssetId = localId;
|
||||
|
||||
@override
|
||||
@@ -50,8 +48,6 @@ class RemoteAsset extends BaseAsset {
|
||||
@override
|
||||
bool get isEditable => isImage && !isMotionPhoto && !isAnimatedImage;
|
||||
|
||||
bool get isTrashed => deletedAt != null;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return '''Asset {
|
||||
@@ -90,8 +86,7 @@ class RemoteAsset extends BaseAsset {
|
||||
thumbHash == other.thumbHash &&
|
||||
visibility == other.visibility &&
|
||||
stackId == other.stackId &&
|
||||
uploadedAt == other.uploadedAt &&
|
||||
deletedAt == other.deletedAt;
|
||||
uploadedAt == other.uploadedAt;
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -103,8 +98,7 @@ class RemoteAsset extends BaseAsset {
|
||||
thumbHash.hashCode ^
|
||||
visibility.hashCode ^
|
||||
stackId.hashCode ^
|
||||
uploadedAt.hashCode ^
|
||||
deletedAt.hashCode;
|
||||
uploadedAt.hashCode;
|
||||
|
||||
RemoteAsset copyWith({
|
||||
String? id,
|
||||
@@ -125,7 +119,6 @@ class RemoteAsset extends BaseAsset {
|
||||
String? livePhotoVideoId,
|
||||
String? stackId,
|
||||
bool? isEdited,
|
||||
DateTime? deletedAt,
|
||||
}) {
|
||||
return RemoteAsset(
|
||||
id: id ?? this.id,
|
||||
@@ -146,7 +139,6 @@ class RemoteAsset extends BaseAsset {
|
||||
livePhotoVideoId: livePhotoVideoId ?? this.livePhotoVideoId,
|
||||
stackId: stackId ?? this.stackId,
|
||||
isEdited: isEdited ?? this.isEdited,
|
||||
deletedAt: deletedAt ?? this.deletedAt,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -164,7 +156,6 @@ class RemoteAssetExif extends RemoteAsset {
|
||||
required super.createdAt,
|
||||
required super.updatedAt,
|
||||
super.uploadedAt,
|
||||
super.deletedAt,
|
||||
super.width,
|
||||
super.height,
|
||||
super.durationMs,
|
||||
@@ -202,7 +193,6 @@ class RemoteAssetExif extends RemoteAsset {
|
||||
DateTime? createdAt,
|
||||
DateTime? updatedAt,
|
||||
DateTime? uploadedAt,
|
||||
DateTime? deletedAt,
|
||||
int? width,
|
||||
int? height,
|
||||
int? durationMs,
|
||||
@@ -224,7 +214,6 @@ class RemoteAssetExif extends RemoteAsset {
|
||||
createdAt: createdAt ?? this.createdAt,
|
||||
updatedAt: updatedAt ?? this.updatedAt,
|
||||
uploadedAt: uploadedAt ?? this.uploadedAt,
|
||||
deletedAt: deletedAt ?? this.deletedAt,
|
||||
width: width ?? this.width,
|
||||
height: height ?? this.height,
|
||||
durationMs: durationMs ?? this.durationMs,
|
||||
|
||||
@@ -4,15 +4,25 @@ import 'package:immich_mobile/domain/models/user.model.dart';
|
||||
/// Defines the data type for each value
|
||||
enum StoreKey<T> {
|
||||
version<int>._(0),
|
||||
assetETag<String>._(1),
|
||||
currentUser<UserDto>._(2),
|
||||
deviceIdHash<int>._(3),
|
||||
deviceId<String>._(4),
|
||||
backupFailedSince<DateTime>._(5),
|
||||
backupRequireWifi<bool>._(6),
|
||||
backupRequireCharging<bool>._(7),
|
||||
backupTriggerDelay<int>._(8),
|
||||
serverUrl<String>._(10),
|
||||
accessToken<String>._(11),
|
||||
serverEndpoint<String>._(12),
|
||||
autoBackup<bool>._(13),
|
||||
backgroundBackup<bool>._(14),
|
||||
sslClientCertData<String>._(15),
|
||||
sslClientPasswd<String>._(16),
|
||||
uploadErrorNotificationGracePeriod<int>._(106),
|
||||
selectedAlbumSortOrder<int>._(113),
|
||||
advancedTroubleshooting<bool>._(114),
|
||||
selfSignedCert<bool>._(120),
|
||||
selectedAlbumSortReverse<bool>._(123),
|
||||
enableHapticFeedback<bool>._(126),
|
||||
customHeaders<String>._(127),
|
||||
@@ -28,6 +38,7 @@ enum StoreKey<T> {
|
||||
// Read-only Mode settings
|
||||
readonlyModeEnabled<bool>._(138),
|
||||
albumGridView<bool>._(140),
|
||||
loadOriginal<bool>._(101),
|
||||
|
||||
// Experimental stuff
|
||||
enableBackup<bool>._(1003),
|
||||
|
||||
@@ -74,6 +74,5 @@ extension RemoteAssetEntityDataDomainEx on RemoteAssetEntityData {
|
||||
localId: localId,
|
||||
stackId: stackId,
|
||||
isEdited: isEdited,
|
||||
deletedAt: deletedAt,
|
||||
);
|
||||
}
|
||||
|
||||
+2
-9
@@ -18,15 +18,8 @@ class DeletePermanentActionButton extends ConsumerWidget {
|
||||
final ActionSource source;
|
||||
final bool iconOnly;
|
||||
final bool menuItem;
|
||||
final bool useShortLabel;
|
||||
|
||||
const DeletePermanentActionButton({
|
||||
super.key,
|
||||
required this.source,
|
||||
this.iconOnly = false,
|
||||
this.menuItem = false,
|
||||
this.useShortLabel = false,
|
||||
});
|
||||
const DeletePermanentActionButton({super.key, required this.source, this.iconOnly = false, this.menuItem = false});
|
||||
|
||||
void _onTap(BuildContext context, WidgetRef ref) async {
|
||||
if (!context.mounted) {
|
||||
@@ -71,7 +64,7 @@ class DeletePermanentActionButton extends ConsumerWidget {
|
||||
return BaseActionButton(
|
||||
maxWidth: 110.0,
|
||||
iconData: Icons.delete_forever,
|
||||
label: useShortLabel ? "delete".t(context: context) : "delete_permanently".t(context: context),
|
||||
label: "delete_permanently".t(context: context),
|
||||
iconOnly: iconOnly,
|
||||
menuItem: menuItem,
|
||||
onPressed: () => _onTap(context, ref),
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/constants/enums.dart';
|
||||
import 'package:immich_mobile/domain/models/events.model.dart';
|
||||
import 'package:immich_mobile/domain/utils/event_stream.dart';
|
||||
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/action_buttons/base_action_button.widget.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/action.provider.dart';
|
||||
import 'package:immich_mobile/providers/timeline/multiselect.provider.dart';
|
||||
import 'package:immich_mobile/widgets/common/immich_toast.dart';
|
||||
|
||||
class RestoreActionButton extends ConsumerWidget {
|
||||
final ActionSource source;
|
||||
final bool iconOnly;
|
||||
final bool menuItem;
|
||||
|
||||
const RestoreActionButton({super.key, required this.source, this.iconOnly = false, this.menuItem = false});
|
||||
|
||||
void _onTap(BuildContext context, WidgetRef ref) async {
|
||||
if (!context.mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
final result = await ref.read(actionProvider.notifier).restoreTrash(source);
|
||||
ref.read(multiSelectProvider.notifier).reset();
|
||||
|
||||
if (source == ActionSource.viewer) {
|
||||
EventStream.shared.emit(const ViewerReloadAssetEvent());
|
||||
}
|
||||
|
||||
final successMessage = 'assets_restored_count'.t(context: context, args: {'count': result.count.toString()});
|
||||
|
||||
if (context.mounted) {
|
||||
ImmichToast.show(
|
||||
context: context,
|
||||
msg: result.success ? successMessage : 'scaffold_body_error_occurred'.t(context: context),
|
||||
gravity: ToastGravity.BOTTOM,
|
||||
toastType: result.success ? ToastType.success : ToastType.error,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
return BaseActionButton(
|
||||
iconData: Icons.history_rounded,
|
||||
label: 'restore'.t(context: context),
|
||||
iconOnly: iconOnly,
|
||||
menuItem: menuItem,
|
||||
onPressed: () => _onTap(context, ref),
|
||||
maxWidth: 100.0,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -2,19 +2,15 @@ import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/constants/enums.dart';
|
||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||
import 'package:immich_mobile/domain/services/timeline.service.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/action_buttons/add_action_button.widget.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/action_buttons/delete_action_button.widget.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/action_buttons/delete_local_action_button.widget.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/action_buttons/delete_permanent_action_button.widget.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/action_buttons/edit_image_action_button.widget.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/action_buttons/restore_action_button.widget.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/action_buttons/share_action_button.widget.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/action_buttons/upload_action_button.widget.dart';
|
||||
import 'package:immich_mobile/providers/asset_viewer/asset_viewer.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/readonly_mode.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart';
|
||||
import 'package:immich_mobile/providers/routes.provider.dart';
|
||||
import 'package:immich_mobile/providers/server_info.provider.dart';
|
||||
import 'package:immich_mobile/providers/user.provider.dart';
|
||||
@@ -37,31 +33,23 @@ class ViewerBottomBar extends ConsumerWidget {
|
||||
final showingDetails = ref.watch(assetViewerProvider.select((s) => s.showingDetails));
|
||||
final isInLockedView = ref.watch(inLockedViewProvider);
|
||||
final serverInfo = ref.watch(serverInfoProvider);
|
||||
final isInTrash = ref.read(timelineServiceProvider).origin == TimelineOrigin.trash;
|
||||
|
||||
final originalTheme = context.themeData;
|
||||
|
||||
final actions = <Widget>[
|
||||
if (isInTrash && isOwner && asset.hasRemote)
|
||||
const RestoreActionButton(source: ActionSource.viewer)
|
||||
else
|
||||
const ShareActionButton(source: ActionSource.viewer),
|
||||
const ShareActionButton(source: ActionSource.viewer),
|
||||
|
||||
if (!isInLockedView) ...[
|
||||
if (!isInTrash) ...[
|
||||
if (asset.isLocalOnly) const UploadActionButton(source: ActionSource.viewer),
|
||||
// edit sync was added in 2.6.0
|
||||
if (asset.isEditable && serverInfo.serverVersion >= const SemVer(major: 2, minor: 6, patch: 0))
|
||||
const EditImageActionButton(),
|
||||
if (asset.hasRemote) AddActionButton(originalTheme: originalTheme),
|
||||
],
|
||||
if (asset.isLocalOnly) const UploadActionButton(source: ActionSource.viewer),
|
||||
// edit sync was added in 2.6.0
|
||||
if (asset.isEditable && serverInfo.serverVersion >= const SemVer(major: 2, minor: 6, patch: 0))
|
||||
const EditImageActionButton(),
|
||||
if (asset.hasRemote) AddActionButton(originalTheme: originalTheme),
|
||||
|
||||
if (isOwner) ...[
|
||||
if (asset.isLocalOnly)
|
||||
const DeleteLocalActionButton(source: ActionSource.viewer)
|
||||
else if (asset.isTrashed)
|
||||
const DeletePermanentActionButton(source: ActionSource.viewer, useShortLabel: true)
|
||||
else
|
||||
const DeleteActionButton(source: ActionSource.viewer, showConfirmation: true),
|
||||
asset.isLocalOnly
|
||||
? const DeleteLocalActionButton(source: ActionSource.viewer)
|
||||
: const DeleteActionButton(source: ActionSource.viewer, showConfirmation: true),
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
@@ -11,11 +11,12 @@ import 'package:immich_mobile/providers/api.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/user.provider.dart';
|
||||
import 'package:immich_mobile/services/api.service.dart';
|
||||
import 'package:immich_mobile/services/auth.service.dart';
|
||||
import 'package:immich_mobile/services/background_upload.service.dart';
|
||||
import 'package:immich_mobile/services/foreground_upload.service.dart';
|
||||
import 'package:immich_mobile/services/secure_storage.service.dart';
|
||||
import 'package:immich_mobile/services/background_upload.service.dart';
|
||||
import 'package:immich_mobile/services/widget.service.dart';
|
||||
import 'package:immich_mobile/utils/debug_print.dart';
|
||||
import 'package:immich_mobile/utils/hash.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:openapi/api.dart';
|
||||
|
||||
@@ -143,6 +144,7 @@ class AuthNotifier extends StateNotifier<AuthState> {
|
||||
// Due to the flow of the code, this will always happen on first login
|
||||
user = serverUser;
|
||||
await Store.put(StoreKey.deviceId, deviceId);
|
||||
await Store.put(StoreKey.deviceIdHash, fastHash(deviceId));
|
||||
}
|
||||
} on ApiException catch (error, stackTrace) {
|
||||
if (error.code == 401) {
|
||||
|
||||
@@ -2,9 +2,15 @@ import 'package:immich_mobile/domain/models/store.model.dart';
|
||||
import 'package:immich_mobile/entities/store.entity.dart';
|
||||
|
||||
enum AppSettingsEnum<T> {
|
||||
uploadErrorNotificationGracePeriod<int>(
|
||||
StoreKey.uploadErrorNotificationGracePeriod,
|
||||
"uploadErrorNotificationGracePeriod",
|
||||
2,
|
||||
),
|
||||
selectedAlbumSortOrder<int>(StoreKey.selectedAlbumSortOrder, "selectedAlbumSortOrder", 2),
|
||||
advancedTroubleshooting<bool>(StoreKey.advancedTroubleshooting, null, false),
|
||||
manageLocalMediaAndroid<bool>(StoreKey.manageLocalMediaAndroid, null, false),
|
||||
allowSelfSignedSSLCert<bool>(StoreKey.selfSignedCert, null, false),
|
||||
selectedAlbumSortReverse<bool>(StoreKey.selectedAlbumSortReverse, null, true),
|
||||
enableHapticFeedback<bool>(StoreKey.enableHapticFeedback, null, true),
|
||||
syncAlbums<bool>(StoreKey.syncAlbums, null, false),
|
||||
|
||||
@@ -123,6 +123,7 @@ class AuthService {
|
||||
_authRepository.clearLocalData(),
|
||||
Store.delete(StoreKey.currentUser),
|
||||
Store.delete(StoreKey.accessToken),
|
||||
Store.delete(StoreKey.assetETag),
|
||||
Store.delete(StoreKey.autoEndpointSwitching),
|
||||
Store.delete(StoreKey.preferredWifiName),
|
||||
Store.delete(StoreKey.localEndpoint),
|
||||
|
||||
@@ -21,7 +21,6 @@ import 'package:immich_mobile/presentation/widgets/action_buttons/move_to_lock_f
|
||||
import 'package:immich_mobile/presentation/widgets/action_buttons/open_in_browser_action_button.widget.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/action_buttons/remove_from_album_action_button.widget.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/action_buttons/remove_from_lock_folder_action_button.widget.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/action_buttons/restore_action_button.widget.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/action_buttons/set_album_cover.widget.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/action_buttons/set_profile_picture_action_button.widget.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/action_buttons/share_action_button.widget.dart';
|
||||
@@ -82,7 +81,6 @@ enum ActionButtonType {
|
||||
moveToLockFolder,
|
||||
removeFromLockFolder,
|
||||
removeFromAlbum,
|
||||
restoreTrash,
|
||||
trash,
|
||||
deleteLocal,
|
||||
deletePermanent,
|
||||
@@ -114,17 +112,12 @@ enum ActionButtonType {
|
||||
context.isOwner && //
|
||||
!context.isInLockedView && //
|
||||
context.asset.hasRemote && //
|
||||
context.isTrashEnabled && //
|
||||
context.timelineOrigin != TimelineOrigin.trash,
|
||||
ActionButtonType.restoreTrash =>
|
||||
context.isOwner && //
|
||||
!context.isInLockedView && //
|
||||
context.asset.hasRemote && //
|
||||
context.timelineOrigin == TimelineOrigin.trash,
|
||||
context.isTrashEnabled,
|
||||
ActionButtonType.deletePermanent =>
|
||||
context.isOwner && //
|
||||
context.asset.hasRemote && //
|
||||
(!context.isTrashEnabled || context.timelineOrigin == TimelineOrigin.trash || context.isInLockedView),
|
||||
context.asset.hasRemote && //
|
||||
!context.isTrashEnabled ||
|
||||
context.isInLockedView,
|
||||
ActionButtonType.delete =>
|
||||
context.isOwner && //
|
||||
!context.isInLockedView && //
|
||||
@@ -208,11 +201,6 @@ enum ActionButtonType {
|
||||
),
|
||||
ActionButtonType.download => DownloadActionButton(source: context.source, iconOnly: iconOnly, menuItem: menuItem),
|
||||
ActionButtonType.trash => TrashActionButton(source: context.source, iconOnly: iconOnly, menuItem: menuItem),
|
||||
ActionButtonType.restoreTrash => RestoreActionButton(
|
||||
source: context.source,
|
||||
iconOnly: iconOnly,
|
||||
menuItem: menuItem,
|
||||
),
|
||||
ActionButtonType.deletePermanent => DeletePermanentActionButton(
|
||||
source: context.source,
|
||||
iconOnly: iconOnly,
|
||||
@@ -304,7 +292,6 @@ enum ActionButtonType {
|
||||
ActionButtonType.moveToLockFolder => 10,
|
||||
ActionButtonType.deleteLocal => 10,
|
||||
ActionButtonType.delete => 10,
|
||||
ActionButtonType.restoreTrash => 10,
|
||||
// 90: advancedInfo
|
||||
ActionButtonType.advancedInfo => 90,
|
||||
// 1: others
|
||||
@@ -322,8 +309,6 @@ class ActionButtonBuilder {
|
||||
ActionButtonType.delete,
|
||||
ActionButtonType.archive,
|
||||
ActionButtonType.unarchive,
|
||||
ActionButtonType.restoreTrash,
|
||||
ActionButtonType.deletePermanent,
|
||||
};
|
||||
|
||||
static List<Widget> build(ActionButtonContext context) {
|
||||
|
||||
@@ -3,7 +3,10 @@ import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/providers/notification_permission.provider.dart';
|
||||
import 'package:immich_mobile/services/app_settings.service.dart';
|
||||
import 'package:immich_mobile/utils/hooks/app_settings_update_hook.dart';
|
||||
import 'package:immich_mobile/widgets/settings/settings_button_list_tile.dart';
|
||||
import 'package:immich_mobile/widgets/settings/settings_slider_list_tile.dart';
|
||||
import 'package:immich_mobile/widgets/settings/settings_sub_page_scaffold.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
|
||||
@@ -13,6 +16,9 @@ class NotificationSetting extends HookConsumerWidget {
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final permissionService = ref.watch(notificationPermissionProvider);
|
||||
|
||||
final sliderValue = useAppSettingsState(AppSettingsEnum.uploadErrorNotificationGracePeriod);
|
||||
|
||||
final hasPermission = permissionService == PermissionStatus.granted;
|
||||
|
||||
openAppNotificationSettings(BuildContext ctx) {
|
||||
@@ -35,6 +41,8 @@ class NotificationSetting extends HookConsumerWidget {
|
||||
);
|
||||
}
|
||||
|
||||
final String formattedValue = _formatSliderValue(sliderValue.value.toDouble());
|
||||
|
||||
final notificationSettings = [
|
||||
if (!hasPermission)
|
||||
SettingsButtonListTile(
|
||||
@@ -49,8 +57,32 @@ class NotificationSetting extends HookConsumerWidget {
|
||||
}
|
||||
}),
|
||||
),
|
||||
SettingsSliderListTile(
|
||||
enabled: hasPermission,
|
||||
valueNotifier: sliderValue,
|
||||
text: 'setting_notifications_notify_failures_grace_period'.tr(namedArgs: {'duration': formattedValue}),
|
||||
maxValue: 5.0,
|
||||
noDivisons: 5,
|
||||
label: formattedValue,
|
||||
),
|
||||
];
|
||||
|
||||
return SettingsSubPageScaffold(settings: notificationSettings);
|
||||
}
|
||||
}
|
||||
|
||||
String _formatSliderValue(double v) {
|
||||
if (v == 0.0) {
|
||||
return 'setting_notifications_notify_immediately'.tr();
|
||||
} else if (v == 1.0) {
|
||||
return 'setting_notifications_notify_minutes'.tr(namedArgs: {'count': '30'});
|
||||
} else if (v == 2.0) {
|
||||
return 'setting_notifications_notify_hours'.tr(namedArgs: {'count': '2'});
|
||||
} else if (v == 3.0) {
|
||||
return 'setting_notifications_notify_hours'.tr(namedArgs: {'count': '8'});
|
||||
} else if (v == 4.0) {
|
||||
return 'setting_notifications_notify_hours'.tr(namedArgs: {'count': '24'});
|
||||
} else {
|
||||
return 'setting_notifications_notify_never'.tr();
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+16
-12
@@ -205,8 +205,8 @@ Class | Method | HTTP request | Description
|
||||
*PeopleApi* | [**updatePeople**](doc//PeopleApi.md#updatepeople) | **PUT** /people | Update people
|
||||
*PeopleApi* | [**updatePerson**](doc//PeopleApi.md#updateperson) | **PUT** /people/{id} | Update person
|
||||
*PluginsApi* | [**getPlugin**](doc//PluginsApi.md#getplugin) | **GET** /plugins/{id} | Retrieve a plugin
|
||||
*PluginsApi* | [**searchPluginMethods**](doc//PluginsApi.md#searchpluginmethods) | **GET** /plugins/methods | Retrieve plugin methods
|
||||
*PluginsApi* | [**searchPlugins**](doc//PluginsApi.md#searchplugins) | **GET** /plugins | List all plugins
|
||||
*PluginsApi* | [**getPluginTriggers**](doc//PluginsApi.md#getplugintriggers) | **GET** /plugins/triggers | List all plugin triggers
|
||||
*PluginsApi* | [**getPlugins**](doc//PluginsApi.md#getplugins) | **GET** /plugins | List all plugins
|
||||
*QueuesApi* | [**emptyQueue**](doc//QueuesApi.md#emptyqueue) | **DELETE** /queues/{name}/jobs | Empty a queue
|
||||
*QueuesApi* | [**getQueue**](doc//QueuesApi.md#getqueue) | **GET** /queues/{name} | Retrieve a queue
|
||||
*QueuesApi* | [**getQueueJobs**](doc//QueuesApi.md#getqueuejobs) | **GET** /queues/{name}/jobs | Retrieve queue jobs
|
||||
@@ -314,9 +314,7 @@ Class | Method | HTTP request | Description
|
||||
*WorkflowsApi* | [**createWorkflow**](doc//WorkflowsApi.md#createworkflow) | **POST** /workflows | Create a workflow
|
||||
*WorkflowsApi* | [**deleteWorkflow**](doc//WorkflowsApi.md#deleteworkflow) | **DELETE** /workflows/{id} | Delete a workflow
|
||||
*WorkflowsApi* | [**getWorkflow**](doc//WorkflowsApi.md#getworkflow) | **GET** /workflows/{id} | Retrieve a workflow
|
||||
*WorkflowsApi* | [**getWorkflowForShare**](doc//WorkflowsApi.md#getworkflowforshare) | **GET** /workflows/{id}/share | Retrieve a workflow
|
||||
*WorkflowsApi* | [**getWorkflowTriggers**](doc//WorkflowsApi.md#getworkflowtriggers) | **GET** /workflows/triggers | List all workflow triggers
|
||||
*WorkflowsApi* | [**searchWorkflows**](doc//WorkflowsApi.md#searchworkflows) | **GET** /workflows | List all workflows
|
||||
*WorkflowsApi* | [**getWorkflows**](doc//WorkflowsApi.md#getworkflows) | **GET** /workflows | List all workflows
|
||||
*WorkflowsApi* | [**updateWorkflow**](doc//WorkflowsApi.md#updateworkflow) | **PUT** /workflows/{id} | Update a workflow
|
||||
|
||||
|
||||
@@ -489,8 +487,16 @@ Class | Method | HTTP request | Description
|
||||
- [PinCodeResetDto](doc//PinCodeResetDto.md)
|
||||
- [PinCodeSetupDto](doc//PinCodeSetupDto.md)
|
||||
- [PlacesResponseDto](doc//PlacesResponseDto.md)
|
||||
- [PluginMethodResponseDto](doc//PluginMethodResponseDto.md)
|
||||
- [PluginActionResponseDto](doc//PluginActionResponseDto.md)
|
||||
- [PluginContextType](doc//PluginContextType.md)
|
||||
- [PluginFilterResponseDto](doc//PluginFilterResponseDto.md)
|
||||
- [PluginJsonSchema](doc//PluginJsonSchema.md)
|
||||
- [PluginJsonSchemaProperty](doc//PluginJsonSchemaProperty.md)
|
||||
- [PluginJsonSchemaPropertyAdditionalProperties](doc//PluginJsonSchemaPropertyAdditionalProperties.md)
|
||||
- [PluginJsonSchemaType](doc//PluginJsonSchemaType.md)
|
||||
- [PluginResponseDto](doc//PluginResponseDto.md)
|
||||
- [PluginTriggerResponseDto](doc//PluginTriggerResponseDto.md)
|
||||
- [PluginTriggerType](doc//PluginTriggerType.md)
|
||||
- [PurchaseResponse](doc//PurchaseResponse.md)
|
||||
- [PurchaseUpdate](doc//PurchaseUpdate.md)
|
||||
- [QueueCommand](doc//QueueCommand.md)
|
||||
@@ -663,14 +669,12 @@ Class | Method | HTTP request | Description
|
||||
- [VersionCheckStateResponseDto](doc//VersionCheckStateResponseDto.md)
|
||||
- [VideoCodec](doc//VideoCodec.md)
|
||||
- [VideoContainer](doc//VideoContainer.md)
|
||||
- [WorkflowActionItemDto](doc//WorkflowActionItemDto.md)
|
||||
- [WorkflowActionResponseDto](doc//WorkflowActionResponseDto.md)
|
||||
- [WorkflowCreateDto](doc//WorkflowCreateDto.md)
|
||||
- [WorkflowFilterItemDto](doc//WorkflowFilterItemDto.md)
|
||||
- [WorkflowFilterResponseDto](doc//WorkflowFilterResponseDto.md)
|
||||
- [WorkflowResponseDto](doc//WorkflowResponseDto.md)
|
||||
- [WorkflowShareResponseDto](doc//WorkflowShareResponseDto.md)
|
||||
- [WorkflowShareStepDto](doc//WorkflowShareStepDto.md)
|
||||
- [WorkflowStepDto](doc//WorkflowStepDto.md)
|
||||
- [WorkflowTrigger](doc//WorkflowTrigger.md)
|
||||
- [WorkflowTriggerResponseDto](doc//WorkflowTriggerResponseDto.md)
|
||||
- [WorkflowType](doc//WorkflowType.md)
|
||||
- [WorkflowUpdateDto](doc//WorkflowUpdateDto.md)
|
||||
|
||||
|
||||
|
||||
Generated
+13
-7
@@ -235,8 +235,16 @@ part 'model/pin_code_change_dto.dart';
|
||||
part 'model/pin_code_reset_dto.dart';
|
||||
part 'model/pin_code_setup_dto.dart';
|
||||
part 'model/places_response_dto.dart';
|
||||
part 'model/plugin_method_response_dto.dart';
|
||||
part 'model/plugin_action_response_dto.dart';
|
||||
part 'model/plugin_context_type.dart';
|
||||
part 'model/plugin_filter_response_dto.dart';
|
||||
part 'model/plugin_json_schema.dart';
|
||||
part 'model/plugin_json_schema_property.dart';
|
||||
part 'model/plugin_json_schema_property_additional_properties.dart';
|
||||
part 'model/plugin_json_schema_type.dart';
|
||||
part 'model/plugin_response_dto.dart';
|
||||
part 'model/plugin_trigger_response_dto.dart';
|
||||
part 'model/plugin_trigger_type.dart';
|
||||
part 'model/purchase_response.dart';
|
||||
part 'model/purchase_update.dart';
|
||||
part 'model/queue_command.dart';
|
||||
@@ -409,14 +417,12 @@ part 'model/validate_library_response_dto.dart';
|
||||
part 'model/version_check_state_response_dto.dart';
|
||||
part 'model/video_codec.dart';
|
||||
part 'model/video_container.dart';
|
||||
part 'model/workflow_action_item_dto.dart';
|
||||
part 'model/workflow_action_response_dto.dart';
|
||||
part 'model/workflow_create_dto.dart';
|
||||
part 'model/workflow_filter_item_dto.dart';
|
||||
part 'model/workflow_filter_response_dto.dart';
|
||||
part 'model/workflow_response_dto.dart';
|
||||
part 'model/workflow_share_response_dto.dart';
|
||||
part 'model/workflow_share_step_dto.dart';
|
||||
part 'model/workflow_step_dto.dart';
|
||||
part 'model/workflow_trigger.dart';
|
||||
part 'model/workflow_trigger_response_dto.dart';
|
||||
part 'model/workflow_type.dart';
|
||||
part 'model/workflow_update_dto.dart';
|
||||
|
||||
|
||||
|
||||
Generated
+13
-144
@@ -73,40 +73,14 @@ class PluginsApi {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Retrieve plugin methods
|
||||
/// List all plugin triggers
|
||||
///
|
||||
/// Retrieve a list of plugin methods
|
||||
/// Retrieve a list of all available plugin triggers.
|
||||
///
|
||||
/// Note: This method returns the HTTP [Response].
|
||||
///
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [String] description:
|
||||
///
|
||||
/// * [bool] enabled:
|
||||
/// Whether the plugin method is enabled
|
||||
///
|
||||
/// * [String] id:
|
||||
/// Plugin method ID
|
||||
///
|
||||
/// * [String] name:
|
||||
///
|
||||
/// * [String] pluginName:
|
||||
/// Plugin name
|
||||
///
|
||||
/// * [String] pluginVersion:
|
||||
/// Plugin version
|
||||
///
|
||||
/// * [String] title:
|
||||
///
|
||||
/// * [WorkflowTrigger] trigger:
|
||||
/// Workflow trigger
|
||||
///
|
||||
/// * [WorkflowType] type:
|
||||
/// Workflow types
|
||||
Future<Response> searchPluginMethodsWithHttpInfo({ String? description, bool? enabled, String? id, String? name, String? pluginName, String? pluginVersion, String? title, WorkflowTrigger? trigger, WorkflowType? type, }) async {
|
||||
Future<Response> getPluginTriggersWithHttpInfo() async {
|
||||
// ignore: prefer_const_declarations
|
||||
final apiPath = r'/plugins/methods';
|
||||
final apiPath = r'/plugins/triggers';
|
||||
|
||||
// ignore: prefer_final_locals
|
||||
Object? postBody;
|
||||
@@ -115,34 +89,6 @@ class PluginsApi {
|
||||
final headerParams = <String, String>{};
|
||||
final formParams = <String, String>{};
|
||||
|
||||
if (description != null) {
|
||||
queryParams.addAll(_queryParams('', 'description', description));
|
||||
}
|
||||
if (enabled != null) {
|
||||
queryParams.addAll(_queryParams('', 'enabled', enabled));
|
||||
}
|
||||
if (id != null) {
|
||||
queryParams.addAll(_queryParams('', 'id', id));
|
||||
}
|
||||
if (name != null) {
|
||||
queryParams.addAll(_queryParams('', 'name', name));
|
||||
}
|
||||
if (pluginName != null) {
|
||||
queryParams.addAll(_queryParams('', 'pluginName', pluginName));
|
||||
}
|
||||
if (pluginVersion != null) {
|
||||
queryParams.addAll(_queryParams('', 'pluginVersion', pluginVersion));
|
||||
}
|
||||
if (title != null) {
|
||||
queryParams.addAll(_queryParams('', 'title', title));
|
||||
}
|
||||
if (trigger != null) {
|
||||
queryParams.addAll(_queryParams('', 'trigger', trigger));
|
||||
}
|
||||
if (type != null) {
|
||||
queryParams.addAll(_queryParams('', 'type', type));
|
||||
}
|
||||
|
||||
const contentTypes = <String>[];
|
||||
|
||||
|
||||
@@ -157,37 +103,11 @@ class PluginsApi {
|
||||
);
|
||||
}
|
||||
|
||||
/// Retrieve plugin methods
|
||||
/// List all plugin triggers
|
||||
///
|
||||
/// Retrieve a list of plugin methods
|
||||
///
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [String] description:
|
||||
///
|
||||
/// * [bool] enabled:
|
||||
/// Whether the plugin method is enabled
|
||||
///
|
||||
/// * [String] id:
|
||||
/// Plugin method ID
|
||||
///
|
||||
/// * [String] name:
|
||||
///
|
||||
/// * [String] pluginName:
|
||||
/// Plugin name
|
||||
///
|
||||
/// * [String] pluginVersion:
|
||||
/// Plugin version
|
||||
///
|
||||
/// * [String] title:
|
||||
///
|
||||
/// * [WorkflowTrigger] trigger:
|
||||
/// Workflow trigger
|
||||
///
|
||||
/// * [WorkflowType] type:
|
||||
/// Workflow types
|
||||
Future<List<PluginMethodResponseDto>?> searchPluginMethods({ String? description, bool? enabled, String? id, String? name, String? pluginName, String? pluginVersion, String? title, WorkflowTrigger? trigger, WorkflowType? type, }) async {
|
||||
final response = await searchPluginMethodsWithHttpInfo( description: description, enabled: enabled, id: id, name: name, pluginName: pluginName, pluginVersion: pluginVersion, title: title, trigger: trigger, type: type, );
|
||||
/// Retrieve a list of all available plugin triggers.
|
||||
Future<List<PluginTriggerResponseDto>?> getPluginTriggers() async {
|
||||
final response = await getPluginTriggersWithHttpInfo();
|
||||
if (response.statusCode >= HttpStatus.badRequest) {
|
||||
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||
}
|
||||
@@ -196,8 +116,8 @@ class PluginsApi {
|
||||
// FormatException when trying to decode an empty string.
|
||||
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
|
||||
final responseBody = await _decodeBodyBytes(response);
|
||||
return (await apiClient.deserializeAsync(responseBody, 'List<PluginMethodResponseDto>') as List)
|
||||
.cast<PluginMethodResponseDto>()
|
||||
return (await apiClient.deserializeAsync(responseBody, 'List<PluginTriggerResponseDto>') as List)
|
||||
.cast<PluginTriggerResponseDto>()
|
||||
.toList(growable: false);
|
||||
|
||||
}
|
||||
@@ -209,23 +129,7 @@ class PluginsApi {
|
||||
/// Retrieve a list of plugins available to the authenticated user.
|
||||
///
|
||||
/// Note: This method returns the HTTP [Response].
|
||||
///
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [String] description:
|
||||
///
|
||||
/// * [bool] enabled:
|
||||
/// Whether the plugin is enabled
|
||||
///
|
||||
/// * [String] id:
|
||||
/// Plugin ID
|
||||
///
|
||||
/// * [String] name:
|
||||
///
|
||||
/// * [String] title:
|
||||
///
|
||||
/// * [String] version:
|
||||
Future<Response> searchPluginsWithHttpInfo({ String? description, bool? enabled, String? id, String? name, String? title, String? version, }) async {
|
||||
Future<Response> getPluginsWithHttpInfo() async {
|
||||
// ignore: prefer_const_declarations
|
||||
final apiPath = r'/plugins';
|
||||
|
||||
@@ -236,25 +140,6 @@ class PluginsApi {
|
||||
final headerParams = <String, String>{};
|
||||
final formParams = <String, String>{};
|
||||
|
||||
if (description != null) {
|
||||
queryParams.addAll(_queryParams('', 'description', description));
|
||||
}
|
||||
if (enabled != null) {
|
||||
queryParams.addAll(_queryParams('', 'enabled', enabled));
|
||||
}
|
||||
if (id != null) {
|
||||
queryParams.addAll(_queryParams('', 'id', id));
|
||||
}
|
||||
if (name != null) {
|
||||
queryParams.addAll(_queryParams('', 'name', name));
|
||||
}
|
||||
if (title != null) {
|
||||
queryParams.addAll(_queryParams('', 'title', title));
|
||||
}
|
||||
if (version != null) {
|
||||
queryParams.addAll(_queryParams('', 'version', version));
|
||||
}
|
||||
|
||||
const contentTypes = <String>[];
|
||||
|
||||
|
||||
@@ -272,24 +157,8 @@ class PluginsApi {
|
||||
/// List all plugins
|
||||
///
|
||||
/// Retrieve a list of plugins available to the authenticated user.
|
||||
///
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [String] description:
|
||||
///
|
||||
/// * [bool] enabled:
|
||||
/// Whether the plugin is enabled
|
||||
///
|
||||
/// * [String] id:
|
||||
/// Plugin ID
|
||||
///
|
||||
/// * [String] name:
|
||||
///
|
||||
/// * [String] title:
|
||||
///
|
||||
/// * [String] version:
|
||||
Future<List<PluginResponseDto>?> searchPlugins({ String? description, bool? enabled, String? id, String? name, String? title, String? version, }) async {
|
||||
final response = await searchPluginsWithHttpInfo( description: description, enabled: enabled, id: id, name: name, title: title, version: version, );
|
||||
Future<List<PluginResponseDto>?> getPlugins() async {
|
||||
final response = await getPluginsWithHttpInfo();
|
||||
if (response.statusCode >= HttpStatus.badRequest) {
|
||||
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||
}
|
||||
|
||||
+3
-161
@@ -178,137 +178,12 @@ class WorkflowsApi {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Retrieve a workflow
|
||||
///
|
||||
/// Retrieve a workflow details without ids, default values, etc.
|
||||
///
|
||||
/// Note: This method returns the HTTP [Response].
|
||||
///
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [String] id (required):
|
||||
Future<Response> getWorkflowForShareWithHttpInfo(String id,) async {
|
||||
// ignore: prefer_const_declarations
|
||||
final apiPath = r'/workflows/{id}/share'
|
||||
.replaceAll('{id}', id);
|
||||
|
||||
// ignore: prefer_final_locals
|
||||
Object? postBody;
|
||||
|
||||
final queryParams = <QueryParam>[];
|
||||
final headerParams = <String, String>{};
|
||||
final formParams = <String, String>{};
|
||||
|
||||
const contentTypes = <String>[];
|
||||
|
||||
|
||||
return apiClient.invokeAPI(
|
||||
apiPath,
|
||||
'GET',
|
||||
queryParams,
|
||||
postBody,
|
||||
headerParams,
|
||||
formParams,
|
||||
contentTypes.isEmpty ? null : contentTypes.first,
|
||||
);
|
||||
}
|
||||
|
||||
/// Retrieve a workflow
|
||||
///
|
||||
/// Retrieve a workflow details without ids, default values, etc.
|
||||
///
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [String] id (required):
|
||||
Future<WorkflowShareResponseDto?> getWorkflowForShare(String id,) async {
|
||||
final response = await getWorkflowForShareWithHttpInfo(id,);
|
||||
if (response.statusCode >= HttpStatus.badRequest) {
|
||||
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||
}
|
||||
// When a remote server returns no body with a status of 204, we shall not decode it.
|
||||
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
|
||||
// FormatException when trying to decode an empty string.
|
||||
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
|
||||
return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'WorkflowShareResponseDto',) as WorkflowShareResponseDto;
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// List all workflow triggers
|
||||
///
|
||||
/// Retrieve a list of all available workflow triggers.
|
||||
///
|
||||
/// Note: This method returns the HTTP [Response].
|
||||
Future<Response> getWorkflowTriggersWithHttpInfo() async {
|
||||
// ignore: prefer_const_declarations
|
||||
final apiPath = r'/workflows/triggers';
|
||||
|
||||
// ignore: prefer_final_locals
|
||||
Object? postBody;
|
||||
|
||||
final queryParams = <QueryParam>[];
|
||||
final headerParams = <String, String>{};
|
||||
final formParams = <String, String>{};
|
||||
|
||||
const contentTypes = <String>[];
|
||||
|
||||
|
||||
return apiClient.invokeAPI(
|
||||
apiPath,
|
||||
'GET',
|
||||
queryParams,
|
||||
postBody,
|
||||
headerParams,
|
||||
formParams,
|
||||
contentTypes.isEmpty ? null : contentTypes.first,
|
||||
);
|
||||
}
|
||||
|
||||
/// List all workflow triggers
|
||||
///
|
||||
/// Retrieve a list of all available workflow triggers.
|
||||
Future<List<WorkflowTriggerResponseDto>?> getWorkflowTriggers() async {
|
||||
final response = await getWorkflowTriggersWithHttpInfo();
|
||||
if (response.statusCode >= HttpStatus.badRequest) {
|
||||
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||
}
|
||||
// When a remote server returns no body with a status of 204, we shall not decode it.
|
||||
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
|
||||
// FormatException when trying to decode an empty string.
|
||||
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
|
||||
final responseBody = await _decodeBodyBytes(response);
|
||||
return (await apiClient.deserializeAsync(responseBody, 'List<WorkflowTriggerResponseDto>') as List)
|
||||
.cast<WorkflowTriggerResponseDto>()
|
||||
.toList(growable: false);
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// List all workflows
|
||||
///
|
||||
/// Retrieve a list of workflows available to the authenticated user.
|
||||
///
|
||||
/// Note: This method returns the HTTP [Response].
|
||||
///
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [String] description:
|
||||
/// Workflow description
|
||||
///
|
||||
/// * [bool] enabled:
|
||||
/// Workflow enabled
|
||||
///
|
||||
/// * [String] id:
|
||||
/// Workflow ID
|
||||
///
|
||||
/// * [String] name:
|
||||
/// Workflow name
|
||||
///
|
||||
/// * [WorkflowTrigger] trigger:
|
||||
/// Workflow trigger type
|
||||
Future<Response> searchWorkflowsWithHttpInfo({ String? description, bool? enabled, String? id, String? name, WorkflowTrigger? trigger, }) async {
|
||||
Future<Response> getWorkflowsWithHttpInfo() async {
|
||||
// ignore: prefer_const_declarations
|
||||
final apiPath = r'/workflows';
|
||||
|
||||
@@ -319,22 +194,6 @@ class WorkflowsApi {
|
||||
final headerParams = <String, String>{};
|
||||
final formParams = <String, String>{};
|
||||
|
||||
if (description != null) {
|
||||
queryParams.addAll(_queryParams('', 'description', description));
|
||||
}
|
||||
if (enabled != null) {
|
||||
queryParams.addAll(_queryParams('', 'enabled', enabled));
|
||||
}
|
||||
if (id != null) {
|
||||
queryParams.addAll(_queryParams('', 'id', id));
|
||||
}
|
||||
if (name != null) {
|
||||
queryParams.addAll(_queryParams('', 'name', name));
|
||||
}
|
||||
if (trigger != null) {
|
||||
queryParams.addAll(_queryParams('', 'trigger', trigger));
|
||||
}
|
||||
|
||||
const contentTypes = <String>[];
|
||||
|
||||
|
||||
@@ -352,25 +211,8 @@ class WorkflowsApi {
|
||||
/// List all workflows
|
||||
///
|
||||
/// Retrieve a list of workflows available to the authenticated user.
|
||||
///
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [String] description:
|
||||
/// Workflow description
|
||||
///
|
||||
/// * [bool] enabled:
|
||||
/// Workflow enabled
|
||||
///
|
||||
/// * [String] id:
|
||||
/// Workflow ID
|
||||
///
|
||||
/// * [String] name:
|
||||
/// Workflow name
|
||||
///
|
||||
/// * [WorkflowTrigger] trigger:
|
||||
/// Workflow trigger type
|
||||
Future<List<WorkflowResponseDto>?> searchWorkflows({ String? description, bool? enabled, String? id, String? name, WorkflowTrigger? trigger, }) async {
|
||||
final response = await searchWorkflowsWithHttpInfo( description: description, enabled: enabled, id: id, name: name, trigger: trigger, );
|
||||
Future<List<WorkflowResponseDto>?> getWorkflows() async {
|
||||
final response = await getWorkflowsWithHttpInfo();
|
||||
if (response.statusCode >= HttpStatus.badRequest) {
|
||||
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||
}
|
||||
|
||||
Generated
+26
-14
@@ -516,10 +516,26 @@ class ApiClient {
|
||||
return PinCodeSetupDto.fromJson(value);
|
||||
case 'PlacesResponseDto':
|
||||
return PlacesResponseDto.fromJson(value);
|
||||
case 'PluginMethodResponseDto':
|
||||
return PluginMethodResponseDto.fromJson(value);
|
||||
case 'PluginActionResponseDto':
|
||||
return PluginActionResponseDto.fromJson(value);
|
||||
case 'PluginContextType':
|
||||
return PluginContextTypeTypeTransformer().decode(value);
|
||||
case 'PluginFilterResponseDto':
|
||||
return PluginFilterResponseDto.fromJson(value);
|
||||
case 'PluginJsonSchema':
|
||||
return PluginJsonSchema.fromJson(value);
|
||||
case 'PluginJsonSchemaProperty':
|
||||
return PluginJsonSchemaProperty.fromJson(value);
|
||||
case 'PluginJsonSchemaPropertyAdditionalProperties':
|
||||
return PluginJsonSchemaPropertyAdditionalProperties.fromJson(value);
|
||||
case 'PluginJsonSchemaType':
|
||||
return PluginJsonSchemaTypeTypeTransformer().decode(value);
|
||||
case 'PluginResponseDto':
|
||||
return PluginResponseDto.fromJson(value);
|
||||
case 'PluginTriggerResponseDto':
|
||||
return PluginTriggerResponseDto.fromJson(value);
|
||||
case 'PluginTriggerType':
|
||||
return PluginTriggerTypeTypeTransformer().decode(value);
|
||||
case 'PurchaseResponse':
|
||||
return PurchaseResponse.fromJson(value);
|
||||
case 'PurchaseUpdate':
|
||||
@@ -864,22 +880,18 @@ class ApiClient {
|
||||
return VideoCodecTypeTransformer().decode(value);
|
||||
case 'VideoContainer':
|
||||
return VideoContainerTypeTransformer().decode(value);
|
||||
case 'WorkflowActionItemDto':
|
||||
return WorkflowActionItemDto.fromJson(value);
|
||||
case 'WorkflowActionResponseDto':
|
||||
return WorkflowActionResponseDto.fromJson(value);
|
||||
case 'WorkflowCreateDto':
|
||||
return WorkflowCreateDto.fromJson(value);
|
||||
case 'WorkflowFilterItemDto':
|
||||
return WorkflowFilterItemDto.fromJson(value);
|
||||
case 'WorkflowFilterResponseDto':
|
||||
return WorkflowFilterResponseDto.fromJson(value);
|
||||
case 'WorkflowResponseDto':
|
||||
return WorkflowResponseDto.fromJson(value);
|
||||
case 'WorkflowShareResponseDto':
|
||||
return WorkflowShareResponseDto.fromJson(value);
|
||||
case 'WorkflowShareStepDto':
|
||||
return WorkflowShareStepDto.fromJson(value);
|
||||
case 'WorkflowStepDto':
|
||||
return WorkflowStepDto.fromJson(value);
|
||||
case 'WorkflowTrigger':
|
||||
return WorkflowTriggerTypeTransformer().decode(value);
|
||||
case 'WorkflowTriggerResponseDto':
|
||||
return WorkflowTriggerResponseDto.fromJson(value);
|
||||
case 'WorkflowType':
|
||||
return WorkflowTypeTypeTransformer().decode(value);
|
||||
case 'WorkflowUpdateDto':
|
||||
return WorkflowUpdateDto.fromJson(value);
|
||||
default:
|
||||
|
||||
Generated
+9
-6
@@ -142,6 +142,15 @@ String parameterToString(dynamic value) {
|
||||
if (value is Permission) {
|
||||
return PermissionTypeTransformer().encode(value).toString();
|
||||
}
|
||||
if (value is PluginContextType) {
|
||||
return PluginContextTypeTypeTransformer().encode(value).toString();
|
||||
}
|
||||
if (value is PluginJsonSchemaType) {
|
||||
return PluginJsonSchemaTypeTypeTransformer().encode(value).toString();
|
||||
}
|
||||
if (value is PluginTriggerType) {
|
||||
return PluginTriggerTypeTypeTransformer().encode(value).toString();
|
||||
}
|
||||
if (value is QueueCommand) {
|
||||
return QueueCommandTypeTransformer().encode(value).toString();
|
||||
}
|
||||
@@ -199,12 +208,6 @@ String parameterToString(dynamic value) {
|
||||
if (value is VideoContainer) {
|
||||
return VideoContainerTypeTransformer().encode(value).toString();
|
||||
}
|
||||
if (value is WorkflowTrigger) {
|
||||
return WorkflowTriggerTypeTransformer().encode(value).toString();
|
||||
}
|
||||
if (value is WorkflowType) {
|
||||
return WorkflowTypeTypeTransformer().encode(value).toString();
|
||||
}
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
|
||||
Generated
+3
-3
@@ -77,7 +77,7 @@ class JobName {
|
||||
static const versionCheck = JobName._(r'VersionCheck');
|
||||
static const ocrQueueAll = JobName._(r'OcrQueueAll');
|
||||
static const ocr = JobName._(r'Ocr');
|
||||
static const workflowAssetCreate = JobName._(r'WorkflowAssetCreate');
|
||||
static const workflowRun = JobName._(r'WorkflowRun');
|
||||
|
||||
/// List of all possible values in this [enum][JobName].
|
||||
static const values = <JobName>[
|
||||
@@ -135,7 +135,7 @@ class JobName {
|
||||
versionCheck,
|
||||
ocrQueueAll,
|
||||
ocr,
|
||||
workflowAssetCreate,
|
||||
workflowRun,
|
||||
];
|
||||
|
||||
static JobName? fromJson(dynamic value) => JobNameTypeTransformer().decode(value);
|
||||
@@ -228,7 +228,7 @@ class JobNameTypeTransformer {
|
||||
case r'VersionCheck': return JobName.versionCheck;
|
||||
case r'OcrQueueAll': return JobName.ocrQueueAll;
|
||||
case r'Ocr': return JobName.ocr;
|
||||
case r'WorkflowAssetCreate': return JobName.workflowAssetCreate;
|
||||
case r'WorkflowRun': return JobName.workflowRun;
|
||||
default:
|
||||
if (!allowNull) {
|
||||
throw ArgumentError('Unknown enum value to decode: $data');
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.18
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
part of openapi.api;
|
||||
|
||||
class PluginActionResponseDto {
|
||||
/// Returns a new [PluginActionResponseDto] instance.
|
||||
PluginActionResponseDto({
|
||||
required this.description,
|
||||
required this.id,
|
||||
required this.methodName,
|
||||
required this.pluginId,
|
||||
required this.schema,
|
||||
this.supportedContexts = const [],
|
||||
required this.title,
|
||||
});
|
||||
|
||||
/// Action description
|
||||
String description;
|
||||
|
||||
/// Action ID
|
||||
String id;
|
||||
|
||||
/// Method name
|
||||
String methodName;
|
||||
|
||||
/// Plugin ID
|
||||
String pluginId;
|
||||
|
||||
/// Action schema
|
||||
PluginJsonSchema? schema;
|
||||
|
||||
/// Supported contexts
|
||||
List<PluginContextType> supportedContexts;
|
||||
|
||||
/// Action title
|
||||
String title;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is PluginActionResponseDto &&
|
||||
other.description == description &&
|
||||
other.id == id &&
|
||||
other.methodName == methodName &&
|
||||
other.pluginId == pluginId &&
|
||||
other.schema == schema &&
|
||||
_deepEquality.equals(other.supportedContexts, supportedContexts) &&
|
||||
other.title == title;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(description.hashCode) +
|
||||
(id.hashCode) +
|
||||
(methodName.hashCode) +
|
||||
(pluginId.hashCode) +
|
||||
(schema == null ? 0 : schema!.hashCode) +
|
||||
(supportedContexts.hashCode) +
|
||||
(title.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'PluginActionResponseDto[description=$description, id=$id, methodName=$methodName, pluginId=$pluginId, schema=$schema, supportedContexts=$supportedContexts, title=$title]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
json[r'description'] = this.description;
|
||||
json[r'id'] = this.id;
|
||||
json[r'methodName'] = this.methodName;
|
||||
json[r'pluginId'] = this.pluginId;
|
||||
if (this.schema != null) {
|
||||
json[r'schema'] = this.schema;
|
||||
} else {
|
||||
// json[r'schema'] = null;
|
||||
}
|
||||
json[r'supportedContexts'] = this.supportedContexts;
|
||||
json[r'title'] = this.title;
|
||||
return json;
|
||||
}
|
||||
|
||||
/// Returns a new [PluginActionResponseDto] instance and imports its values from
|
||||
/// [value] if it's a [Map], null otherwise.
|
||||
// ignore: prefer_constructors_over_static_methods
|
||||
static PluginActionResponseDto? fromJson(dynamic value) {
|
||||
upgradeDto(value, "PluginActionResponseDto");
|
||||
if (value is Map) {
|
||||
final json = value.cast<String, dynamic>();
|
||||
|
||||
return PluginActionResponseDto(
|
||||
description: mapValueOfType<String>(json, r'description')!,
|
||||
id: mapValueOfType<String>(json, r'id')!,
|
||||
methodName: mapValueOfType<String>(json, r'methodName')!,
|
||||
pluginId: mapValueOfType<String>(json, r'pluginId')!,
|
||||
schema: PluginJsonSchema.fromJson(json[r'schema']),
|
||||
supportedContexts: PluginContextType.listFromJson(json[r'supportedContexts']),
|
||||
title: mapValueOfType<String>(json, r'title')!,
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static List<PluginActionResponseDto> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <PluginActionResponseDto>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = PluginActionResponseDto.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList(growable: growable);
|
||||
}
|
||||
|
||||
static Map<String, PluginActionResponseDto> mapFromJson(dynamic json) {
|
||||
final map = <String, PluginActionResponseDto>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||
for (final entry in json.entries) {
|
||||
final value = PluginActionResponseDto.fromJson(entry.value);
|
||||
if (value != null) {
|
||||
map[entry.key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
// maps a json object with a list of PluginActionResponseDto-objects as value to a dart map
|
||||
static Map<String, List<PluginActionResponseDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||
final map = <String, List<PluginActionResponseDto>>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
// ignore: parameter_assignments
|
||||
json = json.cast<String, dynamic>();
|
||||
for (final entry in json.entries) {
|
||||
map[entry.key] = PluginActionResponseDto.listFromJson(entry.value, growable: growable,);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/// The list of required keys that must be present in a JSON.
|
||||
static const requiredKeys = <String>{
|
||||
'description',
|
||||
'id',
|
||||
'methodName',
|
||||
'pluginId',
|
||||
'schema',
|
||||
'supportedContexts',
|
||||
'title',
|
||||
};
|
||||
}
|
||||
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.18
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
part of openapi.api;
|
||||
|
||||
/// Plugin context
|
||||
class PluginContextType {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const PluginContextType._(this.value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const asset = PluginContextType._(r'asset');
|
||||
static const album = PluginContextType._(r'album');
|
||||
static const person = PluginContextType._(r'person');
|
||||
|
||||
/// List of all possible values in this [enum][PluginContextType].
|
||||
static const values = <PluginContextType>[
|
||||
asset,
|
||||
album,
|
||||
person,
|
||||
];
|
||||
|
||||
static PluginContextType? fromJson(dynamic value) => PluginContextTypeTypeTransformer().decode(value);
|
||||
|
||||
static List<PluginContextType> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <PluginContextType>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = PluginContextType.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList(growable: growable);
|
||||
}
|
||||
}
|
||||
|
||||
/// Transformation class that can [encode] an instance of [PluginContextType] to String,
|
||||
/// and [decode] dynamic data back to [PluginContextType].
|
||||
class PluginContextTypeTypeTransformer {
|
||||
factory PluginContextTypeTypeTransformer() => _instance ??= const PluginContextTypeTypeTransformer._();
|
||||
|
||||
const PluginContextTypeTypeTransformer._();
|
||||
|
||||
String encode(PluginContextType data) => data.value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a PluginContextType.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
/// cannot be decoded successfully, then an [UnimplementedError] is thrown.
|
||||
///
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
PluginContextType? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'asset': return PluginContextType.asset;
|
||||
case r'album': return PluginContextType.album;
|
||||
case r'person': return PluginContextType.person;
|
||||
default:
|
||||
if (!allowNull) {
|
||||
throw ArgumentError('Unknown enum value to decode: $data');
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [PluginContextTypeTypeTransformer] instance.
|
||||
static PluginContextTypeTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.18
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
part of openapi.api;
|
||||
|
||||
class PluginFilterResponseDto {
|
||||
/// Returns a new [PluginFilterResponseDto] instance.
|
||||
PluginFilterResponseDto({
|
||||
required this.description,
|
||||
required this.id,
|
||||
required this.methodName,
|
||||
required this.pluginId,
|
||||
required this.schema,
|
||||
this.supportedContexts = const [],
|
||||
required this.title,
|
||||
});
|
||||
|
||||
/// Filter description
|
||||
String description;
|
||||
|
||||
/// Filter ID
|
||||
String id;
|
||||
|
||||
/// Method name
|
||||
String methodName;
|
||||
|
||||
/// Plugin ID
|
||||
String pluginId;
|
||||
|
||||
/// Filter schema
|
||||
PluginJsonSchema? schema;
|
||||
|
||||
/// Supported contexts
|
||||
List<PluginContextType> supportedContexts;
|
||||
|
||||
/// Filter title
|
||||
String title;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is PluginFilterResponseDto &&
|
||||
other.description == description &&
|
||||
other.id == id &&
|
||||
other.methodName == methodName &&
|
||||
other.pluginId == pluginId &&
|
||||
other.schema == schema &&
|
||||
_deepEquality.equals(other.supportedContexts, supportedContexts) &&
|
||||
other.title == title;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(description.hashCode) +
|
||||
(id.hashCode) +
|
||||
(methodName.hashCode) +
|
||||
(pluginId.hashCode) +
|
||||
(schema == null ? 0 : schema!.hashCode) +
|
||||
(supportedContexts.hashCode) +
|
||||
(title.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'PluginFilterResponseDto[description=$description, id=$id, methodName=$methodName, pluginId=$pluginId, schema=$schema, supportedContexts=$supportedContexts, title=$title]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
json[r'description'] = this.description;
|
||||
json[r'id'] = this.id;
|
||||
json[r'methodName'] = this.methodName;
|
||||
json[r'pluginId'] = this.pluginId;
|
||||
if (this.schema != null) {
|
||||
json[r'schema'] = this.schema;
|
||||
} else {
|
||||
// json[r'schema'] = null;
|
||||
}
|
||||
json[r'supportedContexts'] = this.supportedContexts;
|
||||
json[r'title'] = this.title;
|
||||
return json;
|
||||
}
|
||||
|
||||
/// Returns a new [PluginFilterResponseDto] instance and imports its values from
|
||||
/// [value] if it's a [Map], null otherwise.
|
||||
// ignore: prefer_constructors_over_static_methods
|
||||
static PluginFilterResponseDto? fromJson(dynamic value) {
|
||||
upgradeDto(value, "PluginFilterResponseDto");
|
||||
if (value is Map) {
|
||||
final json = value.cast<String, dynamic>();
|
||||
|
||||
return PluginFilterResponseDto(
|
||||
description: mapValueOfType<String>(json, r'description')!,
|
||||
id: mapValueOfType<String>(json, r'id')!,
|
||||
methodName: mapValueOfType<String>(json, r'methodName')!,
|
||||
pluginId: mapValueOfType<String>(json, r'pluginId')!,
|
||||
schema: PluginJsonSchema.fromJson(json[r'schema']),
|
||||
supportedContexts: PluginContextType.listFromJson(json[r'supportedContexts']),
|
||||
title: mapValueOfType<String>(json, r'title')!,
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static List<PluginFilterResponseDto> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <PluginFilterResponseDto>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = PluginFilterResponseDto.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList(growable: growable);
|
||||
}
|
||||
|
||||
static Map<String, PluginFilterResponseDto> mapFromJson(dynamic json) {
|
||||
final map = <String, PluginFilterResponseDto>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||
for (final entry in json.entries) {
|
||||
final value = PluginFilterResponseDto.fromJson(entry.value);
|
||||
if (value != null) {
|
||||
map[entry.key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
// maps a json object with a list of PluginFilterResponseDto-objects as value to a dart map
|
||||
static Map<String, List<PluginFilterResponseDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||
final map = <String, List<PluginFilterResponseDto>>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
// ignore: parameter_assignments
|
||||
json = json.cast<String, dynamic>();
|
||||
for (final entry in json.entries) {
|
||||
map[entry.key] = PluginFilterResponseDto.listFromJson(entry.value, growable: growable,);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/// The list of required keys that must be present in a JSON.
|
||||
static const requiredKeys = <String>{
|
||||
'description',
|
||||
'id',
|
||||
'methodName',
|
||||
'pluginId',
|
||||
'schema',
|
||||
'supportedContexts',
|
||||
'title',
|
||||
};
|
||||
}
|
||||
|
||||
+158
@@ -0,0 +1,158 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.18
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
part of openapi.api;
|
||||
|
||||
class PluginJsonSchema {
|
||||
/// Returns a new [PluginJsonSchema] instance.
|
||||
PluginJsonSchema({
|
||||
this.additionalProperties,
|
||||
this.description,
|
||||
this.properties = const {},
|
||||
this.required_ = const [],
|
||||
this.type,
|
||||
});
|
||||
|
||||
///
|
||||
/// Please note: This property should have been non-nullable! Since the specification file
|
||||
/// does not include a default value (using the "default:" property), however, the generated
|
||||
/// source code must fall back to having a nullable type.
|
||||
/// Consider adding a "default:" property in the specification file to hide this note.
|
||||
///
|
||||
bool? additionalProperties;
|
||||
|
||||
///
|
||||
/// Please note: This property should have been non-nullable! Since the specification file
|
||||
/// does not include a default value (using the "default:" property), however, the generated
|
||||
/// source code must fall back to having a nullable type.
|
||||
/// Consider adding a "default:" property in the specification file to hide this note.
|
||||
///
|
||||
String? description;
|
||||
|
||||
Map<String, PluginJsonSchemaProperty> properties;
|
||||
|
||||
List<String> required_;
|
||||
|
||||
///
|
||||
/// Please note: This property should have been non-nullable! Since the specification file
|
||||
/// does not include a default value (using the "default:" property), however, the generated
|
||||
/// source code must fall back to having a nullable type.
|
||||
/// Consider adding a "default:" property in the specification file to hide this note.
|
||||
///
|
||||
PluginJsonSchemaType? type;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is PluginJsonSchema &&
|
||||
other.additionalProperties == additionalProperties &&
|
||||
other.description == description &&
|
||||
_deepEquality.equals(other.properties, properties) &&
|
||||
_deepEquality.equals(other.required_, required_) &&
|
||||
other.type == type;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(additionalProperties == null ? 0 : additionalProperties!.hashCode) +
|
||||
(description == null ? 0 : description!.hashCode) +
|
||||
(properties.hashCode) +
|
||||
(required_.hashCode) +
|
||||
(type == null ? 0 : type!.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'PluginJsonSchema[additionalProperties=$additionalProperties, description=$description, properties=$properties, required_=$required_, type=$type]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
if (this.additionalProperties != null) {
|
||||
json[r'additionalProperties'] = this.additionalProperties;
|
||||
} else {
|
||||
// json[r'additionalProperties'] = null;
|
||||
}
|
||||
if (this.description != null) {
|
||||
json[r'description'] = this.description;
|
||||
} else {
|
||||
// json[r'description'] = null;
|
||||
}
|
||||
json[r'properties'] = this.properties;
|
||||
json[r'required'] = this.required_;
|
||||
if (this.type != null) {
|
||||
json[r'type'] = this.type;
|
||||
} else {
|
||||
// json[r'type'] = null;
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
/// Returns a new [PluginJsonSchema] instance and imports its values from
|
||||
/// [value] if it's a [Map], null otherwise.
|
||||
// ignore: prefer_constructors_over_static_methods
|
||||
static PluginJsonSchema? fromJson(dynamic value) {
|
||||
upgradeDto(value, "PluginJsonSchema");
|
||||
if (value is Map) {
|
||||
final json = value.cast<String, dynamic>();
|
||||
|
||||
return PluginJsonSchema(
|
||||
additionalProperties: mapValueOfType<bool>(json, r'additionalProperties'),
|
||||
description: mapValueOfType<String>(json, r'description'),
|
||||
properties: PluginJsonSchemaProperty.mapFromJson(json[r'properties']),
|
||||
required_: json[r'required'] is Iterable
|
||||
? (json[r'required'] as Iterable).cast<String>().toList(growable: false)
|
||||
: const [],
|
||||
type: PluginJsonSchemaType.fromJson(json[r'type']),
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static List<PluginJsonSchema> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <PluginJsonSchema>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = PluginJsonSchema.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList(growable: growable);
|
||||
}
|
||||
|
||||
static Map<String, PluginJsonSchema> mapFromJson(dynamic json) {
|
||||
final map = <String, PluginJsonSchema>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||
for (final entry in json.entries) {
|
||||
final value = PluginJsonSchema.fromJson(entry.value);
|
||||
if (value != null) {
|
||||
map[entry.key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
// maps a json object with a list of PluginJsonSchema-objects as value to a dart map
|
||||
static Map<String, List<PluginJsonSchema>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||
final map = <String, List<PluginJsonSchema>>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
// ignore: parameter_assignments
|
||||
json = json.cast<String, dynamic>();
|
||||
for (final entry in json.entries) {
|
||||
map[entry.key] = PluginJsonSchema.listFromJson(entry.value, growable: growable,);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/// The list of required keys that must be present in a JSON.
|
||||
static const requiredKeys = <String>{
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,195 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.18
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
part of openapi.api;
|
||||
|
||||
class PluginJsonSchemaProperty {
|
||||
/// Returns a new [PluginJsonSchemaProperty] instance.
|
||||
PluginJsonSchemaProperty({
|
||||
this.additionalProperties,
|
||||
this.default_,
|
||||
this.description,
|
||||
this.enum_ = const [],
|
||||
this.items,
|
||||
this.properties = const {},
|
||||
this.required_ = const [],
|
||||
this.type,
|
||||
});
|
||||
|
||||
///
|
||||
/// Please note: This property should have been non-nullable! Since the specification file
|
||||
/// does not include a default value (using the "default:" property), however, the generated
|
||||
/// source code must fall back to having a nullable type.
|
||||
/// Consider adding a "default:" property in the specification file to hide this note.
|
||||
///
|
||||
PluginJsonSchemaPropertyAdditionalProperties? additionalProperties;
|
||||
|
||||
Object? default_;
|
||||
|
||||
///
|
||||
/// Please note: This property should have been non-nullable! Since the specification file
|
||||
/// does not include a default value (using the "default:" property), however, the generated
|
||||
/// source code must fall back to having a nullable type.
|
||||
/// Consider adding a "default:" property in the specification file to hide this note.
|
||||
///
|
||||
String? description;
|
||||
|
||||
List<String> enum_;
|
||||
|
||||
///
|
||||
/// Please note: This property should have been non-nullable! Since the specification file
|
||||
/// does not include a default value (using the "default:" property), however, the generated
|
||||
/// source code must fall back to having a nullable type.
|
||||
/// Consider adding a "default:" property in the specification file to hide this note.
|
||||
///
|
||||
PluginJsonSchemaProperty? items;
|
||||
|
||||
Map<String, PluginJsonSchemaProperty> properties;
|
||||
|
||||
List<String> required_;
|
||||
|
||||
///
|
||||
/// Please note: This property should have been non-nullable! Since the specification file
|
||||
/// does not include a default value (using the "default:" property), however, the generated
|
||||
/// source code must fall back to having a nullable type.
|
||||
/// Consider adding a "default:" property in the specification file to hide this note.
|
||||
///
|
||||
PluginJsonSchemaType? type;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is PluginJsonSchemaProperty &&
|
||||
other.additionalProperties == additionalProperties &&
|
||||
other.default_ == default_ &&
|
||||
other.description == description &&
|
||||
_deepEquality.equals(other.enum_, enum_) &&
|
||||
other.items == items &&
|
||||
_deepEquality.equals(other.properties, properties) &&
|
||||
_deepEquality.equals(other.required_, required_) &&
|
||||
other.type == type;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(additionalProperties == null ? 0 : additionalProperties!.hashCode) +
|
||||
(default_ == null ? 0 : default_!.hashCode) +
|
||||
(description == null ? 0 : description!.hashCode) +
|
||||
(enum_.hashCode) +
|
||||
(items == null ? 0 : items!.hashCode) +
|
||||
(properties.hashCode) +
|
||||
(required_.hashCode) +
|
||||
(type == null ? 0 : type!.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'PluginJsonSchemaProperty[additionalProperties=$additionalProperties, default_=$default_, description=$description, enum_=$enum_, items=$items, properties=$properties, required_=$required_, type=$type]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
if (this.additionalProperties != null) {
|
||||
json[r'additionalProperties'] = this.additionalProperties;
|
||||
} else {
|
||||
// json[r'additionalProperties'] = null;
|
||||
}
|
||||
if (this.default_ != null) {
|
||||
json[r'default'] = this.default_;
|
||||
} else {
|
||||
// json[r'default'] = null;
|
||||
}
|
||||
if (this.description != null) {
|
||||
json[r'description'] = this.description;
|
||||
} else {
|
||||
// json[r'description'] = null;
|
||||
}
|
||||
json[r'enum'] = this.enum_;
|
||||
if (this.items != null) {
|
||||
json[r'items'] = this.items;
|
||||
} else {
|
||||
// json[r'items'] = null;
|
||||
}
|
||||
json[r'properties'] = this.properties;
|
||||
json[r'required'] = this.required_;
|
||||
if (this.type != null) {
|
||||
json[r'type'] = this.type;
|
||||
} else {
|
||||
// json[r'type'] = null;
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
/// Returns a new [PluginJsonSchemaProperty] instance and imports its values from
|
||||
/// [value] if it's a [Map], null otherwise.
|
||||
// ignore: prefer_constructors_over_static_methods
|
||||
static PluginJsonSchemaProperty? fromJson(dynamic value) {
|
||||
upgradeDto(value, "PluginJsonSchemaProperty");
|
||||
if (value is Map) {
|
||||
final json = value.cast<String, dynamic>();
|
||||
|
||||
return PluginJsonSchemaProperty(
|
||||
additionalProperties: PluginJsonSchemaPropertyAdditionalProperties.fromJson(json[r'additionalProperties']),
|
||||
default_: mapValueOfType<Object>(json, r'default'),
|
||||
description: mapValueOfType<String>(json, r'description'),
|
||||
enum_: json[r'enum'] is Iterable
|
||||
? (json[r'enum'] as Iterable).cast<String>().toList(growable: false)
|
||||
: const [],
|
||||
items: PluginJsonSchemaProperty.fromJson(json[r'items']),
|
||||
properties: PluginJsonSchemaProperty.mapFromJson(json[r'properties']),
|
||||
required_: json[r'required'] is Iterable
|
||||
? (json[r'required'] as Iterable).cast<String>().toList(growable: false)
|
||||
: const [],
|
||||
type: PluginJsonSchemaType.fromJson(json[r'type']),
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static List<PluginJsonSchemaProperty> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <PluginJsonSchemaProperty>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = PluginJsonSchemaProperty.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList(growable: growable);
|
||||
}
|
||||
|
||||
static Map<String, PluginJsonSchemaProperty> mapFromJson(dynamic json) {
|
||||
final map = <String, PluginJsonSchemaProperty>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||
for (final entry in json.entries) {
|
||||
final value = PluginJsonSchemaProperty.fromJson(entry.value);
|
||||
if (value != null) {
|
||||
map[entry.key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
// maps a json object with a list of PluginJsonSchemaProperty-objects as value to a dart map
|
||||
static Map<String, List<PluginJsonSchemaProperty>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||
final map = <String, List<PluginJsonSchemaProperty>>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
// ignore: parameter_assignments
|
||||
json = json.cast<String, dynamic>();
|
||||
for (final entry in json.entries) {
|
||||
map[entry.key] = PluginJsonSchemaProperty.listFromJson(entry.value, growable: growable,);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/// The list of required keys that must be present in a JSON.
|
||||
static const requiredKeys = <String>{
|
||||
};
|
||||
}
|
||||
|
||||
+195
@@ -0,0 +1,195 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.18
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
part of openapi.api;
|
||||
|
||||
class PluginJsonSchemaPropertyAdditionalProperties {
|
||||
/// Returns a new [PluginJsonSchemaPropertyAdditionalProperties] instance.
|
||||
PluginJsonSchemaPropertyAdditionalProperties({
|
||||
this.additionalProperties,
|
||||
this.default_,
|
||||
this.description,
|
||||
this.enum_ = const [],
|
||||
this.items,
|
||||
this.properties = const {},
|
||||
this.required_ = const [],
|
||||
this.type,
|
||||
});
|
||||
|
||||
///
|
||||
/// Please note: This property should have been non-nullable! Since the specification file
|
||||
/// does not include a default value (using the "default:" property), however, the generated
|
||||
/// source code must fall back to having a nullable type.
|
||||
/// Consider adding a "default:" property in the specification file to hide this note.
|
||||
///
|
||||
PluginJsonSchemaPropertyAdditionalProperties? additionalProperties;
|
||||
|
||||
Object? default_;
|
||||
|
||||
///
|
||||
/// Please note: This property should have been non-nullable! Since the specification file
|
||||
/// does not include a default value (using the "default:" property), however, the generated
|
||||
/// source code must fall back to having a nullable type.
|
||||
/// Consider adding a "default:" property in the specification file to hide this note.
|
||||
///
|
||||
String? description;
|
||||
|
||||
List<String> enum_;
|
||||
|
||||
///
|
||||
/// Please note: This property should have been non-nullable! Since the specification file
|
||||
/// does not include a default value (using the "default:" property), however, the generated
|
||||
/// source code must fall back to having a nullable type.
|
||||
/// Consider adding a "default:" property in the specification file to hide this note.
|
||||
///
|
||||
PluginJsonSchemaProperty? items;
|
||||
|
||||
Map<String, PluginJsonSchemaProperty> properties;
|
||||
|
||||
List<String> required_;
|
||||
|
||||
///
|
||||
/// Please note: This property should have been non-nullable! Since the specification file
|
||||
/// does not include a default value (using the "default:" property), however, the generated
|
||||
/// source code must fall back to having a nullable type.
|
||||
/// Consider adding a "default:" property in the specification file to hide this note.
|
||||
///
|
||||
PluginJsonSchemaType? type;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is PluginJsonSchemaPropertyAdditionalProperties &&
|
||||
other.additionalProperties == additionalProperties &&
|
||||
other.default_ == default_ &&
|
||||
other.description == description &&
|
||||
_deepEquality.equals(other.enum_, enum_) &&
|
||||
other.items == items &&
|
||||
_deepEquality.equals(other.properties, properties) &&
|
||||
_deepEquality.equals(other.required_, required_) &&
|
||||
other.type == type;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(additionalProperties == null ? 0 : additionalProperties!.hashCode) +
|
||||
(default_ == null ? 0 : default_!.hashCode) +
|
||||
(description == null ? 0 : description!.hashCode) +
|
||||
(enum_.hashCode) +
|
||||
(items == null ? 0 : items!.hashCode) +
|
||||
(properties.hashCode) +
|
||||
(required_.hashCode) +
|
||||
(type == null ? 0 : type!.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'PluginJsonSchemaPropertyAdditionalProperties[additionalProperties=$additionalProperties, default_=$default_, description=$description, enum_=$enum_, items=$items, properties=$properties, required_=$required_, type=$type]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
if (this.additionalProperties != null) {
|
||||
json[r'additionalProperties'] = this.additionalProperties;
|
||||
} else {
|
||||
// json[r'additionalProperties'] = null;
|
||||
}
|
||||
if (this.default_ != null) {
|
||||
json[r'default'] = this.default_;
|
||||
} else {
|
||||
// json[r'default'] = null;
|
||||
}
|
||||
if (this.description != null) {
|
||||
json[r'description'] = this.description;
|
||||
} else {
|
||||
// json[r'description'] = null;
|
||||
}
|
||||
json[r'enum'] = this.enum_;
|
||||
if (this.items != null) {
|
||||
json[r'items'] = this.items;
|
||||
} else {
|
||||
// json[r'items'] = null;
|
||||
}
|
||||
json[r'properties'] = this.properties;
|
||||
json[r'required'] = this.required_;
|
||||
if (this.type != null) {
|
||||
json[r'type'] = this.type;
|
||||
} else {
|
||||
// json[r'type'] = null;
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
/// Returns a new [PluginJsonSchemaPropertyAdditionalProperties] instance and imports its values from
|
||||
/// [value] if it's a [Map], null otherwise.
|
||||
// ignore: prefer_constructors_over_static_methods
|
||||
static PluginJsonSchemaPropertyAdditionalProperties? fromJson(dynamic value) {
|
||||
upgradeDto(value, "PluginJsonSchemaPropertyAdditionalProperties");
|
||||
if (value is Map) {
|
||||
final json = value.cast<String, dynamic>();
|
||||
|
||||
return PluginJsonSchemaPropertyAdditionalProperties(
|
||||
additionalProperties: PluginJsonSchemaPropertyAdditionalProperties.fromJson(json[r'additionalProperties']),
|
||||
default_: mapValueOfType<Object>(json, r'default'),
|
||||
description: mapValueOfType<String>(json, r'description'),
|
||||
enum_: json[r'enum'] is Iterable
|
||||
? (json[r'enum'] as Iterable).cast<String>().toList(growable: false)
|
||||
: const [],
|
||||
items: PluginJsonSchemaProperty.fromJson(json[r'items']),
|
||||
properties: PluginJsonSchemaProperty.mapFromJson(json[r'properties']),
|
||||
required_: json[r'required'] is Iterable
|
||||
? (json[r'required'] as Iterable).cast<String>().toList(growable: false)
|
||||
: const [],
|
||||
type: PluginJsonSchemaType.fromJson(json[r'type']),
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static List<PluginJsonSchemaPropertyAdditionalProperties> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <PluginJsonSchemaPropertyAdditionalProperties>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = PluginJsonSchemaPropertyAdditionalProperties.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList(growable: growable);
|
||||
}
|
||||
|
||||
static Map<String, PluginJsonSchemaPropertyAdditionalProperties> mapFromJson(dynamic json) {
|
||||
final map = <String, PluginJsonSchemaPropertyAdditionalProperties>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||
for (final entry in json.entries) {
|
||||
final value = PluginJsonSchemaPropertyAdditionalProperties.fromJson(entry.value);
|
||||
if (value != null) {
|
||||
map[entry.key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
// maps a json object with a list of PluginJsonSchemaPropertyAdditionalProperties-objects as value to a dart map
|
||||
static Map<String, List<PluginJsonSchemaPropertyAdditionalProperties>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||
final map = <String, List<PluginJsonSchemaPropertyAdditionalProperties>>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
// ignore: parameter_assignments
|
||||
json = json.cast<String, dynamic>();
|
||||
for (final entry in json.entries) {
|
||||
map[entry.key] = PluginJsonSchemaPropertyAdditionalProperties.listFromJson(entry.value, growable: growable,);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/// The list of required keys that must be present in a JSON.
|
||||
static const requiredKeys = <String>{
|
||||
};
|
||||
}
|
||||
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.18
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
part of openapi.api;
|
||||
|
||||
|
||||
class PluginJsonSchemaType {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const PluginJsonSchemaType._(this.value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const string = PluginJsonSchemaType._(r'string');
|
||||
static const number = PluginJsonSchemaType._(r'number');
|
||||
static const integer = PluginJsonSchemaType._(r'integer');
|
||||
static const boolean = PluginJsonSchemaType._(r'boolean');
|
||||
static const object = PluginJsonSchemaType._(r'object');
|
||||
static const array = PluginJsonSchemaType._(r'array');
|
||||
static const null_ = PluginJsonSchemaType._(r'null');
|
||||
|
||||
/// List of all possible values in this [enum][PluginJsonSchemaType].
|
||||
static const values = <PluginJsonSchemaType>[
|
||||
string,
|
||||
number,
|
||||
integer,
|
||||
boolean,
|
||||
object,
|
||||
array,
|
||||
null_,
|
||||
];
|
||||
|
||||
static PluginJsonSchemaType? fromJson(dynamic value) => PluginJsonSchemaTypeTypeTransformer().decode(value);
|
||||
|
||||
static List<PluginJsonSchemaType> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <PluginJsonSchemaType>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = PluginJsonSchemaType.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList(growable: growable);
|
||||
}
|
||||
}
|
||||
|
||||
/// Transformation class that can [encode] an instance of [PluginJsonSchemaType] to String,
|
||||
/// and [decode] dynamic data back to [PluginJsonSchemaType].
|
||||
class PluginJsonSchemaTypeTypeTransformer {
|
||||
factory PluginJsonSchemaTypeTypeTransformer() => _instance ??= const PluginJsonSchemaTypeTypeTransformer._();
|
||||
|
||||
const PluginJsonSchemaTypeTypeTransformer._();
|
||||
|
||||
String encode(PluginJsonSchemaType data) => data.value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a PluginJsonSchemaType.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
/// cannot be decoded successfully, then an [UnimplementedError] is thrown.
|
||||
///
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
PluginJsonSchemaType? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'string': return PluginJsonSchemaType.string;
|
||||
case r'number': return PluginJsonSchemaType.number;
|
||||
case r'integer': return PluginJsonSchemaType.integer;
|
||||
case r'boolean': return PluginJsonSchemaType.boolean;
|
||||
case r'object': return PluginJsonSchemaType.object;
|
||||
case r'array': return PluginJsonSchemaType.array;
|
||||
case r'null': return PluginJsonSchemaType.null_;
|
||||
default:
|
||||
if (!allowNull) {
|
||||
throw ArgumentError('Unknown enum value to decode: $data');
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [PluginJsonSchemaTypeTypeTransformer] instance.
|
||||
static PluginJsonSchemaTypeTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
@@ -1,172 +0,0 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.18
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
part of openapi.api;
|
||||
|
||||
class PluginMethodResponseDto {
|
||||
/// Returns a new [PluginMethodResponseDto] instance.
|
||||
PluginMethodResponseDto({
|
||||
required this.description,
|
||||
required this.hostFunctions,
|
||||
required this.key,
|
||||
required this.name,
|
||||
this.schema,
|
||||
required this.title,
|
||||
this.types = const [],
|
||||
this.uiHints = const [],
|
||||
});
|
||||
|
||||
/// Description
|
||||
String description;
|
||||
|
||||
bool hostFunctions;
|
||||
|
||||
/// Key
|
||||
String key;
|
||||
|
||||
/// Name
|
||||
String name;
|
||||
|
||||
///
|
||||
/// Please note: This property should have been non-nullable! Since the specification file
|
||||
/// does not include a default value (using the "default:" property), however, the generated
|
||||
/// source code must fall back to having a nullable type.
|
||||
/// Consider adding a "default:" property in the specification file to hide this note.
|
||||
///
|
||||
Object? schema;
|
||||
|
||||
/// Title
|
||||
String title;
|
||||
|
||||
/// Workflow types
|
||||
List<WorkflowType> types;
|
||||
|
||||
/// Ui hints
|
||||
List<String> uiHints;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is PluginMethodResponseDto &&
|
||||
other.description == description &&
|
||||
other.hostFunctions == hostFunctions &&
|
||||
other.key == key &&
|
||||
other.name == name &&
|
||||
other.schema == schema &&
|
||||
other.title == title &&
|
||||
_deepEquality.equals(other.types, types) &&
|
||||
_deepEquality.equals(other.uiHints, uiHints);
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(description.hashCode) +
|
||||
(hostFunctions.hashCode) +
|
||||
(key.hashCode) +
|
||||
(name.hashCode) +
|
||||
(schema == null ? 0 : schema!.hashCode) +
|
||||
(title.hashCode) +
|
||||
(types.hashCode) +
|
||||
(uiHints.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'PluginMethodResponseDto[description=$description, hostFunctions=$hostFunctions, key=$key, name=$name, schema=$schema, title=$title, types=$types, uiHints=$uiHints]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
json[r'description'] = this.description;
|
||||
json[r'hostFunctions'] = this.hostFunctions;
|
||||
json[r'key'] = this.key;
|
||||
json[r'name'] = this.name;
|
||||
if (this.schema != null) {
|
||||
json[r'schema'] = this.schema;
|
||||
} else {
|
||||
// json[r'schema'] = null;
|
||||
}
|
||||
json[r'title'] = this.title;
|
||||
json[r'types'] = this.types;
|
||||
json[r'uiHints'] = this.uiHints;
|
||||
return json;
|
||||
}
|
||||
|
||||
/// Returns a new [PluginMethodResponseDto] instance and imports its values from
|
||||
/// [value] if it's a [Map], null otherwise.
|
||||
// ignore: prefer_constructors_over_static_methods
|
||||
static PluginMethodResponseDto? fromJson(dynamic value) {
|
||||
upgradeDto(value, "PluginMethodResponseDto");
|
||||
if (value is Map) {
|
||||
final json = value.cast<String, dynamic>();
|
||||
|
||||
return PluginMethodResponseDto(
|
||||
description: mapValueOfType<String>(json, r'description')!,
|
||||
hostFunctions: mapValueOfType<bool>(json, r'hostFunctions')!,
|
||||
key: mapValueOfType<String>(json, r'key')!,
|
||||
name: mapValueOfType<String>(json, r'name')!,
|
||||
schema: mapValueOfType<Object>(json, r'schema'),
|
||||
title: mapValueOfType<String>(json, r'title')!,
|
||||
types: WorkflowType.listFromJson(json[r'types']),
|
||||
uiHints: json[r'uiHints'] is Iterable
|
||||
? (json[r'uiHints'] as Iterable).cast<String>().toList(growable: false)
|
||||
: const [],
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static List<PluginMethodResponseDto> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <PluginMethodResponseDto>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = PluginMethodResponseDto.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList(growable: growable);
|
||||
}
|
||||
|
||||
static Map<String, PluginMethodResponseDto> mapFromJson(dynamic json) {
|
||||
final map = <String, PluginMethodResponseDto>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||
for (final entry in json.entries) {
|
||||
final value = PluginMethodResponseDto.fromJson(entry.value);
|
||||
if (value != null) {
|
||||
map[entry.key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
// maps a json object with a list of PluginMethodResponseDto-objects as value to a dart map
|
||||
static Map<String, List<PluginMethodResponseDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||
final map = <String, List<PluginMethodResponseDto>>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
// ignore: parameter_assignments
|
||||
json = json.cast<String, dynamic>();
|
||||
for (final entry in json.entries) {
|
||||
map[entry.key] = PluginMethodResponseDto.listFromJson(entry.value, growable: growable,);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/// The list of required keys that must be present in a JSON.
|
||||
static const requiredKeys = <String>{
|
||||
'description',
|
||||
'hostFunctions',
|
||||
'key',
|
||||
'name',
|
||||
'title',
|
||||
'types',
|
||||
'uiHints',
|
||||
};
|
||||
}
|
||||
|
||||
+19
-10
@@ -13,17 +13,21 @@ part of openapi.api;
|
||||
class PluginResponseDto {
|
||||
/// Returns a new [PluginResponseDto] instance.
|
||||
PluginResponseDto({
|
||||
this.actions = const [],
|
||||
required this.author,
|
||||
required this.createdAt,
|
||||
required this.description,
|
||||
this.filters = const [],
|
||||
required this.id,
|
||||
this.methods = const [],
|
||||
required this.name,
|
||||
required this.title,
|
||||
required this.updatedAt,
|
||||
required this.version,
|
||||
});
|
||||
|
||||
/// Plugin actions
|
||||
List<PluginActionResponseDto> actions;
|
||||
|
||||
/// Plugin author
|
||||
String author;
|
||||
|
||||
@@ -33,12 +37,12 @@ class PluginResponseDto {
|
||||
/// Plugin description
|
||||
String description;
|
||||
|
||||
/// Plugin filters
|
||||
List<PluginFilterResponseDto> filters;
|
||||
|
||||
/// Plugin ID
|
||||
String id;
|
||||
|
||||
/// Plugin methods
|
||||
List<PluginMethodResponseDto> methods;
|
||||
|
||||
/// Plugin name
|
||||
String name;
|
||||
|
||||
@@ -53,11 +57,12 @@ class PluginResponseDto {
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is PluginResponseDto &&
|
||||
_deepEquality.equals(other.actions, actions) &&
|
||||
other.author == author &&
|
||||
other.createdAt == createdAt &&
|
||||
other.description == description &&
|
||||
_deepEquality.equals(other.filters, filters) &&
|
||||
other.id == id &&
|
||||
_deepEquality.equals(other.methods, methods) &&
|
||||
other.name == name &&
|
||||
other.title == title &&
|
||||
other.updatedAt == updatedAt &&
|
||||
@@ -66,26 +71,28 @@ class PluginResponseDto {
|
||||
@override
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(actions.hashCode) +
|
||||
(author.hashCode) +
|
||||
(createdAt.hashCode) +
|
||||
(description.hashCode) +
|
||||
(filters.hashCode) +
|
||||
(id.hashCode) +
|
||||
(methods.hashCode) +
|
||||
(name.hashCode) +
|
||||
(title.hashCode) +
|
||||
(updatedAt.hashCode) +
|
||||
(version.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'PluginResponseDto[author=$author, createdAt=$createdAt, description=$description, id=$id, methods=$methods, name=$name, title=$title, updatedAt=$updatedAt, version=$version]';
|
||||
String toString() => 'PluginResponseDto[actions=$actions, author=$author, createdAt=$createdAt, description=$description, filters=$filters, id=$id, name=$name, title=$title, updatedAt=$updatedAt, version=$version]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
json[r'actions'] = this.actions;
|
||||
json[r'author'] = this.author;
|
||||
json[r'createdAt'] = this.createdAt;
|
||||
json[r'description'] = this.description;
|
||||
json[r'filters'] = this.filters;
|
||||
json[r'id'] = this.id;
|
||||
json[r'methods'] = this.methods;
|
||||
json[r'name'] = this.name;
|
||||
json[r'title'] = this.title;
|
||||
json[r'updatedAt'] = this.updatedAt;
|
||||
@@ -102,11 +109,12 @@ class PluginResponseDto {
|
||||
final json = value.cast<String, dynamic>();
|
||||
|
||||
return PluginResponseDto(
|
||||
actions: PluginActionResponseDto.listFromJson(json[r'actions']),
|
||||
author: mapValueOfType<String>(json, r'author')!,
|
||||
createdAt: mapValueOfType<String>(json, r'createdAt')!,
|
||||
description: mapValueOfType<String>(json, r'description')!,
|
||||
filters: PluginFilterResponseDto.listFromJson(json[r'filters']),
|
||||
id: mapValueOfType<String>(json, r'id')!,
|
||||
methods: PluginMethodResponseDto.listFromJson(json[r'methods']),
|
||||
name: mapValueOfType<String>(json, r'name')!,
|
||||
title: mapValueOfType<String>(json, r'title')!,
|
||||
updatedAt: mapValueOfType<String>(json, r'updatedAt')!,
|
||||
@@ -158,11 +166,12 @@ class PluginResponseDto {
|
||||
|
||||
/// The list of required keys that must be present in a JSON.
|
||||
static const requiredKeys = <String>{
|
||||
'actions',
|
||||
'author',
|
||||
'createdAt',
|
||||
'description',
|
||||
'filters',
|
||||
'id',
|
||||
'methods',
|
||||
'name',
|
||||
'title',
|
||||
'updatedAt',
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.18
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
part of openapi.api;
|
||||
|
||||
class PluginTriggerResponseDto {
|
||||
/// Returns a new [PluginTriggerResponseDto] instance.
|
||||
PluginTriggerResponseDto({
|
||||
required this.contextType,
|
||||
required this.type,
|
||||
});
|
||||
|
||||
PluginContextType contextType;
|
||||
|
||||
PluginTriggerType type;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is PluginTriggerResponseDto &&
|
||||
other.contextType == contextType &&
|
||||
other.type == type;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(contextType.hashCode) +
|
||||
(type.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'PluginTriggerResponseDto[contextType=$contextType, type=$type]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
json[r'contextType'] = this.contextType;
|
||||
json[r'type'] = this.type;
|
||||
return json;
|
||||
}
|
||||
|
||||
/// Returns a new [PluginTriggerResponseDto] instance and imports its values from
|
||||
/// [value] if it's a [Map], null otherwise.
|
||||
// ignore: prefer_constructors_over_static_methods
|
||||
static PluginTriggerResponseDto? fromJson(dynamic value) {
|
||||
upgradeDto(value, "PluginTriggerResponseDto");
|
||||
if (value is Map) {
|
||||
final json = value.cast<String, dynamic>();
|
||||
|
||||
return PluginTriggerResponseDto(
|
||||
contextType: PluginContextType.fromJson(json[r'contextType'])!,
|
||||
type: PluginTriggerType.fromJson(json[r'type'])!,
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static List<PluginTriggerResponseDto> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <PluginTriggerResponseDto>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = PluginTriggerResponseDto.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList(growable: growable);
|
||||
}
|
||||
|
||||
static Map<String, PluginTriggerResponseDto> mapFromJson(dynamic json) {
|
||||
final map = <String, PluginTriggerResponseDto>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||
for (final entry in json.entries) {
|
||||
final value = PluginTriggerResponseDto.fromJson(entry.value);
|
||||
if (value != null) {
|
||||
map[entry.key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
// maps a json object with a list of PluginTriggerResponseDto-objects as value to a dart map
|
||||
static Map<String, List<PluginTriggerResponseDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||
final map = <String, List<PluginTriggerResponseDto>>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
// ignore: parameter_assignments
|
||||
json = json.cast<String, dynamic>();
|
||||
for (final entry in json.entries) {
|
||||
map[entry.key] = PluginTriggerResponseDto.listFromJson(entry.value, growable: growable,);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/// The list of required keys that must be present in a JSON.
|
||||
static const requiredKeys = <String>{
|
||||
'contextType',
|
||||
'type',
|
||||
};
|
||||
}
|
||||
|
||||
Generated
+22
-22
@@ -11,9 +11,9 @@
|
||||
part of openapi.api;
|
||||
|
||||
/// Plugin trigger type
|
||||
class WorkflowTrigger {
|
||||
class PluginTriggerType {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const WorkflowTrigger._(this.value);
|
||||
const PluginTriggerType._(this.value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
@@ -23,22 +23,22 @@ class WorkflowTrigger {
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const assetCreate = WorkflowTrigger._(r'AssetCreate');
|
||||
static const personRecognized = WorkflowTrigger._(r'PersonRecognized');
|
||||
static const assetCreate = PluginTriggerType._(r'AssetCreate');
|
||||
static const personRecognized = PluginTriggerType._(r'PersonRecognized');
|
||||
|
||||
/// List of all possible values in this [enum][WorkflowTrigger].
|
||||
static const values = <WorkflowTrigger>[
|
||||
/// List of all possible values in this [enum][PluginTriggerType].
|
||||
static const values = <PluginTriggerType>[
|
||||
assetCreate,
|
||||
personRecognized,
|
||||
];
|
||||
|
||||
static WorkflowTrigger? fromJson(dynamic value) => WorkflowTriggerTypeTransformer().decode(value);
|
||||
static PluginTriggerType? fromJson(dynamic value) => PluginTriggerTypeTypeTransformer().decode(value);
|
||||
|
||||
static List<WorkflowTrigger> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <WorkflowTrigger>[];
|
||||
static List<PluginTriggerType> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <PluginTriggerType>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = WorkflowTrigger.fromJson(row);
|
||||
final value = PluginTriggerType.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
@@ -48,16 +48,16 @@ class WorkflowTrigger {
|
||||
}
|
||||
}
|
||||
|
||||
/// Transformation class that can [encode] an instance of [WorkflowTrigger] to String,
|
||||
/// and [decode] dynamic data back to [WorkflowTrigger].
|
||||
class WorkflowTriggerTypeTransformer {
|
||||
factory WorkflowTriggerTypeTransformer() => _instance ??= const WorkflowTriggerTypeTransformer._();
|
||||
/// Transformation class that can [encode] an instance of [PluginTriggerType] to String,
|
||||
/// and [decode] dynamic data back to [PluginTriggerType].
|
||||
class PluginTriggerTypeTypeTransformer {
|
||||
factory PluginTriggerTypeTypeTransformer() => _instance ??= const PluginTriggerTypeTypeTransformer._();
|
||||
|
||||
const WorkflowTriggerTypeTransformer._();
|
||||
const PluginTriggerTypeTypeTransformer._();
|
||||
|
||||
String encode(WorkflowTrigger data) => data.value;
|
||||
String encode(PluginTriggerType data) => data.value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a WorkflowTrigger.
|
||||
/// Decodes a [dynamic value][data] to a PluginTriggerType.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -65,11 +65,11 @@ class WorkflowTriggerTypeTransformer {
|
||||
///
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
WorkflowTrigger? decode(dynamic data, {bool allowNull = true}) {
|
||||
PluginTriggerType? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'AssetCreate': return WorkflowTrigger.assetCreate;
|
||||
case r'PersonRecognized': return WorkflowTrigger.personRecognized;
|
||||
case r'AssetCreate': return PluginTriggerType.assetCreate;
|
||||
case r'PersonRecognized': return PluginTriggerType.personRecognized;
|
||||
default:
|
||||
if (!allowNull) {
|
||||
throw ArgumentError('Unknown enum value to decode: $data');
|
||||
@@ -79,7 +79,7 @@ class WorkflowTriggerTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [WorkflowTriggerTypeTransformer] instance.
|
||||
static WorkflowTriggerTypeTransformer? _instance;
|
||||
/// Singleton [PluginTriggerTypeTypeTransformer] instance.
|
||||
static PluginTriggerTypeTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.18
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
part of openapi.api;
|
||||
|
||||
class WorkflowActionItemDto {
|
||||
/// Returns a new [WorkflowActionItemDto] instance.
|
||||
WorkflowActionItemDto({
|
||||
this.actionConfig = const {},
|
||||
required this.pluginActionId,
|
||||
});
|
||||
|
||||
Map<String, Object> actionConfig;
|
||||
|
||||
/// Plugin action ID
|
||||
String pluginActionId;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is WorkflowActionItemDto &&
|
||||
_deepEquality.equals(other.actionConfig, actionConfig) &&
|
||||
other.pluginActionId == pluginActionId;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(actionConfig.hashCode) +
|
||||
(pluginActionId.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'WorkflowActionItemDto[actionConfig=$actionConfig, pluginActionId=$pluginActionId]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
json[r'actionConfig'] = this.actionConfig;
|
||||
json[r'pluginActionId'] = this.pluginActionId;
|
||||
return json;
|
||||
}
|
||||
|
||||
/// Returns a new [WorkflowActionItemDto] instance and imports its values from
|
||||
/// [value] if it's a [Map], null otherwise.
|
||||
// ignore: prefer_constructors_over_static_methods
|
||||
static WorkflowActionItemDto? fromJson(dynamic value) {
|
||||
upgradeDto(value, "WorkflowActionItemDto");
|
||||
if (value is Map) {
|
||||
final json = value.cast<String, dynamic>();
|
||||
|
||||
return WorkflowActionItemDto(
|
||||
actionConfig: mapCastOfType<String, Object>(json, r'actionConfig') ?? const {},
|
||||
pluginActionId: mapValueOfType<String>(json, r'pluginActionId')!,
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static List<WorkflowActionItemDto> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <WorkflowActionItemDto>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = WorkflowActionItemDto.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList(growable: growable);
|
||||
}
|
||||
|
||||
static Map<String, WorkflowActionItemDto> mapFromJson(dynamic json) {
|
||||
final map = <String, WorkflowActionItemDto>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||
for (final entry in json.entries) {
|
||||
final value = WorkflowActionItemDto.fromJson(entry.value);
|
||||
if (value != null) {
|
||||
map[entry.key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
// maps a json object with a list of WorkflowActionItemDto-objects as value to a dart map
|
||||
static Map<String, List<WorkflowActionItemDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||
final map = <String, List<WorkflowActionItemDto>>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
// ignore: parameter_assignments
|
||||
json = json.cast<String, dynamic>();
|
||||
for (final entry in json.entries) {
|
||||
map[entry.key] = WorkflowActionItemDto.listFromJson(entry.value, growable: growable,);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/// The list of required keys that must be present in a JSON.
|
||||
static const requiredKeys = <String>{
|
||||
'pluginActionId',
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.18
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
part of openapi.api;
|
||||
|
||||
class WorkflowActionResponseDto {
|
||||
/// Returns a new [WorkflowActionResponseDto] instance.
|
||||
WorkflowActionResponseDto({
|
||||
required this.actionConfig,
|
||||
required this.id,
|
||||
required this.order,
|
||||
required this.pluginActionId,
|
||||
required this.workflowId,
|
||||
});
|
||||
|
||||
Map<String, Object>? actionConfig;
|
||||
|
||||
/// Action ID
|
||||
String id;
|
||||
|
||||
/// Action order
|
||||
///
|
||||
/// Minimum value: -9007199254740991
|
||||
/// Maximum value: 9007199254740991
|
||||
int order;
|
||||
|
||||
/// Plugin action ID
|
||||
String pluginActionId;
|
||||
|
||||
/// Workflow ID
|
||||
String workflowId;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is WorkflowActionResponseDto &&
|
||||
_deepEquality.equals(other.actionConfig, actionConfig) &&
|
||||
other.id == id &&
|
||||
other.order == order &&
|
||||
other.pluginActionId == pluginActionId &&
|
||||
other.workflowId == workflowId;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(actionConfig == null ? 0 : actionConfig!.hashCode) +
|
||||
(id.hashCode) +
|
||||
(order.hashCode) +
|
||||
(pluginActionId.hashCode) +
|
||||
(workflowId.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'WorkflowActionResponseDto[actionConfig=$actionConfig, id=$id, order=$order, pluginActionId=$pluginActionId, workflowId=$workflowId]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
if (this.actionConfig != null) {
|
||||
json[r'actionConfig'] = this.actionConfig;
|
||||
} else {
|
||||
// json[r'actionConfig'] = null;
|
||||
}
|
||||
json[r'id'] = this.id;
|
||||
json[r'order'] = this.order;
|
||||
json[r'pluginActionId'] = this.pluginActionId;
|
||||
json[r'workflowId'] = this.workflowId;
|
||||
return json;
|
||||
}
|
||||
|
||||
/// Returns a new [WorkflowActionResponseDto] instance and imports its values from
|
||||
/// [value] if it's a [Map], null otherwise.
|
||||
// ignore: prefer_constructors_over_static_methods
|
||||
static WorkflowActionResponseDto? fromJson(dynamic value) {
|
||||
upgradeDto(value, "WorkflowActionResponseDto");
|
||||
if (value is Map) {
|
||||
final json = value.cast<String, dynamic>();
|
||||
|
||||
return WorkflowActionResponseDto(
|
||||
actionConfig: mapCastOfType<String, Object>(json, r'actionConfig'),
|
||||
id: mapValueOfType<String>(json, r'id')!,
|
||||
order: mapValueOfType<int>(json, r'order')!,
|
||||
pluginActionId: mapValueOfType<String>(json, r'pluginActionId')!,
|
||||
workflowId: mapValueOfType<String>(json, r'workflowId')!,
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static List<WorkflowActionResponseDto> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <WorkflowActionResponseDto>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = WorkflowActionResponseDto.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList(growable: growable);
|
||||
}
|
||||
|
||||
static Map<String, WorkflowActionResponseDto> mapFromJson(dynamic json) {
|
||||
final map = <String, WorkflowActionResponseDto>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||
for (final entry in json.entries) {
|
||||
final value = WorkflowActionResponseDto.fromJson(entry.value);
|
||||
if (value != null) {
|
||||
map[entry.key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
// maps a json object with a list of WorkflowActionResponseDto-objects as value to a dart map
|
||||
static Map<String, List<WorkflowActionResponseDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||
final map = <String, List<WorkflowActionResponseDto>>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
// ignore: parameter_assignments
|
||||
json = json.cast<String, dynamic>();
|
||||
for (final entry in json.entries) {
|
||||
map[entry.key] = WorkflowActionResponseDto.listFromJson(entry.value, growable: growable,);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/// The list of required keys that must be present in a JSON.
|
||||
static const requiredKeys = <String>{
|
||||
'actionConfig',
|
||||
'id',
|
||||
'order',
|
||||
'pluginActionId',
|
||||
'workflowId',
|
||||
};
|
||||
}
|
||||
|
||||
+37
-23
@@ -13,14 +13,24 @@ part of openapi.api;
|
||||
class WorkflowCreateDto {
|
||||
/// Returns a new [WorkflowCreateDto] instance.
|
||||
WorkflowCreateDto({
|
||||
this.actions = const [],
|
||||
this.description,
|
||||
this.enabled,
|
||||
this.name,
|
||||
this.steps = const [],
|
||||
required this.trigger,
|
||||
this.filters = const [],
|
||||
required this.name,
|
||||
required this.triggerType,
|
||||
});
|
||||
|
||||
/// Workflow actions
|
||||
List<WorkflowActionItemDto> actions;
|
||||
|
||||
/// Workflow description
|
||||
///
|
||||
/// Please note: This property should have been non-nullable! Since the specification file
|
||||
/// does not include a default value (using the "default:" property), however, the generated
|
||||
/// source code must fall back to having a nullable type.
|
||||
/// Consider adding a "default:" property in the specification file to hide this note.
|
||||
///
|
||||
String? description;
|
||||
|
||||
/// Workflow enabled
|
||||
@@ -32,35 +42,39 @@ class WorkflowCreateDto {
|
||||
///
|
||||
bool? enabled;
|
||||
|
||||
/// Workflow filters
|
||||
List<WorkflowFilterItemDto> filters;
|
||||
|
||||
/// Workflow name
|
||||
String? name;
|
||||
String name;
|
||||
|
||||
List<WorkflowStepDto> steps;
|
||||
|
||||
WorkflowTrigger trigger;
|
||||
PluginTriggerType triggerType;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is WorkflowCreateDto &&
|
||||
_deepEquality.equals(other.actions, actions) &&
|
||||
other.description == description &&
|
||||
other.enabled == enabled &&
|
||||
_deepEquality.equals(other.filters, filters) &&
|
||||
other.name == name &&
|
||||
_deepEquality.equals(other.steps, steps) &&
|
||||
other.trigger == trigger;
|
||||
other.triggerType == triggerType;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(actions.hashCode) +
|
||||
(description == null ? 0 : description!.hashCode) +
|
||||
(enabled == null ? 0 : enabled!.hashCode) +
|
||||
(name == null ? 0 : name!.hashCode) +
|
||||
(steps.hashCode) +
|
||||
(trigger.hashCode);
|
||||
(filters.hashCode) +
|
||||
(name.hashCode) +
|
||||
(triggerType.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'WorkflowCreateDto[description=$description, enabled=$enabled, name=$name, steps=$steps, trigger=$trigger]';
|
||||
String toString() => 'WorkflowCreateDto[actions=$actions, description=$description, enabled=$enabled, filters=$filters, name=$name, triggerType=$triggerType]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
json[r'actions'] = this.actions;
|
||||
if (this.description != null) {
|
||||
json[r'description'] = this.description;
|
||||
} else {
|
||||
@@ -71,13 +85,9 @@ class WorkflowCreateDto {
|
||||
} else {
|
||||
// json[r'enabled'] = null;
|
||||
}
|
||||
if (this.name != null) {
|
||||
json[r'filters'] = this.filters;
|
||||
json[r'name'] = this.name;
|
||||
} else {
|
||||
// json[r'name'] = null;
|
||||
}
|
||||
json[r'steps'] = this.steps;
|
||||
json[r'trigger'] = this.trigger;
|
||||
json[r'triggerType'] = this.triggerType;
|
||||
return json;
|
||||
}
|
||||
|
||||
@@ -90,11 +100,12 @@ class WorkflowCreateDto {
|
||||
final json = value.cast<String, dynamic>();
|
||||
|
||||
return WorkflowCreateDto(
|
||||
actions: WorkflowActionItemDto.listFromJson(json[r'actions']),
|
||||
description: mapValueOfType<String>(json, r'description'),
|
||||
enabled: mapValueOfType<bool>(json, r'enabled'),
|
||||
name: mapValueOfType<String>(json, r'name'),
|
||||
steps: WorkflowStepDto.listFromJson(json[r'steps']),
|
||||
trigger: WorkflowTrigger.fromJson(json[r'trigger'])!,
|
||||
filters: WorkflowFilterItemDto.listFromJson(json[r'filters']),
|
||||
name: mapValueOfType<String>(json, r'name')!,
|
||||
triggerType: PluginTriggerType.fromJson(json[r'triggerType'])!,
|
||||
);
|
||||
}
|
||||
return null;
|
||||
@@ -142,7 +153,10 @@ class WorkflowCreateDto {
|
||||
|
||||
/// The list of required keys that must be present in a JSON.
|
||||
static const requiredKeys = <String>{
|
||||
'trigger',
|
||||
'actions',
|
||||
'filters',
|
||||
'name',
|
||||
'triggerType',
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.18
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
part of openapi.api;
|
||||
|
||||
class WorkflowFilterItemDto {
|
||||
/// Returns a new [WorkflowFilterItemDto] instance.
|
||||
WorkflowFilterItemDto({
|
||||
this.filterConfig = const {},
|
||||
required this.pluginFilterId,
|
||||
});
|
||||
|
||||
Map<String, Object> filterConfig;
|
||||
|
||||
/// Plugin filter ID
|
||||
String pluginFilterId;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is WorkflowFilterItemDto &&
|
||||
_deepEquality.equals(other.filterConfig, filterConfig) &&
|
||||
other.pluginFilterId == pluginFilterId;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(filterConfig.hashCode) +
|
||||
(pluginFilterId.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'WorkflowFilterItemDto[filterConfig=$filterConfig, pluginFilterId=$pluginFilterId]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
json[r'filterConfig'] = this.filterConfig;
|
||||
json[r'pluginFilterId'] = this.pluginFilterId;
|
||||
return json;
|
||||
}
|
||||
|
||||
/// Returns a new [WorkflowFilterItemDto] instance and imports its values from
|
||||
/// [value] if it's a [Map], null otherwise.
|
||||
// ignore: prefer_constructors_over_static_methods
|
||||
static WorkflowFilterItemDto? fromJson(dynamic value) {
|
||||
upgradeDto(value, "WorkflowFilterItemDto");
|
||||
if (value is Map) {
|
||||
final json = value.cast<String, dynamic>();
|
||||
|
||||
return WorkflowFilterItemDto(
|
||||
filterConfig: mapCastOfType<String, Object>(json, r'filterConfig') ?? const {},
|
||||
pluginFilterId: mapValueOfType<String>(json, r'pluginFilterId')!,
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static List<WorkflowFilterItemDto> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <WorkflowFilterItemDto>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = WorkflowFilterItemDto.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList(growable: growable);
|
||||
}
|
||||
|
||||
static Map<String, WorkflowFilterItemDto> mapFromJson(dynamic json) {
|
||||
final map = <String, WorkflowFilterItemDto>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||
for (final entry in json.entries) {
|
||||
final value = WorkflowFilterItemDto.fromJson(entry.value);
|
||||
if (value != null) {
|
||||
map[entry.key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
// maps a json object with a list of WorkflowFilterItemDto-objects as value to a dart map
|
||||
static Map<String, List<WorkflowFilterItemDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||
final map = <String, List<WorkflowFilterItemDto>>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
// ignore: parameter_assignments
|
||||
json = json.cast<String, dynamic>();
|
||||
for (final entry in json.entries) {
|
||||
map[entry.key] = WorkflowFilterItemDto.listFromJson(entry.value, growable: growable,);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/// The list of required keys that must be present in a JSON.
|
||||
static const requiredKeys = <String>{
|
||||
'pluginFilterId',
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.18
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
part of openapi.api;
|
||||
|
||||
class WorkflowFilterResponseDto {
|
||||
/// Returns a new [WorkflowFilterResponseDto] instance.
|
||||
WorkflowFilterResponseDto({
|
||||
required this.filterConfig,
|
||||
required this.id,
|
||||
required this.order,
|
||||
required this.pluginFilterId,
|
||||
required this.workflowId,
|
||||
});
|
||||
|
||||
Map<String, Object>? filterConfig;
|
||||
|
||||
/// Filter ID
|
||||
String id;
|
||||
|
||||
/// Filter order
|
||||
///
|
||||
/// Minimum value: -9007199254740991
|
||||
/// Maximum value: 9007199254740991
|
||||
int order;
|
||||
|
||||
/// Plugin filter ID
|
||||
String pluginFilterId;
|
||||
|
||||
/// Workflow ID
|
||||
String workflowId;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is WorkflowFilterResponseDto &&
|
||||
_deepEquality.equals(other.filterConfig, filterConfig) &&
|
||||
other.id == id &&
|
||||
other.order == order &&
|
||||
other.pluginFilterId == pluginFilterId &&
|
||||
other.workflowId == workflowId;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(filterConfig == null ? 0 : filterConfig!.hashCode) +
|
||||
(id.hashCode) +
|
||||
(order.hashCode) +
|
||||
(pluginFilterId.hashCode) +
|
||||
(workflowId.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'WorkflowFilterResponseDto[filterConfig=$filterConfig, id=$id, order=$order, pluginFilterId=$pluginFilterId, workflowId=$workflowId]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
if (this.filterConfig != null) {
|
||||
json[r'filterConfig'] = this.filterConfig;
|
||||
} else {
|
||||
// json[r'filterConfig'] = null;
|
||||
}
|
||||
json[r'id'] = this.id;
|
||||
json[r'order'] = this.order;
|
||||
json[r'pluginFilterId'] = this.pluginFilterId;
|
||||
json[r'workflowId'] = this.workflowId;
|
||||
return json;
|
||||
}
|
||||
|
||||
/// Returns a new [WorkflowFilterResponseDto] instance and imports its values from
|
||||
/// [value] if it's a [Map], null otherwise.
|
||||
// ignore: prefer_constructors_over_static_methods
|
||||
static WorkflowFilterResponseDto? fromJson(dynamic value) {
|
||||
upgradeDto(value, "WorkflowFilterResponseDto");
|
||||
if (value is Map) {
|
||||
final json = value.cast<String, dynamic>();
|
||||
|
||||
return WorkflowFilterResponseDto(
|
||||
filterConfig: mapCastOfType<String, Object>(json, r'filterConfig'),
|
||||
id: mapValueOfType<String>(json, r'id')!,
|
||||
order: mapValueOfType<int>(json, r'order')!,
|
||||
pluginFilterId: mapValueOfType<String>(json, r'pluginFilterId')!,
|
||||
workflowId: mapValueOfType<String>(json, r'workflowId')!,
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static List<WorkflowFilterResponseDto> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <WorkflowFilterResponseDto>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = WorkflowFilterResponseDto.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList(growable: growable);
|
||||
}
|
||||
|
||||
static Map<String, WorkflowFilterResponseDto> mapFromJson(dynamic json) {
|
||||
final map = <String, WorkflowFilterResponseDto>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||
for (final entry in json.entries) {
|
||||
final value = WorkflowFilterResponseDto.fromJson(entry.value);
|
||||
if (value != null) {
|
||||
map[entry.key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
// maps a json object with a list of WorkflowFilterResponseDto-objects as value to a dart map
|
||||
static Map<String, List<WorkflowFilterResponseDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||
final map = <String, List<WorkflowFilterResponseDto>>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
// ignore: parameter_assignments
|
||||
json = json.cast<String, dynamic>();
|
||||
for (final entry in json.entries) {
|
||||
map[entry.key] = WorkflowFilterResponseDto.listFromJson(entry.value, growable: growable,);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/// The list of required keys that must be present in a JSON.
|
||||
static const requiredKeys = <String>{
|
||||
'filterConfig',
|
||||
'id',
|
||||
'order',
|
||||
'pluginFilterId',
|
||||
'workflowId',
|
||||
};
|
||||
}
|
||||
|
||||
+37
-32
@@ -13,83 +13,86 @@ part of openapi.api;
|
||||
class WorkflowResponseDto {
|
||||
/// Returns a new [WorkflowResponseDto] instance.
|
||||
WorkflowResponseDto({
|
||||
this.actions = const [],
|
||||
required this.createdAt,
|
||||
required this.description,
|
||||
required this.enabled,
|
||||
this.filters = const [],
|
||||
required this.id,
|
||||
required this.name,
|
||||
this.steps = const [],
|
||||
required this.trigger,
|
||||
required this.updatedAt,
|
||||
required this.ownerId,
|
||||
required this.triggerType,
|
||||
});
|
||||
|
||||
/// Workflow actions
|
||||
List<WorkflowActionResponseDto> actions;
|
||||
|
||||
/// Creation date
|
||||
String createdAt;
|
||||
|
||||
/// Workflow description
|
||||
String? description;
|
||||
String description;
|
||||
|
||||
/// Workflow enabled
|
||||
bool enabled;
|
||||
|
||||
/// Workflow filters
|
||||
List<WorkflowFilterResponseDto> filters;
|
||||
|
||||
/// Workflow ID
|
||||
String id;
|
||||
|
||||
/// Workflow name
|
||||
String? name;
|
||||
|
||||
/// Workflow steps
|
||||
List<WorkflowStepDto> steps;
|
||||
/// Owner user ID
|
||||
String ownerId;
|
||||
|
||||
WorkflowTrigger trigger;
|
||||
|
||||
/// Update date
|
||||
String updatedAt;
|
||||
PluginTriggerType triggerType;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is WorkflowResponseDto &&
|
||||
_deepEquality.equals(other.actions, actions) &&
|
||||
other.createdAt == createdAt &&
|
||||
other.description == description &&
|
||||
other.enabled == enabled &&
|
||||
_deepEquality.equals(other.filters, filters) &&
|
||||
other.id == id &&
|
||||
other.name == name &&
|
||||
_deepEquality.equals(other.steps, steps) &&
|
||||
other.trigger == trigger &&
|
||||
other.updatedAt == updatedAt;
|
||||
other.ownerId == ownerId &&
|
||||
other.triggerType == triggerType;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(actions.hashCode) +
|
||||
(createdAt.hashCode) +
|
||||
(description == null ? 0 : description!.hashCode) +
|
||||
(description.hashCode) +
|
||||
(enabled.hashCode) +
|
||||
(filters.hashCode) +
|
||||
(id.hashCode) +
|
||||
(name == null ? 0 : name!.hashCode) +
|
||||
(steps.hashCode) +
|
||||
(trigger.hashCode) +
|
||||
(updatedAt.hashCode);
|
||||
(ownerId.hashCode) +
|
||||
(triggerType.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'WorkflowResponseDto[createdAt=$createdAt, description=$description, enabled=$enabled, id=$id, name=$name, steps=$steps, trigger=$trigger, updatedAt=$updatedAt]';
|
||||
String toString() => 'WorkflowResponseDto[actions=$actions, createdAt=$createdAt, description=$description, enabled=$enabled, filters=$filters, id=$id, name=$name, ownerId=$ownerId, triggerType=$triggerType]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
json[r'actions'] = this.actions;
|
||||
json[r'createdAt'] = this.createdAt;
|
||||
if (this.description != null) {
|
||||
json[r'description'] = this.description;
|
||||
} else {
|
||||
// json[r'description'] = null;
|
||||
}
|
||||
json[r'enabled'] = this.enabled;
|
||||
json[r'filters'] = this.filters;
|
||||
json[r'id'] = this.id;
|
||||
if (this.name != null) {
|
||||
json[r'name'] = this.name;
|
||||
} else {
|
||||
// json[r'name'] = null;
|
||||
}
|
||||
json[r'steps'] = this.steps;
|
||||
json[r'trigger'] = this.trigger;
|
||||
json[r'updatedAt'] = this.updatedAt;
|
||||
json[r'ownerId'] = this.ownerId;
|
||||
json[r'triggerType'] = this.triggerType;
|
||||
return json;
|
||||
}
|
||||
|
||||
@@ -102,14 +105,15 @@ class WorkflowResponseDto {
|
||||
final json = value.cast<String, dynamic>();
|
||||
|
||||
return WorkflowResponseDto(
|
||||
actions: WorkflowActionResponseDto.listFromJson(json[r'actions']),
|
||||
createdAt: mapValueOfType<String>(json, r'createdAt')!,
|
||||
description: mapValueOfType<String>(json, r'description'),
|
||||
description: mapValueOfType<String>(json, r'description')!,
|
||||
enabled: mapValueOfType<bool>(json, r'enabled')!,
|
||||
filters: WorkflowFilterResponseDto.listFromJson(json[r'filters']),
|
||||
id: mapValueOfType<String>(json, r'id')!,
|
||||
name: mapValueOfType<String>(json, r'name'),
|
||||
steps: WorkflowStepDto.listFromJson(json[r'steps']),
|
||||
trigger: WorkflowTrigger.fromJson(json[r'trigger'])!,
|
||||
updatedAt: mapValueOfType<String>(json, r'updatedAt')!,
|
||||
ownerId: mapValueOfType<String>(json, r'ownerId')!,
|
||||
triggerType: PluginTriggerType.fromJson(json[r'triggerType'])!,
|
||||
);
|
||||
}
|
||||
return null;
|
||||
@@ -157,14 +161,15 @@ class WorkflowResponseDto {
|
||||
|
||||
/// The list of required keys that must be present in a JSON.
|
||||
static const requiredKeys = <String>{
|
||||
'actions',
|
||||
'createdAt',
|
||||
'description',
|
||||
'enabled',
|
||||
'filters',
|
||||
'id',
|
||||
'name',
|
||||
'steps',
|
||||
'trigger',
|
||||
'updatedAt',
|
||||
'ownerId',
|
||||
'triggerType',
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,134 +0,0 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.18
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
part of openapi.api;
|
||||
|
||||
class WorkflowShareResponseDto {
|
||||
/// Returns a new [WorkflowShareResponseDto] instance.
|
||||
WorkflowShareResponseDto({
|
||||
required this.description,
|
||||
required this.name,
|
||||
this.steps = const [],
|
||||
required this.trigger,
|
||||
});
|
||||
|
||||
/// Workflow description
|
||||
String? description;
|
||||
|
||||
/// Workflow name
|
||||
String? name;
|
||||
|
||||
/// Workflow steps
|
||||
List<WorkflowShareStepDto> steps;
|
||||
|
||||
WorkflowTrigger trigger;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is WorkflowShareResponseDto &&
|
||||
other.description == description &&
|
||||
other.name == name &&
|
||||
_deepEquality.equals(other.steps, steps) &&
|
||||
other.trigger == trigger;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(description == null ? 0 : description!.hashCode) +
|
||||
(name == null ? 0 : name!.hashCode) +
|
||||
(steps.hashCode) +
|
||||
(trigger.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'WorkflowShareResponseDto[description=$description, name=$name, steps=$steps, trigger=$trigger]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
if (this.description != null) {
|
||||
json[r'description'] = this.description;
|
||||
} else {
|
||||
// json[r'description'] = null;
|
||||
}
|
||||
if (this.name != null) {
|
||||
json[r'name'] = this.name;
|
||||
} else {
|
||||
// json[r'name'] = null;
|
||||
}
|
||||
json[r'steps'] = this.steps;
|
||||
json[r'trigger'] = this.trigger;
|
||||
return json;
|
||||
}
|
||||
|
||||
/// Returns a new [WorkflowShareResponseDto] instance and imports its values from
|
||||
/// [value] if it's a [Map], null otherwise.
|
||||
// ignore: prefer_constructors_over_static_methods
|
||||
static WorkflowShareResponseDto? fromJson(dynamic value) {
|
||||
upgradeDto(value, "WorkflowShareResponseDto");
|
||||
if (value is Map) {
|
||||
final json = value.cast<String, dynamic>();
|
||||
|
||||
return WorkflowShareResponseDto(
|
||||
description: mapValueOfType<String>(json, r'description'),
|
||||
name: mapValueOfType<String>(json, r'name'),
|
||||
steps: WorkflowShareStepDto.listFromJson(json[r'steps']),
|
||||
trigger: WorkflowTrigger.fromJson(json[r'trigger'])!,
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static List<WorkflowShareResponseDto> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <WorkflowShareResponseDto>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = WorkflowShareResponseDto.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList(growable: growable);
|
||||
}
|
||||
|
||||
static Map<String, WorkflowShareResponseDto> mapFromJson(dynamic json) {
|
||||
final map = <String, WorkflowShareResponseDto>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||
for (final entry in json.entries) {
|
||||
final value = WorkflowShareResponseDto.fromJson(entry.value);
|
||||
if (value != null) {
|
||||
map[entry.key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
// maps a json object with a list of WorkflowShareResponseDto-objects as value to a dart map
|
||||
static Map<String, List<WorkflowShareResponseDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||
final map = <String, List<WorkflowShareResponseDto>>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
// ignore: parameter_assignments
|
||||
json = json.cast<String, dynamic>();
|
||||
for (final entry in json.entries) {
|
||||
map[entry.key] = WorkflowShareResponseDto.listFromJson(entry.value, growable: growable,);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/// The list of required keys that must be present in a JSON.
|
||||
static const requiredKeys = <String>{
|
||||
'description',
|
||||
'name',
|
||||
'steps',
|
||||
'trigger',
|
||||
};
|
||||
}
|
||||
|
||||
-131
@@ -1,131 +0,0 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.18
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
part of openapi.api;
|
||||
|
||||
class WorkflowShareStepDto {
|
||||
/// Returns a new [WorkflowShareStepDto] instance.
|
||||
WorkflowShareStepDto({
|
||||
this.config = const {},
|
||||
this.enabled,
|
||||
required this.method,
|
||||
});
|
||||
|
||||
/// Step configuration
|
||||
Map<String, Object>? config;
|
||||
|
||||
/// Step is enabled
|
||||
///
|
||||
/// Please note: This property should have been non-nullable! Since the specification file
|
||||
/// does not include a default value (using the "default:" property), however, the generated
|
||||
/// source code must fall back to having a nullable type.
|
||||
/// Consider adding a "default:" property in the specification file to hide this note.
|
||||
///
|
||||
bool? enabled;
|
||||
|
||||
/// Step plugin method
|
||||
String method;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is WorkflowShareStepDto &&
|
||||
_deepEquality.equals(other.config, config) &&
|
||||
other.enabled == enabled &&
|
||||
other.method == method;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(config == null ? 0 : config!.hashCode) +
|
||||
(enabled == null ? 0 : enabled!.hashCode) +
|
||||
(method.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'WorkflowShareStepDto[config=$config, enabled=$enabled, method=$method]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
if (this.config != null) {
|
||||
json[r'config'] = this.config;
|
||||
} else {
|
||||
// json[r'config'] = null;
|
||||
}
|
||||
if (this.enabled != null) {
|
||||
json[r'enabled'] = this.enabled;
|
||||
} else {
|
||||
// json[r'enabled'] = null;
|
||||
}
|
||||
json[r'method'] = this.method;
|
||||
return json;
|
||||
}
|
||||
|
||||
/// Returns a new [WorkflowShareStepDto] instance and imports its values from
|
||||
/// [value] if it's a [Map], null otherwise.
|
||||
// ignore: prefer_constructors_over_static_methods
|
||||
static WorkflowShareStepDto? fromJson(dynamic value) {
|
||||
upgradeDto(value, "WorkflowShareStepDto");
|
||||
if (value is Map) {
|
||||
final json = value.cast<String, dynamic>();
|
||||
|
||||
return WorkflowShareStepDto(
|
||||
config: mapCastOfType<String, Object>(json, r'config'),
|
||||
enabled: mapValueOfType<bool>(json, r'enabled'),
|
||||
method: mapValueOfType<String>(json, r'method')!,
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static List<WorkflowShareStepDto> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <WorkflowShareStepDto>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = WorkflowShareStepDto.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList(growable: growable);
|
||||
}
|
||||
|
||||
static Map<String, WorkflowShareStepDto> mapFromJson(dynamic json) {
|
||||
final map = <String, WorkflowShareStepDto>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||
for (final entry in json.entries) {
|
||||
final value = WorkflowShareStepDto.fromJson(entry.value);
|
||||
if (value != null) {
|
||||
map[entry.key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
// maps a json object with a list of WorkflowShareStepDto-objects as value to a dart map
|
||||
static Map<String, List<WorkflowShareStepDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||
final map = <String, List<WorkflowShareStepDto>>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
// ignore: parameter_assignments
|
||||
json = json.cast<String, dynamic>();
|
||||
for (final entry in json.entries) {
|
||||
map[entry.key] = WorkflowShareStepDto.listFromJson(entry.value, growable: growable,);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/// The list of required keys that must be present in a JSON.
|
||||
static const requiredKeys = <String>{
|
||||
'config',
|
||||
'method',
|
||||
};
|
||||
}
|
||||
|
||||
-131
@@ -1,131 +0,0 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.18
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
part of openapi.api;
|
||||
|
||||
class WorkflowStepDto {
|
||||
/// Returns a new [WorkflowStepDto] instance.
|
||||
WorkflowStepDto({
|
||||
this.config = const {},
|
||||
this.enabled,
|
||||
required this.method,
|
||||
});
|
||||
|
||||
/// Step configuration
|
||||
Map<String, Object>? config;
|
||||
|
||||
/// Step is enabled
|
||||
///
|
||||
/// Please note: This property should have been non-nullable! Since the specification file
|
||||
/// does not include a default value (using the "default:" property), however, the generated
|
||||
/// source code must fall back to having a nullable type.
|
||||
/// Consider adding a "default:" property in the specification file to hide this note.
|
||||
///
|
||||
bool? enabled;
|
||||
|
||||
/// Step plugin method
|
||||
String method;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is WorkflowStepDto &&
|
||||
_deepEquality.equals(other.config, config) &&
|
||||
other.enabled == enabled &&
|
||||
other.method == method;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(config == null ? 0 : config!.hashCode) +
|
||||
(enabled == null ? 0 : enabled!.hashCode) +
|
||||
(method.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'WorkflowStepDto[config=$config, enabled=$enabled, method=$method]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
if (this.config != null) {
|
||||
json[r'config'] = this.config;
|
||||
} else {
|
||||
// json[r'config'] = null;
|
||||
}
|
||||
if (this.enabled != null) {
|
||||
json[r'enabled'] = this.enabled;
|
||||
} else {
|
||||
// json[r'enabled'] = null;
|
||||
}
|
||||
json[r'method'] = this.method;
|
||||
return json;
|
||||
}
|
||||
|
||||
/// Returns a new [WorkflowStepDto] instance and imports its values from
|
||||
/// [value] if it's a [Map], null otherwise.
|
||||
// ignore: prefer_constructors_over_static_methods
|
||||
static WorkflowStepDto? fromJson(dynamic value) {
|
||||
upgradeDto(value, "WorkflowStepDto");
|
||||
if (value is Map) {
|
||||
final json = value.cast<String, dynamic>();
|
||||
|
||||
return WorkflowStepDto(
|
||||
config: mapCastOfType<String, Object>(json, r'config'),
|
||||
enabled: mapValueOfType<bool>(json, r'enabled'),
|
||||
method: mapValueOfType<String>(json, r'method')!,
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static List<WorkflowStepDto> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <WorkflowStepDto>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = WorkflowStepDto.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList(growable: growable);
|
||||
}
|
||||
|
||||
static Map<String, WorkflowStepDto> mapFromJson(dynamic json) {
|
||||
final map = <String, WorkflowStepDto>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||
for (final entry in json.entries) {
|
||||
final value = WorkflowStepDto.fromJson(entry.value);
|
||||
if (value != null) {
|
||||
map[entry.key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
// maps a json object with a list of WorkflowStepDto-objects as value to a dart map
|
||||
static Map<String, List<WorkflowStepDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||
final map = <String, List<WorkflowStepDto>>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
// ignore: parameter_assignments
|
||||
json = json.cast<String, dynamic>();
|
||||
for (final entry in json.entries) {
|
||||
map[entry.key] = WorkflowStepDto.listFromJson(entry.value, growable: growable,);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/// The list of required keys that must be present in a JSON.
|
||||
static const requiredKeys = <String>{
|
||||
'config',
|
||||
'method',
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.18
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
part of openapi.api;
|
||||
|
||||
class WorkflowTriggerResponseDto {
|
||||
/// Returns a new [WorkflowTriggerResponseDto] instance.
|
||||
WorkflowTriggerResponseDto({
|
||||
required this.trigger,
|
||||
this.types = const [],
|
||||
});
|
||||
|
||||
WorkflowTrigger trigger;
|
||||
|
||||
/// Workflow types
|
||||
List<WorkflowType> types;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is WorkflowTriggerResponseDto &&
|
||||
other.trigger == trigger &&
|
||||
_deepEquality.equals(other.types, types);
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(trigger.hashCode) +
|
||||
(types.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'WorkflowTriggerResponseDto[trigger=$trigger, types=$types]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
json[r'trigger'] = this.trigger;
|
||||
json[r'types'] = this.types;
|
||||
return json;
|
||||
}
|
||||
|
||||
/// Returns a new [WorkflowTriggerResponseDto] instance and imports its values from
|
||||
/// [value] if it's a [Map], null otherwise.
|
||||
// ignore: prefer_constructors_over_static_methods
|
||||
static WorkflowTriggerResponseDto? fromJson(dynamic value) {
|
||||
upgradeDto(value, "WorkflowTriggerResponseDto");
|
||||
if (value is Map) {
|
||||
final json = value.cast<String, dynamic>();
|
||||
|
||||
return WorkflowTriggerResponseDto(
|
||||
trigger: WorkflowTrigger.fromJson(json[r'trigger'])!,
|
||||
types: WorkflowType.listFromJson(json[r'types']),
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static List<WorkflowTriggerResponseDto> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <WorkflowTriggerResponseDto>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = WorkflowTriggerResponseDto.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList(growable: growable);
|
||||
}
|
||||
|
||||
static Map<String, WorkflowTriggerResponseDto> mapFromJson(dynamic json) {
|
||||
final map = <String, WorkflowTriggerResponseDto>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||
for (final entry in json.entries) {
|
||||
final value = WorkflowTriggerResponseDto.fromJson(entry.value);
|
||||
if (value != null) {
|
||||
map[entry.key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
// maps a json object with a list of WorkflowTriggerResponseDto-objects as value to a dart map
|
||||
static Map<String, List<WorkflowTriggerResponseDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||
final map = <String, List<WorkflowTriggerResponseDto>>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
// ignore: parameter_assignments
|
||||
json = json.cast<String, dynamic>();
|
||||
for (final entry in json.entries) {
|
||||
map[entry.key] = WorkflowTriggerResponseDto.listFromJson(entry.value, growable: growable,);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/// The list of required keys that must be present in a JSON.
|
||||
static const requiredKeys = <String>{
|
||||
'trigger',
|
||||
'types',
|
||||
};
|
||||
}
|
||||
|
||||
-85
@@ -1,85 +0,0 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.18
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
part of openapi.api;
|
||||
|
||||
/// Workflow type
|
||||
class WorkflowType {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const WorkflowType._(this.value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const assetV1 = WorkflowType._(r'AssetV1');
|
||||
static const assetPersonV1 = WorkflowType._(r'AssetPersonV1');
|
||||
|
||||
/// List of all possible values in this [enum][WorkflowType].
|
||||
static const values = <WorkflowType>[
|
||||
assetV1,
|
||||
assetPersonV1,
|
||||
];
|
||||
|
||||
static WorkflowType? fromJson(dynamic value) => WorkflowTypeTypeTransformer().decode(value);
|
||||
|
||||
static List<WorkflowType> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <WorkflowType>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = WorkflowType.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList(growable: growable);
|
||||
}
|
||||
}
|
||||
|
||||
/// Transformation class that can [encode] an instance of [WorkflowType] to String,
|
||||
/// and [decode] dynamic data back to [WorkflowType].
|
||||
class WorkflowTypeTypeTransformer {
|
||||
factory WorkflowTypeTypeTransformer() => _instance ??= const WorkflowTypeTypeTransformer._();
|
||||
|
||||
const WorkflowTypeTypeTransformer._();
|
||||
|
||||
String encode(WorkflowType data) => data.value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a WorkflowType.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
/// cannot be decoded successfully, then an [UnimplementedError] is thrown.
|
||||
///
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
WorkflowType? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'AssetV1': return WorkflowType.assetV1;
|
||||
case r'AssetPersonV1': return WorkflowType.assetPersonV1;
|
||||
default:
|
||||
if (!allowNull) {
|
||||
throw ArgumentError('Unknown enum value to decode: $data');
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [WorkflowTypeTypeTransformer] instance.
|
||||
static WorkflowTypeTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
+38
-17
@@ -13,14 +13,24 @@ part of openapi.api;
|
||||
class WorkflowUpdateDto {
|
||||
/// Returns a new [WorkflowUpdateDto] instance.
|
||||
WorkflowUpdateDto({
|
||||
this.actions = const [],
|
||||
this.description,
|
||||
this.enabled,
|
||||
this.filters = const [],
|
||||
this.name,
|
||||
this.steps = const [],
|
||||
this.trigger,
|
||||
this.triggerType,
|
||||
});
|
||||
|
||||
/// Workflow actions
|
||||
List<WorkflowActionItemDto> actions;
|
||||
|
||||
/// Workflow description
|
||||
///
|
||||
/// Please note: This property should have been non-nullable! Since the specification file
|
||||
/// does not include a default value (using the "default:" property), however, the generated
|
||||
/// source code must fall back to having a nullable type.
|
||||
/// Consider adding a "default:" property in the specification file to hide this note.
|
||||
///
|
||||
String? description;
|
||||
|
||||
/// Workflow enabled
|
||||
@@ -32,10 +42,17 @@ class WorkflowUpdateDto {
|
||||
///
|
||||
bool? enabled;
|
||||
|
||||
/// Workflow name
|
||||
String? name;
|
||||
/// Workflow filters
|
||||
List<WorkflowFilterItemDto> filters;
|
||||
|
||||
List<WorkflowStepDto> steps;
|
||||
/// Workflow name
|
||||
///
|
||||
/// Please note: This property should have been non-nullable! Since the specification file
|
||||
/// does not include a default value (using the "default:" property), however, the generated
|
||||
/// source code must fall back to having a nullable type.
|
||||
/// Consider adding a "default:" property in the specification file to hide this note.
|
||||
///
|
||||
String? name;
|
||||
|
||||
///
|
||||
/// Please note: This property should have been non-nullable! Since the specification file
|
||||
@@ -43,30 +60,33 @@ class WorkflowUpdateDto {
|
||||
/// source code must fall back to having a nullable type.
|
||||
/// Consider adding a "default:" property in the specification file to hide this note.
|
||||
///
|
||||
WorkflowTrigger? trigger;
|
||||
PluginTriggerType? triggerType;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is WorkflowUpdateDto &&
|
||||
_deepEquality.equals(other.actions, actions) &&
|
||||
other.description == description &&
|
||||
other.enabled == enabled &&
|
||||
_deepEquality.equals(other.filters, filters) &&
|
||||
other.name == name &&
|
||||
_deepEquality.equals(other.steps, steps) &&
|
||||
other.trigger == trigger;
|
||||
other.triggerType == triggerType;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(actions.hashCode) +
|
||||
(description == null ? 0 : description!.hashCode) +
|
||||
(enabled == null ? 0 : enabled!.hashCode) +
|
||||
(filters.hashCode) +
|
||||
(name == null ? 0 : name!.hashCode) +
|
||||
(steps.hashCode) +
|
||||
(trigger == null ? 0 : trigger!.hashCode);
|
||||
(triggerType == null ? 0 : triggerType!.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'WorkflowUpdateDto[description=$description, enabled=$enabled, name=$name, steps=$steps, trigger=$trigger]';
|
||||
String toString() => 'WorkflowUpdateDto[actions=$actions, description=$description, enabled=$enabled, filters=$filters, name=$name, triggerType=$triggerType]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
json[r'actions'] = this.actions;
|
||||
if (this.description != null) {
|
||||
json[r'description'] = this.description;
|
||||
} else {
|
||||
@@ -77,16 +97,16 @@ class WorkflowUpdateDto {
|
||||
} else {
|
||||
// json[r'enabled'] = null;
|
||||
}
|
||||
json[r'filters'] = this.filters;
|
||||
if (this.name != null) {
|
||||
json[r'name'] = this.name;
|
||||
} else {
|
||||
// json[r'name'] = null;
|
||||
}
|
||||
json[r'steps'] = this.steps;
|
||||
if (this.trigger != null) {
|
||||
json[r'trigger'] = this.trigger;
|
||||
if (this.triggerType != null) {
|
||||
json[r'triggerType'] = this.triggerType;
|
||||
} else {
|
||||
// json[r'trigger'] = null;
|
||||
// json[r'triggerType'] = null;
|
||||
}
|
||||
return json;
|
||||
}
|
||||
@@ -100,11 +120,12 @@ class WorkflowUpdateDto {
|
||||
final json = value.cast<String, dynamic>();
|
||||
|
||||
return WorkflowUpdateDto(
|
||||
actions: WorkflowActionItemDto.listFromJson(json[r'actions']),
|
||||
description: mapValueOfType<String>(json, r'description'),
|
||||
enabled: mapValueOfType<bool>(json, r'enabled'),
|
||||
filters: WorkflowFilterItemDto.listFromJson(json[r'filters']),
|
||||
name: mapValueOfType<String>(json, r'name'),
|
||||
steps: WorkflowStepDto.listFromJson(json[r'steps']),
|
||||
trigger: WorkflowTrigger.fromJson(json[r'trigger']),
|
||||
triggerType: PluginTriggerType.fromJson(json[r'triggerType']),
|
||||
);
|
||||
}
|
||||
return null;
|
||||
|
||||
@@ -9,8 +9,9 @@ import 'package:mocktail/mocktail.dart';
|
||||
import '../../infrastructure/repository.mock.dart';
|
||||
|
||||
const _kAccessToken = '#ThisIsAToken';
|
||||
const _kEnableBackup = false;
|
||||
const _kBackgroundBackup = false;
|
||||
const _kVersion = 2;
|
||||
final _kBackupFailedSince = DateTime.utc(2023);
|
||||
|
||||
void main() {
|
||||
late StoreService sut;
|
||||
@@ -23,13 +24,15 @@ void main() {
|
||||
// For generics, we need to provide fallback to each concrete type to avoid runtime errors
|
||||
registerFallbackValue(StoreKey.accessToken);
|
||||
registerFallbackValue(StoreKey.backupTriggerDelay);
|
||||
registerFallbackValue(StoreKey.enableBackup);
|
||||
registerFallbackValue(StoreKey.backgroundBackup);
|
||||
registerFallbackValue(StoreKey.backupFailedSince);
|
||||
|
||||
when(() => mockDriftStoreRepo.getAll()).thenAnswer(
|
||||
(_) async => [
|
||||
const StoreDto(StoreKey.accessToken, _kAccessToken),
|
||||
const StoreDto(StoreKey.enableBackup, _kEnableBackup),
|
||||
const StoreDto(StoreKey.backgroundBackup, _kBackgroundBackup),
|
||||
const StoreDto(StoreKey.version, _kVersion),
|
||||
StoreDto(StoreKey.backupFailedSince, _kBackupFailedSince),
|
||||
],
|
||||
);
|
||||
when(() => mockDriftStoreRepo.watchAll()).thenAnswer((_) => controller.stream);
|
||||
@@ -46,8 +49,9 @@ void main() {
|
||||
test('Populates the internal cache on init', () {
|
||||
verify(() => mockDriftStoreRepo.getAll()).called(1);
|
||||
expect(sut.tryGet(StoreKey.accessToken), _kAccessToken);
|
||||
expect(sut.tryGet(StoreKey.enableBackup), _kEnableBackup);
|
||||
expect(sut.tryGet(StoreKey.backgroundBackup), _kBackgroundBackup);
|
||||
expect(sut.tryGet(StoreKey.version), _kVersion);
|
||||
expect(sut.tryGet(StoreKey.backupFailedSince), _kBackupFailedSince);
|
||||
// Other keys should be null
|
||||
expect(sut.tryGet(StoreKey.currentUser), isNull);
|
||||
});
|
||||
@@ -147,8 +151,9 @@ void main() {
|
||||
await sut.clear();
|
||||
verify(() => mockDriftStoreRepo.deleteAll()).called(1);
|
||||
expect(sut.tryGet(StoreKey.accessToken), isNull);
|
||||
expect(sut.tryGet(StoreKey.enableBackup), isNull);
|
||||
expect(sut.tryGet(StoreKey.backgroundBackup), isNull);
|
||||
expect(sut.tryGet(StoreKey.version), isNull);
|
||||
expect(sut.tryGet(StoreKey.backupFailedSince), isNull);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -12,8 +12,9 @@ import 'package:immich_mobile/infrastructure/repositories/store.repository.dart'
|
||||
import '../../fixtures/user.stub.dart';
|
||||
|
||||
const _kTestAccessToken = "#TestToken";
|
||||
final _kTestBackupFailed = DateTime(2025, 2, 20, 11, 45);
|
||||
const _kTestVersion = 10;
|
||||
const _kTestBackupRequireCharging = false;
|
||||
const _kTestBackupRequireWifi = false;
|
||||
final _kTestUser = UserStub.admin;
|
||||
|
||||
Future<void> _populateStore(Drift db) async {
|
||||
@@ -21,8 +22,16 @@ Future<void> _populateStore(Drift db) async {
|
||||
batch.insert(
|
||||
db.storeEntity,
|
||||
StoreEntityCompanion(
|
||||
id: Value(StoreKey.backupRequireCharging.id),
|
||||
intValue: const Value(_kTestBackupRequireCharging ? 1 : 0),
|
||||
id: Value(StoreKey.backupRequireWifi.id),
|
||||
intValue: const Value(_kTestBackupRequireWifi ? 1 : 0),
|
||||
stringValue: const Value(null),
|
||||
),
|
||||
);
|
||||
batch.insert(
|
||||
db.storeEntity,
|
||||
StoreEntityCompanion(
|
||||
id: Value(StoreKey.backupFailedSince.id),
|
||||
intValue: Value(_kTestBackupFailed.millisecondsSinceEpoch),
|
||||
stringValue: const Value(null),
|
||||
),
|
||||
);
|
||||
@@ -75,12 +84,20 @@ void main() {
|
||||
expect(accessToken, _kTestAccessToken);
|
||||
});
|
||||
|
||||
test('converts datetime', () async {
|
||||
DateTime? backupFailedSince = await sut.tryGet(StoreKey.backupFailedSince);
|
||||
expect(backupFailedSince, isNull);
|
||||
await sut.upsert(StoreKey.backupFailedSince, _kTestBackupFailed);
|
||||
backupFailedSince = await sut.tryGet(StoreKey.backupFailedSince);
|
||||
expect(backupFailedSince, _kTestBackupFailed);
|
||||
});
|
||||
|
||||
test('converts bool', () async {
|
||||
bool? backupRequireCharging = await sut.tryGet(StoreKey.backupRequireCharging);
|
||||
expect(backupRequireCharging, isNull);
|
||||
await sut.upsert(StoreKey.backupRequireCharging, _kTestBackupRequireCharging);
|
||||
backupRequireCharging = await sut.tryGet(StoreKey.backupRequireCharging);
|
||||
expect(backupRequireCharging, _kTestBackupRequireCharging);
|
||||
bool? backupRequireWifi = await sut.tryGet(StoreKey.backupRequireWifi);
|
||||
expect(backupRequireWifi, isNull);
|
||||
await sut.upsert(StoreKey.backupRequireWifi, _kTestBackupRequireWifi);
|
||||
backupRequireWifi = await sut.tryGet(StoreKey.backupRequireWifi);
|
||||
expect(backupRequireWifi, _kTestBackupRequireWifi);
|
||||
});
|
||||
|
||||
test('converts user', () async {
|
||||
@@ -98,11 +115,11 @@ void main() {
|
||||
});
|
||||
|
||||
test('delete()', () async {
|
||||
bool? backupRequireCharging = await sut.tryGet(StoreKey.backupRequireCharging);
|
||||
expect(backupRequireCharging, isFalse);
|
||||
await sut.delete(StoreKey.backupRequireCharging);
|
||||
backupRequireCharging = await sut.tryGet(StoreKey.backupRequireCharging);
|
||||
expect(backupRequireCharging, isNull);
|
||||
bool? backupRequireWifi = await sut.tryGet(StoreKey.backupRequireWifi);
|
||||
expect(backupRequireWifi, isFalse);
|
||||
await sut.delete(StoreKey.backupRequireWifi);
|
||||
backupRequireWifi = await sut.tryGet(StoreKey.backupRequireWifi);
|
||||
expect(backupRequireWifi, isNull);
|
||||
});
|
||||
|
||||
test('deleteAll()', () async {
|
||||
@@ -147,12 +164,14 @@ void main() {
|
||||
emitsInOrder([
|
||||
[
|
||||
const StoreDto<Object>(StoreKey.version, _kTestVersion),
|
||||
const StoreDto<Object>(StoreKey.backupRequireCharging, _kTestBackupRequireCharging),
|
||||
StoreDto<Object>(StoreKey.backupFailedSince, _kTestBackupFailed),
|
||||
const StoreDto<Object>(StoreKey.backupRequireWifi, _kTestBackupRequireWifi),
|
||||
const StoreDto<Object>(StoreKey.accessToken, _kTestAccessToken),
|
||||
],
|
||||
[
|
||||
const StoreDto<Object>(StoreKey.version, _kTestVersion + 10),
|
||||
const StoreDto<Object>(StoreKey.backupRequireCharging, _kTestBackupRequireCharging),
|
||||
StoreDto<Object>(StoreKey.backupFailedSince, _kTestBackupFailed),
|
||||
const StoreDto<Object>(StoreKey.backupRequireWifi, _kTestBackupRequireWifi),
|
||||
const StoreDto<Object>(StoreKey.accessToken, _kTestAccessToken),
|
||||
],
|
||||
]),
|
||||
|
||||
@@ -3,7 +3,6 @@ import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:immich_mobile/constants/enums.dart';
|
||||
import 'package:immich_mobile/domain/models/album/album.model.dart';
|
||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||
import 'package:immich_mobile/domain/services/timeline.service.dart';
|
||||
import 'package:immich_mobile/utils/action_button.utils.dart';
|
||||
|
||||
LocalAsset createLocalAsset({
|
||||
@@ -38,7 +37,6 @@ RemoteAsset createRemoteAsset({
|
||||
DateTime? updatedAt,
|
||||
DateTime? uploadedAt,
|
||||
bool isFavorite = false,
|
||||
DateTime? deletedAt,
|
||||
}) {
|
||||
return RemoteAsset(
|
||||
id: 'remote-id',
|
||||
@@ -52,7 +50,6 @@ RemoteAsset createRemoteAsset({
|
||||
uploadedAt: uploadedAt ?? DateTime.now(),
|
||||
isFavorite: isFavorite,
|
||||
isEdited: false,
|
||||
deletedAt: deletedAt,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -461,62 +458,6 @@ void main() {
|
||||
|
||||
expect(ActionButtonType.trash.shouldShow(context), isFalse);
|
||||
});
|
||||
|
||||
test('should not show when asset is already trashed', () {
|
||||
final remoteAsset = createRemoteAsset(deletedAt: DateTime(2024));
|
||||
final context = ActionButtonContext(
|
||||
asset: remoteAsset,
|
||||
isOwner: true,
|
||||
isArchived: false,
|
||||
isTrashEnabled: true,
|
||||
isInLockedView: false,
|
||||
currentAlbum: null,
|
||||
advancedTroubleshooting: false,
|
||||
isStacked: false,
|
||||
source: ActionSource.viewer,
|
||||
timelineOrigin: TimelineOrigin.trash,
|
||||
);
|
||||
|
||||
expect(ActionButtonType.trash.shouldShow(context), isFalse);
|
||||
});
|
||||
});
|
||||
|
||||
group('restoreTrash button', () {
|
||||
test('should show when owner, not locked, has remote, and is in trash timeline', () {
|
||||
final remoteAsset = createRemoteAsset();
|
||||
final context = ActionButtonContext(
|
||||
asset: remoteAsset,
|
||||
isOwner: true,
|
||||
isArchived: false,
|
||||
isTrashEnabled: true,
|
||||
isInLockedView: false,
|
||||
currentAlbum: null,
|
||||
advancedTroubleshooting: false,
|
||||
isStacked: false,
|
||||
source: ActionSource.timeline,
|
||||
timelineOrigin: TimelineOrigin.trash,
|
||||
);
|
||||
|
||||
expect(ActionButtonType.restoreTrash.shouldShow(context), isTrue);
|
||||
});
|
||||
|
||||
test('should not show when not in trash timeline', () {
|
||||
final remoteAsset = createRemoteAsset();
|
||||
final context = ActionButtonContext(
|
||||
asset: remoteAsset,
|
||||
isOwner: true,
|
||||
isArchived: false,
|
||||
isTrashEnabled: false,
|
||||
isInLockedView: false,
|
||||
currentAlbum: null,
|
||||
advancedTroubleshooting: false,
|
||||
isStacked: false,
|
||||
source: ActionSource.timeline,
|
||||
timelineOrigin: TimelineOrigin.main,
|
||||
);
|
||||
|
||||
expect(ActionButtonType.restoreTrash.shouldShow(context), isFalse);
|
||||
});
|
||||
});
|
||||
|
||||
group('deletePermanent button', () {
|
||||
@@ -553,24 +494,6 @@ void main() {
|
||||
|
||||
expect(ActionButtonType.deletePermanent.shouldShow(context), isFalse);
|
||||
});
|
||||
|
||||
test('should show when asset is trashed even with trash enabled', () {
|
||||
final remoteAsset = createRemoteAsset(deletedAt: DateTime(2024));
|
||||
final context = ActionButtonContext(
|
||||
asset: remoteAsset,
|
||||
isOwner: true,
|
||||
isArchived: false,
|
||||
isTrashEnabled: true,
|
||||
isInLockedView: false,
|
||||
currentAlbum: null,
|
||||
advancedTroubleshooting: false,
|
||||
isStacked: false,
|
||||
source: ActionSource.viewer,
|
||||
timelineOrigin: TimelineOrigin.trash,
|
||||
);
|
||||
|
||||
expect(ActionButtonType.deletePermanent.shouldShow(context), isTrue);
|
||||
});
|
||||
});
|
||||
|
||||
group('delete button', () {
|
||||
|
||||
+455
-494
File diff suppressed because it is too large
Load Diff
@@ -1,2 +0,0 @@
|
||||
/dist
|
||||
/node_modules
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"singleQuote": true,
|
||||
"trailingComma": "all",
|
||||
"printWidth": 120,
|
||||
"semi": true
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
const esbuild = require('esbuild');
|
||||
|
||||
esbuild.build({
|
||||
entryPoints: ['src/index.ts'],
|
||||
outdir: 'dist',
|
||||
bundle: true,
|
||||
sourcemap: false,
|
||||
minify: false, // might want to use true for production build
|
||||
format: 'cjs', // needs to be CJS for now
|
||||
target: ['es2020'], // don't go over es2020 because quickjs doesn't support it
|
||||
});
|
||||
@@ -1,258 +0,0 @@
|
||||
{
|
||||
"name": "immich-plugin-core",
|
||||
"version": "2.0.1",
|
||||
"title": "Immich Core Plugin",
|
||||
"description": "Core workflow capabilities for Immich",
|
||||
"author": "Immich Team",
|
||||
"wasmPath": "dist/plugin.wasm",
|
||||
"methods": [
|
||||
{
|
||||
"name": "assetFileFilter",
|
||||
"title": "Filter by filename",
|
||||
"description": "Filter assets by filename pattern using text matching or regular expressions",
|
||||
"types": ["AssetV1"],
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"title": "Filename pattern",
|
||||
"description": "Text or regex pattern to match against filename"
|
||||
},
|
||||
"matchType": {
|
||||
"type": "string",
|
||||
"title": "Match type",
|
||||
"enum": ["contains", "startsWith", "exact", "regex"],
|
||||
"default": "contains",
|
||||
"description": "Type of pattern matching to perform"
|
||||
},
|
||||
"caseSensitive": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"title": "Case sensitive",
|
||||
"description": "Whether matching should be case-sensitive"
|
||||
}
|
||||
},
|
||||
"required": ["pattern"]
|
||||
},
|
||||
"uiHints": ["filter"]
|
||||
},
|
||||
{
|
||||
"name": "filterFileType",
|
||||
"title": "Filter by file type",
|
||||
"description": "Filter assets by file type",
|
||||
"types": ["AssetV1"],
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"fileTypes": {
|
||||
"title": "File types",
|
||||
"description": "Allowed file types",
|
||||
"type": "string",
|
||||
"array": true,
|
||||
"enum": ["image", "video"]
|
||||
}
|
||||
},
|
||||
"required": ["fileTypes"]
|
||||
},
|
||||
"uiHints": ["filter"]
|
||||
},
|
||||
{
|
||||
"name": "filterPerson",
|
||||
"title": "Filter by person",
|
||||
"description": "Filter by detected person",
|
||||
"types": ["AssetV1"],
|
||||
"schema": {
|
||||
"properties": {
|
||||
"personIds": {
|
||||
"type": "string",
|
||||
"array": true,
|
||||
"title": "Person IDs",
|
||||
"description": "List of person to match",
|
||||
"uiHint": "personI"
|
||||
},
|
||||
"matchAny": {
|
||||
"type": "boolean",
|
||||
"title": "Match any",
|
||||
"default": true,
|
||||
"description": "Match any name (true) or require all names (false)"
|
||||
}
|
||||
},
|
||||
"required": ["personIds"]
|
||||
},
|
||||
"uiHints": ["filter"]
|
||||
},
|
||||
{
|
||||
"name": "assetArchive",
|
||||
"title": "Archive asset",
|
||||
"description": "Change asset visibility to archive",
|
||||
"types": ["AssetV1"],
|
||||
"schema": {
|
||||
"properties": {
|
||||
"inverse": {
|
||||
"title": "Inverse",
|
||||
"description": "When true will unarchive any archived assets",
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "assetLock",
|
||||
"title": "Move to locked folder",
|
||||
"description": "Change visibility to locked",
|
||||
"types": ["AssetV1"]
|
||||
},
|
||||
{
|
||||
"name": "assetTimeline",
|
||||
"title": "Move to timeline",
|
||||
"description": "Change visibility to timeline",
|
||||
"types": ["AssetV1"]
|
||||
},
|
||||
{
|
||||
"name": "assetVisibility",
|
||||
"title": "Update visibility",
|
||||
"description": "Change visibility to selected option",
|
||||
"types": ["AssetV1"],
|
||||
"schema": {
|
||||
"properties": {
|
||||
"visibility": {
|
||||
"title": "Visibility",
|
||||
"description": "Asset visibility",
|
||||
"type": "string",
|
||||
"enum": ["archive", "timeline", "locked"]
|
||||
}
|
||||
},
|
||||
"required": ["visibility"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "assetFavorite",
|
||||
"title": "Favorite",
|
||||
"description": "Favorite an asset",
|
||||
"types": ["AssetV1"],
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"inverse": {
|
||||
"type": "boolean",
|
||||
"title": "Inverse",
|
||||
"description": "Unfavorite by default, set to true to favorite instead",
|
||||
"default": false
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "assetAddToAlbums",
|
||||
"title": "Add to Album(s)",
|
||||
"description": "Add asset to selected albums",
|
||||
"types": ["AssetV1"],
|
||||
"hostFunctions": true,
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"albumIds": {
|
||||
"type": "string",
|
||||
"title": "Album IDs",
|
||||
"array": true,
|
||||
"description": "Target album IDs",
|
||||
"uiHint": "albumId"
|
||||
}
|
||||
},
|
||||
"required": ["albumIds"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "noop1",
|
||||
"title": "DEV: Nested properties",
|
||||
"description": "Example configuration with nested properties",
|
||||
"types": ["AssetV1"],
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"number1": {
|
||||
"type": "number",
|
||||
"title": "Number 1",
|
||||
"description": "Basic number"
|
||||
},
|
||||
"number2": {
|
||||
"type": "number",
|
||||
"title": "Number 2",
|
||||
"array": true,
|
||||
"description": "List of numbers"
|
||||
},
|
||||
"string1": {
|
||||
"type": "string",
|
||||
"title": "String 1",
|
||||
"description": "Basic string"
|
||||
},
|
||||
"string2": {
|
||||
"type": "string",
|
||||
"title": "String 2",
|
||||
"array": true,
|
||||
"description": "List of strings"
|
||||
},
|
||||
"string3": {
|
||||
"type": "string",
|
||||
"title": "String 3",
|
||||
"enum": ["choice-1", "choice-2"],
|
||||
"description": "Select from a list"
|
||||
},
|
||||
"nested": {
|
||||
"type": "object",
|
||||
"title": "Nested",
|
||||
"description": "Nested properties for nesting",
|
||||
"properties": {
|
||||
"nested1": {
|
||||
"type": "string",
|
||||
"title": "Nested 1",
|
||||
"description": "Nested string"
|
||||
},
|
||||
"nested2": {
|
||||
"type": "number",
|
||||
"title": "Nested 2",
|
||||
"description": "Nested number"
|
||||
},
|
||||
"nested3": {
|
||||
"type": "object",
|
||||
"title": "Nested 3",
|
||||
"description": "Nested again",
|
||||
"properties": {
|
||||
"nested4": {
|
||||
"type": "boolean",
|
||||
"title": "Nested 4",
|
||||
"description": "Nested, nested boolean"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "noop2",
|
||||
"title": "DEV: Album pickers",
|
||||
"description": "Example configuration with album pickers",
|
||||
"types": ["AssetV1"],
|
||||
"schema": {
|
||||
"properties": {
|
||||
"albumId": {
|
||||
"type": "string",
|
||||
"title": "Album ID",
|
||||
"description": "Target album ID",
|
||||
"uiHint": "albumId"
|
||||
},
|
||||
"albumIds": {
|
||||
"type": "string",
|
||||
"title": "Album IDs",
|
||||
"description": "Target album IDs",
|
||||
"array": true,
|
||||
"uiHint": "albumId"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
[tasks.install]
|
||||
run = "pnpm install --frozen-lockfile"
|
||||
|
||||
[tasks.build]
|
||||
depends = ["install"]
|
||||
run = "pnpm --filter @immich/plugin-sdk --filter @immich/plugin-core build"
|
||||
Vendored
-19
@@ -1,19 +0,0 @@
|
||||
// copy from
|
||||
// import '@immich/plugin-sdk/host-functions';
|
||||
declare module 'extism:host' {
|
||||
interface user {
|
||||
albumAddAssets(ptr: PTR): I64;
|
||||
addAssetsToAlbums(ptr: PTR): I64;
|
||||
}
|
||||
}
|
||||
|
||||
declare module 'main' {
|
||||
export function assetFileFilter(): I32;
|
||||
export function assetFavorite(): I32;
|
||||
export function assetVisibility(): I32;
|
||||
export function assetArchive(): I32;
|
||||
export function assetLock(): I32;
|
||||
export function assetTimeline(): I32;
|
||||
export function assetTrash(): I32;
|
||||
export function assetAddToAlbums(): I32;
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
import { AssetStatus, AssetVisibility, WorkflowType, wrapper } from '@immich/plugin-sdk';
|
||||
|
||||
type AssetFileFilterConfig = {
|
||||
pattern: string;
|
||||
matchType?: 'contains' | 'exact' | 'regex' | 'startsWith';
|
||||
caseSensitive?: boolean;
|
||||
};
|
||||
export const assetFileFilter = () => {
|
||||
return wrapper<WorkflowType.AssetV1, AssetFileFilterConfig>(({ data, config }) => {
|
||||
const { pattern, matchType = 'contains', caseSensitive = false } = config;
|
||||
|
||||
const { asset } = data;
|
||||
|
||||
const fileName = asset.originalFileName || '';
|
||||
const searchName = caseSensitive ? fileName : fileName.toLowerCase();
|
||||
const searchPattern = caseSensitive ? pattern : pattern.toLowerCase();
|
||||
|
||||
switch (matchType) {
|
||||
case 'contains': {
|
||||
return { workflow: { continue: searchName.includes(searchPattern) } };
|
||||
}
|
||||
|
||||
case 'exact': {
|
||||
return { workflow: { continue: searchName === searchPattern } };
|
||||
}
|
||||
|
||||
case 'startsWith': {
|
||||
return { workflow: { continue: searchName.startsWith(searchPattern) } };
|
||||
}
|
||||
|
||||
case 'regex': {
|
||||
const flags = caseSensitive ? '' : 'i';
|
||||
const regex = new RegExp(searchPattern, flags);
|
||||
return { workflow: { continue: regex.test(fileName) } };
|
||||
}
|
||||
|
||||
default: {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const assetFavorite = () => {
|
||||
return wrapper<WorkflowType.AssetV1, { inverse?: boolean }>(({ config, data }) => {
|
||||
const target = config.inverse ? false : true;
|
||||
if (target !== data.asset.isFavorite) {
|
||||
return {
|
||||
changes: {
|
||||
asset: { isFavorite: target },
|
||||
},
|
||||
};
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const assetVisibility = () => {
|
||||
return wrapper<WorkflowType.AssetV1, { visibility: AssetVisibility }>(({ config }) => ({
|
||||
changes: { asset: { visibility: config.visibility } },
|
||||
}));
|
||||
};
|
||||
|
||||
export const assetArchive = () => {
|
||||
return wrapper<WorkflowType.AssetV1, { inverse?: boolean }>(({ config, data }) => {
|
||||
if (!config.inverse && data.asset.visibility !== AssetVisibility.Archive) {
|
||||
return { changes: { asset: { visibility: AssetVisibility.Archive } } };
|
||||
}
|
||||
|
||||
if (config.inverse && data.asset.visibility === AssetVisibility.Archive) {
|
||||
return { changes: { asset: { visibility: AssetVisibility.Timeline } } };
|
||||
}
|
||||
|
||||
return {};
|
||||
});
|
||||
};
|
||||
|
||||
export const assetLock = () => {
|
||||
return wrapper<WorkflowType.AssetV1, { inverse?: boolean }>(({ config, data }) => {
|
||||
if (!config.inverse && data.asset.visibility !== AssetVisibility.Locked) {
|
||||
return { changes: { asset: { visibility: AssetVisibility.Locked } } };
|
||||
}
|
||||
|
||||
if (config.inverse && data.asset.visibility === AssetVisibility.Locked) {
|
||||
return { changes: { asset: { visibility: AssetVisibility.Timeline } } };
|
||||
}
|
||||
|
||||
return {};
|
||||
});
|
||||
};
|
||||
|
||||
export const assetTrash = () => {
|
||||
return wrapper<WorkflowType.AssetV1, { inverse?: boolean }>(({ config, data }) => ({
|
||||
changes: {
|
||||
asset: config.inverse
|
||||
? { deletedAt: null, status: AssetStatus.Active }
|
||||
: { deletedAt: new Date(), status: AssetStatus.Trashed },
|
||||
},
|
||||
}));
|
||||
};
|
||||
|
||||
export const assetAddToAlbums = () => {
|
||||
return wrapper<WorkflowType.AssetV1, { albumIds: string[] }>(({ config, data, functions }) => {
|
||||
if (config.albumIds.length === 1) {
|
||||
functions.albumAddAssets(config.albumIds[0], [data.asset.id]);
|
||||
return {};
|
||||
}
|
||||
|
||||
functions.addAssetsToAlbums({ albumIds: config.albumIds, assetIds: [data.asset.id] });
|
||||
return {};
|
||||
});
|
||||
};
|
||||
@@ -1,2 +0,0 @@
|
||||
/dist
|
||||
/node_modules
|
||||
@@ -1,11 +0,0 @@
|
||||
import esbuild from 'esbuild';
|
||||
|
||||
esbuild.build({
|
||||
entryPoints: ['src/index.ts'],
|
||||
outdir: 'dist',
|
||||
bundle: true,
|
||||
sourcemap: false,
|
||||
minify: false,
|
||||
format: 'esm',
|
||||
target: ['es2020'],
|
||||
});
|
||||
@@ -1,38 +0,0 @@
|
||||
{
|
||||
"name": "@immich/plugin-sdk",
|
||||
"version": "0.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
"./host-functions": {
|
||||
"import": "./dist/host-functions.js",
|
||||
"types": "./dist/host-functions.d.ts"
|
||||
},
|
||||
".": {
|
||||
"import": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"build": "node esbuild.js && tsc --emitDeclarationOnly && tsc-alias"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "GNU Affero General Public License version 3",
|
||||
"packageManager": "pnpm@10.30.3",
|
||||
"devDependencies": {
|
||||
"@extism/js-pdk": "^1.1.1",
|
||||
"@types/node": "^24.11.0",
|
||||
"esbuild": "^0.27.3",
|
||||
"tsc-alias": "^1.8.16",
|
||||
"typescript": "^5.9.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@extism/js-pdk": "^1.1.1"
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
export enum WorkflowTrigger {
|
||||
AssetCreate = 'AssetCreate',
|
||||
PersonRecognized = 'PersonRecognized',
|
||||
}
|
||||
|
||||
export enum WorkflowType {
|
||||
AssetV1 = 'AssetV1',
|
||||
AssetPersonV1 = 'AssetPersonV1',
|
||||
}
|
||||
|
||||
export enum AssetType {
|
||||
Image = 'IMAGE',
|
||||
Video = 'VIDEO',
|
||||
Audio = 'AUDIO',
|
||||
Other = 'OTHER',
|
||||
}
|
||||
|
||||
export enum AssetStatus {
|
||||
Active = 'active',
|
||||
Trashed = 'trashed',
|
||||
Deleted = 'deleted',
|
||||
}
|
||||
|
||||
export enum AssetVisibility {
|
||||
Archive = 'archive',
|
||||
Timeline = 'timeline',
|
||||
|
||||
/**
|
||||
* Video part of the LivePhotos and MotionPhotos
|
||||
*/
|
||||
Hidden = 'hidden',
|
||||
Locked = 'locked',
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
declare module 'extism:host' {
|
||||
interface user {
|
||||
albumAddAssets(ptr: PTR): I64;
|
||||
addAssetsToAlbums(ptr: PTR): I64;
|
||||
}
|
||||
}
|
||||
|
||||
const host = Host.getFunctions();
|
||||
type HostFunctionName = keyof typeof host;
|
||||
type HostFunctionSuccessResult<T> = { success: true; response: T };
|
||||
type HostFunctionErrorResult = {
|
||||
success: false;
|
||||
status: number;
|
||||
message: string;
|
||||
};
|
||||
type HostFunctionResult<T> =
|
||||
| HostFunctionSuccessResult<T>
|
||||
| HostFunctionErrorResult;
|
||||
|
||||
const call = <T, R>(name: HostFunctionName, authToken: string, args: T) => {
|
||||
const pointer1 = Memory.fromString(JSON.stringify({ authToken, args }));
|
||||
const fn = host[name];
|
||||
const handler = Memory.find(fn(pointer1.offset));
|
||||
|
||||
try {
|
||||
const result = JSON.parse(handler.readString()) as HostFunctionResult<R>;
|
||||
|
||||
if (result.success) {
|
||||
return result.response;
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
`Failed to call host function "${String(name)}", received ${result.status} - ${JSON.stringify(result.message)}`,
|
||||
);
|
||||
} finally {
|
||||
handler.free();
|
||||
pointer1.free();
|
||||
}
|
||||
};
|
||||
|
||||
type AlbumsToAssets = {
|
||||
assetIds: string[];
|
||||
albumIds: string[];
|
||||
};
|
||||
|
||||
export const hostFunctions = (authToken: string) => ({
|
||||
albumAddAssets: (albumId: string, assetIds: string[]) =>
|
||||
call('albumAddAssets', authToken, [albumId, { ids: assetIds }]),
|
||||
addAssetsToAlbums: ({ assetIds, albumIds }: AlbumsToAssets) =>
|
||||
call('addAssetsToAlbums', authToken, [{ albumIds, assetIds }]),
|
||||
});
|
||||
@@ -1,4 +0,0 @@
|
||||
export * from 'src/enum.js';
|
||||
export * from 'src/host-functions.js';
|
||||
export * from 'src/sdk.js';
|
||||
export * from 'src/types.js';
|
||||
@@ -1,43 +0,0 @@
|
||||
import type { WorkflowType } from 'src/enum.js';
|
||||
import { hostFunctions } from 'src/host-functions.js';
|
||||
import type {
|
||||
ConfigValue,
|
||||
WorkflowEventPayload,
|
||||
WorkflowResponse,
|
||||
} from 'src/types.js';
|
||||
|
||||
export const wrapper = <
|
||||
T extends WorkflowType = WorkflowType,
|
||||
TConfig extends ConfigValue = ConfigValue,
|
||||
>(
|
||||
fn: (
|
||||
payload: WorkflowEventPayload<T, TConfig> & {
|
||||
functions: ReturnType<typeof hostFunctions>;
|
||||
},
|
||||
) => WorkflowResponse<T> | undefined,
|
||||
) => {
|
||||
const input = Host.inputString();
|
||||
|
||||
try {
|
||||
const event = JSON.parse(input) as WorkflowEventPayload<T, TConfig>;
|
||||
// const debug = event.workflow.debug ?? false;
|
||||
|
||||
console.debug(
|
||||
`Inputs: trigger=${event.trigger}, event=${event.type}, config=${JSON.stringify(event.config)}`,
|
||||
);
|
||||
|
||||
const response =
|
||||
fn({ ...event, functions: hostFunctions(event.workflow.authToken) }) ??
|
||||
{};
|
||||
|
||||
console.debug(
|
||||
`Outputs: workflow=${JSON.stringify(response.workflow)}, changes=${JSON.stringify(response.changes)}, data=${JSON.stringify(response.data)}`,
|
||||
);
|
||||
|
||||
const output = JSON.stringify(response);
|
||||
Host.outputString(output);
|
||||
} catch (error: Error | any) {
|
||||
console.error(`Unhandled plugin exception: ${error.message || error}`);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
@@ -1,129 +0,0 @@
|
||||
import type {
|
||||
AssetStatus,
|
||||
AssetType,
|
||||
AssetVisibility,
|
||||
WorkflowTrigger,
|
||||
WorkflowType,
|
||||
} from 'src/enum.js';
|
||||
|
||||
type DeepPartial<T> = T extends Date
|
||||
? T
|
||||
: T extends Record<string, unknown>
|
||||
? { [K in keyof T]?: DeepPartial<T[K]> }
|
||||
: T extends Array<infer R>
|
||||
? DeepPartial<R>[]
|
||||
: T;
|
||||
|
||||
export type WorkflowEventMap = {
|
||||
[WorkflowType.AssetV1]: AssetV1;
|
||||
[WorkflowType.AssetPersonV1]: AssetPersonV1;
|
||||
};
|
||||
|
||||
export type WorkflowEventData<T extends WorkflowType> = WorkflowEventMap[T];
|
||||
|
||||
export type WorkflowEventPayload<
|
||||
T extends WorkflowType = WorkflowType,
|
||||
TConfig = WorkflowStepConfig,
|
||||
> = {
|
||||
trigger: WorkflowTrigger;
|
||||
type: T;
|
||||
data: WorkflowEventData<T>;
|
||||
config: TConfig;
|
||||
workflow: {
|
||||
id: string;
|
||||
authToken: string;
|
||||
stepId: string;
|
||||
debug?: boolean;
|
||||
};
|
||||
};
|
||||
|
||||
export type WorkflowChanges<T extends WorkflowType = WorkflowType> =
|
||||
DeepPartial<WorkflowEventData<T>>;
|
||||
|
||||
export type WorkflowResponse<T extends WorkflowType = WorkflowType> = {
|
||||
workflow?: {
|
||||
/** stop the workflow */
|
||||
continue?: boolean;
|
||||
};
|
||||
changes?: WorkflowChanges<T>;
|
||||
/** data to be passed to the next workflow step */
|
||||
data?: Record<string, unknown>;
|
||||
};
|
||||
|
||||
export type WorkflowStepConfig = {
|
||||
[key: string]: ConfigValue;
|
||||
};
|
||||
|
||||
export type ConfigValue =
|
||||
| string
|
||||
| number
|
||||
| boolean
|
||||
| null
|
||||
| ConfigValue[]
|
||||
| { [key: string]: ConfigValue };
|
||||
|
||||
export type AssetV1 = {
|
||||
asset: {
|
||||
id: string;
|
||||
ownerId: string;
|
||||
type: AssetType;
|
||||
originalPath: string;
|
||||
fileCreatedAt: Date;
|
||||
fileModifiedAt: Date;
|
||||
isFavorite: boolean;
|
||||
checksum: Buffer; // sha1 checksum
|
||||
livePhotoVideoId: string | null;
|
||||
updatedAt: Date;
|
||||
createdAt: Date;
|
||||
originalFileName: string;
|
||||
isOffline: boolean;
|
||||
libraryId: string | null;
|
||||
isExternal: boolean;
|
||||
deletedAt: Date | null;
|
||||
localDateTime: Date;
|
||||
stackId: string | null;
|
||||
duplicateId: string | null;
|
||||
status: AssetStatus;
|
||||
visibility: AssetVisibility;
|
||||
isEdited: boolean;
|
||||
exifInfo: {
|
||||
make: string | null;
|
||||
model: string | null;
|
||||
exifImageWidth: number | null;
|
||||
exifImageHeight: number | null;
|
||||
fileSizeInByte: number | null;
|
||||
orientation: string | null;
|
||||
dateTimeOriginal: Date | null;
|
||||
modifyDate: Date | null;
|
||||
lensModel: string | null;
|
||||
fNumber: number | null;
|
||||
focalLength: number | null;
|
||||
iso: number | null;
|
||||
latitude: number | null;
|
||||
longitude: number | null;
|
||||
city: string | null;
|
||||
state: string | null;
|
||||
country: string | null;
|
||||
description: string | null;
|
||||
fps: number | null;
|
||||
exposureTime: string | null;
|
||||
livePhotoCID: string | null;
|
||||
timeZone: string | null;
|
||||
projectionType: string | null;
|
||||
profileDescription: string | null;
|
||||
colorspace: string | null;
|
||||
bitsPerSample: number | null;
|
||||
autoStackId: string | null;
|
||||
rating: number | null;
|
||||
tags: string[] | null;
|
||||
updatedAt: Date | null;
|
||||
} | null;
|
||||
};
|
||||
};
|
||||
|
||||
export type AssetPersonV1 = AssetV1 & {
|
||||
person: {
|
||||
id: string;
|
||||
name: string;
|
||||
};
|
||||
};
|
||||
@@ -1,26 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"declaration": true,
|
||||
"emitDeclarationOnly": true,
|
||||
"esModuleInterop": true,
|
||||
"exactOptionalPropertyTypes": true,
|
||||
"isolatedModules": true,
|
||||
"lib": ["esnext"],
|
||||
"module": "nodenext",
|
||||
"moduleDetection": "force",
|
||||
"noUncheckedIndexedAccess": true,
|
||||
"noUncheckedSideEffectImports": true,
|
||||
"outDir": "./dist",
|
||||
"paths": {
|
||||
"src/*": ["./src/*"]
|
||||
},
|
||||
"removeComments": true,
|
||||
"rootDir": "./src",
|
||||
"skipLibCheck": true,
|
||||
"sourceMap": false,
|
||||
"strict": true,
|
||||
"target": "esnext",
|
||||
"types": ["node", "@extism/js-pdk"],
|
||||
"verbatimModuleSyntax": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
node_modules
|
||||
dist
|
||||
@@ -0,0 +1,26 @@
|
||||
Copyright 2024, The Extism Authors.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -0,0 +1,12 @@
|
||||
const esbuild = require('esbuild');
|
||||
|
||||
esbuild
|
||||
.build({
|
||||
entryPoints: ['src/index.ts'],
|
||||
outdir: 'dist',
|
||||
bundle: true,
|
||||
sourcemap: true,
|
||||
minify: false, // might want to use true for production build
|
||||
format: 'cjs', // needs to be CJS for now
|
||||
target: ['es2020'] // don't go over es2020 because quickjs doesn't support it
|
||||
})
|
||||
@@ -0,0 +1,159 @@
|
||||
{
|
||||
"name": "immich-core",
|
||||
"version": "2.0.1",
|
||||
"title": "Immich Core",
|
||||
"description": "Core workflow capabilities for Immich",
|
||||
"author": "Immich Team",
|
||||
"wasm": {
|
||||
"path": "dist/plugin.wasm"
|
||||
},
|
||||
"filters": [
|
||||
{
|
||||
"methodName": "filterFileName",
|
||||
"title": "Filter by filename",
|
||||
"description": "Filter assets by filename pattern using text matching or regular expressions",
|
||||
"supportedContexts": [
|
||||
"asset"
|
||||
],
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"title": "Filename pattern",
|
||||
"description": "Text or regex pattern to match against filename"
|
||||
},
|
||||
"matchType": {
|
||||
"type": "string",
|
||||
"title": "Match type",
|
||||
"enum": [
|
||||
"contains",
|
||||
"regex",
|
||||
"exact"
|
||||
],
|
||||
"default": "contains",
|
||||
"description": "Type of pattern matching to perform"
|
||||
},
|
||||
"caseSensitive": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Whether matching should be case-sensitive"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"pattern"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"methodName": "filterFileType",
|
||||
"title": "Filter by file type",
|
||||
"description": "Filter assets by file type",
|
||||
"supportedContexts": [
|
||||
"asset"
|
||||
],
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"fileTypes": {
|
||||
"type": "array",
|
||||
"title": "File types",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"image",
|
||||
"video"
|
||||
]
|
||||
},
|
||||
"description": "Allowed file types"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"fileTypes"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"methodName": "filterPerson",
|
||||
"title": "Filter by person",
|
||||
"description": "Filter by detected person",
|
||||
"supportedContexts": [
|
||||
"person"
|
||||
],
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"personIds": {
|
||||
"type": "array",
|
||||
"title": "Person IDs",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "List of person to match",
|
||||
"subType": "people-picker"
|
||||
},
|
||||
"matchAny": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Match any name (true) or require all names (false)"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"personIds"
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"methodName": "actionArchive",
|
||||
"title": "Archive",
|
||||
"description": "Move the asset to archive",
|
||||
"supportedContexts": [
|
||||
"asset"
|
||||
],
|
||||
"schema": {}
|
||||
},
|
||||
{
|
||||
"methodName": "actionFavorite",
|
||||
"title": "Favorite",
|
||||
"description": "Mark the asset as favorite or unfavorite",
|
||||
"supportedContexts": [
|
||||
"asset"
|
||||
],
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"favorite": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Set favorite (true) or unfavorite (false)"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"methodName": "actionAddToAlbum",
|
||||
"title": "Add to Album",
|
||||
"description": "Add the item to a specified album",
|
||||
"supportedContexts": [
|
||||
"asset",
|
||||
"person"
|
||||
],
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"albumId": {
|
||||
"type": "string",
|
||||
"title": "Album ID",
|
||||
"description": "Target album ID",
|
||||
"subType": "album-picker"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"albumId"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
[tools]
|
||||
"github:extism/cli" = "1.6.3"
|
||||
"github:webassembly/binaryen" = "version_124"
|
||||
"github:extism/js-pdk" = "1.6.0"
|
||||
|
||||
[tasks.install]
|
||||
run = "pnpm install --frozen-lockfile"
|
||||
|
||||
[tasks.build]
|
||||
depends = ["install"]
|
||||
run = "pnpm run build"
|
||||
Generated
+533
@@ -0,0 +1,533 @@
|
||||
{
|
||||
"name": "plugins",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "plugins",
|
||||
"version": "1.0.0",
|
||||
"license": "AGPL-3.0",
|
||||
"devDependencies": {
|
||||
"@extism/js-pdk": "^1.0.1",
|
||||
"esbuild": "^0.28.0",
|
||||
"typescript": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/aix-ppc64": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.0.tgz",
|
||||
"integrity": "sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"aix"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-arm": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.0.tgz",
|
||||
"integrity": "sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-arm64": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.0.tgz",
|
||||
"integrity": "sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-x64": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.0.tgz",
|
||||
"integrity": "sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/darwin-arm64": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.0.tgz",
|
||||
"integrity": "sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/darwin-x64": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.0.tgz",
|
||||
"integrity": "sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/freebsd-arm64": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.0.tgz",
|
||||
"integrity": "sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/freebsd-x64": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.0.tgz",
|
||||
"integrity": "sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-arm": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.0.tgz",
|
||||
"integrity": "sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-arm64": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.0.tgz",
|
||||
"integrity": "sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-ia32": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.0.tgz",
|
||||
"integrity": "sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-loong64": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.0.tgz",
|
||||
"integrity": "sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg==",
|
||||
"cpu": [
|
||||
"loong64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-mips64el": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.0.tgz",
|
||||
"integrity": "sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w==",
|
||||
"cpu": [
|
||||
"mips64el"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-ppc64": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.0.tgz",
|
||||
"integrity": "sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-riscv64": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.0.tgz",
|
||||
"integrity": "sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-s390x": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.0.tgz",
|
||||
"integrity": "sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-x64": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.0.tgz",
|
||||
"integrity": "sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/netbsd-arm64": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.0.tgz",
|
||||
"integrity": "sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"netbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/netbsd-x64": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.0.tgz",
|
||||
"integrity": "sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"netbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/openbsd-arm64": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.0.tgz",
|
||||
"integrity": "sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/openbsd-x64": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.0.tgz",
|
||||
"integrity": "sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/openharmony-arm64": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.0.tgz",
|
||||
"integrity": "sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openharmony"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/sunos-x64": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.0.tgz",
|
||||
"integrity": "sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"sunos"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-arm64": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.0.tgz",
|
||||
"integrity": "sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-ia32": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.0.tgz",
|
||||
"integrity": "sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-x64": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.0.tgz",
|
||||
"integrity": "sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@extism/js-pdk": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@extism/js-pdk/-/js-pdk-1.1.1.tgz",
|
||||
"integrity": "sha512-VZLn/dX0ttA1uKk2PZeR/FL3N+nA1S5Vc7E5gdjkR60LuUIwCZT9cYON245V4HowHlBA7YOegh0TLjkx+wNbrA==",
|
||||
"dev": true,
|
||||
"license": "BSD-Clause-3",
|
||||
"dependencies": {
|
||||
"urlpattern-polyfill": "^8.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.28.0",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.0.tgz",
|
||||
"integrity": "sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"esbuild": "bin/esbuild"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@esbuild/aix-ppc64": "0.28.0",
|
||||
"@esbuild/android-arm": "0.28.0",
|
||||
"@esbuild/android-arm64": "0.28.0",
|
||||
"@esbuild/android-x64": "0.28.0",
|
||||
"@esbuild/darwin-arm64": "0.28.0",
|
||||
"@esbuild/darwin-x64": "0.28.0",
|
||||
"@esbuild/freebsd-arm64": "0.28.0",
|
||||
"@esbuild/freebsd-x64": "0.28.0",
|
||||
"@esbuild/linux-arm": "0.28.0",
|
||||
"@esbuild/linux-arm64": "0.28.0",
|
||||
"@esbuild/linux-ia32": "0.28.0",
|
||||
"@esbuild/linux-loong64": "0.28.0",
|
||||
"@esbuild/linux-mips64el": "0.28.0",
|
||||
"@esbuild/linux-ppc64": "0.28.0",
|
||||
"@esbuild/linux-riscv64": "0.28.0",
|
||||
"@esbuild/linux-s390x": "0.28.0",
|
||||
"@esbuild/linux-x64": "0.28.0",
|
||||
"@esbuild/netbsd-arm64": "0.28.0",
|
||||
"@esbuild/netbsd-x64": "0.28.0",
|
||||
"@esbuild/openbsd-arm64": "0.28.0",
|
||||
"@esbuild/openbsd-x64": "0.28.0",
|
||||
"@esbuild/openharmony-arm64": "0.28.0",
|
||||
"@esbuild/sunos-x64": "0.28.0",
|
||||
"@esbuild/win32-arm64": "0.28.0",
|
||||
"@esbuild/win32-ia32": "0.28.0",
|
||||
"@esbuild/win32-x64": "0.28.0"
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "6.0.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz",
|
||||
"integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/urlpattern-polyfill": {
|
||||
"version": "8.0.2",
|
||||
"resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-8.0.2.tgz",
|
||||
"integrity": "sha512-Qp95D4TPJl1kC9SKigDcqgyM2VDVO4RiJc2d4qe5GrYm+zbIQCWWKAFaJNQ4BhdFeDGwBmAxqJBwWSJDb9T3BQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "@immich/plugin-core",
|
||||
"name": "plugins",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "src/index.ts",
|
||||
@@ -13,7 +13,6 @@
|
||||
"license": "AGPL-3.0",
|
||||
"devDependencies": {
|
||||
"@extism/js-pdk": "^1.0.1",
|
||||
"@immich/plugin-sdk": "workspace:*",
|
||||
"esbuild": "^0.28.0",
|
||||
"typescript": "^6.0.0"
|
||||
}
|
||||
Vendored
+12
@@ -0,0 +1,12 @@
|
||||
declare module 'main' {
|
||||
export function filterFileName(): I32;
|
||||
export function actionAddToAlbum(): I32;
|
||||
export function actionArchive(): I32;
|
||||
}
|
||||
|
||||
declare module 'extism:host' {
|
||||
interface user {
|
||||
updateAsset(ptr: PTR): I32;
|
||||
addAssetToAlbum(ptr: PTR): I32;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
const { updateAsset, addAssetToAlbum } = Host.getFunctions();
|
||||
|
||||
function parseInput() {
|
||||
return JSON.parse(Host.inputString());
|
||||
}
|
||||
|
||||
function returnOutput(output: any) {
|
||||
Host.outputString(JSON.stringify(output));
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function filterFileName() {
|
||||
const input = parseInput();
|
||||
const { data, config } = input;
|
||||
const { pattern, matchType = 'contains', caseSensitive = false } = config;
|
||||
|
||||
const fileName = data.asset.originalFileName || data.asset.fileName || '';
|
||||
const searchName = caseSensitive ? fileName : fileName.toLowerCase();
|
||||
const searchPattern = caseSensitive ? pattern : pattern.toLowerCase();
|
||||
|
||||
let passed = false;
|
||||
|
||||
if (matchType === 'exact') {
|
||||
passed = searchName === searchPattern;
|
||||
} else if (matchType === 'regex') {
|
||||
const flags = caseSensitive ? '' : 'i';
|
||||
const regex = new RegExp(searchPattern, flags);
|
||||
passed = regex.test(fileName);
|
||||
} else {
|
||||
// contains
|
||||
passed = searchName.includes(searchPattern);
|
||||
}
|
||||
|
||||
return returnOutput({ passed });
|
||||
}
|
||||
|
||||
export function actionAddToAlbum() {
|
||||
const input = parseInput();
|
||||
const { authToken, config, data } = input;
|
||||
const { albumId } = config;
|
||||
|
||||
const ptr = Memory.fromString(
|
||||
JSON.stringify({
|
||||
authToken,
|
||||
assetId: data.asset.id,
|
||||
albumId: albumId,
|
||||
}),
|
||||
);
|
||||
|
||||
addAssetToAlbum(ptr.offset);
|
||||
ptr.free();
|
||||
|
||||
return returnOutput({ success: true });
|
||||
}
|
||||
|
||||
export function actionArchive() {
|
||||
const input = parseInput();
|
||||
const { authToken, data } = input;
|
||||
const ptr = Memory.fromString(
|
||||
JSON.stringify({
|
||||
authToken,
|
||||
id: data.asset.id,
|
||||
visibility: 'archive',
|
||||
}),
|
||||
);
|
||||
|
||||
updateAsset(ptr.offset);
|
||||
ptr.free();
|
||||
|
||||
return returnOutput({ success: true });
|
||||
}
|
||||
@@ -1,24 +1,20 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"allowJs": true, // Allow JavaScript files to be compiled
|
||||
"declaration": true,
|
||||
"emitDeclarationOnly": true,
|
||||
"esModuleInterop": true, // Enables compatibility with Babel-style module imports
|
||||
"lib": ["es2020"], // Specify a list of library files to be included in the compilation
|
||||
"module": "nodenext", // Specify module code generation
|
||||
"moduleResolution": "nodenext",
|
||||
"noEmit": true, // Do not emit outputs (no .js or .d.ts files)
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src",
|
||||
"skipLibCheck": true, // Skip type checking of declaration files
|
||||
"strict": true, // Enable all strict type-checking options
|
||||
"target": "es2020", // Specify ECMAScript target version
|
||||
"types": ["./src/index.d.ts", "./node_modules/@extism/js-pdk"] // Specify a list of type definition files to be included in the compilation
|
||||
"module": "commonjs", // Specify module code generation
|
||||
"lib": ["es2020"], // Specify a list of library files to be included in the compilation
|
||||
"types": ["./src/index.d.ts", "./node_modules/@extism/js-pdk"], // Specify a list of type definition files to be included in the compilation
|
||||
"strict": true, // Enable all strict type-checking options
|
||||
"esModuleInterop": true, // Enables compatibility with Babel-style module imports
|
||||
"skipLibCheck": true, // Skip type checking of declaration files
|
||||
"allowJs": true, // Allow JavaScript files to be compiled
|
||||
"rootDir": "./src",
|
||||
"noEmit": true // Do not emit outputs (no .js or .d.ts files)
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules" // Exclude the node_modules directory
|
||||
],
|
||||
"include": [
|
||||
"src/**/*.ts" // Include all TypeScript files in src directory
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules" // Exclude the node_modules directory
|
||||
]
|
||||
}
|
||||
+141
-150
@@ -1478,33 +1478,72 @@ export type PersonStatisticsResponseDto = {
|
||||
/** Number of assets */
|
||||
assets: number;
|
||||
};
|
||||
export type PluginMethodResponseDto = {
|
||||
/** Description */
|
||||
export type PluginJsonSchemaProperty = {
|
||||
additionalProperties?: boolean | PluginJsonSchemaProperty;
|
||||
"default"?: any;
|
||||
description?: string;
|
||||
"enum"?: string[];
|
||||
items?: PluginJsonSchemaProperty;
|
||||
properties?: {
|
||||
[key: string]: PluginJsonSchemaProperty;
|
||||
};
|
||||
required?: string[];
|
||||
"type"?: PluginJsonSchemaType;
|
||||
};
|
||||
export type PluginJsonSchema = {
|
||||
additionalProperties?: boolean;
|
||||
description?: string;
|
||||
properties?: {
|
||||
[key: string]: PluginJsonSchemaProperty;
|
||||
};
|
||||
required?: string[];
|
||||
"type"?: PluginJsonSchemaType;
|
||||
};
|
||||
export type PluginActionResponseDto = {
|
||||
/** Action description */
|
||||
description: string;
|
||||
hostFunctions: boolean;
|
||||
/** Key */
|
||||
key: string;
|
||||
/** Name */
|
||||
name: string;
|
||||
schema?: {};
|
||||
/** Title */
|
||||
/** Action ID */
|
||||
id: string;
|
||||
/** Method name */
|
||||
methodName: string;
|
||||
/** Plugin ID */
|
||||
pluginId: string;
|
||||
/** Action schema */
|
||||
schema: (PluginJsonSchema) | null;
|
||||
/** Supported contexts */
|
||||
supportedContexts: PluginContextType[];
|
||||
/** Action title */
|
||||
title: string;
|
||||
};
|
||||
export type PluginFilterResponseDto = {
|
||||
/** Filter description */
|
||||
description: string;
|
||||
/** Filter ID */
|
||||
id: string;
|
||||
/** Method name */
|
||||
methodName: string;
|
||||
/** Plugin ID */
|
||||
pluginId: string;
|
||||
/** Filter schema */
|
||||
schema: (PluginJsonSchema) | null;
|
||||
/** Supported contexts */
|
||||
supportedContexts: PluginContextType[];
|
||||
/** Filter title */
|
||||
title: string;
|
||||
/** Workflow types */
|
||||
types: WorkflowType[];
|
||||
/** Ui hints */
|
||||
uiHints: string[];
|
||||
};
|
||||
export type PluginResponseDto = {
|
||||
/** Plugin actions */
|
||||
actions: PluginActionResponseDto[];
|
||||
/** Plugin author */
|
||||
author: string;
|
||||
/** Creation date */
|
||||
createdAt: string;
|
||||
/** Plugin description */
|
||||
description: string;
|
||||
/** Plugin filters */
|
||||
filters: PluginFilterResponseDto[];
|
||||
/** Plugin ID */
|
||||
id: string;
|
||||
/** Plugin methods */
|
||||
methods: PluginMethodResponseDto[];
|
||||
/** Plugin name */
|
||||
name: string;
|
||||
/** Plugin title */
|
||||
@@ -1514,6 +1553,10 @@ export type PluginResponseDto = {
|
||||
/** Plugin version */
|
||||
version: string;
|
||||
};
|
||||
export type PluginTriggerResponseDto = {
|
||||
contextType: PluginContextType;
|
||||
"type": PluginTriggerType;
|
||||
};
|
||||
export type QueueResponseDto = {
|
||||
/** Whether the queue is paused */
|
||||
isPaused: boolean;
|
||||
@@ -2667,81 +2710,89 @@ export type CreateProfileImageResponseDto = {
|
||||
/** User ID */
|
||||
userId: string;
|
||||
};
|
||||
export type WorkflowStepDto = {
|
||||
/** Step configuration */
|
||||
config: {
|
||||
[key: string]: any;
|
||||
} | null;
|
||||
/** Step is enabled */
|
||||
enabled?: boolean;
|
||||
/** Step plugin method */
|
||||
method: string;
|
||||
export type PluginConfigValue = any;
|
||||
export type WorkflowActionConfig = {
|
||||
[key: string]: PluginConfigValue;
|
||||
};
|
||||
export type WorkflowActionResponseDto = {
|
||||
actionConfig: (WorkflowActionConfig) | null;
|
||||
/** Action ID */
|
||||
id: string;
|
||||
/** Action order */
|
||||
order: number;
|
||||
/** Plugin action ID */
|
||||
pluginActionId: string;
|
||||
/** Workflow ID */
|
||||
workflowId: string;
|
||||
};
|
||||
export type WorkflowFilterConfig = {
|
||||
[key: string]: PluginConfigValue;
|
||||
};
|
||||
export type WorkflowFilterResponseDto = {
|
||||
filterConfig: (WorkflowFilterConfig) | null;
|
||||
/** Filter ID */
|
||||
id: string;
|
||||
/** Filter order */
|
||||
order: number;
|
||||
/** Plugin filter ID */
|
||||
pluginFilterId: string;
|
||||
/** Workflow ID */
|
||||
workflowId: string;
|
||||
};
|
||||
export type WorkflowResponseDto = {
|
||||
/** Workflow actions */
|
||||
actions: WorkflowActionResponseDto[];
|
||||
/** Creation date */
|
||||
createdAt: string;
|
||||
/** Workflow description */
|
||||
description: string | null;
|
||||
description: string;
|
||||
/** Workflow enabled */
|
||||
enabled: boolean;
|
||||
/** Workflow filters */
|
||||
filters: WorkflowFilterResponseDto[];
|
||||
/** Workflow ID */
|
||||
id: string;
|
||||
/** Workflow name */
|
||||
name: string | null;
|
||||
/** Workflow steps */
|
||||
steps: WorkflowStepDto[];
|
||||
/** Workflow trigger type */
|
||||
trigger: WorkflowTrigger;
|
||||
/** Update date */
|
||||
updatedAt: string;
|
||||
/** Owner user ID */
|
||||
ownerId: string;
|
||||
triggerType: PluginTriggerType;
|
||||
};
|
||||
export type WorkflowActionItemDto = {
|
||||
actionConfig?: WorkflowActionConfig;
|
||||
/** Plugin action ID */
|
||||
pluginActionId: string;
|
||||
};
|
||||
export type WorkflowFilterItemDto = {
|
||||
filterConfig?: WorkflowFilterConfig;
|
||||
/** Plugin filter ID */
|
||||
pluginFilterId: string;
|
||||
};
|
||||
export type WorkflowCreateDto = {
|
||||
/** Workflow actions */
|
||||
actions: WorkflowActionItemDto[];
|
||||
/** Workflow description */
|
||||
description?: string | null;
|
||||
description?: string;
|
||||
/** Workflow enabled */
|
||||
enabled?: boolean;
|
||||
/** Workflow filters */
|
||||
filters: WorkflowFilterItemDto[];
|
||||
/** Workflow name */
|
||||
name?: string | null;
|
||||
steps?: WorkflowStepDto[];
|
||||
/** Workflow trigger type */
|
||||
trigger: WorkflowTrigger;
|
||||
};
|
||||
export type WorkflowTriggerResponseDto = {
|
||||
/** Trigger type */
|
||||
trigger: WorkflowTrigger;
|
||||
/** Workflow types */
|
||||
types: WorkflowType[];
|
||||
name: string;
|
||||
triggerType: PluginTriggerType;
|
||||
};
|
||||
export type WorkflowUpdateDto = {
|
||||
/** Workflow actions */
|
||||
actions?: WorkflowActionItemDto[];
|
||||
/** Workflow description */
|
||||
description?: string | null;
|
||||
description?: string;
|
||||
/** Workflow enabled */
|
||||
enabled?: boolean;
|
||||
/** Workflow filters */
|
||||
filters?: WorkflowFilterItemDto[];
|
||||
/** Workflow name */
|
||||
name?: string | null;
|
||||
steps?: WorkflowStepDto[];
|
||||
/** Workflow trigger type */
|
||||
trigger?: WorkflowTrigger;
|
||||
};
|
||||
export type WorkflowShareStepDto = {
|
||||
/** Step configuration */
|
||||
config: {
|
||||
[key: string]: any;
|
||||
} | null;
|
||||
/** Step is enabled */
|
||||
enabled?: boolean;
|
||||
/** Step plugin method */
|
||||
method: string;
|
||||
};
|
||||
export type WorkflowShareResponseDto = {
|
||||
/** Workflow description */
|
||||
description: string | null;
|
||||
/** Workflow name */
|
||||
name: string | null;
|
||||
/** Workflow steps */
|
||||
steps: WorkflowShareStepDto[];
|
||||
/** Workflow trigger type */
|
||||
trigger: WorkflowTrigger;
|
||||
name?: string;
|
||||
triggerType?: PluginTriggerType;
|
||||
};
|
||||
export type LicenseResponseDto = UserLicense;
|
||||
export type SyncAckV1 = {};
|
||||
@@ -5189,56 +5240,22 @@ export function getPersonThumbnail({ id }: {
|
||||
/**
|
||||
* List all plugins
|
||||
*/
|
||||
export function searchPlugins({ description, enabled, id, name, title, version }: {
|
||||
description?: string;
|
||||
enabled?: boolean;
|
||||
id?: string;
|
||||
name?: string;
|
||||
title?: string;
|
||||
version?: string;
|
||||
}, opts?: Oazapfts.RequestOpts) {
|
||||
export function getPlugins(opts?: Oazapfts.RequestOpts) {
|
||||
return oazapfts.ok(oazapfts.fetchJson<{
|
||||
status: 200;
|
||||
data: PluginResponseDto[];
|
||||
}>(`/plugins${QS.query(QS.explode({
|
||||
description,
|
||||
enabled,
|
||||
id,
|
||||
name,
|
||||
title,
|
||||
version
|
||||
}))}`, {
|
||||
}>("/plugins", {
|
||||
...opts
|
||||
}));
|
||||
}
|
||||
/**
|
||||
* Retrieve plugin methods
|
||||
* List all plugin triggers
|
||||
*/
|
||||
export function searchPluginMethods({ description, enabled, id, name, pluginName, pluginVersion, title, trigger, $type }: {
|
||||
description?: string;
|
||||
enabled?: boolean;
|
||||
id?: string;
|
||||
name?: string;
|
||||
pluginName?: string;
|
||||
pluginVersion?: string;
|
||||
title?: string;
|
||||
trigger?: WorkflowTrigger;
|
||||
$type?: WorkflowType;
|
||||
}, opts?: Oazapfts.RequestOpts) {
|
||||
export function getPluginTriggers(opts?: Oazapfts.RequestOpts) {
|
||||
return oazapfts.ok(oazapfts.fetchJson<{
|
||||
status: 200;
|
||||
data: PluginMethodResponseDto[];
|
||||
}>(`/plugins/methods${QS.query(QS.explode({
|
||||
description,
|
||||
enabled,
|
||||
id,
|
||||
name,
|
||||
pluginName,
|
||||
pluginVersion,
|
||||
title,
|
||||
trigger,
|
||||
"type": $type
|
||||
}))}`, {
|
||||
data: PluginTriggerResponseDto[];
|
||||
}>("/plugins/triggers", {
|
||||
...opts
|
||||
}));
|
||||
}
|
||||
@@ -6614,23 +6631,11 @@ export function getUniqueOriginalPaths(opts?: Oazapfts.RequestOpts) {
|
||||
/**
|
||||
* List all workflows
|
||||
*/
|
||||
export function searchWorkflows({ description, enabled, id, name, trigger }: {
|
||||
description?: string;
|
||||
enabled?: boolean;
|
||||
id?: string;
|
||||
name?: string;
|
||||
trigger?: WorkflowTrigger;
|
||||
}, opts?: Oazapfts.RequestOpts) {
|
||||
export function getWorkflows(opts?: Oazapfts.RequestOpts) {
|
||||
return oazapfts.ok(oazapfts.fetchJson<{
|
||||
status: 200;
|
||||
data: WorkflowResponseDto[];
|
||||
}>(`/workflows${QS.query(QS.explode({
|
||||
description,
|
||||
enabled,
|
||||
id,
|
||||
name,
|
||||
trigger
|
||||
}))}`, {
|
||||
}>("/workflows", {
|
||||
...opts
|
||||
}));
|
||||
}
|
||||
@@ -6649,17 +6654,6 @@ export function createWorkflow({ workflowCreateDto }: {
|
||||
body: workflowCreateDto
|
||||
})));
|
||||
}
|
||||
/**
|
||||
* List all workflow triggers
|
||||
*/
|
||||
export function getWorkflowTriggers(opts?: Oazapfts.RequestOpts) {
|
||||
return oazapfts.ok(oazapfts.fetchJson<{
|
||||
status: 200;
|
||||
data: WorkflowTriggerResponseDto[];
|
||||
}>("/workflows/triggers", {
|
||||
...opts
|
||||
}));
|
||||
}
|
||||
/**
|
||||
* Delete a workflow
|
||||
*/
|
||||
@@ -6700,19 +6694,6 @@ export function updateWorkflow({ id, workflowUpdateDto }: {
|
||||
body: workflowUpdateDto
|
||||
})));
|
||||
}
|
||||
/**
|
||||
* Retrieve a workflow
|
||||
*/
|
||||
export function getWorkflowForShare({ id }: {
|
||||
id: string;
|
||||
}, opts?: Oazapfts.RequestOpts) {
|
||||
return oazapfts.ok(oazapfts.fetchJson<{
|
||||
status: 200;
|
||||
data: WorkflowShareResponseDto;
|
||||
}>(`/workflows/${encodeURIComponent(id)}/share`, {
|
||||
...opts
|
||||
}));
|
||||
}
|
||||
export enum ReactionLevel {
|
||||
Album = "album",
|
||||
Asset = "asset"
|
||||
@@ -7036,11 +7017,21 @@ export enum PartnerDirection {
|
||||
SharedBy = "shared-by",
|
||||
SharedWith = "shared-with"
|
||||
}
|
||||
export enum WorkflowType {
|
||||
AssetV1 = "AssetV1",
|
||||
AssetPersonV1 = "AssetPersonV1"
|
||||
export enum PluginJsonSchemaType {
|
||||
String = "string",
|
||||
Number = "number",
|
||||
Integer = "integer",
|
||||
Boolean = "boolean",
|
||||
Object = "object",
|
||||
Array = "array",
|
||||
Null = "null"
|
||||
}
|
||||
export enum WorkflowTrigger {
|
||||
export enum PluginContextType {
|
||||
Asset = "asset",
|
||||
Album = "album",
|
||||
Person = "person"
|
||||
}
|
||||
export enum PluginTriggerType {
|
||||
AssetCreate = "AssetCreate",
|
||||
PersonRecognized = "PersonRecognized"
|
||||
}
|
||||
@@ -7107,7 +7098,7 @@ export enum JobName {
|
||||
VersionCheck = "VersionCheck",
|
||||
OcrQueueAll = "OcrQueueAll",
|
||||
Ocr = "Ocr",
|
||||
WorkflowAssetCreate = "WorkflowAssetCreate"
|
||||
WorkflowRun = "WorkflowRun"
|
||||
}
|
||||
export enum SearchSuggestionType {
|
||||
Country = "country",
|
||||
|
||||
Generated
+1
-75
@@ -312,14 +312,11 @@ importers:
|
||||
specifier: ^4.20.6
|
||||
version: 4.21.0
|
||||
|
||||
packages/plugin-core:
|
||||
packages/plugins:
|
||||
devDependencies:
|
||||
'@extism/js-pdk':
|
||||
specifier: ^1.0.1
|
||||
version: 1.1.1
|
||||
'@immich/plugin-sdk':
|
||||
specifier: workspace:*
|
||||
version: link:../plugin-sdk
|
||||
esbuild:
|
||||
specifier: ^0.28.0
|
||||
version: 0.28.0
|
||||
@@ -327,24 +324,6 @@ importers:
|
||||
specifier: ^6.0.0
|
||||
version: 6.0.3
|
||||
|
||||
packages/plugin-sdk:
|
||||
devDependencies:
|
||||
'@extism/js-pdk':
|
||||
specifier: ^1.1.1
|
||||
version: 1.1.1
|
||||
'@types/node':
|
||||
specifier: ^24.11.0
|
||||
version: 24.12.2
|
||||
esbuild:
|
||||
specifier: ^0.27.3
|
||||
version: 0.27.4
|
||||
tsc-alias:
|
||||
specifier: ^1.8.16
|
||||
version: 1.8.16
|
||||
typescript:
|
||||
specifier: ^5.9.3
|
||||
version: 5.9.3
|
||||
|
||||
packages/sdk:
|
||||
dependencies:
|
||||
'@oazapfts/runtime':
|
||||
@@ -363,9 +342,6 @@ importers:
|
||||
'@extism/extism':
|
||||
specifier: 2.0.0-rc13
|
||||
version: 2.0.0-rc13
|
||||
'@immich/plugin-sdk':
|
||||
specifier: workspace:*
|
||||
version: link:../packages/plugin-sdk
|
||||
'@immich/sql-tools':
|
||||
specifier: ^0.5.1
|
||||
version: 0.5.2
|
||||
@@ -477,9 +453,6 @@ importers:
|
||||
fluent-ffmpeg:
|
||||
specifier: ^2.1.2
|
||||
version: 2.1.3
|
||||
generic-pool:
|
||||
specifier: ^3.9.0
|
||||
version: 3.9.0
|
||||
geo-tz:
|
||||
specifier: ^8.0.0
|
||||
version: 8.1.6
|
||||
@@ -6473,10 +6446,6 @@ packages:
|
||||
resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==}
|
||||
engines: {node: '>= 12'}
|
||||
|
||||
commander@9.5.0:
|
||||
resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==}
|
||||
engines: {node: ^12.20.0 || >=14}
|
||||
|
||||
comment-json@5.0.0:
|
||||
resolution: {integrity: sha512-uiqLcOiVDJtBP8WGkZHEP+FZIhTzP1dxvn59EfoYUi9gqupjrBWVQkO2atDrbnKPwLeotFYDsuNb26uBMqB+hw==}
|
||||
engines: {node: '>= 6'}
|
||||
@@ -7848,10 +7817,6 @@ packages:
|
||||
engines: {node: '>=10'}
|
||||
deprecated: This package is no longer supported.
|
||||
|
||||
generic-pool@3.9.0:
|
||||
resolution: {integrity: sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==}
|
||||
engines: {node: '>= 4'}
|
||||
|
||||
gensync@1.0.0-beta.2:
|
||||
resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
@@ -9497,10 +9462,6 @@ packages:
|
||||
resolution: {integrity: sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==}
|
||||
engines: {node: ^18.17.0 || >=20.5.0}
|
||||
|
||||
mylas@2.1.14:
|
||||
resolution: {integrity: sha512-BzQguy9W9NJgoVn2mRWzbFrFWWztGCcng2QI9+41frfk+Athwgx3qhqhvStz7ExeUUu7Kzw427sNzHpEZNINog==}
|
||||
engines: {node: '>=16.0.0'}
|
||||
|
||||
mz@2.7.0:
|
||||
resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
|
||||
|
||||
@@ -10039,10 +10000,6 @@ packages:
|
||||
engines: {node: '>=18'}
|
||||
hasBin: true
|
||||
|
||||
plimit-lit@1.6.1:
|
||||
resolution: {integrity: sha512-B7+VDyb8Tl6oMJT9oSO2CW8XC/T4UcJGrwOVoNGwOQsQYhlpfajmrMj5xeejqaASq3V/EqThyOeATEOMuSEXiA==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
pluralize@8.0.0:
|
||||
resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==}
|
||||
engines: {node: '>=4'}
|
||||
@@ -10685,10 +10642,6 @@ packages:
|
||||
resolution: {integrity: sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==}
|
||||
engines: {node: '>=0.6'}
|
||||
|
||||
queue-lit@1.5.2:
|
||||
resolution: {integrity: sha512-tLc36IOPeMAubu8BkW8YDBV+WyIgKlYU7zUNs0J5Vk9skSZ4JfGlPOqplP0aHdfv7HL0B2Pg6nwiq60Qc6M2Hw==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
queue-microtask@1.2.3:
|
||||
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
|
||||
|
||||
@@ -11915,11 +11868,6 @@ packages:
|
||||
ts-interface-checker@0.1.13:
|
||||
resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==}
|
||||
|
||||
tsc-alias@1.8.16:
|
||||
resolution: {integrity: sha512-QjCyu55NFyRSBAl6+MTFwplpFcnm2Pq01rR/uxfqJoLMm6X3O14KEGtaSDZpJYaE1bJBGDjD0eSuiIWPe2T58g==}
|
||||
engines: {node: '>=16.20.2'}
|
||||
hasBin: true
|
||||
|
||||
tsconfck@3.1.6:
|
||||
resolution: {integrity: sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w==}
|
||||
engines: {node: ^18 || >=20}
|
||||
@@ -19050,8 +18998,6 @@ snapshots:
|
||||
|
||||
commander@8.3.0: {}
|
||||
|
||||
commander@9.5.0: {}
|
||||
|
||||
comment-json@5.0.0:
|
||||
dependencies:
|
||||
array-timsort: 1.0.3
|
||||
@@ -20697,8 +20643,6 @@ snapshots:
|
||||
strip-ansi: 6.0.1
|
||||
wide-align: 1.1.5
|
||||
|
||||
generic-pool@3.9.0: {}
|
||||
|
||||
gensync@1.0.0-beta.2: {}
|
||||
|
||||
geo-coordinates-parser@1.7.4: {}
|
||||
@@ -22740,8 +22684,6 @@ snapshots:
|
||||
|
||||
mute-stream@2.0.0: {}
|
||||
|
||||
mylas@2.1.14: {}
|
||||
|
||||
mz@2.7.0:
|
||||
dependencies:
|
||||
any-promise: 1.3.0
|
||||
@@ -23299,10 +23241,6 @@ snapshots:
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.2
|
||||
|
||||
plimit-lit@1.6.1:
|
||||
dependencies:
|
||||
queue-lit: 1.5.2
|
||||
|
||||
pluralize@8.0.0: {}
|
||||
|
||||
pmtiles@3.2.1:
|
||||
@@ -23987,8 +23925,6 @@ snapshots:
|
||||
dependencies:
|
||||
side-channel: 1.1.0
|
||||
|
||||
queue-lit@1.5.2: {}
|
||||
|
||||
queue-microtask@1.2.3: {}
|
||||
|
||||
quick-lru@5.1.1: {}
|
||||
@@ -25582,16 +25518,6 @@ snapshots:
|
||||
|
||||
ts-interface-checker@0.1.13: {}
|
||||
|
||||
tsc-alias@1.8.16:
|
||||
dependencies:
|
||||
chokidar: 3.6.0
|
||||
commander: 9.5.0
|
||||
get-tsconfig: 4.13.0
|
||||
globby: 11.1.0
|
||||
mylas: 2.1.14
|
||||
normalize-path: 3.0.0
|
||||
plimit-lit: 1.6.1
|
||||
|
||||
tsconfck@3.1.6(typescript@6.0.3):
|
||||
optionalDependencies:
|
||||
typescript: 6.0.3
|
||||
|
||||
@@ -7,7 +7,6 @@ packages:
|
||||
- plugins
|
||||
- web
|
||||
- .github
|
||||
- packages/*
|
||||
ignoredBuiltDependencies:
|
||||
- '@nestjs/core'
|
||||
- '@parcel/watcher'
|
||||
|
||||
+10
-15
@@ -13,13 +13,12 @@ FROM builder AS server
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
COPY ./server ./server/
|
||||
COPY ./packages/plugin-sdk ./packages/plugin-sdk/
|
||||
RUN --mount=type=cache,id=pnpm-server,target=/buildcache/pnpm-store \
|
||||
--mount=type=bind,source=package.json,target=package.json \
|
||||
--mount=type=bind,source=.pnpmfile.cjs,target=.pnpmfile.cjs \
|
||||
--mount=type=bind,source=pnpm-lock.yaml,target=pnpm-lock.yaml \
|
||||
--mount=type=bind,source=pnpm-workspace.yaml,target=pnpm-workspace.yaml \
|
||||
SHARP_IGNORE_GLOBAL_LIBVIPS=true pnpm --filter immich --filter @immich/plugin-sdk --frozen-lockfile build && \
|
||||
SHARP_IGNORE_GLOBAL_LIBVIPS=true pnpm --filter immich --frozen-lockfile build && \
|
||||
SHARP_FORCE_GLOBAL_LIBVIPS=true pnpm --filter immich --frozen-lockfile --prod --no-optional deploy /output/server-pruned
|
||||
|
||||
FROM builder AS web
|
||||
@@ -57,26 +56,22 @@ ARG TARGETPLATFORM
|
||||
|
||||
COPY --from=ghcr.io/jdx/mise:2026.3.12@sha256:0210678cbf58413806531a27adb2c7daf1c37238e56e8f7ea381d73521571775 /usr/local/bin/mise /usr/local/bin/mise
|
||||
|
||||
WORKDIR /app
|
||||
COPY ./mise.toml ./mise.toml
|
||||
COPY ./packages/plugin-core/mise.toml ./packages/plugin-core/
|
||||
ENV MISE_TRUSTED_CONFIG_PATHS=/app/mise.toml
|
||||
WORKDIR /usr/src/app
|
||||
COPY ./packages/plugins/mise.toml ./packages/plugins/
|
||||
ENV MISE_TRUSTED_CONFIG_PATHS=/usr/src/app/packages/plugins/mise.toml
|
||||
ENV MISE_DATA_DIR=/buildcache/mise
|
||||
ENV MISE_DISABLE_TOOLS=flutter
|
||||
RUN --mount=type=cache,id=mise-tools-${TARGETPLATFORM},target=/buildcache/mise \
|
||||
mise install
|
||||
|
||||
COPY ./packages/plugin-core ./packages/plugin-core/
|
||||
COPY ./packages/plugin-sdk ./packages/plugin-sdk/
|
||||
mise install --cd packages/plugins
|
||||
|
||||
COPY ./packages/plugins ./packages/plugins/
|
||||
# Build plugins
|
||||
RUN --mount=type=cache,id=pnpm-packages,target=/buildcache/pnpm-store \
|
||||
RUN --mount=type=cache,id=pnpm-plugins,target=/buildcache/pnpm-store \
|
||||
--mount=type=bind,source=package.json,target=package.json \
|
||||
--mount=type=bind,source=.pnpmfile.cjs,target=.pnpmfile.cjs \
|
||||
--mount=type=bind,source=pnpm-lock.yaml,target=pnpm-lock.yaml \
|
||||
--mount=type=bind,source=pnpm-workspace.yaml,target=pnpm-workspace.yaml \
|
||||
--mount=type=cache,id=mise-tools-${TARGETPLATFORM},target=/buildcache/mise \
|
||||
mise //:plugins
|
||||
cd packages/plugins && mise run build
|
||||
|
||||
FROM ghcr.io/immich-app/base-server-prod:202605051129@sha256:50f7ffe4ed31e360c90c4905bd5f6658f2a121297544e3fe9368e338b3f76bcd
|
||||
|
||||
@@ -88,8 +83,8 @@ ENV NODE_ENV=production \
|
||||
COPY --from=server /output/server-pruned ./server
|
||||
COPY --from=web /usr/src/app/web/build /build/www
|
||||
COPY --from=cli /output/cli-pruned ./cli
|
||||
COPY --from=plugins /app/packages/plugin-core/dist /build/plugins/immich-core-plugin/dist
|
||||
COPY --from=plugins /app/packages/plugin-core/manifest.json /build/plugins/immich-core-plugin/manifest.json
|
||||
COPY --from=plugins /usr/src/app/packages/plugins/dist /build/corePlugin/dist
|
||||
COPY --from=plugins /usr/src/app/packages/plugins/manifest.json /build/corePlugin/manifest.json
|
||||
RUN ln -s ../../cli/bin/immich server/bin/immich
|
||||
COPY LICENSE /licenses/LICENSE.txt
|
||||
COPY LICENSE /LICENSE
|
||||
|
||||
@@ -58,7 +58,6 @@ run = "email dev -p 3050 --dir src/emails"
|
||||
[tasks.ci-unit]
|
||||
run = [
|
||||
{ task = ":install" },
|
||||
{ task = "//:plugins" },
|
||||
{ task = ":format" },
|
||||
{ task = ":lint" },
|
||||
{ task = ":check" },
|
||||
@@ -68,7 +67,6 @@ run = [
|
||||
[tasks.ci-medium]
|
||||
run = [
|
||||
{ task = ":install" },
|
||||
{ task = "//packages/plugin-core:build" },
|
||||
{ task = ":test-medium --run" },
|
||||
]
|
||||
|
||||
|
||||
@@ -37,7 +37,6 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@extism/extism": "2.0.0-rc13",
|
||||
"@immich/plugin-sdk": "workspace:*",
|
||||
"@immich/sql-tools": "^0.5.1",
|
||||
"@nestjs/bullmq": "^11.0.1",
|
||||
"@nestjs/common": "^11.0.4",
|
||||
@@ -75,7 +74,6 @@
|
||||
"express": "^5.1.0",
|
||||
"fast-glob": "^3.3.2",
|
||||
"fluent-ffmpeg": "^2.1.2",
|
||||
"generic-pool": "^3.9.0",
|
||||
"geo-tz": "^8.0.0",
|
||||
"handlebars": "^4.7.8",
|
||||
"helmet": "^8.1.0",
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
import { PluginController } from 'src/controllers/plugin.controller';
|
||||
import { LoggingRepository } from 'src/repositories/logging.repository';
|
||||
import { PluginService } from 'src/services/plugin.service';
|
||||
import request from 'supertest';
|
||||
import { errorDto } from 'test/medium/responses';
|
||||
import { factory } from 'test/small.factory';
|
||||
import { automock, ControllerContext, controllerSetup, mockBaseService } from 'test/utils';
|
||||
|
||||
describe(PluginController.name, () => {
|
||||
let ctx: ControllerContext;
|
||||
const service = mockBaseService(PluginService);
|
||||
|
||||
beforeAll(async () => {
|
||||
ctx = await controllerSetup(PluginController, [
|
||||
{ provide: PluginService, useValue: service },
|
||||
{ provide: LoggingRepository, useValue: automock(LoggingRepository, { strict: false }) },
|
||||
]);
|
||||
return () => ctx.close();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
service.resetAllMocks();
|
||||
ctx.reset();
|
||||
});
|
||||
|
||||
describe('GET /plugins', () => {
|
||||
it('should be an authenticated route', async () => {
|
||||
await request(ctx.getHttpServer()).get('/plugins');
|
||||
expect(ctx.authenticate).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it(`should require id to be a uuid`, async () => {
|
||||
const { status, body } = await request(ctx.getHttpServer())
|
||||
.get(`/plugins`)
|
||||
.query({ id: 'invalid' })
|
||||
.set('Authorization', `Bearer token`);
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(errorDto.validationError([{ path: ['id'], message: 'Invalid UUID' }]));
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /plugins/:id', () => {
|
||||
it('should be an authenticated route', async () => {
|
||||
await request(ctx.getHttpServer()).get(`/plugins/${factory.uuid()}`);
|
||||
expect(ctx.authenticate).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it(`should require id to be a uuid`, async () => {
|
||||
const { status, body } = await request(ctx.getHttpServer())
|
||||
.get(`/plugins/invalid`)
|
||||
.set('Authorization', `Bearer token`);
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(errorDto.validationError([{ path: ['id'], message: 'Invalid UUID' }]));
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,12 +1,7 @@
|
||||
import { Controller, Get, Param, Query } from '@nestjs/common';
|
||||
import { Controller, Get, Param } from '@nestjs/common';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
import { Endpoint, HistoryBuilder } from 'src/decorators';
|
||||
import {
|
||||
PluginMethodResponseDto,
|
||||
PluginMethodSearchDto,
|
||||
PluginResponseDto,
|
||||
PluginSearchDto,
|
||||
} from 'src/dtos/plugin.dto';
|
||||
import { PluginResponseDto, PluginTriggerResponseDto } from 'src/dtos/plugin.dto';
|
||||
import { Permission } from 'src/enum';
|
||||
import { Authenticated } from 'src/middleware/auth.guard';
|
||||
import { PluginService } from 'src/services/plugin.service';
|
||||
@@ -17,26 +12,26 @@ import { UUIDParamDto } from 'src/validation';
|
||||
export class PluginController {
|
||||
constructor(private service: PluginService) {}
|
||||
|
||||
@Get('triggers')
|
||||
@Authenticated({ permission: Permission.PluginRead })
|
||||
@Endpoint({
|
||||
summary: 'List all plugin triggers',
|
||||
description: 'Retrieve a list of all available plugin triggers.',
|
||||
history: new HistoryBuilder().added('v2.3.0').alpha('v2.3.0'),
|
||||
})
|
||||
getPluginTriggers(): PluginTriggerResponseDto[] {
|
||||
return this.service.getTriggers();
|
||||
}
|
||||
|
||||
@Get()
|
||||
@Authenticated({ permission: Permission.PluginRead })
|
||||
@Endpoint({
|
||||
summary: 'List all plugins',
|
||||
description: 'Retrieve a list of plugins available to the authenticated user.',
|
||||
history: HistoryBuilder.v3(),
|
||||
history: new HistoryBuilder().added('v2.3.0').alpha('v2.3.0'),
|
||||
})
|
||||
searchPlugins(@Query() dto: PluginSearchDto): Promise<PluginResponseDto[]> {
|
||||
return this.service.search(dto);
|
||||
}
|
||||
|
||||
@Get('methods')
|
||||
@Authenticated({ permission: Permission.PluginRead })
|
||||
@Endpoint({
|
||||
summary: 'Retrieve plugin methods',
|
||||
description: 'Retrieve a list of plugin methods',
|
||||
history: HistoryBuilder.v3(),
|
||||
})
|
||||
searchPluginMethods(@Query() dto: PluginMethodSearchDto): Promise<PluginMethodResponseDto[]> {
|
||||
return this.service.searchMethods(dto);
|
||||
getPlugins(): Promise<PluginResponseDto[]> {
|
||||
return this.service.getAll();
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
@@ -44,7 +39,7 @@ export class PluginController {
|
||||
@Endpoint({
|
||||
summary: 'Retrieve a plugin',
|
||||
description: 'Retrieve information about a specific plugin by its ID.',
|
||||
history: HistoryBuilder.v3(),
|
||||
history: new HistoryBuilder().added('v2.3.0').alpha('v2.3.0'),
|
||||
})
|
||||
getPlugin(@Param() { id }: UUIDParamDto): Promise<PluginResponseDto> {
|
||||
return this.service.get(id);
|
||||
|
||||
@@ -1,113 +0,0 @@
|
||||
import { WorkflowController } from 'src/controllers/workflow.controller';
|
||||
import { WorkflowTrigger } from 'src/enum';
|
||||
import { LoggingRepository } from 'src/repositories/logging.repository';
|
||||
import { WorkflowService } from 'src/services/workflow.service';
|
||||
import request from 'supertest';
|
||||
import { errorDto } from 'test/medium/responses';
|
||||
import { factory } from 'test/small.factory';
|
||||
import { automock, ControllerContext, controllerSetup, mockBaseService } from 'test/utils';
|
||||
|
||||
describe(WorkflowController.name, () => {
|
||||
let ctx: ControllerContext;
|
||||
const service = mockBaseService(WorkflowService);
|
||||
|
||||
beforeAll(async () => {
|
||||
ctx = await controllerSetup(WorkflowController, [
|
||||
{ provide: WorkflowService, useValue: service },
|
||||
{ provide: LoggingRepository, useValue: automock(LoggingRepository, { strict: false }) },
|
||||
]);
|
||||
return () => ctx.close();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
service.resetAllMocks();
|
||||
ctx.reset();
|
||||
});
|
||||
|
||||
describe('POST /workflows', () => {
|
||||
it('should be an authenticated route', async () => {
|
||||
await request(ctx.getHttpServer()).post('/workflows').send({});
|
||||
expect(ctx.authenticate).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it(`should require a valid trigger`, async () => {
|
||||
const { status, body } = await request(ctx.getHttpServer())
|
||||
.post(`/workflows`)
|
||||
.send({ trigger: 'invalid' })
|
||||
.set('Authorization', `Bearer token`);
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(
|
||||
errorDto.validationError([
|
||||
{ path: ['trigger'], message: expect.stringContaining('Invalid option: expected one of') },
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
it(`should require a valid enabled value`, async () => {
|
||||
const { status, body } = await request(ctx.getHttpServer())
|
||||
.post(`/workflows`)
|
||||
.send({ enabled: 'invalid' })
|
||||
.set('Authorization', `Bearer token`);
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(
|
||||
errorDto.validationError([{ path: ['enabled'], message: 'Invalid input: expected boolean, received string' }]),
|
||||
);
|
||||
});
|
||||
|
||||
it(`should not require a name`, async () => {
|
||||
const { status } = await request(ctx.getHttpServer())
|
||||
.post(`/workflows`)
|
||||
.send({ trigger: WorkflowTrigger.AssetCreate })
|
||||
.set('Authorization', `Bearer token`);
|
||||
expect(status).toBe(201);
|
||||
expect(service.create).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /workflows', () => {
|
||||
it('should be an authenticated route', async () => {
|
||||
await request(ctx.getHttpServer()).get('/workflows');
|
||||
expect(ctx.authenticate).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it(`should require id to be a uuid`, async () => {
|
||||
const { status, body } = await request(ctx.getHttpServer())
|
||||
.get(`/workflows`)
|
||||
.query({ id: 'invalid' })
|
||||
.set('Authorization', `Bearer token`);
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(errorDto.validationError([{ path: ['id'], message: 'Invalid UUID' }]));
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /workflows/:id', () => {
|
||||
it('should be an authenticated route', async () => {
|
||||
await request(ctx.getHttpServer()).get(`/workflows/${factory.uuid()}`);
|
||||
expect(ctx.authenticate).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it(`should require id to be a uuid`, async () => {
|
||||
const { status, body } = await request(ctx.getHttpServer())
|
||||
.get(`/workflows/invalid`)
|
||||
.set('Authorization', `Bearer token`);
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(errorDto.validationError([{ path: ['id'], message: 'Invalid UUID' }]));
|
||||
});
|
||||
});
|
||||
|
||||
describe('PUT /workflows/:id', () => {
|
||||
it('should be an authenticated route', async () => {
|
||||
await request(ctx.getHttpServer()).put(`/workflows/${factory.uuid()}`).send({});
|
||||
expect(ctx.authenticate).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it(`should require id to be a uuid`, async () => {
|
||||
const { status, body } = await request(ctx.getHttpServer())
|
||||
.put(`/workflows/invalid`)
|
||||
.set('Authorization', `Bearer token`)
|
||||
.send({});
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(errorDto.validationError([{ path: ['id'], message: 'Invalid UUID' }]));
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,15 +1,8 @@
|
||||
import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Post, Put, Query } from '@nestjs/common';
|
||||
import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Post, Put } from '@nestjs/common';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
import { Endpoint, HistoryBuilder } from 'src/decorators';
|
||||
import { AuthDto } from 'src/dtos/auth.dto';
|
||||
import {
|
||||
WorkflowCreateDto,
|
||||
WorkflowResponseDto,
|
||||
WorkflowSearchDto,
|
||||
WorkflowShareResponseDto,
|
||||
WorkflowTriggerResponseDto,
|
||||
WorkflowUpdateDto,
|
||||
} from 'src/dtos/workflow.dto';
|
||||
import { WorkflowCreateDto, WorkflowResponseDto, WorkflowUpdateDto } from 'src/dtos/workflow.dto';
|
||||
import { Permission } from 'src/enum';
|
||||
import { Auth, Authenticated } from 'src/middleware/auth.guard';
|
||||
import { WorkflowService } from 'src/services/workflow.service';
|
||||
@@ -25,7 +18,7 @@ export class WorkflowController {
|
||||
@Endpoint({
|
||||
summary: 'Create a workflow',
|
||||
description: 'Create a new workflow, the workflow can also be created with empty filters and actions.',
|
||||
history: HistoryBuilder.v3(),
|
||||
history: new HistoryBuilder().added('v2.3.0').alpha('v2.3.0'),
|
||||
})
|
||||
createWorkflow(@Auth() auth: AuthDto, @Body() dto: WorkflowCreateDto): Promise<WorkflowResponseDto> {
|
||||
return this.service.create(auth, dto);
|
||||
@@ -36,21 +29,10 @@ export class WorkflowController {
|
||||
@Endpoint({
|
||||
summary: 'List all workflows',
|
||||
description: 'Retrieve a list of workflows available to the authenticated user.',
|
||||
history: HistoryBuilder.v3(),
|
||||
history: new HistoryBuilder().added('v2.3.0').alpha('v2.3.0'),
|
||||
})
|
||||
searchWorkflows(@Auth() auth: AuthDto, @Query() dto: WorkflowSearchDto): Promise<WorkflowResponseDto[]> {
|
||||
return this.service.search(auth, dto);
|
||||
}
|
||||
|
||||
@Get('triggers')
|
||||
@Authenticated({ permission: false })
|
||||
@Endpoint({
|
||||
summary: 'List all workflow triggers',
|
||||
description: 'Retrieve a list of all available workflow triggers.',
|
||||
history: HistoryBuilder.v3(),
|
||||
})
|
||||
getWorkflowTriggers(): WorkflowTriggerResponseDto[] {
|
||||
return this.service.getTriggers();
|
||||
getWorkflows(@Auth() auth: AuthDto): Promise<WorkflowResponseDto[]> {
|
||||
return this.service.getAll(auth);
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
@@ -58,30 +40,19 @@ export class WorkflowController {
|
||||
@Endpoint({
|
||||
summary: 'Retrieve a workflow',
|
||||
description: 'Retrieve information about a specific workflow by its ID.',
|
||||
history: HistoryBuilder.v3(),
|
||||
history: new HistoryBuilder().added('v2.3.0').alpha('v2.3.0'),
|
||||
})
|
||||
getWorkflow(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<WorkflowResponseDto> {
|
||||
return this.service.get(auth, id);
|
||||
}
|
||||
|
||||
@Get(':id/share')
|
||||
@Authenticated({ permission: Permission.WorkflowRead })
|
||||
@Endpoint({
|
||||
summary: 'Retrieve a workflow',
|
||||
description: 'Retrieve a workflow details without ids, default values, etc.',
|
||||
history: HistoryBuilder.v3(),
|
||||
})
|
||||
getWorkflowForShare(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<WorkflowShareResponseDto> {
|
||||
return this.service.share(auth, id);
|
||||
}
|
||||
|
||||
@Put(':id')
|
||||
@Authenticated({ permission: Permission.WorkflowUpdate })
|
||||
@Endpoint({
|
||||
summary: 'Update a workflow',
|
||||
description:
|
||||
'Update the information of a specific workflow by its ID. This endpoint can be used to update the workflow name, description, trigger type, filters and actions order, etc.',
|
||||
history: HistoryBuilder.v3(),
|
||||
history: new HistoryBuilder().added('v2.3.0').alpha('v2.3.0'),
|
||||
})
|
||||
updateWorkflow(
|
||||
@Auth() auth: AuthDto,
|
||||
@@ -97,7 +68,7 @@ export class WorkflowController {
|
||||
@Endpoint({
|
||||
summary: 'Delete a workflow',
|
||||
description: 'Delete a workflow by its ID.',
|
||||
history: HistoryBuilder.v3(),
|
||||
history: new HistoryBuilder().added('v2.3.0').alpha('v2.3.0'),
|
||||
})
|
||||
deleteWorkflow(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<void> {
|
||||
return this.service.delete(auth, id);
|
||||
|
||||
+52
-37
@@ -8,6 +8,8 @@ import {
|
||||
ChecksumAlgorithm,
|
||||
MemoryType,
|
||||
Permission,
|
||||
PluginContext,
|
||||
PluginTriggerType,
|
||||
SharedLinkType,
|
||||
SourceType,
|
||||
UserAvatarColor,
|
||||
@@ -16,8 +18,10 @@ import {
|
||||
import { AlbumTable } from 'src/schema/tables/album.table';
|
||||
import { AssetExifTable } from 'src/schema/tables/asset-exif.table';
|
||||
import { AssetTable } from 'src/schema/tables/asset.table';
|
||||
import { PluginTable } from 'src/schema/tables/plugin.table';
|
||||
import { PluginActionTable, PluginFilterTable } from 'src/schema/tables/plugin.table';
|
||||
import { WorkflowActionTable, WorkflowFilterTable, WorkflowTable } from 'src/schema/tables/workflow.table';
|
||||
import { UserMetadataItem } from 'src/types';
|
||||
import type { ActionConfig, FilterConfig, JSONSchema } from 'src/types/plugin-schema.types';
|
||||
|
||||
export type AuthUser = {
|
||||
id: string;
|
||||
@@ -272,7 +276,42 @@ export type AssetFace = {
|
||||
isVisible: boolean;
|
||||
};
|
||||
|
||||
export type Plugin = Selectable<PluginTable>;
|
||||
export type PluginFilter = Selectable<PluginFilterTable> & {
|
||||
methodName: string;
|
||||
title: string;
|
||||
description: string;
|
||||
supportedContexts: PluginContext[];
|
||||
schema: JSONSchema | null;
|
||||
};
|
||||
|
||||
export type PluginAction = Selectable<PluginActionTable> & {
|
||||
methodName: string;
|
||||
title: string;
|
||||
description: string;
|
||||
supportedContexts: PluginContext[];
|
||||
schema: JSONSchema | null;
|
||||
};
|
||||
|
||||
export type Workflow = Selectable<WorkflowTable> & {
|
||||
triggerType: PluginTriggerType;
|
||||
name: string | null;
|
||||
description: string;
|
||||
enabled: boolean;
|
||||
};
|
||||
|
||||
export type WorkflowFilter = Selectable<WorkflowFilterTable> & {
|
||||
workflowId: string;
|
||||
pluginFilterId: string;
|
||||
filterConfig: FilterConfig | null;
|
||||
order: number;
|
||||
};
|
||||
|
||||
export type WorkflowAction = Selectable<WorkflowActionTable> & {
|
||||
workflowId: string;
|
||||
pluginActionId: string;
|
||||
actionConfig: ActionConfig | null;
|
||||
order: number;
|
||||
};
|
||||
|
||||
const userColumns = ['id', 'name', 'email', 'avatarColor', 'profileImagePath', 'profileChangedAt'] as const;
|
||||
const userWithPrefixColumns = [
|
||||
@@ -304,32 +343,6 @@ export const columns = {
|
||||
'asset.height',
|
||||
'asset.isEdited',
|
||||
],
|
||||
workflowAssetV1: [
|
||||
'asset.id',
|
||||
'asset.ownerId',
|
||||
'asset.stackId',
|
||||
'asset.livePhotoVideoId',
|
||||
'asset.libraryId',
|
||||
'asset.duplicateId',
|
||||
'asset.createdAt',
|
||||
'asset.updatedAt',
|
||||
'asset.deletedAt',
|
||||
'asset.fileCreatedAt',
|
||||
'asset.fileModifiedAt',
|
||||
'asset.localDateTime',
|
||||
'asset.type',
|
||||
'asset.status',
|
||||
'asset.visibility',
|
||||
'asset.duration',
|
||||
'asset.checksum',
|
||||
'asset.originalPath',
|
||||
'asset.originalFileName',
|
||||
'asset.isOffline',
|
||||
'asset.isFavorite',
|
||||
'asset.isExternal',
|
||||
'asset.isEdited',
|
||||
'asset.isFavorite',
|
||||
],
|
||||
assetFiles: ['asset_file.id', 'asset_file.path', 'asset_file.type', 'asset_file.isEdited'],
|
||||
assetFilesForThumbnail: [
|
||||
'asset_file.id',
|
||||
@@ -361,15 +374,6 @@ export const columns = {
|
||||
tag: ['tag.id', 'tag.value', 'tag.createdAt', 'tag.updatedAt', 'tag.color', 'tag.parentId'],
|
||||
apiKey: ['id', 'name', 'userId', 'createdAt', 'updatedAt', 'permissions'],
|
||||
notification: ['id', 'createdAt', 'level', 'type', 'title', 'description', 'data', 'readAt'],
|
||||
pluginMethod: [
|
||||
'plugin_method.name',
|
||||
'plugin_method.title',
|
||||
'plugin_method.description',
|
||||
'plugin_method.types',
|
||||
'plugin_method.schema',
|
||||
'plugin_method.hostFunctions',
|
||||
'plugin_method.uiHints',
|
||||
],
|
||||
syncAsset: [
|
||||
'asset.id',
|
||||
'asset.ownerId',
|
||||
@@ -483,6 +487,17 @@ export const columns = {
|
||||
'asset_exif.tags',
|
||||
'asset_exif.timeZone',
|
||||
],
|
||||
plugin: [
|
||||
'plugin.id as id',
|
||||
'plugin.name as name',
|
||||
'plugin.title as title',
|
||||
'plugin.description as description',
|
||||
'plugin.author as author',
|
||||
'plugin.version as version',
|
||||
'plugin.wasmPath as wasmPath',
|
||||
'plugin.createdAt as createdAt',
|
||||
'plugin.updatedAt as updatedAt',
|
||||
],
|
||||
} as const;
|
||||
|
||||
export type LockableProperty = (typeof lockableProperties)[number];
|
||||
|
||||
@@ -200,10 +200,6 @@ export class HistoryBuilder {
|
||||
private hasDeprecated = false;
|
||||
private items: HistoryEntry[] = [];
|
||||
|
||||
static v3() {
|
||||
return new HistoryBuilder().added('v3.0.0');
|
||||
}
|
||||
|
||||
added(version: string, description?: string) {
|
||||
return this.push({ version, state: 'Added', description });
|
||||
}
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
import { createZodDto } from 'nestjs-zod';
|
||||
import z from 'zod';
|
||||
|
||||
export const JsonSchemaTypeSchema = z
|
||||
.enum(['string', 'number', 'integer', 'boolean', 'object'])
|
||||
.meta({ id: 'JsonSchemaType' });
|
||||
|
||||
const JsonSchemaPropertySchema = z
|
||||
.object({
|
||||
type: JsonSchemaTypeSchema.optional().default('object').describe('Type'),
|
||||
title: z.string().describe('Title'),
|
||||
description: z.string().describe('Description'),
|
||||
default: z.any().optional().describe('Default value'),
|
||||
enum: z.array(z.string()).optional().describe('Valid choices for enum types'),
|
||||
array: z.boolean().optional().describe('Type is an array type'),
|
||||
required: z.array(z.string()).optional().describe('A list of required properties'),
|
||||
uiHint: z.string().optional(),
|
||||
get properties() {
|
||||
return z.record(z.string(), JsonSchemaPropertySchema).optional();
|
||||
},
|
||||
})
|
||||
.meta({ id: 'JsonSchemaPropertyDto' });
|
||||
|
||||
export const JsonSchemaSchema = z
|
||||
.object({
|
||||
...JsonSchemaPropertySchema.shape,
|
||||
title: z.string().optional().describe('Title'),
|
||||
description: z.string().optional().describe('Description'),
|
||||
})
|
||||
.meta({ id: 'JsonSchemaDto' });
|
||||
|
||||
export class JsonSchemaDto extends createZodDto(JsonSchemaSchema) {}
|
||||
@@ -1,29 +1,39 @@
|
||||
import { createZodDto } from 'nestjs-zod';
|
||||
import { JsonSchemaSchema } from 'src/dtos/json-schema.dto';
|
||||
import { WorkflowTypeSchema } from 'src/enum';
|
||||
import { PluginContextSchema } from 'src/enum';
|
||||
import { JSONSchemaSchema } from 'src/types/plugin-schema.types';
|
||||
import z from 'zod';
|
||||
|
||||
const pluginNameRegex = /^[a-z0-9-]+[a-z0-9]$/;
|
||||
const semverRegex =
|
||||
/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/;
|
||||
|
||||
export const PluginManifestMethodSchemaSchema = JsonSchemaSchema.nullable()
|
||||
.optional()
|
||||
.transform((value) => (value && Object.keys(value).length === 0 ? null : value));
|
||||
|
||||
const PluginManifestMethodSchema = z
|
||||
const PluginManifestWasmSchema = z
|
||||
.object({
|
||||
name: z.string().min(1).describe('Method name'),
|
||||
title: z.string().min(1).describe('Method title'),
|
||||
description: z.string().min(1).describe('Method description'),
|
||||
types: z.array(WorkflowTypeSchema).min(1).describe('Workflow type'),
|
||||
hostFunctions: z.boolean().optional().default(false).describe('Method uses host functions'),
|
||||
schema: PluginManifestMethodSchemaSchema.describe('Schema'),
|
||||
uiHints: z.array(z.string()).optional().describe('Ui hints, for example "filter"'),
|
||||
path: z.string().describe('WASM file path'),
|
||||
})
|
||||
.meta({ id: 'PluginManifestMethodDto' });
|
||||
.meta({ id: 'PluginManifestWasmDto' });
|
||||
|
||||
const PluginManifestSchema = z
|
||||
const PluginManifestFilterSchema = z
|
||||
.object({
|
||||
methodName: z.string().describe('Filter method name'),
|
||||
title: z.string().describe('Filter title'),
|
||||
description: z.string().describe('Filter description'),
|
||||
supportedContexts: z.array(PluginContextSchema).min(1).describe('Supported contexts'),
|
||||
schema: JSONSchemaSchema.optional(),
|
||||
})
|
||||
.meta({ id: 'PluginManifestFilterDto' });
|
||||
|
||||
const PluginManifestActionSchema = z
|
||||
.object({
|
||||
methodName: z.string().describe('Action method name'),
|
||||
title: z.string().describe('Action title'),
|
||||
description: z.string().describe('Action description'),
|
||||
supportedContexts: z.array(PluginContextSchema).min(1).describe('Supported contexts'),
|
||||
schema: JSONSchemaSchema.optional(),
|
||||
})
|
||||
.meta({ id: 'PluginManifestActionDto' });
|
||||
|
||||
export const PluginManifestSchema = z
|
||||
.object({
|
||||
name: z
|
||||
.string()
|
||||
@@ -34,11 +44,12 @@ const PluginManifestSchema = z
|
||||
)
|
||||
.describe('Plugin name (lowercase, numbers, hyphens only)'),
|
||||
version: z.string().regex(semverRegex).describe('Plugin version (semver)'),
|
||||
title: z.string().min(1).describe('Plugin title'),
|
||||
description: z.string().min(1).describe('Plugin description'),
|
||||
wasmPath: z.string().min(1).describe('WASM file path'),
|
||||
author: z.string().min(1).describe('Plugin author'),
|
||||
methods: z.array(PluginManifestMethodSchema).optional().default([]).describe('Plugin methods'),
|
||||
title: z.string().describe('Plugin title'),
|
||||
description: z.string().describe('Plugin description'),
|
||||
author: z.string().describe('Plugin author'),
|
||||
wasm: PluginManifestWasmSchema,
|
||||
filters: z.array(PluginManifestFilterSchema).optional().describe('Plugin filters'),
|
||||
actions: z.array(PluginManifestActionSchema).optional().describe('Plugin actions'),
|
||||
})
|
||||
.meta({ id: 'PluginManifestDto' });
|
||||
|
||||
|
||||
@@ -1,33 +1,39 @@
|
||||
import { createZodDto } from 'nestjs-zod';
|
||||
import { JsonSchemaDto } from 'src/dtos/json-schema.dto';
|
||||
import { WorkflowTriggerSchema, WorkflowType, WorkflowTypeSchema } from 'src/enum';
|
||||
import { asMethodString } from 'src/utils/workflow';
|
||||
import { PluginAction, PluginFilter } from 'src/database';
|
||||
import { PluginContextSchema, PluginTriggerTypeSchema } from 'src/enum';
|
||||
import { JSONSchemaSchema } from 'src/types/plugin-schema.types';
|
||||
import z from 'zod';
|
||||
|
||||
const PluginSearchSchema = z
|
||||
const PluginTriggerResponseSchema = z
|
||||
.object({
|
||||
id: z.uuidv4().optional().describe('Plugin ID'),
|
||||
enabled: z.boolean().optional().describe('Whether the plugin is enabled'),
|
||||
name: z.string().optional(),
|
||||
version: z.string().optional(),
|
||||
title: z.string().optional(),
|
||||
description: z.string().optional(),
|
||||
type: PluginTriggerTypeSchema,
|
||||
contextType: PluginContextSchema,
|
||||
})
|
||||
.meta({ id: 'PluginSearchDto' });
|
||||
.meta({ id: 'PluginTriggerResponseDto' });
|
||||
|
||||
const PluginMethodResponseSchema = z
|
||||
const PluginFilterResponseSchema = z
|
||||
.object({
|
||||
key: z.string().describe('Key'),
|
||||
name: z.string().describe('Name'),
|
||||
title: z.string().describe('Title'),
|
||||
description: z.string().describe('Description'),
|
||||
types: z.array(WorkflowTypeSchema).describe('Workflow types'),
|
||||
uiHints: z.array(z.string()).describe('Ui hints'),
|
||||
// TODO fix this
|
||||
schema: z.object().optional(),
|
||||
hostFunctions: z.boolean(),
|
||||
id: z.string().describe('Filter ID'),
|
||||
pluginId: z.string().describe('Plugin ID'),
|
||||
methodName: z.string().describe('Method name'),
|
||||
title: z.string().describe('Filter title'),
|
||||
description: z.string().describe('Filter description'),
|
||||
supportedContexts: z.array(PluginContextSchema).describe('Supported contexts'),
|
||||
schema: JSONSchemaSchema.nullable().describe('Filter schema'),
|
||||
})
|
||||
.meta({ id: 'PluginMethodResponseDto' });
|
||||
.meta({ id: 'PluginFilterResponseDto' });
|
||||
|
||||
const PluginActionResponseSchema = z
|
||||
.object({
|
||||
id: z.string().describe('Action ID'),
|
||||
pluginId: z.string().describe('Plugin ID'),
|
||||
methodName: z.string().describe('Method name'),
|
||||
title: z.string().describe('Action title'),
|
||||
description: z.string().describe('Action description'),
|
||||
supportedContexts: z.array(PluginContextSchema).describe('Supported contexts'),
|
||||
schema: JSONSchemaSchema.nullable().describe('Action schema'),
|
||||
})
|
||||
.meta({ id: 'PluginActionResponseDto' });
|
||||
|
||||
const PluginResponseSchema = z
|
||||
.object({
|
||||
@@ -39,53 +45,29 @@ const PluginResponseSchema = z
|
||||
version: z.string().describe('Plugin version'),
|
||||
createdAt: z.string().describe('Creation date'),
|
||||
updatedAt: z.string().describe('Last update date'),
|
||||
methods: z.array(PluginMethodResponseSchema).describe('Plugin methods'),
|
||||
filters: z.array(PluginFilterResponseSchema).describe('Plugin filters'),
|
||||
actions: z.array(PluginActionResponseSchema).describe('Plugin actions'),
|
||||
})
|
||||
.meta({ id: 'PluginResponseDto' });
|
||||
|
||||
const PluginMethodSearchSchema = z
|
||||
.object({
|
||||
id: z.uuidv4().optional().describe('Plugin method ID'),
|
||||
enabled: z.boolean().optional().describe('Whether the plugin method is enabled'),
|
||||
name: z.string().optional(),
|
||||
title: z.string().optional(),
|
||||
description: z.string().optional(),
|
||||
type: WorkflowTypeSchema.optional().describe('Workflow types'),
|
||||
trigger: WorkflowTriggerSchema.optional().describe('Workflow trigger'),
|
||||
pluginName: z.string().optional().describe('Plugin name'),
|
||||
pluginVersion: z.string().optional().describe('Plugin version'),
|
||||
})
|
||||
.meta({ id: 'PluginMethodSearchDto' });
|
||||
|
||||
export class PluginSearchDto extends createZodDto(PluginSearchSchema) {}
|
||||
export class PluginTriggerResponseDto extends createZodDto(PluginTriggerResponseSchema) {}
|
||||
export class PluginResponseDto extends createZodDto(PluginResponseSchema) {}
|
||||
export class PluginMethodSearchDto extends createZodDto(PluginMethodSearchSchema) {}
|
||||
export class PluginMethodResponseDto extends createZodDto(PluginMethodResponseSchema) {}
|
||||
|
||||
type Plugin = {
|
||||
type MapPlugin = {
|
||||
id: string;
|
||||
name: string;
|
||||
title: string;
|
||||
description: string;
|
||||
author: string;
|
||||
version: string;
|
||||
wasmPath: string;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
methods: PluginMethod[];
|
||||
filters: PluginFilter[];
|
||||
actions: PluginAction[];
|
||||
};
|
||||
|
||||
type PluginMethod = {
|
||||
pluginName: string;
|
||||
name: string;
|
||||
title: string;
|
||||
description: string;
|
||||
types: WorkflowType[];
|
||||
schema: JsonSchemaDto | null;
|
||||
hostFunctions: boolean;
|
||||
uiHints: string[];
|
||||
};
|
||||
|
||||
export function mapPlugin(plugin: Plugin): PluginResponseDto {
|
||||
export function mapPlugin(plugin: MapPlugin): PluginResponseDto {
|
||||
return {
|
||||
id: plugin.id,
|
||||
name: plugin.name,
|
||||
@@ -95,19 +77,7 @@ export function mapPlugin(plugin: Plugin): PluginResponseDto {
|
||||
version: plugin.version,
|
||||
createdAt: plugin.createdAt.toISOString(),
|
||||
updatedAt: plugin.updatedAt.toISOString(),
|
||||
methods: plugin.methods.map((method) => mapMethod(method)),
|
||||
filters: plugin.filters,
|
||||
actions: plugin.actions,
|
||||
};
|
||||
}
|
||||
|
||||
export const mapMethod = (method: PluginMethod): PluginMethodResponseDto => {
|
||||
return {
|
||||
key: asMethodString({ pluginName: method.pluginName, methodName: method.name }),
|
||||
name: method.name,
|
||||
title: method.title,
|
||||
hostFunctions: method.hostFunctions,
|
||||
uiHints: method.uiHints,
|
||||
description: method.description,
|
||||
types: method.types,
|
||||
schema: method.schema as any,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,135 +1,101 @@
|
||||
import type { WorkflowStepConfig } from '@immich/plugin-sdk';
|
||||
import { createZodDto } from 'nestjs-zod';
|
||||
import { WorkflowTrigger, WorkflowTriggerSchema, WorkflowTypeSchema } from 'src/enum';
|
||||
import type { WorkflowAction, WorkflowFilter } from 'src/database';
|
||||
import { PluginTriggerTypeSchema } from 'src/enum';
|
||||
import { ActionConfigSchema, FilterConfigSchema } from 'src/types/plugin-schema.types';
|
||||
import z from 'zod';
|
||||
|
||||
const WorkflowTriggerResponseSchema = z
|
||||
const WorkflowFilterItemSchema = z
|
||||
.object({
|
||||
trigger: WorkflowTriggerSchema.describe('Trigger type'),
|
||||
types: z.array(WorkflowTypeSchema).describe('Workflow types'),
|
||||
pluginFilterId: z.uuidv4().describe('Plugin filter ID'),
|
||||
filterConfig: FilterConfigSchema.optional(),
|
||||
})
|
||||
.meta({ id: 'WorkflowTriggerResponseDto' });
|
||||
.meta({ id: 'WorkflowFilterItemDto' });
|
||||
|
||||
const WorkflowSearchSchema = z
|
||||
const WorkflowActionItemSchema = z
|
||||
.object({
|
||||
id: z.uuidv4().optional().describe('Workflow ID'),
|
||||
trigger: WorkflowTriggerSchema.optional().describe('Workflow trigger type'),
|
||||
name: z.string().optional().describe('Workflow name'),
|
||||
description: z.string().optional().describe('Workflow description'),
|
||||
enabled: z.boolean().optional().describe('Workflow enabled'),
|
||||
pluginActionId: z.uuidv4().describe('Plugin action ID'),
|
||||
actionConfig: ActionConfigSchema.optional(),
|
||||
})
|
||||
.meta({ id: 'WorkflowSearchDto' });
|
||||
|
||||
const WorkflowStepSchema = z
|
||||
.object({
|
||||
method: z.string().describe('Step plugin method'),
|
||||
config: z.record(z.string(), z.unknown()).nullable().describe('Step configuration'),
|
||||
enabled: z.boolean().optional().describe('Step is enabled'),
|
||||
})
|
||||
.meta({ id: 'WorkflowStepDto' });
|
||||
|
||||
const WorkflowShareStepSchema = z
|
||||
.object({
|
||||
method: z.string().describe('Step plugin method'),
|
||||
config: z.record(z.string(), z.unknown()).nullable().describe('Step configuration'),
|
||||
enabled: z.boolean().optional().describe('Step is enabled'),
|
||||
})
|
||||
.meta({ id: 'WorkflowShareStepDto' });
|
||||
.meta({ id: 'WorkflowActionItemDto' });
|
||||
|
||||
const WorkflowCreateSchema = z
|
||||
.object({
|
||||
trigger: WorkflowTriggerSchema.describe('Workflow trigger type'),
|
||||
name: z.string().nullable().optional().describe('Workflow name'),
|
||||
description: z.string().nullable().optional().describe('Workflow description'),
|
||||
triggerType: PluginTriggerTypeSchema,
|
||||
name: z.string().describe('Workflow name'),
|
||||
description: z.string().optional().describe('Workflow description'),
|
||||
enabled: z.boolean().optional().describe('Workflow enabled'),
|
||||
steps: z.array(WorkflowStepSchema).optional(),
|
||||
filters: z.array(WorkflowFilterItemSchema).describe('Workflow filters'),
|
||||
actions: z.array(WorkflowActionItemSchema).describe('Workflow actions'),
|
||||
})
|
||||
.meta({ id: 'WorkflowCreateDto' });
|
||||
|
||||
const WorkflowUpdateSchema = z
|
||||
.object({
|
||||
trigger: WorkflowTriggerSchema.optional().describe('Workflow trigger type'),
|
||||
name: z.string().nullable().optional().describe('Workflow name'),
|
||||
description: z.string().nullable().optional().describe('Workflow description'),
|
||||
triggerType: PluginTriggerTypeSchema.optional(),
|
||||
name: z.string().optional().describe('Workflow name'),
|
||||
description: z.string().optional().describe('Workflow description'),
|
||||
enabled: z.boolean().optional().describe('Workflow enabled'),
|
||||
steps: z.array(WorkflowStepSchema).optional(),
|
||||
filters: z.array(WorkflowFilterItemSchema).optional().describe('Workflow filters'),
|
||||
actions: z.array(WorkflowActionItemSchema).optional().describe('Workflow actions'),
|
||||
})
|
||||
.meta({ id: 'WorkflowUpdateDto' });
|
||||
|
||||
const WorkflowFilterResponseSchema = z
|
||||
.object({
|
||||
id: z.string().describe('Filter ID'),
|
||||
workflowId: z.string().describe('Workflow ID'),
|
||||
pluginFilterId: z.string().describe('Plugin filter ID'),
|
||||
filterConfig: FilterConfigSchema.nullable(),
|
||||
order: z.int().describe('Filter order'),
|
||||
})
|
||||
.meta({ id: 'WorkflowFilterResponseDto' });
|
||||
|
||||
const WorkflowActionResponseSchema = z
|
||||
.object({
|
||||
id: z.string().describe('Action ID'),
|
||||
workflowId: z.string().describe('Workflow ID'),
|
||||
pluginActionId: z.string().describe('Plugin action ID'),
|
||||
actionConfig: ActionConfigSchema.nullable(),
|
||||
order: z.int().describe('Action order'),
|
||||
})
|
||||
.meta({ id: 'WorkflowActionResponseDto' });
|
||||
|
||||
const WorkflowResponseSchema = z
|
||||
.object({
|
||||
id: z.string().describe('Workflow ID'),
|
||||
trigger: WorkflowTriggerSchema.describe('Workflow trigger type'),
|
||||
ownerId: z.string().describe('Owner user ID'),
|
||||
triggerType: PluginTriggerTypeSchema,
|
||||
name: z.string().nullable().describe('Workflow name'),
|
||||
description: z.string().nullable().describe('Workflow description'),
|
||||
description: z.string().describe('Workflow description'),
|
||||
createdAt: z.string().describe('Creation date'),
|
||||
updatedAt: z.string().describe('Update date'),
|
||||
enabled: z.boolean().describe('Workflow enabled'),
|
||||
steps: z.array(WorkflowStepSchema).describe('Workflow steps'),
|
||||
filters: z.array(WorkflowFilterResponseSchema).describe('Workflow filters'),
|
||||
actions: z.array(WorkflowActionResponseSchema).describe('Workflow actions'),
|
||||
})
|
||||
.meta({ id: 'WorkflowResponseDto' });
|
||||
|
||||
const WorkflowShareResponseSchema = z
|
||||
.object({
|
||||
trigger: WorkflowTriggerSchema.describe('Workflow trigger type'),
|
||||
name: z.string().nullable().describe('Workflow name'),
|
||||
description: z.string().nullable().describe('Workflow description'),
|
||||
steps: z.array(WorkflowShareStepSchema).describe('Workflow steps'),
|
||||
})
|
||||
.meta({ id: 'WorkflowShareResponseDto' });
|
||||
|
||||
export class WorkflowTriggerResponseDto extends createZodDto(WorkflowTriggerResponseSchema) {}
|
||||
export class WorkflowSearchDto extends createZodDto(WorkflowSearchSchema) {}
|
||||
export class WorkflowCreateDto extends createZodDto(WorkflowCreateSchema) {}
|
||||
export class WorkflowUpdateDto extends createZodDto(WorkflowUpdateSchema) {}
|
||||
export class WorkflowResponseDto extends createZodDto(WorkflowResponseSchema) {}
|
||||
export class WorkflowShareResponseDto extends createZodDto(WorkflowShareResponseSchema) {}
|
||||
class WorkflowFilterResponseDto extends createZodDto(WorkflowFilterResponseSchema) {}
|
||||
class WorkflowActionResponseDto extends createZodDto(WorkflowActionResponseSchema) {}
|
||||
|
||||
type Workflow = {
|
||||
id: string;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
trigger: WorkflowTrigger;
|
||||
name: string | null;
|
||||
description: string | null;
|
||||
enabled: boolean;
|
||||
};
|
||||
|
||||
type WorkflowStep = {
|
||||
enabled: boolean;
|
||||
methodName: string;
|
||||
config: WorkflowStepConfig | null;
|
||||
pluginName: string;
|
||||
};
|
||||
|
||||
export const mapWorkflow = (workflow: Workflow & { steps: WorkflowStep[] }): WorkflowResponseDto => {
|
||||
export function mapWorkflowFilter(filter: WorkflowFilter): WorkflowFilterResponseDto {
|
||||
return {
|
||||
id: workflow.id,
|
||||
enabled: workflow.enabled,
|
||||
trigger: workflow.trigger,
|
||||
name: workflow.name,
|
||||
description: workflow.description,
|
||||
createdAt: workflow.createdAt.toISOString(),
|
||||
updatedAt: workflow.updatedAt.toISOString(),
|
||||
steps: workflow.steps.map((step) => ({
|
||||
method: `${step.pluginName}#${step.methodName}`,
|
||||
// TODO fix this
|
||||
config: step.config as any,
|
||||
enabled: step.enabled,
|
||||
})),
|
||||
id: filter.id,
|
||||
workflowId: filter.workflowId,
|
||||
pluginFilterId: filter.pluginFilterId,
|
||||
filterConfig: filter.filterConfig,
|
||||
order: filter.order,
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export const mapWorkflowShare = (workflow: Workflow & { steps: WorkflowStep[] }): WorkflowShareResponseDto => {
|
||||
export function mapWorkflowAction(action: WorkflowAction): WorkflowActionResponseDto {
|
||||
return {
|
||||
trigger: workflow.trigger,
|
||||
name: workflow.name,
|
||||
description: workflow.description,
|
||||
steps: workflow.steps.map((step) => ({
|
||||
method: `${step.pluginName}#${step.methodName}`,
|
||||
// TODO fix this
|
||||
config: step.config as any,
|
||||
enabled: step.enabled ? undefined : false,
|
||||
})),
|
||||
id: action.id,
|
||||
workflowId: action.workflowId,
|
||||
pluginActionId: action.pluginActionId,
|
||||
actionConfig: action.actionConfig,
|
||||
order: action.order,
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
+6
-17
@@ -749,11 +749,8 @@ export enum BootstrapEventPriority {
|
||||
StorageService = -195,
|
||||
// Other services may need to queue jobs on bootstrap.
|
||||
JobService = -190,
|
||||
// Initialize config after other bootstrap services, stop other services from using config on bootstrap
|
||||
// Initialise config after other bootstrap services, stop other services from using config on bootstrap
|
||||
SystemConfig = 100,
|
||||
PluginSync = 190,
|
||||
// Load plugins into memory after sync
|
||||
PluginLoad = 200,
|
||||
}
|
||||
|
||||
export enum QueueName {
|
||||
@@ -866,7 +863,7 @@ export enum JobName {
|
||||
Ocr = 'Ocr',
|
||||
|
||||
// Workflow
|
||||
WorkflowAssetCreate = 'WorkflowAssetCreate',
|
||||
WorkflowRun = 'WorkflowRun',
|
||||
}
|
||||
|
||||
export const JobNameSchema = z.enum(JobName).describe('Job name').meta({ id: 'JobName' });
|
||||
@@ -912,7 +909,6 @@ export enum DatabaseLock {
|
||||
CLIPDimSize = 512,
|
||||
Library = 1337,
|
||||
NightlyJobs = 600,
|
||||
PluginImport = 666,
|
||||
MediaLocation = 700,
|
||||
GetSystemConfig = 69,
|
||||
BackupDatabase = 42,
|
||||
@@ -1164,19 +1160,12 @@ export enum PluginContext {
|
||||
|
||||
export const PluginContextSchema = z.enum(PluginContext).describe('Plugin context').meta({ id: 'PluginContextType' });
|
||||
|
||||
export enum WorkflowTrigger {
|
||||
export enum PluginTriggerType {
|
||||
AssetCreate = 'AssetCreate',
|
||||
PersonRecognized = 'PersonRecognized',
|
||||
}
|
||||
|
||||
export const WorkflowTriggerSchema = z
|
||||
.enum(WorkflowTrigger)
|
||||
export const PluginTriggerTypeSchema = z
|
||||
.enum(PluginTriggerType)
|
||||
.describe('Plugin trigger type')
|
||||
.meta({ id: 'WorkflowTrigger' });
|
||||
|
||||
export enum WorkflowType {
|
||||
AssetV1 = 'AssetV1',
|
||||
AssetPersonV1 = 'AssetPersonV1',
|
||||
}
|
||||
|
||||
export const WorkflowTypeSchema = z.enum(WorkflowType).describe('Workflow type').meta({ id: 'WorkflowType' });
|
||||
.meta({ id: 'PluginTriggerType' });
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
import { PluginContext, PluginTriggerType } from 'src/enum';
|
||||
|
||||
export type PluginTrigger = {
|
||||
type: PluginTriggerType;
|
||||
contextType: PluginContext;
|
||||
};
|
||||
|
||||
export const pluginTriggers: PluginTrigger[] = [
|
||||
{
|
||||
type: PluginTriggerType.AssetCreate,
|
||||
contextType: PluginContext.Asset,
|
||||
},
|
||||
{
|
||||
type: PluginTriggerType.PersonRecognized,
|
||||
contextType: PluginContext.Person,
|
||||
},
|
||||
];
|
||||
@@ -1,159 +1,159 @@
|
||||
-- NOTE: This file is auto generated by ./sql-generator
|
||||
|
||||
-- PluginRepository.getForLoad
|
||||
-- PluginRepository.getPlugin
|
||||
select
|
||||
"plugin"."id",
|
||||
"plugin"."name",
|
||||
"plugin"."version",
|
||||
"plugin"."wasmBytes",
|
||||
"plugin"."id" as "id",
|
||||
"plugin"."name" as "name",
|
||||
"plugin"."title" as "title",
|
||||
"plugin"."description" as "description",
|
||||
"plugin"."author" as "author",
|
||||
"plugin"."version" as "version",
|
||||
"plugin"."wasmPath" as "wasmPath",
|
||||
"plugin"."createdAt" as "createdAt",
|
||||
"plugin"."updatedAt" as "updatedAt",
|
||||
(
|
||||
select
|
||||
coalesce(json_agg(agg), '[]')
|
||||
from
|
||||
(
|
||||
select
|
||||
"plugin_method"."name",
|
||||
"plugin_method"."hostFunctions"
|
||||
*
|
||||
from
|
||||
"plugin_method"
|
||||
"plugin_filter"
|
||||
where
|
||||
"plugin_method"."pluginId" = "plugin"."id"
|
||||
"plugin_filter"."pluginId" = "plugin"."id"
|
||||
) as agg
|
||||
) as "methods"
|
||||
from
|
||||
"plugin"
|
||||
where
|
||||
"enabled" = $1
|
||||
|
||||
-- PluginRepository.search
|
||||
select
|
||||
"plugin"."id",
|
||||
"plugin"."name",
|
||||
"plugin"."title",
|
||||
"plugin"."description",
|
||||
"plugin"."author",
|
||||
"plugin"."version",
|
||||
"plugin"."createdAt",
|
||||
"plugin"."updatedAt",
|
||||
) as "filters",
|
||||
(
|
||||
select
|
||||
coalesce(json_agg(agg), '[]')
|
||||
from
|
||||
(
|
||||
select
|
||||
"plugin_method"."name",
|
||||
"plugin_method"."title",
|
||||
"plugin_method"."description",
|
||||
"plugin_method"."types",
|
||||
"plugin_method"."schema",
|
||||
"plugin_method"."hostFunctions",
|
||||
"plugin_method"."uiHints",
|
||||
"plugin"."name" as "pluginName"
|
||||
*
|
||||
from
|
||||
"plugin_method"
|
||||
"plugin_action"
|
||||
where
|
||||
"plugin_method"."pluginId" = "plugin"."id"
|
||||
"plugin_action"."pluginId" = "plugin"."id"
|
||||
) as agg
|
||||
) as "methods"
|
||||
from
|
||||
"plugin"
|
||||
order by
|
||||
"plugin"."name"
|
||||
|
||||
-- PluginRepository.getByName
|
||||
select
|
||||
"plugin"."id",
|
||||
"plugin"."name",
|
||||
"plugin"."title",
|
||||
"plugin"."description",
|
||||
"plugin"."author",
|
||||
"plugin"."version",
|
||||
"plugin"."createdAt",
|
||||
"plugin"."updatedAt",
|
||||
(
|
||||
select
|
||||
coalesce(json_agg(agg), '[]')
|
||||
from
|
||||
(
|
||||
select
|
||||
"plugin_method"."name",
|
||||
"plugin_method"."title",
|
||||
"plugin_method"."description",
|
||||
"plugin_method"."types",
|
||||
"plugin_method"."schema",
|
||||
"plugin_method"."hostFunctions",
|
||||
"plugin_method"."uiHints",
|
||||
"plugin"."name" as "pluginName"
|
||||
from
|
||||
"plugin_method"
|
||||
where
|
||||
"plugin_method"."pluginId" = "plugin"."id"
|
||||
) as agg
|
||||
) as "methods"
|
||||
from
|
||||
"plugin"
|
||||
where
|
||||
"plugin"."name" = $1
|
||||
|
||||
-- PluginRepository.get
|
||||
select
|
||||
"plugin"."id",
|
||||
"plugin"."name",
|
||||
"plugin"."title",
|
||||
"plugin"."description",
|
||||
"plugin"."author",
|
||||
"plugin"."version",
|
||||
"plugin"."createdAt",
|
||||
"plugin"."updatedAt",
|
||||
(
|
||||
select
|
||||
coalesce(json_agg(agg), '[]')
|
||||
from
|
||||
(
|
||||
select
|
||||
"plugin_method"."name",
|
||||
"plugin_method"."title",
|
||||
"plugin_method"."description",
|
||||
"plugin_method"."types",
|
||||
"plugin_method"."schema",
|
||||
"plugin_method"."hostFunctions",
|
||||
"plugin_method"."uiHints",
|
||||
"plugin"."name" as "pluginName"
|
||||
from
|
||||
"plugin_method"
|
||||
where
|
||||
"plugin_method"."pluginId" = "plugin"."id"
|
||||
) as agg
|
||||
) as "methods"
|
||||
) as "actions"
|
||||
from
|
||||
"plugin"
|
||||
where
|
||||
"plugin"."id" = $1
|
||||
|
||||
-- PluginRepository.getForValidation
|
||||
-- PluginRepository.getPluginByName
|
||||
select
|
||||
"plugin_method"."id",
|
||||
"plugin_method"."name",
|
||||
"plugin"."name" as "pluginName",
|
||||
"plugin_method"."types"
|
||||
"plugin"."id" as "id",
|
||||
"plugin"."name" as "name",
|
||||
"plugin"."title" as "title",
|
||||
"plugin"."description" as "description",
|
||||
"plugin"."author" as "author",
|
||||
"plugin"."version" as "version",
|
||||
"plugin"."wasmPath" as "wasmPath",
|
||||
"plugin"."createdAt" as "createdAt",
|
||||
"plugin"."updatedAt" as "updatedAt",
|
||||
(
|
||||
select
|
||||
coalesce(json_agg(agg), '[]')
|
||||
from
|
||||
(
|
||||
select
|
||||
*
|
||||
from
|
||||
"plugin_filter"
|
||||
where
|
||||
"plugin_filter"."pluginId" = "plugin"."id"
|
||||
) as agg
|
||||
) as "filters",
|
||||
(
|
||||
select
|
||||
coalesce(json_agg(agg), '[]')
|
||||
from
|
||||
(
|
||||
select
|
||||
*
|
||||
from
|
||||
"plugin_action"
|
||||
where
|
||||
"plugin_action"."pluginId" = "plugin"."id"
|
||||
) as agg
|
||||
) as "actions"
|
||||
from
|
||||
"plugin_method"
|
||||
inner join "plugin" on "plugin_method"."pluginId" = "plugin"."id"
|
||||
"plugin"
|
||||
where
|
||||
"plugin"."name" = $1
|
||||
|
||||
-- PluginRepository.searchMethods
|
||||
-- PluginRepository.getAllPlugins
|
||||
select
|
||||
"plugin"."name" as "pluginName",
|
||||
"plugin_method"."pluginId",
|
||||
"plugin_method"."id",
|
||||
"plugin_method"."name",
|
||||
"plugin_method"."title",
|
||||
"plugin_method"."description",
|
||||
"plugin_method"."types",
|
||||
"plugin_method"."schema",
|
||||
"plugin_method"."hostFunctions",
|
||||
"plugin_method"."uiHints"
|
||||
"plugin"."id" as "id",
|
||||
"plugin"."name" as "name",
|
||||
"plugin"."title" as "title",
|
||||
"plugin"."description" as "description",
|
||||
"plugin"."author" as "author",
|
||||
"plugin"."version" as "version",
|
||||
"plugin"."wasmPath" as "wasmPath",
|
||||
"plugin"."createdAt" as "createdAt",
|
||||
"plugin"."updatedAt" as "updatedAt",
|
||||
(
|
||||
select
|
||||
coalesce(json_agg(agg), '[]')
|
||||
from
|
||||
(
|
||||
select
|
||||
*
|
||||
from
|
||||
"plugin_filter"
|
||||
where
|
||||
"plugin_filter"."pluginId" = "plugin"."id"
|
||||
) as agg
|
||||
) as "filters",
|
||||
(
|
||||
select
|
||||
coalesce(json_agg(agg), '[]')
|
||||
from
|
||||
(
|
||||
select
|
||||
*
|
||||
from
|
||||
"plugin_action"
|
||||
where
|
||||
"plugin_action"."pluginId" = "plugin"."id"
|
||||
) as agg
|
||||
) as "actions"
|
||||
from
|
||||
"plugin_method"
|
||||
inner join "plugin" on "plugin"."id" = "plugin_method"."pluginId"
|
||||
"plugin"
|
||||
order by
|
||||
"plugin_method"."name"
|
||||
"plugin"."name"
|
||||
|
||||
-- PluginRepository.getFilter
|
||||
select
|
||||
*
|
||||
from
|
||||
"plugin_filter"
|
||||
where
|
||||
"id" = $1
|
||||
|
||||
-- PluginRepository.getFiltersByPlugin
|
||||
select
|
||||
*
|
||||
from
|
||||
"plugin_filter"
|
||||
where
|
||||
"pluginId" = $1
|
||||
|
||||
-- PluginRepository.getAction
|
||||
select
|
||||
*
|
||||
from
|
||||
"plugin_action"
|
||||
where
|
||||
"id" = $1
|
||||
|
||||
-- PluginRepository.getActionsByPlugin
|
||||
select
|
||||
*
|
||||
from
|
||||
"plugin_action"
|
||||
where
|
||||
"pluginId" = $1
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user