# Appwrite schema bootstrap (PowerShell) fuer Appwrite Server 1.8.x # Ziel: Alte Struktur behalten (kompatibel) + neue "upright v1" Felder integrieren. # # Tabellen: users, accounts, products, product_details # # Prereqs: # appwrite login # appwrite init project # # Run: # pwsh .\appwrite_schema_upright_v1.ps1 -DatabaseId "YOUR_DATABASE_ID" param( [Parameter(Mandatory = $true)] [string]$DatabaseId, # Optional: setze auf $true, wenn du Fulltext-Indizes wirklich nutzen willst. [bool]$EnableFulltextIndexes = $false ) Set-StrictMode -Version Latest $ErrorActionPreference = "Stop" # ---------------- CONFIG ---------------- $T_USERS = "users" $T_ACCOUNTS = "accounts" $T_PRODUCTS = "products" $T_PRODUCT_DETAILS = "product_details" # Minimal offene Defaults (spaeter ggf. locken) $PERMS_ANY_CRUD = @('create(any)','read(any)','update(any)','delete(any)') # ---------------- HELPERS ---------------- function Try-Cmd { param( [Parameter(Mandatory = $true)] [string[]]$Args ) $cmd = "appwrite " + ($Args -join " ") Write-Host ("+ " + $cmd) try { & appwrite @Args | Out-Host } catch { Write-Host (" (ignored error) " + $_.Exception.Message) } } function Create-Table { param( [Parameter(Mandatory = $true)][string]$TableId, [Parameter(Mandatory = $true)][string]$Name ) # Note: Permissions für TablesDB werden anders verwaltet (optional) # Hier erstellen wir die Tabelle ohne Permissions $argsList = @( "tables-db","create-table", "--database-id",$DatabaseId, "--table-id",$TableId, "--name",$Name, "--row-security","false" ) Try-Cmd $argsList } # ---------------- CREATE TABLES ---------------- Create-Table -TableId $T_USERS -Name "users" Create-Table -TableId $T_ACCOUNTS -Name "accounts" Create-Table -TableId $T_PRODUCTS -Name "products" Create-Table -TableId $T_PRODUCT_DETAILS -Name "product_details" # ---------------- USERS COLUMNS ---------------- # Legacy kompatibel: user_note Try-Cmd @("tables-db","create-string-column","--database-id",$DatabaseId,"--table-id",$T_USERS,"--key","user_note","--size","255","--required","false","--array","false") # Upright v1: created/updated timestamps (optional) Try-Cmd @("tables-db","create-datetime-column","--database-id",$DatabaseId,"--table-id",$T_USERS,"--key","user_created_at","--required","false","--array","false") Try-Cmd @("tables-db","create-datetime-column","--database-id",$DatabaseId,"--table-id",$T_USERS,"--key","user_updated_at","--required","false","--array","false") # Optional index: user_created_at (wenn du sorting/listing brauchst) Try-Cmd @("tables-db","create-index","--database-id",$DatabaseId,"--table-id",$T_USERS,"--key","users_by_created_at","--type","key","--columns","user_created_at") # ---------------- ACCOUNTS COLUMNS ---------------- # Upright v1: Try-Cmd @("tables-db","create-string-column","--database-id",$DatabaseId,"--table-id",$T_ACCOUNTS,"--key","account_owner_user_id","--size","64","--required","false","--array","false") # Legacy: account_managed (alte scripts) Try-Cmd @("tables-db","create-boolean-column","--database-id",$DatabaseId,"--table-id",$T_ACCOUNTS,"--key","account_managed","--required","false","--array","false") # Upright v1: account_team (true = managed/team, false = scanned) Try-Cmd @("tables-db","create-boolean-column","--database-id",$DatabaseId,"--table-id",$T_ACCOUNTS,"--key","account_team","--required","true","--array","false") Try-Cmd @("tables-db","create-enum-column","--database-id",$DatabaseId,"--table-id",$T_ACCOUNTS,"--key","account_platform","--elements",'["amazon","ebay"]',"--required","true","--array","false") Try-Cmd @("tables-db","create-string-column","--database-id",$DatabaseId,"--table-id",$T_ACCOUNTS,"--key","account_platform_account_id","--size","255","--required","true","--array","false") Try-Cmd @("tables-db","create-string-column","--database-id",$DatabaseId,"--table-id",$T_ACCOUNTS,"--key","account_platform_market","--size","32","--required","true","--array","false") Try-Cmd @("tables-db","create-string-column","--database-id",$DatabaseId,"--table-id",$T_ACCOUNTS,"--key","account_shop_name","--size","255","--required","false","--array","false") Try-Cmd @("tables-db","create-url-column","--database-id",$DatabaseId,"--table-id",$T_ACCOUNTS,"--key","account_url","--required","false","--array","false") # Statistik: Anzahl verkaufter Items Try-Cmd @("tables-db","create-integer-column","--database-id",$DatabaseId,"--table-id",$T_ACCOUNTS,"--key","account_sells","--required","false","--array","false") Try-Cmd @("tables-db","create-enum-column","--database-id",$DatabaseId,"--table-id",$T_ACCOUNTS,"--key","account_status","--elements",'["active","unknown","disabled"]',"--required","false","--array","false") Try-Cmd @("tables-db","create-datetime-column","--database-id",$DatabaseId,"--table-id",$T_ACCOUNTS,"--key","account_created_at","--required","false","--array","false") Try-Cmd @("tables-db","create-datetime-column","--database-id",$DatabaseId,"--table-id",$T_ACCOUNTS,"--key","account_updated_at","--required","false","--array","false") # ---------------- ACCOUNTS INDEXES ---------------- Try-Cmd @("tables-db","create-index","--database-id",$DatabaseId,"--table-id",$T_ACCOUNTS,"--key","uniq_plat_mkt_accountid","--type","unique","--columns","account_platform","account_platform_market","account_platform_account_id") Try-Cmd @("tables-db","create-index","--database-id",$DatabaseId,"--table-id",$T_ACCOUNTS,"--key","accounts_by_owner_user","--type","key","--columns","account_owner_user_id") # Optional: account_team index Try-Cmd @("tables-db","create-index","--database-id",$DatabaseId,"--table-id",$T_ACCOUNTS,"--key","accounts_by_team_flag","--type","key","--columns","account_team") # ---------------- PRODUCTS COLUMNS ---------------- # Stable basis (legacy + upright v1) Try-Cmd @("tables-db","create-string-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCTS,"--key","product_account_id","--size","64","--required","true","--array","false") Try-Cmd @("tables-db","create-enum-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCTS,"--key","product_platform","--elements",'["amazon","ebay"]',"--required","true","--array","false") Try-Cmd @("tables-db","create-string-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCTS,"--key","product_platform_market","--size","32","--required","true","--array","false") Try-Cmd @("tables-db","create-string-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCTS,"--key","product_platform_product_id","--size","255","--required","true","--array","false") Try-Cmd @("tables-db","create-url-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCTS,"--key","product_url","--required","false","--array","false") Try-Cmd @("tables-db","create-string-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCTS,"--key","product_title","--size","1024","--required","true","--array","false") # Legacy: product_category Try-Cmd @("tables-db","create-string-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCTS,"--key","product_category","--size","255","--required","false","--array","false") # Condition/status (upright v1 erweitert unknown) Try-Cmd @("tables-db","create-enum-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCTS,"--key","product_condition","--elements",'["new","used_like_new","used_good","used_ok","parts","unknown"]',"--required","false","--array","false") Try-Cmd @("tables-db","create-enum-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCTS,"--key","product_status","--elements",'["active","ended","unknown"]',"--required","false","--array","false") # Volatile (Sparscan) - neue Felder Try-Cmd @("tables-db","create-float-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCTS,"--key","product_price","--required","false","--array","false") Try-Cmd @("tables-db","create-string-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCTS,"--key","product_currency","--size","8","--required","false","--array","false") Try-Cmd @("tables-db","create-integer-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCTS,"--key","product_quantity_available","--required","false","--array","false") Try-Cmd @("tables-db","create-integer-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCTS,"--key","product_quantity_sold","--required","false","--array","false") Try-Cmd @("tables-db","create-integer-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCTS,"--key","product_watch_count","--required","false","--array","false") Try-Cmd @("tables-db","create-integer-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCTS,"--key","product_in_carts_count","--required","false","--array","false") Try-Cmd @("tables-db","create-datetime-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCTS,"--key","product_last_seen_at","--required","false","--array","false") # Legacy kompatibel: product_quantity (alt) Try-Cmd @("tables-db","create-integer-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCTS,"--key","product_quantity","--required","false","--array","false") # Scan-Steuerung Try-Cmd @("tables-db","create-datetime-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCTS,"--key","product_first_fullscan_at","--required","false","--array","false") Try-Cmd @("tables-db","create-datetime-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCTS,"--key","product_last_fullscan_at","--required","false","--array","false") Try-Cmd @("tables-db","create-datetime-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCTS,"--key","product_last_sparscan_at","--required","false","--array","false") Try-Cmd @("tables-db","create-integer-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCTS,"--key","product_details_version","--required","false","--array","false") # ---------------- PRODUCTS INDEXES ---------------- Try-Cmd @("tables-db","create-index","--database-id",$DatabaseId,"--table-id",$T_PRODUCTS,"--key","products_by_account","--type","key","--columns","product_account_id") Try-Cmd @("tables-db","create-index","--database-id",$DatabaseId,"--table-id",$T_PRODUCTS,"--key","uniq_acct_platformprod_id","--type","unique","--columns","product_account_id","product_platform_product_id") # Optional indices Try-Cmd @("tables-db","create-index","--database-id",$DatabaseId,"--table-id",$T_PRODUCTS,"--key","products_by_platform_market","--type","key","--columns","product_platform","product_platform_market") Try-Cmd @("tables-db","create-index","--database-id",$DatabaseId,"--table-id",$T_PRODUCTS,"--key","products_by_status","--type","key","--columns","product_status") if ($EnableFulltextIndexes) { # Hinweis: Fulltext kann je nach Appwrite/CLI Build abweichen. Falls es bei dir anders heisst: # appwrite tables-db create-index --help Try-Cmd @("tables-db","create-index","--database-id",$DatabaseId,"--table-id",$T_PRODUCTS,"--key","products_fulltext_title","--type","fulltext","--columns","product_title") } # ---------------- PRODUCT_DETAILS COLUMNS ---------------- # Upright v1 minimal (neu) Try-Cmd @("tables-db","create-string-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCT_DETAILS,"--key","product_id","--size","64","--required","true","--array","false") Try-Cmd @("tables-db","create-string-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCT_DETAILS,"--key","details_category_path","--size","2048","--required","false","--array","false") Try-Cmd @("tables-db","create-string-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCT_DETAILS,"--key","details_brand","--size","255","--required","false","--array","false") Try-Cmd @("tables-db","create-string-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCT_DETAILS,"--key","details_mpn","--size","64","--required","false","--array","false") Try-Cmd @("tables-db","create-string-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCT_DETAILS,"--key","details_gtin","--size","32","--required","false","--array","false") Try-Cmd @("tables-db","create-string-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCT_DETAILS,"--key","details_description_text","--size","8192","--required","false","--array","false") # Array of image urls Try-Cmd @("tables-db","create-string-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCT_DETAILS,"--key","details_image_urls","--size","2048","--required","false","--array","true") # JSON-as-string Try-Cmd @("tables-db","create-string-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCT_DETAILS,"--key","details_item_specifics_json","--size","8192","--required","false","--array","false") Try-Cmd @("tables-db","create-boolean-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCT_DETAILS,"--key","details_has_variations","--required","false","--array","false") Try-Cmd @("tables-db","create-string-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCT_DETAILS,"--key","details_variations_json","--size","8192","--required","false","--array","false") Try-Cmd @("tables-db","create-datetime-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCT_DETAILS,"--key","details_last_updated_at","--required","false","--array","false") # Legacy detail schema (alt) - behalten fuer Kompatibilitaet Try-Cmd @("tables-db","create-string-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCT_DETAILS,"--key","product_detail_product_id","--size","64","--required","false","--array","false") Try-Cmd @("tables-db","create-enum-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCT_DETAILS,"--key","product_detail_platform","--elements",'["amazon","ebay"]',"--required","false","--array","false") Try-Cmd @("tables-db","create-string-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCT_DETAILS,"--key","product_detail_platform_market","--size","32","--required","false","--array","false") Try-Cmd @("tables-db","create-string-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCT_DETAILS,"--key","product_detail_gtin","--size","32","--required","false","--array","false") Try-Cmd @("tables-db","create-string-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCT_DETAILS,"--key","product_detail_ean","--size","32","--required","false","--array","false") Try-Cmd @("tables-db","create-string-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCT_DETAILS,"--key","product_detail_upc","--size","32","--required","false","--array","false") Try-Cmd @("tables-db","create-string-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCT_DETAILS,"--key","product_detail_isbn","--size","32","--required","false","--array","false") Try-Cmd @("tables-db","create-string-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCT_DETAILS,"--key","product_detail_mpn","--size","64","--required","false","--array","false") Try-Cmd @("tables-db","create-string-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCT_DETAILS,"--key","product_detail_amazon_asin","--size","32","--required","false","--array","false") Try-Cmd @("tables-db","create-string-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCT_DETAILS,"--key","product_detail_ebay_epid","--size","64","--required","false","--array","false") Try-Cmd @("tables-db","create-string-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCT_DETAILS,"--key","product_detail_brand","--size","255","--required","false","--array","false") Try-Cmd @("tables-db","create-string-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCT_DETAILS,"--key","product_detail_manufacturer","--size","255","--required","false","--array","false") Try-Cmd @("tables-db","create-string-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCT_DETAILS,"--key","product_detail_model_name","--size","255","--required","false","--array","false") Try-Cmd @("tables-db","create-string-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCT_DETAILS,"--key","product_detail_model_number","--size","255","--required","false","--array","false") Try-Cmd @("tables-db","create-string-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCT_DETAILS,"--key","product_detail_short_description","--size","2048","--required","false","--array","false") Try-Cmd @("tables-db","create-string-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCT_DETAILS,"--key","product_detail_long_description","--size","8192","--required","false","--array","false") for ($i = 1; $i -le 8; $i++) { Try-Cmd @("tables-db","create-string-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCT_DETAILS,"--key",("product_detail_bullet_" + $i),"--size","512","--required","false","--array","false") } Try-Cmd @("tables-db","create-string-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCT_DETAILS,"--key","product_detail_search_terms","--size","1024","--required","false","--array","false") Try-Cmd @("tables-db","create-string-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCT_DETAILS,"--key","product_detail_color","--size","128","--required","false","--array","false") Try-Cmd @("tables-db","create-string-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCT_DETAILS,"--key","product_detail_size","--size","128","--required","false","--array","false") Try-Cmd @("tables-db","create-string-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCT_DETAILS,"--key","product_detail_material","--size","128","--required","false","--array","false") Try-Cmd @("tables-db","create-string-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCT_DETAILS,"--key","product_detail_pattern","--size","128","--required","false","--array","false") Try-Cmd @("tables-db","create-float-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCT_DETAILS,"--key","product_detail_length","--required","false","--array","false") Try-Cmd @("tables-db","create-float-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCT_DETAILS,"--key","product_detail_width","--required","false","--array","false") Try-Cmd @("tables-db","create-float-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCT_DETAILS,"--key","product_detail_height","--required","false","--array","false") Try-Cmd @("tables-db","create-enum-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCT_DETAILS,"--key","product_detail_dimension_unit","--elements",'["mm","cm","m","in"]',"--required","false","--array","false") Try-Cmd @("tables-db","create-float-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCT_DETAILS,"--key","product_detail_weight","--required","false","--array","false") Try-Cmd @("tables-db","create-enum-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCT_DETAILS,"--key","product_detail_weight_unit","--elements",'["g","kg","oz","lb"]',"--required","false","--array","false") Try-Cmd @("tables-db","create-string-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCT_DETAILS,"--key","product_detail_country_of_origin","--size","64","--required","false","--array","false") Try-Cmd @("tables-db","create-integer-column","--database-id",$DatabaseId,"--table-id",$T_PRODUCT_DETAILS,"--key","product_detail_package_quantity","--required","false","--array","false") # ---------------- PRODUCT_DETAILS INDEXES ---------------- # Upright v1 unique 1:1 Try-Cmd @("tables-db","create-index","--database-id",$DatabaseId,"--table-id",$T_PRODUCT_DETAILS,"--key","prod_details_uniq_product_id","--type","unique","--columns","product_id") # Legacy unique (optional, kann leer bleiben) Try-Cmd @("tables-db","create-index","--database-id",$DatabaseId,"--table-id",$T_PRODUCT_DETAILS,"--key","prod_details_legacy_prod_id","--type","unique","--columns","product_detail_product_id") # Legacy: by platform (wenn du es brauchst) Try-Cmd @("tables-db","create-index","--database-id",$DatabaseId,"--table-id",$T_PRODUCT_DETAILS,"--key","prod_details_by_platform","--type","key","--columns","product_detail_platform") if ($EnableFulltextIndexes) { Try-Cmd @("tables-db","create-index","--database-id",$DatabaseId,"--table-id",$T_PRODUCT_DETAILS,"--key","prod_details_ft_description","--type","fulltext","--columns","details_description_text") } Write-Host "Done. Ensured 4 tables: users, accounts, products, product_details" Write-Host "" Write-Host "App logic reminder (upright v1):" Write-Host "- If account_team == true => account_owner_user_id must be set" Write-Host "- If account_team == false => account_owner_user_id must be null" Write-Host "" Write-Host "Scan rules reminder:" Write-Host "- If account has 0 products => fullscan (products + product_details)" Write-Host "- Else sparscan updates volatile fields in products (price/qty/watch/carts/status/last_seen)" Write-Host "- Fullscan a product if product_details missing OR product_last_fullscan_at older than your threshold (e.g. 30 days)"