@earbug/db-models 0.0.62 → 0.0.63

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/.dockerignore +10 -0
  2. package/.github/workflows/publish.yaml +303 -0
  3. package/.nvmrc +1 -0
  4. package/Dockerfile.generate +19 -0
  5. package/model_options.json +3 -0
  6. package/models/AccessControlPreference.ts +53 -0
  7. package/models/AffinityRelationshipType.ts +96 -0
  8. package/models/AffinityTier.ts +131 -0
  9. package/models/AppUser.ts +577 -0
  10. package/models/AppUserDevice.ts +101 -0
  11. package/models/AppUserDeviceClassicBackup20260906.ts +66 -0
  12. package/models/AppUserFollowRelation.ts +128 -0
  13. package/models/AppUserPlatformRelation.ts +150 -0
  14. package/models/CanonAlbum.ts +229 -0
  15. package/models/CanonAlbumExternalReferenceRelation.ts +92 -0
  16. package/models/CanonAlbumGenreRelation.ts +86 -0
  17. package/models/CanonAlbumLabelRelation.ts +86 -0
  18. package/models/CanonAlbumTrackRelation.ts +92 -0
  19. package/models/CanonArtist.ts +356 -0
  20. package/models/CanonArtistAlbumRelation.ts +92 -0
  21. package/models/CanonArtistExternalReferenceRelation.ts +92 -0
  22. package/models/CanonArtistGenreRelation.ts +86 -0
  23. package/models/CanonArtistMemberRelation.ts +86 -0
  24. package/models/CanonArtistTrackRelation.ts +92 -0
  25. package/models/CanonGenre.ts +273 -0
  26. package/models/CanonGenreExternalReferenceRelation.ts +92 -0
  27. package/models/CanonLabel.ts +129 -0
  28. package/models/CanonLabelExternalReferenceRelation.ts +92 -0
  29. package/models/CanonMember.ts +130 -0
  30. package/models/CanonMemberExternalReferenceRelation.ts +99 -0
  31. package/models/CanonToPlatformAlbumRelation.ts +92 -0
  32. package/models/CanonToPlatformArtistRelation.ts +92 -0
  33. package/models/CanonToPlatformGenreRelation.ts +86 -0
  34. package/models/CanonToPlatformTrackRelation.ts +92 -0
  35. package/models/CanonTrack.ts +232 -0
  36. package/models/ConfigParam.ts +62 -0
  37. package/models/ExternalReference.ts +201 -0
  38. package/models/FeedConfig.ts +65 -0
  39. package/models/FeedContentType.ts +124 -0
  40. package/models/GuestUser.ts +137 -0
  41. package/models/JukeboxAccessType.ts +60 -0
  42. package/models/JukeboxCanonGenreRelation.ts +108 -0
  43. package/models/JukeboxInvite.ts +125 -0
  44. package/models/JukeboxQueueEntry.ts +247 -0
  45. package/models/JukeboxQueueMode.ts +60 -0
  46. package/models/JukeboxSession.ts +334 -0
  47. package/models/JukeboxSessionArtistAffinity.ts +136 -0
  48. package/models/JukeboxSessionGenreAffinity.ts +136 -0
  49. package/models/JukeboxStatus.ts +58 -0
  50. package/models/JukeboxTerminationCondition.ts +60 -0
  51. package/models/JukeboxType.ts +60 -0
  52. package/models/JukeboxUser.ts +182 -0
  53. package/models/JukeboxUserType.ts +58 -0
  54. package/models/KnexMigrations.ts +60 -0
  55. package/models/KnexMigrationsLock.ts +48 -0
  56. package/models/MerchItem.ts +198 -0
  57. package/models/MerchOrchestration.ts +130 -0
  58. package/models/MerchPlatform.ts +95 -0
  59. package/models/MerchType.ts +89 -0
  60. package/models/MetricsDaily.ts +79 -0
  61. package/models/MetricsEvent.ts +124 -0
  62. package/models/NewsArticle.ts +177 -0
  63. package/models/NewsPlatform.ts +76 -0
  64. package/models/NewsSite.ts +75 -0
  65. package/models/Notification.ts +214 -0
  66. package/models/NotificationType.ts +66 -0
  67. package/models/PauseStatusType.ts +58 -0
  68. package/models/Platform.ts +189 -0
  69. package/models/PlatformAlbum.ts +398 -0
  70. package/models/PlatformAlbumGenreRelation.ts +86 -0
  71. package/models/PlatformAlbumTrackRelation.ts +92 -0
  72. package/models/PlatformArtist.ts +358 -0
  73. package/models/PlatformArtistAlbumRelation.ts +92 -0
  74. package/models/PlatformArtistGenreRelation.ts +86 -0
  75. package/models/PlatformArtistTrackRelation.ts +92 -0
  76. package/models/PlatformGenre.ts +194 -0
  77. package/models/PlatformTrack.ts +339 -0
  78. package/models/PlatformTrackGenreRelation.ts +86 -0
  79. package/models/PlatformUserAlbum.ts +152 -0
  80. package/models/PlatformUserAlbumTrack.ts +138 -0
  81. package/models/PlatformUserPlaylist.ts +260 -0
  82. package/models/PlatformUserPlaylistArtistAffinity.ts +136 -0
  83. package/models/PlatformUserPlaylistGenreAffinity.ts +136 -0
  84. package/models/PlatformUserPlaylistTrack.ts +162 -0
  85. package/models/PlaybackStatus.ts +47 -0
  86. package/models/PlaybackStatusType.ts +58 -0
  87. package/models/RadioShow.ts +209 -0
  88. package/models/RadioShowGenres.ts +107 -0
  89. package/models/RadioShowMedia.ts +181 -0
  90. package/models/RadioShowPlacement.ts +115 -0
  91. package/models/RadioShowPublishRequests.ts +86 -0
  92. package/models/State.ts +86 -0
  93. package/models/TrackDeletionReason.ts +58 -0
  94. package/models/UnmatchedAlbum.ts +66 -0
  95. package/models/UnmatchedArtist.ts +81 -0
  96. package/models/UserAbuseReports.ts +232 -0
  97. package/models/UserAffinity.ts +117 -0
  98. package/models/UserArtistAffinity.ts +136 -0
  99. package/models/UserBookmarks.ts +235 -0
  100. package/models/UserComments.ts +271 -0
  101. package/models/UserContacts.ts +155 -0
  102. package/models/UserEngagementFactor.ts +109 -0
  103. package/models/UserGenreAffinity.ts +136 -0
  104. package/models/UserLikes.ts +235 -0
  105. package/models/UserMessages.ts +189 -0
  106. package/models/Versus.ts +438 -0
  107. package/models/VersusAccessType.ts +66 -0
  108. package/models/VersusCoCreator.ts +111 -0
  109. package/models/VersusCreatorScope.ts +66 -0
  110. package/models/VersusEndMode.ts +66 -0
  111. package/models/VersusEndTimerDuration.ts +81 -0
  112. package/models/VersusEndVoteThreshold.ts +67 -0
  113. package/models/VersusEntityKind.ts +79 -0
  114. package/models/VersusOption.ts +258 -0
  115. package/models/VersusPublishIssue.ts +146 -0
  116. package/models/VersusQuestion.ts +123 -0
  117. package/models/VersusQuestionVariableType.ts +66 -0
  118. package/models/VersusVote.ts +99 -0
  119. package/models/VersusVotingListType.ts +66 -0
  120. package/models/VersusVotingMode.ts +66 -0
  121. package/models/index.ts +3 -0
  122. package/models/init-models.ts +1259 -0
  123. package/models/initDb.ts +72 -0
  124. package/models/rdsCaBundle.ts +5 -0
  125. package/package.json +2 -5
  126. package/scripts/generate-and-upload.mjs +123 -0
  127. package/scripts/update-rds-ca-bundle.mjs +44 -0
  128. package/tsconfig.json +52 -0
package/.dockerignore ADDED
@@ -0,0 +1,10 @@
1
+ *
2
+ !.dockerignore
3
+ !Dockerfile.generate
4
+ !package.json
5
+ !package-lock.json
6
+ !model_options.json
7
+ !models/
8
+ !models/**
9
+ !scripts/
10
+ !scripts/generate-and-upload.mjs
@@ -0,0 +1,303 @@
1
+ name: Regenerate Models and Publish
2
+
3
+ on:
4
+ repository_dispatch:
5
+ types: [migration_completed]
6
+
7
+ concurrency:
8
+ group: db-models-publish
9
+ cancel-in-progress: false
10
+
11
+ jobs:
12
+ publish:
13
+ name: Regenerate, Build, and Publish
14
+ runs-on: ubuntu-latest
15
+ timeout-minutes: 30
16
+ environment: dev
17
+ env:
18
+ AWS_REGION: us-east-1
19
+ SSM_PREFIX: /earbug-dev/db-models
20
+ AWS_ACCOUNT_ID: "630596767721"
21
+ ECR_REGISTRY_ACCOUNT_ID: "146319281891"
22
+ permissions:
23
+ contents: read
24
+ id-token: write
25
+ steps:
26
+ - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
27
+ with:
28
+ persist-credentials: false
29
+
30
+ - name: Configure AWS credentials
31
+ uses: aws-actions/configure-aws-credentials@7474bc4690e29a8392af63c5b98e7449536d5c3a # v4
32
+ with:
33
+ role-to-assume: arn:aws:iam::630596767721:role/earbug-db-models-ci-dev
34
+ aws-region: ${{ env.AWS_REGION }}
35
+
36
+ - name: Read ECS job configuration
37
+ run: |
38
+ set -euo pipefail
39
+
40
+ get_parameter() {
41
+ aws ssm get-parameter \
42
+ --name "$SSM_PREFIX/$1" \
43
+ --query Parameter.Value \
44
+ --output text
45
+ }
46
+
47
+ ECS_CLUSTER="$(get_parameter cluster-arn)"
48
+ PRIVATE_SUBNETS="$(get_parameter subnets)"
49
+ SECURITY_GROUP_ID="$(get_parameter security-group-id)"
50
+ TASK_ROLE_ARN="$(get_parameter task-role-arn)"
51
+ EXECUTION_ROLE_ARN="$(get_parameter execution-role-arn)"
52
+ LOG_GROUP_NAME="$(get_parameter log-group-name)"
53
+ ECR_REGISTRY="$(get_parameter ecr-registry)"
54
+ ECR_REPO="$(get_parameter ecr-repo)"
55
+ TASK_FAMILY="$(get_parameter task-family)"
56
+ RDS_SECRET_ARN="$(get_parameter rds-secret-arn)"
57
+ PG_SSL="$(get_parameter pg-ssl)"
58
+ ARTIFACT_BUCKET="$(get_parameter artifact-bucket)"
59
+ ARTIFACT_PREFIX="$(get_parameter artifact-prefix)"
60
+
61
+ for name in ECS_CLUSTER PRIVATE_SUBNETS SECURITY_GROUP_ID TASK_ROLE_ARN EXECUTION_ROLE_ARN \
62
+ LOG_GROUP_NAME ECR_REGISTRY ECR_REPO TASK_FAMILY RDS_SECRET_ARN PG_SSL \
63
+ ARTIFACT_BUCKET ARTIFACT_PREFIX; do
64
+ value="${!name}"
65
+ if [ -z "$value" ] || [ "$value" = "None" ] || [[ "$value" == *$'\n'* ]]; then
66
+ echo "::error::Invalid $name value from SSM"
67
+ exit 1
68
+ fi
69
+ done
70
+
71
+ if [ "$PG_SSL" != "true" ]; then
72
+ echo "::error::PG_SSL must be true"
73
+ exit 1
74
+ fi
75
+
76
+ EXPECTED_ECR_REGISTRY="${ECR_REGISTRY_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com"
77
+ EXPECTED_CLUSTER="arn:aws:ecs:${AWS_REGION}:${AWS_ACCOUNT_ID}:cluster/earbug-dev-cluster"
78
+ EXPECTED_TASK_ROLE="arn:aws:iam::${AWS_ACCOUNT_ID}:role/earbug-dev-db-models-ecs-task-role"
79
+ EXPECTED_EXECUTION_ROLE="arn:aws:iam::${AWS_ACCOUNT_ID}:role/earbug-dev-db-models-ecs-execution-role"
80
+
81
+ [ "$ECS_CLUSTER" = "$EXPECTED_CLUSTER" ] || { echo "::error::Unexpected ECS cluster"; exit 1; }
82
+ [ "$TASK_ROLE_ARN" = "$EXPECTED_TASK_ROLE" ] || { echo "::error::Unexpected task role"; exit 1; }
83
+ [ "$EXECUTION_ROLE_ARN" = "$EXPECTED_EXECUTION_ROLE" ] || { echo "::error::Unexpected execution role"; exit 1; }
84
+ [ "$ECR_REGISTRY" = "$EXPECTED_ECR_REGISTRY" ] || { echo "::error::Unexpected ECR registry"; exit 1; }
85
+ [ "$ECR_REPO" = "earbug/db-models-generate" ] || { echo "::error::Unexpected ECR repository"; exit 1; }
86
+ [ "$TASK_FAMILY" = "earbug-dev-db-models" ] || { echo "::error::Unexpected task family"; exit 1; }
87
+ [ "$LOG_GROUP_NAME" = "/ecs/earbug-dev-db-models" ] || { echo "::error::Unexpected log group"; exit 1; }
88
+ [[ "$PRIVATE_SUBNETS" =~ ^subnet-[a-z0-9]+(,subnet-[a-z0-9]+)*$ ]] || { echo "::error::Invalid subnet list"; exit 1; }
89
+ [[ "$SECURITY_GROUP_ID" =~ ^sg-[a-z0-9]+$ ]] || { echo "::error::Invalid security group"; exit 1; }
90
+ [[ "$RDS_SECRET_ARN" =~ ^arn:aws:secretsmanager:${AWS_REGION}:${AWS_ACCOUNT_ID}:secret:rds/earbug-dev/credentials-[A-Za-z0-9_-]+$ ]] || { echo "::error::Unexpected RDS secret ARN"; exit 1; }
91
+ [ "$ARTIFACT_BUCKET" = "earbug-dev-db-models-artifacts" ] || { echo "::error::Unexpected artifact bucket"; exit 1; }
92
+ [ "$ARTIFACT_PREFIX" = "models/" ] || { echo "::error::Unexpected artifact prefix"; exit 1; }
93
+
94
+ {
95
+ printf 'ECS_CLUSTER=%s\n' "$ECS_CLUSTER"
96
+ printf 'PRIVATE_SUBNETS=%s\n' "$PRIVATE_SUBNETS"
97
+ printf 'SECURITY_GROUP_ID=%s\n' "$SECURITY_GROUP_ID"
98
+ printf 'TASK_ROLE_ARN=%s\n' "$TASK_ROLE_ARN"
99
+ printf 'EXECUTION_ROLE_ARN=%s\n' "$EXECUTION_ROLE_ARN"
100
+ printf 'LOG_GROUP_NAME=%s\n' "$LOG_GROUP_NAME"
101
+ printf 'ECR_REGISTRY=%s\n' "$ECR_REGISTRY"
102
+ printf 'ECR_REPO=%s\n' "$ECR_REPO"
103
+ printf 'TASK_FAMILY=%s\n' "$TASK_FAMILY"
104
+ printf 'RDS_SECRET_ARN=%s\n' "$RDS_SECRET_ARN"
105
+ printf 'PG_SSL=%s\n' "$PG_SSL"
106
+ printf 'ARTIFACT_BUCKET=%s\n' "$ARTIFACT_BUCKET"
107
+ printf 'ARTIFACT_PREFIX=%s\n' "$ARTIFACT_PREFIX"
108
+ } >> "$GITHUB_ENV"
109
+
110
+ - name: Build and push generator image
111
+ run: |
112
+ set -euo pipefail
113
+ IMAGE_TAG="${GITHUB_SHA}-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}"
114
+ IMAGE_URI="${ECR_REGISTRY}/${ECR_REPO}:${IMAGE_TAG}"
115
+ aws ecr get-login-password --region "$AWS_REGION" \
116
+ | docker login --username AWS --password-stdin "$ECR_REGISTRY"
117
+ docker build -f Dockerfile.generate -t "$IMAGE_URI" .
118
+ docker push "$IMAGE_URI"
119
+ echo "IMAGE_URI=$IMAGE_URI" >> "$GITHUB_ENV"
120
+
121
+ - name: Register model-generation task
122
+ run: |
123
+ set -euo pipefail
124
+ ARTIFACT_KEY="${ARTIFACT_PREFIX}${GITHUB_RUN_ID}-${GITHUB_SHA}/models.tgz"
125
+ jq -n \
126
+ --arg family "$TASK_FAMILY" \
127
+ --arg taskRoleArn "$TASK_ROLE_ARN" \
128
+ --arg executionRoleArn "$EXECUTION_ROLE_ARN" \
129
+ --arg image "$IMAGE_URI" \
130
+ --arg region "$AWS_REGION" \
131
+ --arg logGroup "$LOG_GROUP_NAME" \
132
+ --arg secretArn "$RDS_SECRET_ARN" \
133
+ --arg pgSsl "$PG_SSL" \
134
+ --arg artifactBucket "$ARTIFACT_BUCKET" \
135
+ --arg artifactKey "$ARTIFACT_KEY" \
136
+ '{
137
+ family: $family,
138
+ networkMode: "awsvpc",
139
+ requiresCompatibilities: ["FARGATE"],
140
+ cpu: "512",
141
+ memory: "1024",
142
+ taskRoleArn: $taskRoleArn,
143
+ executionRoleArn: $executionRoleArn,
144
+ containerDefinitions: [{
145
+ name: "db-models",
146
+ image: $image,
147
+ essential: true,
148
+ environment: [
149
+ {name: "AWS_REGION", value: $region},
150
+ {name: "PG_SSL", value: $pgSsl},
151
+ {name: "ARTIFACT_BUCKET", value: $artifactBucket},
152
+ {name: "ARTIFACT_KEY", value: $artifactKey}
153
+ ],
154
+ secrets: [
155
+ {name: "PGHOST", valueFrom: ($secretArn + ":host::")},
156
+ {name: "PGPORT", valueFrom: ($secretArn + ":port::")},
157
+ {name: "PGUSER", valueFrom: ($secretArn + ":username::")},
158
+ {name: "PGPASSWORD", valueFrom: ($secretArn + ":password::")},
159
+ {name: "PGDATABASE", valueFrom: ($secretArn + ":dbname::")}
160
+ ],
161
+ logConfiguration: {
162
+ logDriver: "awslogs",
163
+ options: {
164
+ "awslogs-group": $logGroup,
165
+ "awslogs-region": $region,
166
+ "awslogs-stream-prefix": "db-models"
167
+ }
168
+ }
169
+ }]
170
+ }' > /tmp/task-definition.json
171
+
172
+ TASK_DEFINITION_ARN=$(aws ecs register-task-definition \
173
+ --cli-input-json file:///tmp/task-definition.json \
174
+ --query taskDefinition.taskDefinitionArn \
175
+ --output text)
176
+ echo "TASK_DEFINITION_ARN=$TASK_DEFINITION_ARN" >> "$GITHUB_ENV"
177
+ echo "ARTIFACT_KEY=$ARTIFACT_KEY" >> "$GITHUB_ENV"
178
+
179
+ - name: Run model-generation task
180
+ run: |
181
+ set -euo pipefail
182
+ NETWORK_CONFIGURATION=$(jq -cn \
183
+ --arg subnets "$PRIVATE_SUBNETS" \
184
+ --arg securityGroup "$SECURITY_GROUP_ID" \
185
+ '{awsvpcConfiguration: {
186
+ subnets: ($subnets | split(",")),
187
+ securityGroups: [$securityGroup],
188
+ assignPublicIp: "DISABLED"
189
+ }}')
190
+
191
+ RUN_RESULT=$(aws ecs run-task \
192
+ --cluster "$ECS_CLUSTER" \
193
+ --launch-type FARGATE \
194
+ --task-definition "$TASK_DEFINITION_ARN" \
195
+ --network-configuration "$NETWORK_CONFIGURATION" \
196
+ --started-by "github-${GITHUB_RUN_ID}")
197
+ TASK_ARN=$(jq -r '.tasks[0].taskArn // empty' <<< "$RUN_RESULT")
198
+
199
+ if [ -z "$TASK_ARN" ]; then
200
+ jq '.failures' <<< "$RUN_RESULT"
201
+ exit 1
202
+ fi
203
+
204
+ echo "TASK_ARN=$TASK_ARN" >> "$GITHUB_ENV"
205
+ aws ecs wait tasks-stopped --cluster "$ECS_CLUSTER" --tasks "$TASK_ARN"
206
+
207
+ - name: Check model-generation result
208
+ run: |
209
+ set -euo pipefail
210
+ TASK_RESULT=$(aws ecs describe-tasks --cluster "$ECS_CLUSTER" --tasks "$TASK_ARN")
211
+ EXIT_CODE=$(jq -r '.tasks[0].containers[] | select(.name == "db-models") | .exitCode // -1' <<< "$TASK_RESULT")
212
+
213
+ if [ "$EXIT_CODE" -ne 0 ]; then
214
+ TASK_ID="${TASK_ARN##*/}"
215
+ LOG_STREAM="db-models/db-models/${TASK_ID}"
216
+ jq -r '.tasks[0] | "Stopped reason: " + (.stoppedReason // "unknown")' <<< "$TASK_RESULT"
217
+ echo "Task logs: ${LOG_GROUP_NAME}/${LOG_STREAM}"
218
+ exit 1
219
+ fi
220
+
221
+ - name: Download generated models
222
+ run: |
223
+ set -euo pipefail
224
+ aws s3 cp \
225
+ "s3://${ARTIFACT_BUCKET}/${ARTIFACT_KEY}" \
226
+ /tmp/models.tgz \
227
+ --checksum-mode ENABLED \
228
+ --only-show-errors
229
+ rm -rf /tmp/generated-models
230
+ mkdir /tmp/generated-models
231
+ tar -tzf /tmp/models.tgz > /tmp/models.members
232
+ while IFS= read -r member; do
233
+ case "$member" in
234
+ models|models/|models/*) ;;
235
+ *) echo "::error::Artifact contains files outside models/"; exit 1 ;;
236
+ esac
237
+ case "/$member/" in
238
+ */../*) echo "::error::Artifact contains a parent-directory path"; exit 1 ;;
239
+ esac
240
+ case "$member" in
241
+ models/index.ts|models/initDb.ts|models/rdsCaBundle.ts)
242
+ echo "::error::Artifact contains a hand-maintained file"
243
+ exit 1
244
+ ;;
245
+ esac
246
+ done < /tmp/models.members
247
+ tar -tvzf /tmp/models.tgz > /tmp/models.verbose
248
+ if awk 'substr($1, 1, 1) !~ /^[-d]$/ { found=1 } END { exit !found }' /tmp/models.verbose; then
249
+ echo "::error::Artifact contains a link or special file"
250
+ exit 1
251
+ fi
252
+ tar --no-same-owner --no-same-permissions -xzf /tmp/models.tgz -C /tmp/generated-models
253
+ for maintained in index.ts initDb.ts rdsCaBundle.ts; do
254
+ if [ -e "/tmp/generated-models/models/$maintained" ] || [ -L "/tmp/generated-models/models/$maintained" ]; then
255
+ echo "::error::Artifact contains hand-maintained file $maintained"
256
+ exit 1
257
+ fi
258
+ done
259
+ find models -mindepth 1 -maxdepth 1 \
260
+ ! -name index.ts ! -name initDb.ts ! -name rdsCaBundle.ts \
261
+ -exec rm -rf {} +
262
+ cp -a /tmp/generated-models/models/. models/
263
+ git diff --exit-code -- models/index.ts models/initDb.ts models/rdsCaBundle.ts
264
+
265
+ - name: Verify models were generated
266
+ run: |
267
+ set -euo pipefail
268
+ COUNT=$(grep -cE '^import \{ .* as _.* \} from "\./' models/init-models.ts || true)
269
+ echo "init-models.ts imports $COUNT models"
270
+ if [ "$COUNT" -lt 25 ]; then
271
+ echo "::error::Only $COUNT models generated (expected >= 25). Refusing to build or publish."
272
+ exit 1
273
+ fi
274
+
275
+ - uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6
276
+ with:
277
+ node-version: 24
278
+ registry-url: https://registry.npmjs.org
279
+
280
+ - run: npm ci --ignore-scripts
281
+
282
+ - name: Build
283
+ run: npm run build
284
+
285
+ - name: Bump patch version
286
+ id: version
287
+ run: echo "version=$(npm version patch --no-git-tag-version)" >> "$GITHUB_OUTPUT"
288
+
289
+ - name: Publish to npm
290
+ run: npm publish --access public
291
+
292
+ - name: Commit and push changes
293
+ env:
294
+ GH_TOKEN: ${{ secrets.MODELS_DISPATCH_TOKEN }}
295
+ VERSION: ${{ steps.version.outputs.version }}
296
+ run: |
297
+ set -euo pipefail
298
+ gh auth setup-git
299
+ git config user.name "github-actions[bot]"
300
+ git config user.email "github-actions[bot]@users.noreply.github.com"
301
+ git add models/ package.json
302
+ git commit -m "$VERSION - regenerate dev models and publish"
303
+ git push
package/.nvmrc ADDED
@@ -0,0 +1 @@
1
+ 24
@@ -0,0 +1,19 @@
1
+ FROM amazon/aws-cli@sha256:92de75724b6a746951f0e8b915d86bbccd7cb55aff96cd0cb4f7017272160780 AS awscli
2
+ FROM node:24-bookworm-slim@sha256:eae779f20e0cdf264247f6f3b4e62510d91f168a615117ed38430ba295f55590
3
+
4
+ COPY --from=awscli /usr/local/aws-cli /usr/local/aws-cli
5
+ RUN ln -s /usr/local/aws-cli/v2/current/bin/aws /usr/local/bin/aws
6
+
7
+ WORKDIR /app
8
+
9
+ COPY package.json package-lock.json ./
10
+ RUN npm ci --ignore-scripts \
11
+ && sed -i 's/\^(char/\^(citext|char/' node_modules/sequelize-auto/lib/auto-generator.js
12
+
13
+ COPY --chown=node:node model_options.json ./
14
+ COPY --chown=node:node models ./models
15
+ COPY --chown=node:node scripts/generate-and-upload.mjs ./scripts/generate-and-upload.mjs
16
+
17
+ USER node
18
+
19
+ CMD ["node", "scripts/generate-and-upload.mjs"]
@@ -0,0 +1,3 @@
1
+ {
2
+ "timestamps": false
3
+ }
@@ -0,0 +1,53 @@
1
+ import * as Sequelize from 'sequelize';
2
+ import { DataTypes, Model, Optional } from 'sequelize';
3
+
4
+ export interface AccessControlPreferenceAttributes {
5
+ id: number;
6
+ name: string;
7
+ }
8
+
9
+ export type AccessControlPreferencePk = "id";
10
+ export type AccessControlPreferenceId = AccessControlPreference[AccessControlPreferencePk];
11
+ export type AccessControlPreferenceCreationAttributes = AccessControlPreferenceAttributes;
12
+
13
+ export class AccessControlPreference extends Model<AccessControlPreferenceAttributes, AccessControlPreferenceCreationAttributes> implements AccessControlPreferenceAttributes {
14
+ id!: number;
15
+ name!: string;
16
+
17
+
18
+ static initModel(sequelize: Sequelize.Sequelize): typeof AccessControlPreference {
19
+ return AccessControlPreference.init({
20
+ id: {
21
+ type: DataTypes.SMALLINT,
22
+ allowNull: false,
23
+ primaryKey: true
24
+ },
25
+ name: {
26
+ type: DataTypes.TEXT,
27
+ allowNull: false,
28
+ unique: "access_control_preference_name_unique"
29
+ }
30
+ }, {
31
+ sequelize,
32
+ tableName: 'access_control_preference',
33
+ schema: 'eb',
34
+ timestamps: false,
35
+ indexes: [
36
+ {
37
+ name: "access_control_preference_name_unique",
38
+ unique: true,
39
+ fields: [
40
+ { name: "name" },
41
+ ]
42
+ },
43
+ {
44
+ name: "access_control_preference_pkey",
45
+ unique: true,
46
+ fields: [
47
+ { name: "id" },
48
+ ]
49
+ },
50
+ ]
51
+ });
52
+ }
53
+ }
@@ -0,0 +1,96 @@
1
+ import * as Sequelize from 'sequelize';
2
+ import { DataTypes, Model, Optional } from 'sequelize';
3
+ import type { UserAffinity, UserAffinityId } from './UserAffinity';
4
+
5
+ export interface AffinityRelationshipTypeAttributes {
6
+ id: string;
7
+ name: string;
8
+ category: string;
9
+ tier: string;
10
+ createDate?: Date;
11
+ updateDate?: Date;
12
+ }
13
+
14
+ export type AffinityRelationshipTypePk = "id";
15
+ export type AffinityRelationshipTypeId = AffinityRelationshipType[AffinityRelationshipTypePk];
16
+ export type AffinityRelationshipTypeOptionalAttributes = "id" | "createDate" | "updateDate";
17
+ export type AffinityRelationshipTypeCreationAttributes = Optional<AffinityRelationshipTypeAttributes, AffinityRelationshipTypeOptionalAttributes>;
18
+
19
+ export class AffinityRelationshipType extends Model<AffinityRelationshipTypeAttributes, AffinityRelationshipTypeCreationAttributes> implements AffinityRelationshipTypeAttributes {
20
+ id!: string;
21
+ name!: string;
22
+ category!: string;
23
+ tier!: string;
24
+ createDate?: Date;
25
+ updateDate?: Date;
26
+
27
+ // AffinityRelationshipType hasMany UserAffinity via affinityRelationshipTypeId
28
+ userAffinities!: UserAffinity[];
29
+ getUserAffinities!: Sequelize.HasManyGetAssociationsMixin<UserAffinity>;
30
+ setUserAffinities!: Sequelize.HasManySetAssociationsMixin<UserAffinity, UserAffinityId>;
31
+ addUserAffinity!: Sequelize.HasManyAddAssociationMixin<UserAffinity, UserAffinityId>;
32
+ addUserAffinities!: Sequelize.HasManyAddAssociationsMixin<UserAffinity, UserAffinityId>;
33
+ createUserAffinity!: Sequelize.HasManyCreateAssociationMixin<UserAffinity>;
34
+ removeUserAffinity!: Sequelize.HasManyRemoveAssociationMixin<UserAffinity, UserAffinityId>;
35
+ removeUserAffinities!: Sequelize.HasManyRemoveAssociationsMixin<UserAffinity, UserAffinityId>;
36
+ hasUserAffinity!: Sequelize.HasManyHasAssociationMixin<UserAffinity, UserAffinityId>;
37
+ hasUserAffinities!: Sequelize.HasManyHasAssociationsMixin<UserAffinity, UserAffinityId>;
38
+ countUserAffinities!: Sequelize.HasManyCountAssociationsMixin;
39
+
40
+ static initModel(sequelize: Sequelize.Sequelize): typeof AffinityRelationshipType {
41
+ return AffinityRelationshipType.init({
42
+ id: {
43
+ type: DataTypes.UUID,
44
+ allowNull: false,
45
+ defaultValue: DataTypes.UUIDV4,
46
+ primaryKey: true
47
+ },
48
+ name: {
49
+ type: DataTypes.STRING(50),
50
+ allowNull: false,
51
+ unique: "affinity_relationship_type_name_unique"
52
+ },
53
+ category: {
54
+ type: DataTypes.STRING(20),
55
+ allowNull: false
56
+ },
57
+ tier: {
58
+ type: DataTypes.STRING(20),
59
+ allowNull: false
60
+ },
61
+ createDate: {
62
+ type: DataTypes.DATE,
63
+ allowNull: true,
64
+ defaultValue: Sequelize.Sequelize.literal('CURRENT_TIMESTAMP'),
65
+ field: 'create_date'
66
+ },
67
+ updateDate: {
68
+ type: DataTypes.DATE,
69
+ allowNull: true,
70
+ defaultValue: Sequelize.Sequelize.literal('CURRENT_TIMESTAMP'),
71
+ field: 'update_date'
72
+ }
73
+ }, {
74
+ sequelize,
75
+ tableName: 'affinity_relationship_type',
76
+ schema: 'eb',
77
+ timestamps: false,
78
+ indexes: [
79
+ {
80
+ name: "affinity_relationship_type_name_unique",
81
+ unique: true,
82
+ fields: [
83
+ { name: "name" },
84
+ ]
85
+ },
86
+ {
87
+ name: "affinity_relationship_type_pkey",
88
+ unique: true,
89
+ fields: [
90
+ { name: "id" },
91
+ ]
92
+ },
93
+ ]
94
+ });
95
+ }
96
+ }
@@ -0,0 +1,131 @@
1
+ import * as Sequelize from 'sequelize';
2
+ import { DataTypes, Model, Optional } from 'sequelize';
3
+ import type { JukeboxSessionArtistAffinity, JukeboxSessionArtistAffinityId } from './JukeboxSessionArtistAffinity';
4
+ import type { JukeboxSessionGenreAffinity, JukeboxSessionGenreAffinityId } from './JukeboxSessionGenreAffinity';
5
+ import type { PlatformUserPlaylistArtistAffinity, PlatformUserPlaylistArtistAffinityId } from './PlatformUserPlaylistArtistAffinity';
6
+ import type { PlatformUserPlaylistGenreAffinity, PlatformUserPlaylistGenreAffinityId } from './PlatformUserPlaylistGenreAffinity';
7
+ import type { UserArtistAffinity, UserArtistAffinityId } from './UserArtistAffinity';
8
+ import type { UserGenreAffinity, UserGenreAffinityId } from './UserGenreAffinity';
9
+
10
+ export interface AffinityTierAttributes {
11
+ id: number;
12
+ name: string;
13
+ }
14
+
15
+ export type AffinityTierPk = "id";
16
+ export type AffinityTierId = AffinityTier[AffinityTierPk];
17
+ export type AffinityTierCreationAttributes = AffinityTierAttributes;
18
+
19
+ export class AffinityTier extends Model<AffinityTierAttributes, AffinityTierCreationAttributes> implements AffinityTierAttributes {
20
+ id!: number;
21
+ name!: string;
22
+
23
+ // AffinityTier hasMany JukeboxSessionArtistAffinity via affinityTierId
24
+ jukeboxSessionArtistAffinities!: JukeboxSessionArtistAffinity[];
25
+ getJukeboxSessionArtistAffinities!: Sequelize.HasManyGetAssociationsMixin<JukeboxSessionArtistAffinity>;
26
+ setJukeboxSessionArtistAffinities!: Sequelize.HasManySetAssociationsMixin<JukeboxSessionArtistAffinity, JukeboxSessionArtistAffinityId>;
27
+ addJukeboxSessionArtistAffinity!: Sequelize.HasManyAddAssociationMixin<JukeboxSessionArtistAffinity, JukeboxSessionArtistAffinityId>;
28
+ addJukeboxSessionArtistAffinities!: Sequelize.HasManyAddAssociationsMixin<JukeboxSessionArtistAffinity, JukeboxSessionArtistAffinityId>;
29
+ createJukeboxSessionArtistAffinity!: Sequelize.HasManyCreateAssociationMixin<JukeboxSessionArtistAffinity>;
30
+ removeJukeboxSessionArtistAffinity!: Sequelize.HasManyRemoveAssociationMixin<JukeboxSessionArtistAffinity, JukeboxSessionArtistAffinityId>;
31
+ removeJukeboxSessionArtistAffinities!: Sequelize.HasManyRemoveAssociationsMixin<JukeboxSessionArtistAffinity, JukeboxSessionArtistAffinityId>;
32
+ hasJukeboxSessionArtistAffinity!: Sequelize.HasManyHasAssociationMixin<JukeboxSessionArtistAffinity, JukeboxSessionArtistAffinityId>;
33
+ hasJukeboxSessionArtistAffinities!: Sequelize.HasManyHasAssociationsMixin<JukeboxSessionArtistAffinity, JukeboxSessionArtistAffinityId>;
34
+ countJukeboxSessionArtistAffinities!: Sequelize.HasManyCountAssociationsMixin;
35
+ // AffinityTier hasMany JukeboxSessionGenreAffinity via affinityTierId
36
+ jukeboxSessionGenreAffinities!: JukeboxSessionGenreAffinity[];
37
+ getJukeboxSessionGenreAffinities!: Sequelize.HasManyGetAssociationsMixin<JukeboxSessionGenreAffinity>;
38
+ setJukeboxSessionGenreAffinities!: Sequelize.HasManySetAssociationsMixin<JukeboxSessionGenreAffinity, JukeboxSessionGenreAffinityId>;
39
+ addJukeboxSessionGenreAffinity!: Sequelize.HasManyAddAssociationMixin<JukeboxSessionGenreAffinity, JukeboxSessionGenreAffinityId>;
40
+ addJukeboxSessionGenreAffinities!: Sequelize.HasManyAddAssociationsMixin<JukeboxSessionGenreAffinity, JukeboxSessionGenreAffinityId>;
41
+ createJukeboxSessionGenreAffinity!: Sequelize.HasManyCreateAssociationMixin<JukeboxSessionGenreAffinity>;
42
+ removeJukeboxSessionGenreAffinity!: Sequelize.HasManyRemoveAssociationMixin<JukeboxSessionGenreAffinity, JukeboxSessionGenreAffinityId>;
43
+ removeJukeboxSessionGenreAffinities!: Sequelize.HasManyRemoveAssociationsMixin<JukeboxSessionGenreAffinity, JukeboxSessionGenreAffinityId>;
44
+ hasJukeboxSessionGenreAffinity!: Sequelize.HasManyHasAssociationMixin<JukeboxSessionGenreAffinity, JukeboxSessionGenreAffinityId>;
45
+ hasJukeboxSessionGenreAffinities!: Sequelize.HasManyHasAssociationsMixin<JukeboxSessionGenreAffinity, JukeboxSessionGenreAffinityId>;
46
+ countJukeboxSessionGenreAffinities!: Sequelize.HasManyCountAssociationsMixin;
47
+ // AffinityTier hasMany PlatformUserPlaylistArtistAffinity via affinityTierId
48
+ platformUserPlaylistArtistAffinities!: PlatformUserPlaylistArtistAffinity[];
49
+ getPlatformUserPlaylistArtistAffinities!: Sequelize.HasManyGetAssociationsMixin<PlatformUserPlaylistArtistAffinity>;
50
+ setPlatformUserPlaylistArtistAffinities!: Sequelize.HasManySetAssociationsMixin<PlatformUserPlaylistArtistAffinity, PlatformUserPlaylistArtistAffinityId>;
51
+ addPlatformUserPlaylistArtistAffinity!: Sequelize.HasManyAddAssociationMixin<PlatformUserPlaylistArtistAffinity, PlatformUserPlaylistArtistAffinityId>;
52
+ addPlatformUserPlaylistArtistAffinities!: Sequelize.HasManyAddAssociationsMixin<PlatformUserPlaylistArtistAffinity, PlatformUserPlaylistArtistAffinityId>;
53
+ createPlatformUserPlaylistArtistAffinity!: Sequelize.HasManyCreateAssociationMixin<PlatformUserPlaylistArtistAffinity>;
54
+ removePlatformUserPlaylistArtistAffinity!: Sequelize.HasManyRemoveAssociationMixin<PlatformUserPlaylistArtistAffinity, PlatformUserPlaylistArtistAffinityId>;
55
+ removePlatformUserPlaylistArtistAffinities!: Sequelize.HasManyRemoveAssociationsMixin<PlatformUserPlaylistArtistAffinity, PlatformUserPlaylistArtistAffinityId>;
56
+ hasPlatformUserPlaylistArtistAffinity!: Sequelize.HasManyHasAssociationMixin<PlatformUserPlaylistArtistAffinity, PlatformUserPlaylistArtistAffinityId>;
57
+ hasPlatformUserPlaylistArtistAffinities!: Sequelize.HasManyHasAssociationsMixin<PlatformUserPlaylistArtistAffinity, PlatformUserPlaylistArtistAffinityId>;
58
+ countPlatformUserPlaylistArtistAffinities!: Sequelize.HasManyCountAssociationsMixin;
59
+ // AffinityTier hasMany PlatformUserPlaylistGenreAffinity via affinityTierId
60
+ platformUserPlaylistGenreAffinities!: PlatformUserPlaylistGenreAffinity[];
61
+ getPlatformUserPlaylistGenreAffinities!: Sequelize.HasManyGetAssociationsMixin<PlatformUserPlaylistGenreAffinity>;
62
+ setPlatformUserPlaylistGenreAffinities!: Sequelize.HasManySetAssociationsMixin<PlatformUserPlaylistGenreAffinity, PlatformUserPlaylistGenreAffinityId>;
63
+ addPlatformUserPlaylistGenreAffinity!: Sequelize.HasManyAddAssociationMixin<PlatformUserPlaylistGenreAffinity, PlatformUserPlaylistGenreAffinityId>;
64
+ addPlatformUserPlaylistGenreAffinities!: Sequelize.HasManyAddAssociationsMixin<PlatformUserPlaylistGenreAffinity, PlatformUserPlaylistGenreAffinityId>;
65
+ createPlatformUserPlaylistGenreAffinity!: Sequelize.HasManyCreateAssociationMixin<PlatformUserPlaylistGenreAffinity>;
66
+ removePlatformUserPlaylistGenreAffinity!: Sequelize.HasManyRemoveAssociationMixin<PlatformUserPlaylistGenreAffinity, PlatformUserPlaylistGenreAffinityId>;
67
+ removePlatformUserPlaylistGenreAffinities!: Sequelize.HasManyRemoveAssociationsMixin<PlatformUserPlaylistGenreAffinity, PlatformUserPlaylistGenreAffinityId>;
68
+ hasPlatformUserPlaylistGenreAffinity!: Sequelize.HasManyHasAssociationMixin<PlatformUserPlaylistGenreAffinity, PlatformUserPlaylistGenreAffinityId>;
69
+ hasPlatformUserPlaylistGenreAffinities!: Sequelize.HasManyHasAssociationsMixin<PlatformUserPlaylistGenreAffinity, PlatformUserPlaylistGenreAffinityId>;
70
+ countPlatformUserPlaylistGenreAffinities!: Sequelize.HasManyCountAssociationsMixin;
71
+ // AffinityTier hasMany UserArtistAffinity via affinityTierId
72
+ userArtistAffinities!: UserArtistAffinity[];
73
+ getUserArtistAffinities!: Sequelize.HasManyGetAssociationsMixin<UserArtistAffinity>;
74
+ setUserArtistAffinities!: Sequelize.HasManySetAssociationsMixin<UserArtistAffinity, UserArtistAffinityId>;
75
+ addUserArtistAffinity!: Sequelize.HasManyAddAssociationMixin<UserArtistAffinity, UserArtistAffinityId>;
76
+ addUserArtistAffinities!: Sequelize.HasManyAddAssociationsMixin<UserArtistAffinity, UserArtistAffinityId>;
77
+ createUserArtistAffinity!: Sequelize.HasManyCreateAssociationMixin<UserArtistAffinity>;
78
+ removeUserArtistAffinity!: Sequelize.HasManyRemoveAssociationMixin<UserArtistAffinity, UserArtistAffinityId>;
79
+ removeUserArtistAffinities!: Sequelize.HasManyRemoveAssociationsMixin<UserArtistAffinity, UserArtistAffinityId>;
80
+ hasUserArtistAffinity!: Sequelize.HasManyHasAssociationMixin<UserArtistAffinity, UserArtistAffinityId>;
81
+ hasUserArtistAffinities!: Sequelize.HasManyHasAssociationsMixin<UserArtistAffinity, UserArtistAffinityId>;
82
+ countUserArtistAffinities!: Sequelize.HasManyCountAssociationsMixin;
83
+ // AffinityTier hasMany UserGenreAffinity via affinityTierId
84
+ userGenreAffinities!: UserGenreAffinity[];
85
+ getUserGenreAffinities!: Sequelize.HasManyGetAssociationsMixin<UserGenreAffinity>;
86
+ setUserGenreAffinities!: Sequelize.HasManySetAssociationsMixin<UserGenreAffinity, UserGenreAffinityId>;
87
+ addUserGenreAffinity!: Sequelize.HasManyAddAssociationMixin<UserGenreAffinity, UserGenreAffinityId>;
88
+ addUserGenreAffinities!: Sequelize.HasManyAddAssociationsMixin<UserGenreAffinity, UserGenreAffinityId>;
89
+ createUserGenreAffinity!: Sequelize.HasManyCreateAssociationMixin<UserGenreAffinity>;
90
+ removeUserGenreAffinity!: Sequelize.HasManyRemoveAssociationMixin<UserGenreAffinity, UserGenreAffinityId>;
91
+ removeUserGenreAffinities!: Sequelize.HasManyRemoveAssociationsMixin<UserGenreAffinity, UserGenreAffinityId>;
92
+ hasUserGenreAffinity!: Sequelize.HasManyHasAssociationMixin<UserGenreAffinity, UserGenreAffinityId>;
93
+ hasUserGenreAffinities!: Sequelize.HasManyHasAssociationsMixin<UserGenreAffinity, UserGenreAffinityId>;
94
+ countUserGenreAffinities!: Sequelize.HasManyCountAssociationsMixin;
95
+
96
+ static initModel(sequelize: Sequelize.Sequelize): typeof AffinityTier {
97
+ return AffinityTier.init({
98
+ id: {
99
+ type: DataTypes.SMALLINT,
100
+ allowNull: false,
101
+ primaryKey: true
102
+ },
103
+ name: {
104
+ type: DataTypes.STRING(32),
105
+ allowNull: false,
106
+ unique: "affinity_tier_name_unique"
107
+ }
108
+ }, {
109
+ sequelize,
110
+ tableName: 'affinity_tier',
111
+ schema: 'eb',
112
+ timestamps: false,
113
+ indexes: [
114
+ {
115
+ name: "affinity_tier_name_unique",
116
+ unique: true,
117
+ fields: [
118
+ { name: "name" },
119
+ ]
120
+ },
121
+ {
122
+ name: "affinity_tier_pkey",
123
+ unique: true,
124
+ fields: [
125
+ { name: "id" },
126
+ ]
127
+ },
128
+ ]
129
+ });
130
+ }
131
+ }