@maestro-js/agent-skills 1.0.0-alpha.2 → 1.0.0-alpha.21
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.
- package/dist/bin.js +19 -0
- package/package.json +8 -7
- package/{dist → skills}/choosing-an-npm-package/SKILL.md +5 -4
- package/skills/iconify/SKILL.md +82 -0
- package/skills/iconify/scripts/iconify.js +111 -0
- package/skills/iso-fns/SKILL.md +137 -0
- package/skills/iso-fns/references/api_reference.md +435 -0
- package/skills/maestro-architecture/SKILL.md +552 -0
- package/skills/maestro-examples/SKILL.md +140 -0
- package/skills/maestro-examples/references/cadence/cadence-web/.auth/user.json +15 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/app.css +112 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/auth-layout.tsx +39 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/back-link.tsx +24 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/button-group.tsx +78 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/button-link.tsx +77 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/button.tsx +139 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/checkbox.tsx +210 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/chip.tsx +161 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/container.tsx +85 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/date-range.tsx +141 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/date-time-picker.tsx +199 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/empty-state.tsx +19 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/form-page.tsx +41 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/form.tsx +106 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/helpers/animated-popover.tsx +27 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/helpers/button-context.ts +13 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/helpers/calendar-month-year-picker.tsx +283 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/helpers/form-field.tsx +231 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/helpers/get-button-classes.ts +141 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/helpers/headless-button.tsx +39 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/icon.tsx +29 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/inline-alert.tsx +57 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/interaction-form.tsx +87 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/menu.tsx +189 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/optional-link.tsx +18 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/page-header.tsx +19 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/rich-text-editor.tsx +352 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/select.tsx +219 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/spinner.tsx +19 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/table/headless-templated-row-table.ts +553 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/table/index.tsx +44 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/table/server-table.ts +146 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/table/table-actions.tsx +79 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/table/table-container.tsx +176 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/table/table-container.type-test.ts +158 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/table/table-filters/date-range-filter.tsx +230 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/table/table-filters/select-filter.tsx +214 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/table/table-filters/sort.tsx +88 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/table/table-primitives.tsx +229 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/table/table-toolbar.tsx +303 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/table/table-types.ts +64 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/table/use-client-table.ts +160 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/table/use-client-table.type-test.ts +220 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/table/use-server-table.ts +195 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/table/use-server-table.type-test.ts +177 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/tag-editor.tsx +53 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/tag-field.tsx +253 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/text-field.tsx +147 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/toast.tsx +182 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/components/top-nav.tsx +175 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/entry.client.tsx +21 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/entry.server.tsx +13 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/features/csrf-middleware.server.ts +17 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/features/custom-error-status-code-middleware.server.ts +31 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/features/rate-limiting-middleware.server.ts +36 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/features/redirect-with-toast.server.ts +14 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/features/request-context.server.ts +40 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/features/security-headers-middleware.server.ts +10 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/icons/types.ts +36 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/root.tsx +208 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/routes/_index.tsx +5 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/routes/activity.tsx +124 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/routes/archive.tsx +187 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/routes/auth.forgot-password.tsx +108 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/routes/auth.login.tsx +132 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/routes/auth.logout.tsx +17 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/routes/auth.register.tsx +172 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/routes/auth.reset-password.tsx +137 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/routes/contacts.$id.edit.tsx +89 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/routes/contacts.$id.tsx +521 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/routes/contacts.new.tsx +56 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/routes/contacts.tsx +183 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/routes/settings.tsx +158 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/routes/users.tsx +263 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/routes.ts +4 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/services.server.ts +1 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/utils/colors.ts +47 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/utils/compose-event-handlers.ts +13 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/utils/compose-refs.ts +35 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/utils/format-date.ts +10 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/utils/overridable-component-helper.ts +31 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/utils/sanitize-html.ts +16 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/utils/tw.ts +16 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/utils/use-hydrated.ts +12 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/utils/use-prevent-default.ts +30 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/utils/use-query-state.ts +629 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/utils/use-render-props.ts +42 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/utils/use-spin-delay.ts +27 -0
- package/skills/maestro-examples/references/cadence/cadence-web/app/utils/use-stable-accessor.ts +14 -0
- package/skills/maestro-examples/references/cadence/cadence-web/instrument.server.mjs +29 -0
- package/skills/maestro-examples/references/cadence/cadence-web/package.json +60 -0
- package/skills/maestro-examples/references/cadence/cadence-web/playwright.config.ts +39 -0
- package/skills/maestro-examples/references/cadence/cadence-web/react-router.config.ts +12 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tailwind.config.ts +7 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/activity/filter-activity.spec.ts +93 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/activity/recent-activity.spec.ts +70 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/archive/archive-view.spec.ts +62 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/auth/login-invalid.spec.ts +68 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/auth/login-valid.spec.ts +45 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/auth/logout.spec.ts +46 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/auth/password-reset.spec.ts +105 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/auth/register.spec.ts +39 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/auth.setup.ts +48 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/authorization/member-ownership.spec.ts +104 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/authorization/viewer-read-only.spec.ts +103 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/constants.ts +11 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/contacts/archive-restore.spec.ts +77 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/contacts/create-contact.spec.ts +56 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/contacts/delete-contact.spec.ts +53 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/contacts/edit-contact.spec.ts +60 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/contacts/filter-by-last-contacted.spec.ts +85 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/contacts/filter-by-tag.spec.ts +68 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/contacts/global-search.spec.ts +57 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/contacts/sort-contacts.spec.ts +60 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/contacts/tags.spec.ts +85 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/contacts/view-detail.spec.ts +58 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/interactions/delete-interaction.spec.ts +59 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/interactions/edit-interaction.spec.ts +68 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/interactions/log-email.spec.ts +57 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/interactions/log-note.spec.ts +56 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/interactions/rich-text-formatting.spec.ts +97 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/organization/delete.spec.ts +70 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/organization/edit-name.spec.ts +51 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/users/change-role.spec.ts +62 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/users/invite-user.spec.ts +56 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tests/users/remove-user.spec.ts +58 -0
- package/skills/maestro-examples/references/cadence/cadence-web/tsconfig.json +22 -0
- package/skills/maestro-examples/references/cadence/cadence-web/vite.config.ts +37 -0
- package/skills/maestro-examples/references/cadence/config/agent-container.ts +4 -0
- package/skills/maestro-examples/references/cadence/config/cadence-web.ts +12 -0
- package/skills/maestro-examples/references/cadence/config/db-migrate.ts +9 -0
- package/skills/maestro-examples/references/cadence/config/queue-processor.ts +11 -0
- package/skills/maestro-examples/references/cadence/config/services.ts +16 -0
- package/skills/maestro-examples/references/cadence/infrastructure/db-migrations/20260404000001_organizations-and-users.ts +16 -0
- package/skills/maestro-examples/references/cadence/infrastructure/db-migrations/20260404000002_contacts.ts +16 -0
- package/skills/maestro-examples/references/cadence/infrastructure/db-migrations/20260404000003_interactions.ts +16 -0
- package/skills/maestro-examples/references/cadence/infrastructure/db-migrations/20260404000004_remember-me-tokens.ts +16 -0
- package/skills/maestro-examples/references/cadence/infrastructure/db-migrations/20260404000005_password-reset-tokens.ts +16 -0
- package/skills/maestro-examples/references/cadence/infrastructure/db-migrations/20260404000006_queue-and-recurring-jobs.ts +16 -0
- package/skills/maestro-examples/references/cadence/infrastructure/db-migrations/sqls/20260404000001_organizations-and-users-down.sql +2 -0
- package/skills/maestro-examples/references/cadence/infrastructure/db-migrations/sqls/20260404000001_organizations-and-users-up.sql +24 -0
- package/skills/maestro-examples/references/cadence/infrastructure/db-migrations/sqls/20260404000002_contacts-down.sql +1 -0
- package/skills/maestro-examples/references/cadence/infrastructure/db-migrations/sqls/20260404000002_contacts-up.sql +16 -0
- package/skills/maestro-examples/references/cadence/infrastructure/db-migrations/sqls/20260404000003_interactions-down.sql +1 -0
- package/skills/maestro-examples/references/cadence/infrastructure/db-migrations/sqls/20260404000003_interactions-up.sql +15 -0
- package/skills/maestro-examples/references/cadence/infrastructure/db-migrations/sqls/20260404000004_remember-me-tokens-down.sql +1 -0
- package/skills/maestro-examples/references/cadence/infrastructure/db-migrations/sqls/20260404000004_remember-me-tokens-up.sql +12 -0
- package/skills/maestro-examples/references/cadence/infrastructure/db-migrations/sqls/20260404000005_password-reset-tokens-down.sql +1 -0
- package/skills/maestro-examples/references/cadence/infrastructure/db-migrations/sqls/20260404000005_password-reset-tokens-up.sql +11 -0
- package/skills/maestro-examples/references/cadence/infrastructure/db-migrations/sqls/20260404000006_queue-and-recurring-jobs-down.sql +2 -0
- package/skills/maestro-examples/references/cadence/infrastructure/db-migrations/sqls/20260404000006_queue-and-recurring-jobs-up.sql +21 -0
- package/skills/maestro-examples/references/cadence/package.json +17 -0
- package/skills/maestro-examples/references/cadence/packages/schemas/package.json +17 -0
- package/skills/maestro-examples/references/cadence/packages/schemas/src/contact/index.ts +57 -0
- package/skills/maestro-examples/references/cadence/packages/schemas/src/index.ts +4 -0
- package/skills/maestro-examples/references/cadence/packages/schemas/src/interaction/index.ts +45 -0
- package/skills/maestro-examples/references/cadence/packages/schemas/src/organization/index.ts +32 -0
- package/skills/maestro-examples/references/cadence/packages/schemas/src/user/index.ts +69 -0
- package/skills/maestro-examples/references/cadence/packages/schemas/tsconfig.json +9 -0
- package/skills/maestro-examples/references/cadence/packages/services/package.json +43 -0
- package/skills/maestro-examples/references/cadence/packages/services/run-tests.ts +59 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/auth/auth-db-provider.ts +202 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/auth/auth-use-cases.ts +155 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/auth/index.ts +17 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/auth/profile-db-provider.ts +17 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/contact/contact-db-provider.test.ts +120 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/contact/contact-db-provider.ts +145 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/contact/contact-use-cases.ts +196 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/contact/index.ts +29 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/index.ts +23 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/interaction/index.ts +25 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/interaction/interaction-db-provider.test.ts +128 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/interaction/interaction-db-provider.ts +98 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/interaction/interaction-use-cases.ts +171 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/maestro.ts +218 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/organization/index.ts +8 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/organization/organization-db-provider.test.ts +53 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/organization/organization-db-provider.ts +60 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/organization/organization-use-cases.ts +88 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/permissions.ts +28 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/testing/contact-seed.ts +30 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/testing/index.ts +13 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/testing/interaction-seed.ts +29 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/testing/organization-seed.ts +25 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/testing/seed-pipe.ts +38 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/testing/user-seed.ts +27 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/user/index.ts +27 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/user/user-db-provider.test.ts +100 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/user/user-db-provider.ts +69 -0
- package/skills/maestro-examples/references/cadence/packages/services/src/user/user-use-cases.ts +162 -0
- package/skills/maestro-examples/references/cadence/packages/services/tsconfig.json +9 -0
- package/skills/maestro-examples/references/cadence/scripts/foreign-key-delete-behavior.ts +106 -0
- package/skills/maestro-examples/references/cadence/specs/app.md +72 -0
- package/skills/maestro-examples/references/cadence/specs/data-models.md +80 -0
- package/skills/maestro-examples/references/cadence/specs/multi-tenant-security.md +239 -0
- package/skills/maestro-examples/references/cadence/specs/rich-text-editor.md +108 -0
- package/skills/maestro-examples/references/cadence/specs/table.md +151 -0
- package/skills/maestro-examples/references/cadence/specs/use-cases.md +62 -0
- package/skills/maestro-examples/references/cadence/tsconfig.json +29 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/app.css +152 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/alert-dialog.tsx +153 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/avatar.tsx +57 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/button-group.tsx +78 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/button-link.tsx +77 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/button.tsx +139 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/channel-card.tsx +40 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/checkbox-group.tsx +175 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/checkbox.tsx +210 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/chip.tsx +161 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/container.tsx +85 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/date-picker.tsx +214 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/date-time-picker.tsx +199 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/dialog.tsx +114 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/enum-chip.tsx +33 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/file-input.tsx +248 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/form.tsx +106 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/headless-file-input.tsx +365 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/helpers/animated-popover.tsx +27 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/helpers/button-context.ts +13 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/helpers/calendar-month-year-picker.tsx +283 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/helpers/form-field.tsx +231 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/helpers/get-button-classes.ts +141 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/helpers/headless-button.tsx +39 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/helpers/pdf-dist.client.ts +9 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/icon.tsx +29 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/image-grid.tsx +96 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/image-input.tsx +268 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/inline-alert.tsx +57 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/like-button.tsx +48 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/menu.tsx +189 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/pdf-input.tsx +252 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/pdf.tsx +89 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/post-card.tsx +147 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/post-composer.tsx +166 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/radio-group.tsx +115 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/select.tsx +219 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/spinner.tsx +19 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/tag-field.tsx +253 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/text-area.tsx +151 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/text-field.tsx +147 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/components/toast.tsx +179 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/entry.client.tsx +21 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/entry.server.tsx +12 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/features/csrf-hidden-input.tsx +6 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/features/csrf-middleware.server.ts +17 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/features/custom-error-status-code-middleware.server.ts +18 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/features/rate-limiting-middleware.server.ts +36 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/features/redirect-with-toast.server.ts +14 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/features/request-context.server.ts +40 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/features/security-headers-middleware.server.ts +10 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/icons/types.ts +26 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/root.tsx +164 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/routes/_auth/forgot-password.tsx +90 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/routes/_auth/login.tsx +104 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/routes/_auth/logout.tsx +44 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/routes/_auth/reset-password.tsx +130 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/routes/_auth/signup.tsx +91 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/routes/_browse/_layout.tsx +36 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/routes/_browse/c.new.tsx +47 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/routes/_browse/index.tsx +3 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/routes/api/hide-post.$postId.tsx +30 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/routes/api/like.$postId.tsx +22 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/routes/c.$slug/_layout.tsx +108 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/routes/c.$slug/post.new.tsx +59 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/routes/c.$slug.edit.tsx +53 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/routes/c.$slug.manage/_layout.tsx +123 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/routes/c.$slug.manage/add-moderator.tsx +48 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/routes/c.$slug.manage/transfer-ownership.tsx +71 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/routes/c.$slug.post.$postId.tsx +119 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/routes/files.$.tsx +22 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/routes/health.tsx +3 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/routes/settings.tsx +128 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/routes.ts +4 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/services.server.ts +1 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/utils/colors.ts +47 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/utils/compose-refs.ts +35 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/utils/enum-colors.ts +4 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/utils/file-input.ts +52 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/utils/tw.ts +16 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/utils/use-element-size.ts +35 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/utils/use-number-input.ts +143 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/utils/use-pagination.ts +41 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/utils/use-prevent-default.ts +30 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/utils/use-profile.ts +7 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/utils/use-render-props.ts +42 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/utils/use-spin-delay.ts +27 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/utils/use-stable-accessor.ts +14 -0
- package/skills/maestro-examples/references/chorus/chorus-web/app/utils/use-tab-indicator.ts +107 -0
- package/skills/maestro-examples/references/chorus/chorus-web/environment.d.ts +15 -0
- package/skills/maestro-examples/references/chorus/chorus-web/instrument.server.mjs +29 -0
- package/skills/maestro-examples/references/chorus/chorus-web/package.json +54 -0
- package/skills/maestro-examples/references/chorus/chorus-web/playwright.config.ts +39 -0
- package/skills/maestro-examples/references/chorus/chorus-web/react-router.config.ts +12 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/auth-landing.test.ts +8 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/auth-login.test.ts +40 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/auth-logout.test.ts +8 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/auth-signup.test.ts +15 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/auth.setup.ts +42 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/channel-browse.test.ts +43 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/channel-create.test.ts +34 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/channel-edit.test.ts +33 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/channel-manage-moderators.test.ts +59 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/channel-manage-permissions.test.ts +55 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/channel-transfer.test.ts +47 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/constants.ts +7 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/forgot-password.test.ts +33 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/hide-post-author.test.ts +62 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/hide-post-nonauthor.test.ts +36 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/like-toggle.test.ts +60 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/like-unauth.test.ts +37 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/post-create.test.ts +30 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/post-listing.test.ts +33 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/post-reply.test.ts +48 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/post-view-unauth.test.ts +37 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/settings-duplicate.test.ts +28 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/settings-update.test.ts +34 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/settings-view.test.ts +17 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tests/signup-validation.test.ts +51 -0
- package/skills/maestro-examples/references/chorus/chorus-web/tsconfig.json +14 -0
- package/skills/maestro-examples/references/chorus/chorus-web/vite.config.ts +38 -0
- package/skills/maestro-examples/references/chorus/config/app-a.ts +7 -0
- package/skills/maestro-examples/references/chorus/config/chorus-web.ts +7 -0
- package/skills/maestro-examples/references/chorus/config/db-migrate.ts +9 -0
- package/skills/maestro-examples/references/chorus/config/queue-processor.ts +7 -0
- package/skills/maestro-examples/references/chorus/config/services.ts +15 -0
- package/skills/maestro-examples/references/chorus/infrastructure/cdk/index.ts +60 -0
- package/skills/maestro-examples/references/chorus/infrastructure/cdk.context.json +5 -0
- package/skills/maestro-examples/references/chorus/infrastructure/db-migrations/20260303005902_init_authentication.ts +16 -0
- package/skills/maestro-examples/references/chorus/infrastructure/db-migrations/20260308234835_add-maestro-queue-table.ts +16 -0
- package/skills/maestro-examples/references/chorus/infrastructure/db-migrations/20260315051819_channels.ts +16 -0
- package/skills/maestro-examples/references/chorus/infrastructure/db-migrations/20260315052202_channel-moderators.ts +16 -0
- package/skills/maestro-examples/references/chorus/infrastructure/db-migrations/20260315052539_posts.ts +16 -0
- package/skills/maestro-examples/references/chorus/infrastructure/db-migrations/20260315052734_post-images.ts +16 -0
- package/skills/maestro-examples/references/chorus/infrastructure/db-migrations/20260315053110_likes.ts +16 -0
- package/skills/maestro-examples/references/chorus/infrastructure/db-migrations/sqls/20260303005902_init_authentication-down.sql +3 -0
- package/skills/maestro-examples/references/chorus/infrastructure/db-migrations/sqls/20260303005902_init_authentication-up.sql +40 -0
- package/skills/maestro-examples/references/chorus/infrastructure/db-migrations/sqls/20260308234835_add-maestro-queue-table-down.sql +3 -0
- package/skills/maestro-examples/references/chorus/infrastructure/db-migrations/sqls/20260308234835_add-maestro-queue-table-up.sql +23 -0
- package/skills/maestro-examples/references/chorus/infrastructure/db-migrations/sqls/20260315051819_channels-down.sql +1 -0
- package/skills/maestro-examples/references/chorus/infrastructure/db-migrations/sqls/20260315051819_channels-up.sql +11 -0
- package/skills/maestro-examples/references/chorus/infrastructure/db-migrations/sqls/20260315052202_channel-moderators-down.sql +1 -0
- package/skills/maestro-examples/references/chorus/infrastructure/db-migrations/sqls/20260315052202_channel-moderators-up.sql +7 -0
- package/skills/maestro-examples/references/chorus/infrastructure/db-migrations/sqls/20260315052539_posts-down.sql +1 -0
- package/skills/maestro-examples/references/chorus/infrastructure/db-migrations/sqls/20260315052539_posts-up.sql +14 -0
- package/skills/maestro-examples/references/chorus/infrastructure/db-migrations/sqls/20260315052734_post-images-down.sql +1 -0
- package/skills/maestro-examples/references/chorus/infrastructure/db-migrations/sqls/20260315052734_post-images-up.sql +7 -0
- package/skills/maestro-examples/references/chorus/infrastructure/db-migrations/sqls/20260315053110_likes-down.sql +1 -0
- package/skills/maestro-examples/references/chorus/infrastructure/db-migrations/sqls/20260315053110_likes-up.sql +8 -0
- package/skills/maestro-examples/references/chorus/infrastructure/package.json +20 -0
- package/skills/maestro-examples/references/chorus/infrastructure/tsconfig.json +8 -0
- package/skills/maestro-examples/references/chorus/package.json +17 -0
- package/skills/maestro-examples/references/chorus/packages/email-templates/other/generate-email-modules.ts +22 -0
- package/skills/maestro-examples/references/chorus/packages/email-templates/other/generate-email-previews.ts +18 -0
- package/skills/maestro-examples/references/chorus/packages/email-templates/package.json +27 -0
- package/skills/maestro-examples/references/chorus/packages/email-templates/src/components/button.tsx +19 -0
- package/skills/maestro-examples/references/chorus/packages/email-templates/src/components/root-container.tsx +29 -0
- package/skills/maestro-examples/references/chorus/packages/email-templates/src/components/tailwind-wrapper.tsx +113 -0
- package/skills/maestro-examples/references/chorus/packages/email-templates/src/email-modules.ts +9 -0
- package/skills/maestro-examples/references/chorus/packages/email-templates/src/emails/password-reset.tsx +41 -0
- package/skills/maestro-examples/references/chorus/packages/email-templates/src/index.ts +3 -0
- package/skills/maestro-examples/references/chorus/packages/email-templates/src/render-email-template.ts +24 -0
- package/skills/maestro-examples/references/chorus/packages/email-templates/src/utils/tw.ts +5 -0
- package/skills/maestro-examples/references/chorus/packages/email-templates/tsconfig.json +11 -0
- package/skills/maestro-examples/references/chorus/packages/schemas/package.json +17 -0
- package/skills/maestro-examples/references/chorus/packages/schemas/src/channel/index.ts +41 -0
- package/skills/maestro-examples/references/chorus/packages/schemas/src/index.ts +4 -0
- package/skills/maestro-examples/references/chorus/packages/schemas/src/like/index.ts +16 -0
- package/skills/maestro-examples/references/chorus/packages/schemas/src/post/index.ts +44 -0
- package/skills/maestro-examples/references/chorus/packages/schemas/src/profile/index.ts +80 -0
- package/skills/maestro-examples/references/chorus/packages/schemas/tsconfig.json +9 -0
- package/skills/maestro-examples/references/chorus/packages/services/environment.d.ts +7 -0
- package/skills/maestro-examples/references/chorus/packages/services/package.json +47 -0
- package/skills/maestro-examples/references/chorus/packages/services/run-tests.ts +59 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/auth/auth-use-cases.ts +178 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/auth/authenticatable-db-provider.ts +59 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/auth/index.ts +29 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/auth/password-reset-token-db-provider.ts +58 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/auth/remember-me-token-db-provider.ts +82 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/channel/channel-db-provider.test.ts +85 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/channel/channel-db-provider.ts +158 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/channel/channel-use-cases.ts +303 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/channel/index.ts +29 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/index.ts +21 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/like/index.ts +6 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/like/like-db-provider.test.ts +47 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/like/like-db-provider.ts +53 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/like/like-use-cases.ts +31 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/maestro.ts +215 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/permissions.ts +16 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/post/index.ts +25 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/post/post-db-provider.test.ts +68 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/post/post-db-provider.ts +219 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/post/post-use-cases.ts +184 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/post/redact-hidden-post.ts +4 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/profile/index.ts +17 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/profile/profile-db-provider.test.ts +57 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/profile/profile-db-provider.ts +75 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/profile/profile-use-cases.ts +61 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/testing/channel-seed.ts +27 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/testing/index.ts +13 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/testing/like-seed.ts +21 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/testing/post-seed.ts +27 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/testing/profile-seed.ts +28 -0
- package/skills/maestro-examples/references/chorus/packages/services/src/testing/seed-pipe.ts +38 -0
- package/skills/maestro-examples/references/chorus/packages/services/tsconfig.json +9 -0
- package/skills/maestro-examples/references/chorus/scripts/foreign-key-delete-behavior.ts +111 -0
- package/skills/maestro-examples/references/chorus/specs/app.md +73 -0
- package/skills/maestro-examples/references/chorus/specs/data-models.md +48 -0
- package/skills/maestro-examples/references/chorus/specs/database-schema.md +59 -0
- package/skills/maestro-examples/references/chorus/specs/use-cases.md +33 -0
- package/skills/maestro-examples/references/chorus/tsconfig.json +29 -0
- package/skills/maestro-examples/references/setlist/IMPLEMENTATION_PLAN.md +88 -0
- package/skills/maestro-examples/references/setlist/config/db-migrate.ts +9 -0
- package/skills/maestro-examples/references/setlist/config/queue-processor.ts +11 -0
- package/skills/maestro-examples/references/setlist/config/services.ts +16 -0
- package/skills/maestro-examples/references/setlist/config/setlist-web.ts +12 -0
- package/skills/maestro-examples/references/setlist/infrastructure/cdk/index.ts +56 -0
- package/skills/maestro-examples/references/setlist/infrastructure/cdk.context.json +5 -0
- package/skills/maestro-examples/references/setlist/infrastructure/db-migrations/20260316000000_init.ts +16 -0
- package/skills/maestro-examples/references/setlist/infrastructure/db-migrations/20260317000000_add-queue-and-recurring-job-tables.ts +22 -0
- package/skills/maestro-examples/references/setlist/infrastructure/db-migrations/sqls/20260316000000_init-down.sql +5 -0
- package/skills/maestro-examples/references/setlist/infrastructure/db-migrations/sqls/20260316000000_init-up.sql +68 -0
- package/skills/maestro-examples/references/setlist/infrastructure/db-migrations/sqls/20260317000000_add-queue-and-recurring-job-tables-down.sql +2 -0
- package/skills/maestro-examples/references/setlist/infrastructure/db-migrations/sqls/20260317000000_add-queue-and-recurring-job-tables-up.sql +21 -0
- package/skills/maestro-examples/references/setlist/infrastructure/package.json +20 -0
- package/skills/maestro-examples/references/setlist/infrastructure/tsconfig.json +8 -0
- package/skills/maestro-examples/references/setlist/package.json +19 -0
- package/skills/maestro-examples/references/setlist/packages/email-templates/other/generate-email-modules.ts +22 -0
- package/skills/maestro-examples/references/setlist/packages/email-templates/other/generate-email-previews.ts +18 -0
- package/skills/maestro-examples/references/setlist/packages/email-templates/package.json +27 -0
- package/skills/maestro-examples/references/setlist/packages/email-templates/src/components/button.tsx +19 -0
- package/skills/maestro-examples/references/setlist/packages/email-templates/src/components/root-container.tsx +29 -0
- package/skills/maestro-examples/references/setlist/packages/email-templates/src/components/tailwind-wrapper.tsx +113 -0
- package/skills/maestro-examples/references/setlist/packages/email-templates/src/email-modules.ts +9 -0
- package/skills/maestro-examples/references/setlist/packages/email-templates/src/emails/magic-link-login.tsx +49 -0
- package/skills/maestro-examples/references/setlist/packages/email-templates/src/index.ts +3 -0
- package/skills/maestro-examples/references/setlist/packages/email-templates/src/render-email-template.ts +24 -0
- package/skills/maestro-examples/references/setlist/packages/email-templates/src/utils/tw.ts +5 -0
- package/skills/maestro-examples/references/setlist/packages/email-templates/tsconfig.json +11 -0
- package/skills/maestro-examples/references/setlist/packages/email-templates/tsup.config.ts +10 -0
- package/skills/maestro-examples/references/setlist/packages/schemas/package.json +21 -0
- package/skills/maestro-examples/references/setlist/packages/schemas/src/area/index.ts +28 -0
- package/skills/maestro-examples/references/setlist/packages/schemas/src/index.ts +6 -0
- package/skills/maestro-examples/references/setlist/packages/schemas/src/magic-link/index.ts +20 -0
- package/skills/maestro-examples/references/setlist/packages/schemas/src/position.ts +137 -0
- package/skills/maestro-examples/references/setlist/packages/schemas/src/project/index.ts +44 -0
- package/skills/maestro-examples/references/setlist/packages/schemas/src/task/index.ts +41 -0
- package/skills/maestro-examples/references/setlist/packages/schemas/src/user/index.ts +28 -0
- package/skills/maestro-examples/references/setlist/packages/schemas/tests/position.test.ts +106 -0
- package/skills/maestro-examples/references/setlist/packages/schemas/tsconfig.json +9 -0
- package/skills/maestro-examples/references/setlist/packages/services/package.json +40 -0
- package/skills/maestro-examples/references/setlist/packages/services/run-tests.ts +59 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/area/area-db-provider.test.ts +29 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/area/area-db-provider.ts +81 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/area/area-use-cases.ts +130 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/area/index.ts +27 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/auth/auth-db-provider.test.ts +34 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/auth/auth-db-provider.ts +24 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/auth/auth-use-cases.ts +110 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/auth/index.ts +18 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/auth/magic-link-db-provider.test.ts +52 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/auth/magic-link-db-provider.ts +59 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/auth/user-db-provider.test.ts +33 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/auth/user-db-provider.ts +55 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/auth/verify-magic-link-credentials.ts +39 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/index.ts +20 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/maestro.ts +175 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/project/index.ts +29 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/project/project-db-provider.test.ts +46 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/project/project-db-provider.ts +114 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/project/project-use-cases.ts +183 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/task/index.ts +39 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/task/task-db-provider.test.ts +53 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/task/task-db-provider.ts +219 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/task/task-use-cases.ts +303 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/testing/area-seed.ts +25 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/testing/index.ts +13 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/testing/project-seed.ts +29 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/testing/seed-pipe.ts +38 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/testing/task-seed.ts +31 -0
- package/skills/maestro-examples/references/setlist/packages/services/src/testing/user-seed.ts +24 -0
- package/skills/maestro-examples/references/setlist/packages/services/tsconfig.json +9 -0
- package/skills/maestro-examples/references/setlist/queue-processor/package.json +17 -0
- package/skills/maestro-examples/references/setlist/queue-processor/src/index.ts +29 -0
- package/skills/maestro-examples/references/setlist/queue-processor/src/recurring-jobs.ts +13 -0
- package/skills/maestro-examples/references/setlist/queue-processor/tsconfig.json +4 -0
- package/skills/maestro-examples/references/setlist/scripts/foreign-key-delete-behavior.ts +107 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/app.css +158 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/alert-dialog.tsx +153 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/app-dnd-provider.tsx +180 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/area-form.tsx +113 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/button-group.tsx +78 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/button.tsx +139 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/checkbox.tsx +210 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/context-menu.tsx +78 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/date-picker.tsx +214 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/dnd-collision-detection.ts +28 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/dnd-utils.ts +11 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/drag-ghost.tsx +24 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/form.tsx +107 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/helpers/animated-popover.tsx +27 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/helpers/button-context.ts +13 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/helpers/calendar-month-year-picker.tsx +283 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/helpers/form-field.tsx +231 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/helpers/get-button-classes.ts +141 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/helpers/headless-button.tsx +39 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/icon.tsx +29 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/inline-alert.tsx +57 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/project-form.tsx +153 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/select.tsx +219 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/sidebar/helpers.ts +73 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/sidebar/index.ts +6 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/sidebar/inline-inputs.tsx +128 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/sidebar/sidebar.tsx +333 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/sidebar/sortable-rows.tsx +256 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/sidebar/use-sidebar-dnd.ts +261 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/spinner.tsx +19 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/task-inline-create.tsx +51 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/task-list/index.ts +3 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/task-list/task-date-helpers.ts +16 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/task-list/task-expanded-detail.tsx +273 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/task-list/task-keyboard-helpers.ts +5 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/task-list/task-list.tsx +134 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/task-list/task-row.tsx +100 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/task-list/types.ts +49 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/task-list/use-expanded-cache.ts +22 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/task-list/use-sticky-task.ts +24 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/task-list/use-task-reorder.ts +140 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/text-area.tsx +151 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/text-field.tsx +147 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/components/toast.tsx +179 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/entry.client.tsx +21 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/entry.server.tsx +13 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/features/csrf-middleware.server.ts +17 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/features/custom-error-status-code-middleware.server.ts +31 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/features/rate-limiting-middleware.server.ts +36 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/features/redirect-with-toast.server.ts +14 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/features/request-context.server.ts +52 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/features/security-headers-middleware.server.ts +10 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/hooks/use-area-actions.ts +44 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/hooks/use-csrf-token.ts +6 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/hooks/use-project-actions.ts +80 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/hooks/use-task-actions.ts +65 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/root.tsx +218 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/api/areas.$id.delete.tsx +19 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/api/areas.$id.edit.tsx +27 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/api/areas.$id.reorder.tsx +30 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/api/areas.tsx +23 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/api/projects.$id.complete.tsx +19 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/api/projects.$id.delete.tsx +19 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/api/projects.$id.edit.tsx +32 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/api/projects.$id.move.tsx +23 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/api/projects.$id.reorder.tsx +30 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/api/projects.$id.uncomplete.tsx +19 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/api/projects.tsx +23 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/api/tasks.$id.complete.tsx +19 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/api/tasks.$id.delete.tsx +19 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/api/tasks.$id.edit.tsx +27 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/api/tasks.$id.move.tsx +30 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/api/tasks.$id.reorder.tsx +32 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/api/tasks.$id.uncomplete.tsx +19 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/api/tasks.tsx +23 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/areas.$id.tsx +155 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/auth.login.tsx +98 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/auth.logout.tsx +17 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/auth.verify.tsx +154 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/completed.tsx +121 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/inbox.tsx +68 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/projects.$id.tsx +217 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/today.tsx +86 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes/upcoming.tsx +83 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/routes.ts +4 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/services.server.ts +1 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/utils/colors.ts +47 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/utils/compose-refs.ts +35 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/utils/tw.ts +16 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/utils/use-dismiss.ts +27 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/utils/use-fetcher-complete.ts +17 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/utils/use-prevent-default.ts +30 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/utils/use-render-props.ts +42 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/utils/use-spin-delay.ts +27 -0
- package/skills/maestro-examples/references/setlist/setlist-web/app/utils/use-stable-accessor.ts +14 -0
- package/skills/maestro-examples/references/setlist/setlist-web/environment.d.ts +8 -0
- package/skills/maestro-examples/references/setlist/setlist-web/instrument.server.mjs +29 -0
- package/skills/maestro-examples/references/setlist/setlist-web/knip.json +3 -0
- package/skills/maestro-examples/references/setlist/setlist-web/package.json +52 -0
- package/skills/maestro-examples/references/setlist/setlist-web/playwright.config.ts +39 -0
- package/skills/maestro-examples/references/setlist/setlist-web/react-router.config.ts +12 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/areas-create.test.ts +37 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/areas-delete.test.ts +45 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/areas-deleted-not-in-sidebar.test.ts +44 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/areas-detail-view.test.ts +46 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/areas-edit-title.test.ts +48 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/areas-expand-collapse.test.ts +50 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/areas-list-in-sidebar.test.ts +37 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/areas-reorder-dnd.test.ts +82 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/auth-logout.test.ts +18 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/auth-reject-invalid-token.test.ts +35 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/auth-reject-used-token.test.ts +104 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/auth-request-magic-link.test.ts +29 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/auth-verify-via-pasted-token.test.ts +52 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/auth-verify-via-url.test.ts +48 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/auth.setup.ts +55 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/constants.ts +13 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/dnd-inbox-to-area.test.ts +74 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/dnd-inbox-to-project.test.ts +73 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/dnd-move-to-inbox.test.ts +51 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/dnd-project-to-area.test.ts +76 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/dnd-project-to-project.test.ts +75 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/home.test.ts +27 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/projects-complete.test.ts +53 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/projects-completed-not-in-sidebar.test.ts +46 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/projects-create-in-area.test.ts +55 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/projects-create-top-level.test.ts +37 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/projects-delete.test.ts +55 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/projects-edit-notes-date.test.ts +69 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/projects-edit-title.test.ts +48 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/projects-move-into-area.test.ts +72 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/projects-move-out-of-area.test.ts +76 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/projects-reorder-top-level.test.ts +82 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/projects-reorder-within-area.test.ts +91 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/projects-uncomplete.test.ts +39 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/projects-view-tasks.test.ts +48 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/tasks-complete-removes-from-active-views.test.ts +52 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/tasks-complete.test.ts +46 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/tasks-create-in-inbox.test.ts +19 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/tasks-create-in-project.test.ts +44 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/tasks-delete.test.ts +52 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/tasks-edit.test.ts +73 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/tasks-reorder-in-project.test.ts +81 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/tasks-reorder-inbox.test.ts +80 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/tasks-reorder-today.test.ts +103 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/tasks-uncomplete.test.ts +51 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/tasks-view-details.test.ts +51 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/views-active-sidebar-highlight.test.ts +38 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/views-inbox-unassigned-only.test.ts +43 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/views-navigate-to-completed.test.ts +59 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/views-navigate-to-inbox.test.ts +21 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/views-navigate-to-today.test.ts +42 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/views-navigate-to-upcoming.test.ts +59 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/views-sidebar-built-in-views.test.ts +23 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tests/views-today-shows-overdue.test.ts +48 -0
- package/skills/maestro-examples/references/setlist/setlist-web/tsconfig.json +22 -0
- package/skills/maestro-examples/references/setlist/setlist-web/vite.config.ts +37 -0
- package/skills/maestro-examples/references/setlist/specs/app.md +69 -0
- package/skills/maestro-examples/references/setlist/specs/data-models.md +92 -0
- package/skills/maestro-examples/references/setlist/specs/database-schema.md +76 -0
- package/skills/maestro-examples/references/setlist/specs/drag-and-drop.md +89 -0
- package/skills/maestro-examples/references/setlist/specs/magic-link-login.md +300 -0
- package/skills/maestro-examples/references/setlist/specs/position-ordering.md +329 -0
- package/skills/maestro-examples/references/setlist/specs/sidebar.md +65 -0
- package/skills/maestro-examples/references/setlist/specs/use-cases.md +55 -0
- package/skills/maestro-examples/references/setlist/tsconfig.json +28 -0
- package/{dist → skills}/maestro-packages/SKILL.md +3 -3
- package/skills/maestro-packages/permissions.md +215 -0
- package/skills/maestro-packages/queue.md +442 -0
- package/skills/maestro-packages/recurring-jobs.md +238 -0
- package/skills/react-use-effect/SKILL.md +65 -0
- package/skills/react-use-effect/references/patterns.md +283 -0
- package/dist/maestro-packages/queue.md +0 -284
- package/dist/maestro-packages/recurring-jobs.md +0 -353
- package/dist/maestro-packages/tracing.md +0 -240
- /package/{dist → skills}/maestro-cli/SKILL.md +0 -0
- /package/{dist → skills}/maestro-packages/broadcast.md +0 -0
- /package/{dist → skills}/maestro-packages/cache-control.md +0 -0
- /package/{dist → skills}/maestro-packages/cache.md +0 -0
- /package/{dist → skills}/maestro-packages/config.md +0 -0
- /package/{dist → skills}/maestro-packages/context.md +0 -0
- /package/{dist → skills}/maestro-packages/crypt.md +0 -0
- /package/{dist → skills}/maestro-packages/db.md +0 -0
- /package/{dist → skills}/maestro-packages/events.md +0 -0
- /package/{dist → skills}/maestro-packages/exceptions.md +0 -0
- /package/{dist → skills}/maestro-packages/form.md +0 -0
- /package/{dist → skills}/maestro-packages/hash.md +0 -0
- /package/{dist → skills}/maestro-packages/helpers.md +0 -0
- /package/{dist → skills}/maestro-packages/log.md +0 -0
- /package/{dist → skills}/maestro-packages/mail.md +0 -0
- /package/{dist → skills}/maestro-packages/metrics.md +0 -0
- /package/{dist → skills}/maestro-packages/rate-limiting.md +0 -0
- /package/{dist → skills}/maestro-packages/react-router-file-routes.md +0 -0
- /package/{dist → skills}/maestro-packages/sql.md +0 -0
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# App Requirements
|
|
2
|
+
|
|
3
|
+
A community discussion site where users browse channels, read posts, and participate in conversations. Think a simplified Reddit with Twitter-style image layouts.
|
|
4
|
+
|
|
5
|
+
## Channels
|
|
6
|
+
|
|
7
|
+
A channel is a named topic area (e.g. "Photography", "Cooking", "Tech News"). Channels are the top-level organizational unit.
|
|
8
|
+
|
|
9
|
+
- Anyone can browse the list of channels and view a channel's posts without logging in
|
|
10
|
+
- Each channel has a name, a URL-friendly slug (auto-generated from the name, must be unique), a description, and an optional icon/avatar
|
|
11
|
+
- Each channel has a single owner — the user who creates the channel is the owner
|
|
12
|
+
- Each channel has zero or more moderators
|
|
13
|
+
- Only authenticated users can create a channel
|
|
14
|
+
- The owner can edit the channel's name, description, and icon
|
|
15
|
+
- The owner can appoint or remove moderators
|
|
16
|
+
- The owner can transfer ownership to another user
|
|
17
|
+
- Moderators can hide any post or reply within their channel — replies to a hidden post remain visible
|
|
18
|
+
- A channel displays its posts in reverse chronological order (newest first)
|
|
19
|
+
|
|
20
|
+
## Posts
|
|
21
|
+
|
|
22
|
+
A post is a piece of content submitted to a channel by an authenticated user.
|
|
23
|
+
|
|
24
|
+
- Only authenticated users can create a post
|
|
25
|
+
- A post belongs to exactly one channel
|
|
26
|
+
- A post contains text content (required) and optionally up to 4 images
|
|
27
|
+
- Posts display the author's email/name, the timestamp, the number of replies, and the images (if any)
|
|
28
|
+
- Posts cannot be edited or deleted by the author
|
|
29
|
+
- The author can hide their own post — replies to a hidden post remain visible
|
|
30
|
+
- Moderators can also hide posts
|
|
31
|
+
|
|
32
|
+
### Likes
|
|
33
|
+
|
|
34
|
+
- Only authenticated users can like a post
|
|
35
|
+
- A user can like a post at most once; unliking removes the like
|
|
36
|
+
- Posts display their total like count
|
|
37
|
+
- The UI indicates whether the current user has liked a post
|
|
38
|
+
|
|
39
|
+
### Image Display
|
|
40
|
+
|
|
41
|
+
Posts can include 0–4 images. The layout adapts based on the number of images, following Twitter's image grid pattern:
|
|
42
|
+
|
|
43
|
+
- **1 image** — single image fills the full width
|
|
44
|
+
- **2 images** — two images side by side, each taking half the width
|
|
45
|
+
- **3 images** — one large image on the left (half width, full height), two stacked on the right (half width each)
|
|
46
|
+
- **4 images** — 2×2 grid, all images equal size
|
|
47
|
+
|
|
48
|
+
All image containers use a consistent aspect ratio and crop/cover to fit. Clicking an image opens a larger view.
|
|
49
|
+
|
|
50
|
+
## Replies
|
|
51
|
+
|
|
52
|
+
A reply is a response to a post. Replies are structurally identical to posts but nested under a parent.
|
|
53
|
+
|
|
54
|
+
- Only authenticated users can reply
|
|
55
|
+
- A reply contains text content (required) and optionally up to 4 images (same display rules as posts)
|
|
56
|
+
- Replies display the author, timestamp, and images (if any)
|
|
57
|
+
- Replies are displayed in chronological order (oldest first) beneath their parent post
|
|
58
|
+
- Replies cannot be edited or deleted by the author
|
|
59
|
+
- The author can hide their own reply
|
|
60
|
+
- Moderators can also hide replies
|
|
61
|
+
- Replies are single-level only — you reply to a post, not to another reply
|
|
62
|
+
|
|
63
|
+
## Browsing & Reading
|
|
64
|
+
|
|
65
|
+
- The home page shows a list of channels sorted by most activity in the last 24 hours (activity = posts, replies, and likes within the channel)
|
|
66
|
+
- Channels are identified in URLs by their slug (e.g. `/c/photography`)
|
|
67
|
+
- Clicking a channel shows its posts (paginated, newest first)
|
|
68
|
+
- Clicking a post shows the full post with all its replies beneath it
|
|
69
|
+
- All browsing and reading is available to unauthenticated users — no login required to read
|
|
70
|
+
|
|
71
|
+
## Authentication
|
|
72
|
+
|
|
73
|
+
Authentication is already built into the app. The existing signup, login, logout, password reset, and session management flows remain unchanged. The new features simply gate write actions (creating channels, posting, replying, moderating) behind an authenticated session.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Data Models
|
|
2
|
+
|
|
3
|
+
Zod schemas for the community discussion site. Each section defines a zod model. Note: zod models are not necessarily one-to-one with database tables.
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
## Channels
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
const channelModel = z.object({
|
|
11
|
+
id: z.number(),
|
|
12
|
+
ownerProfileId: z.number(),
|
|
13
|
+
name: z.string(),
|
|
14
|
+
slug: z.string(),
|
|
15
|
+
description: z.string(),
|
|
16
|
+
moderatorProfileIds: z.number().array(),
|
|
17
|
+
createdDate: isoZ.instant(),
|
|
18
|
+
lastModifiedDate: isoZ.instant()
|
|
19
|
+
})
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Posts
|
|
23
|
+
|
|
24
|
+
A reply is just a post with a `replyingToPostId`. Top-level posts have `replyingToPostId: null`. Replies are single-level only — a reply's `replyingToPostId` always points to a top-level post, never to another reply.
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
const postModel = z.object({
|
|
28
|
+
id: z.number(),
|
|
29
|
+
channelId: z.number(),
|
|
30
|
+
profileId: z.number(),
|
|
31
|
+
replyingToPostId: z.number().nullable(),
|
|
32
|
+
content: z.string(),
|
|
33
|
+
images: z.array(z.string().max(500)).max(4),
|
|
34
|
+
hiddenDate: isoZ.instant().nullable(),
|
|
35
|
+
createdDate: isoZ.instant(),
|
|
36
|
+
lastModifiedDate: isoZ.instant()
|
|
37
|
+
})
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Likes
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
const likeModel = z.object({
|
|
44
|
+
postId: z.number(),
|
|
45
|
+
profileId: z.number(),
|
|
46
|
+
createdDate: isoZ.instant()
|
|
47
|
+
})
|
|
48
|
+
```
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Database Schema
|
|
2
|
+
|
|
3
|
+
MySQL schema for the community discussion site. Derived from the zod models in `data-models.md`.
|
|
4
|
+
|
|
5
|
+
## Tables
|
|
6
|
+
|
|
7
|
+
```sql
|
|
8
|
+
CREATE TABLE channels (
|
|
9
|
+
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
|
10
|
+
ownerProfileId INT UNSIGNED NOT NULL,
|
|
11
|
+
name VARCHAR(255) NOT NULL,
|
|
12
|
+
slug VARCHAR(255) NOT NULL,
|
|
13
|
+
description VARCHAR(2000) NOT NULL,
|
|
14
|
+
createdDate DATETIME(3) NOT NULL,
|
|
15
|
+
lastModifiedDate DATETIME(3) NOT NULL,
|
|
16
|
+
UNIQUE KEY uq_channels_slug (slug),
|
|
17
|
+
CONSTRAINT fk_channels_ownerProfileId FOREIGN KEY (ownerProfileId) REFERENCES profiles (profileId)
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
CREATE TABLE channelModerators (
|
|
21
|
+
channelId BIGINT UNSIGNED NOT NULL,
|
|
22
|
+
profileId INT UNSIGNED NOT NULL,
|
|
23
|
+
PRIMARY KEY (channelId, profileId),
|
|
24
|
+
CONSTRAINT fk_channelModerators_channelId FOREIGN KEY (channelId) REFERENCES channels (id),
|
|
25
|
+
CONSTRAINT fk_channelModerators_profileId FOREIGN KEY (profileId) REFERENCES profiles (profileId)
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
CREATE TABLE posts (
|
|
29
|
+
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
|
30
|
+
channelId BIGINT UNSIGNED NOT NULL,
|
|
31
|
+
profileId INT UNSIGNED NOT NULL,
|
|
32
|
+
replyingToPostId BIGINT UNSIGNED,
|
|
33
|
+
content TEXT NOT NULL,
|
|
34
|
+
hiddenDate DATETIME(3),
|
|
35
|
+
createdDate DATETIME(3) NOT NULL,
|
|
36
|
+
lastModifiedDate DATETIME(3) NOT NULL,
|
|
37
|
+
KEY idx_posts_channel_created (channelId, createdDate),
|
|
38
|
+
CONSTRAINT fk_posts_channelId FOREIGN KEY (channelId) REFERENCES channels (id),
|
|
39
|
+
CONSTRAINT fk_posts_profileId FOREIGN KEY (profileId) REFERENCES profiles (profileId),
|
|
40
|
+
CONSTRAINT fk_posts_replyingToPostId FOREIGN KEY (replyingToPostId) REFERENCES posts (id)
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
CREATE TABLE postImages (
|
|
44
|
+
postId BIGINT UNSIGNED NOT NULL,
|
|
45
|
+
sortOrder TINYINT UNSIGNED NOT NULL,
|
|
46
|
+
url VARCHAR(500) NOT NULL,
|
|
47
|
+
PRIMARY KEY (postId, sortOrder),
|
|
48
|
+
CONSTRAINT fk_postImages_postId FOREIGN KEY (postId) REFERENCES posts (id)
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
CREATE TABLE likes (
|
|
52
|
+
postId BIGINT UNSIGNED NOT NULL,
|
|
53
|
+
profileId INT UNSIGNED NOT NULL,
|
|
54
|
+
createdDate DATETIME(3) NOT NULL,
|
|
55
|
+
PRIMARY KEY (postId, profileId),
|
|
56
|
+
CONSTRAINT fk_likes_postId FOREIGN KEY (postId) REFERENCES posts (id),
|
|
57
|
+
CONSTRAINT fk_likes_profileId FOREIGN KEY (profileId) REFERENCES profiles (profileId)
|
|
58
|
+
);
|
|
59
|
+
```
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Use Cases
|
|
2
|
+
|
|
3
|
+
Use cases for the community discussion site, grouped by entity.
|
|
4
|
+
|
|
5
|
+
## Channels
|
|
6
|
+
|
|
7
|
+
| # | Use Case | Auth Required | Actor |
|
|
8
|
+
|---|----------|---------------|-------|
|
|
9
|
+
| C1 | Browse list of channels (sorted by most activity in last 24h) | No | Anyone |
|
|
10
|
+
| C2 | View a channel's posts (paginated, newest first) | No | Anyone |
|
|
11
|
+
| C3 | Create a channel (creator becomes owner) | Yes | User |
|
|
12
|
+
| C4 | Edit channel name, description, or icon | Yes | Owner |
|
|
13
|
+
| C5 | Appoint a moderator to a channel | Yes | Owner |
|
|
14
|
+
| C6 | Remove a moderator from a channel | Yes | Owner |
|
|
15
|
+
| C7 | Transfer channel ownership to another user | Yes | Owner |
|
|
16
|
+
|
|
17
|
+
## Posts
|
|
18
|
+
|
|
19
|
+
| # | Use Case | Auth Required | Actor |
|
|
20
|
+
|---|----------|---------------|-------|
|
|
21
|
+
| P1 | View a post with all its replies (chronological) | No | Anyone |
|
|
22
|
+
| P2 | Create a post in a channel (text required, 0-4 images) | Yes | User |
|
|
23
|
+
| P3 | Reply to a post (text required, 0-4 images, single-level only) | Yes | User |
|
|
24
|
+
| P4 | Hide a post (replies remain visible) | Yes | Author or Moderator |
|
|
25
|
+
|
|
26
|
+
## Likes
|
|
27
|
+
|
|
28
|
+
| # | Use Case | Auth Required | Actor |
|
|
29
|
+
|---|----------|---------------|-------|
|
|
30
|
+
| L1 | Like a post | Yes | User |
|
|
31
|
+
| L2 | Unlike a post | Yes | User |
|
|
32
|
+
| L3 | View like count on a post | No | Anyone |
|
|
33
|
+
| L4 | View whether current user has liked a post | Yes | User |
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/tsconfig",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"target": "ES2022",
|
|
5
|
+
"lib": ["ES2022"],
|
|
6
|
+
"moduleDetection": "force",
|
|
7
|
+
|
|
8
|
+
"jsx": "react-jsx",
|
|
9
|
+
"allowJs": true,
|
|
10
|
+
"checkJs": true,
|
|
11
|
+
"esModuleInterop": true,
|
|
12
|
+
"isolatedModules": true,
|
|
13
|
+
"erasableSyntaxOnly": true,
|
|
14
|
+
"skipLibCheck": true,
|
|
15
|
+
|
|
16
|
+
"strict": true,
|
|
17
|
+
"noImplicitAny": false,
|
|
18
|
+
"noImplicitOverride": true,
|
|
19
|
+
"noFallthroughCasesInSwitch": true,
|
|
20
|
+
"forceConsistentCasingInFileNames": true,
|
|
21
|
+
"allowImportingTsExtensions": true,
|
|
22
|
+
|
|
23
|
+
"noEmit": true,
|
|
24
|
+
"verbatimModuleSyntax": true,
|
|
25
|
+
"noUncheckedIndexedAccess": true
|
|
26
|
+
},
|
|
27
|
+
"exclude": ["node_modules"],
|
|
28
|
+
"include": ["./src", "./packages/*/src", "./packages/*/tests", "./sandbox/*/src"]
|
|
29
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Implementation Plan
|
|
2
|
+
|
|
3
|
+
## Progress
|
|
4
|
+
|
|
5
|
+
### Refactoring & Architecture (Issues 0–14)
|
|
6
|
+
|
|
7
|
+
- [x] **#0** — Sidebar: Extract inline components into separate files
|
|
8
|
+
- [x] **#1** — Sidebar: Extract DnD reorder logic into useSidebarDnd hook (depends: #0)
|
|
9
|
+
- [x] **#2** — Sidebar: Remove manual revalidation and useEffects
|
|
10
|
+
- [x] **#3** — Task Detail Panel: Use React key for state reset, remove manual revalidation
|
|
11
|
+
- [x] **#4** — Task Detail Panel: Extract dismiss behavior into a reusable hook
|
|
12
|
+
- [x] **#5** — Context Menu: Replace custom implementation with React Aria Menu
|
|
13
|
+
- [x] **#6** — Project Form: Use Form component and fetcher.Form
|
|
14
|
+
- [x] **#7** — Area Form: Use Form component and fetcher.Form
|
|
15
|
+
- [x] **#8** — App DnD Provider: Extract DragGhost, collision detection, and clean up revalidation
|
|
16
|
+
- [x] **#9** — use-task-reorder: Derive optimistic tasks from fetcher state
|
|
17
|
+
- [x] **#10** — API Routes: Split api.tasks.$id into separate routes per action
|
|
18
|
+
- [x] **#11** — API Routes: Split api.projects.$id into separate routes per action
|
|
19
|
+
- [x] **#12** — API Routes: Split api.areas.$id into separate routes per action
|
|
20
|
+
- [x] **#13** — Create typed hooks for each API action route (depends: #10, #11, #12)
|
|
21
|
+
- [x] **#14** — Sidebar: InlineCreateInput and InlineEditInput should use fetcher.Form (depends: #10, #11, #12)
|
|
22
|
+
|
|
23
|
+
### E2E Tests (Issues 100–152)
|
|
24
|
+
|
|
25
|
+
- [x] **#100** — E2E: Request magic link with valid email
|
|
26
|
+
- [x] **#103** — E2E: Verify magic link via URL (depends: #100)
|
|
27
|
+
- [x] **#104** — E2E: Verify magic link via pasted token (depends: #100)
|
|
28
|
+
- [x] **#105** — E2E: Reject invalid or malformed token (depends: #100)
|
|
29
|
+
- [x] **#106** — E2E: Reject already-used token (depends: #103 or #104)
|
|
30
|
+
- [x] **#107** — E2E: Logout (depends: #103 or #104)
|
|
31
|
+
- [x] **#108** — E2E: Sidebar displays built-in views (depends: #107)
|
|
32
|
+
- [x] **#109** — E2E: Navigate to Inbox (depends: #108)
|
|
33
|
+
- [x] **#110** — E2E: Inbox shows only unassigned tasks (depends: #109)
|
|
34
|
+
- [x] **#111** — E2E: Navigate to Today (depends: #108)
|
|
35
|
+
- [x] **#112** — E2E: Today shows overdue tasks (depends: #111)
|
|
36
|
+
- [x] **#113** — E2E: Navigate to Upcoming (depends: #108)
|
|
37
|
+
- [x] **#114** — E2E: Navigate to Completed (depends: #108)
|
|
38
|
+
- [x] **#115** — E2E: Active sidebar highlight (depends: #109, #111, #113, #114)
|
|
39
|
+
- [x] **#116** — E2E: List areas in sidebar (depends: #108)
|
|
40
|
+
- [x] **#117** — E2E: Create an area (depends: #116)
|
|
41
|
+
- [x] **#118** — E2E: Edit area title (depends: #117)
|
|
42
|
+
- [x] **#119** — E2E: Delete an area (depends: #117)
|
|
43
|
+
- [x] **#120** — E2E: Navigate to area detail view (depends: #116)
|
|
44
|
+
- [x] **#121** — E2E: Area expand/collapse (depends: #116, #120)
|
|
45
|
+
- [x] **#122** — E2E: Reorder areas via DnD (depends: #116)
|
|
46
|
+
- [x] **#123** — E2E: Deleted area not in sidebar (depends: #119)
|
|
47
|
+
- [x] **#124** — E2E: View a project's tasks (depends: #120)
|
|
48
|
+
- [x] **#125** — E2E: Create a project (top-level) (depends: #116)
|
|
49
|
+
- [x] **#126** — E2E: Create a project inside an area (depends: #121, #125)
|
|
50
|
+
- [x] **#127** — E2E: Edit project title (depends: #124)
|
|
51
|
+
- [x] **#128** — E2E: Edit project notes and date (depends: #124)
|
|
52
|
+
- [x] **#129** — E2E: Move project into area via DnD (depends: #125, #126)
|
|
53
|
+
- [x] **#130** — E2E: Move project out of area via DnD (depends: #126)
|
|
54
|
+
- [x] **#131** — E2E: Complete a project (depends: #125)
|
|
55
|
+
- [x] **#132** — E2E: Uncomplete a project (depends: #131)
|
|
56
|
+
- [x] **#133** — E2E: Delete a project (depends: #125)
|
|
57
|
+
- [x] **#134** — E2E: Completed project not in sidebar (depends: #131)
|
|
58
|
+
- [x] **#135** — E2E: Reorder top-level projects via DnD (depends: #125)
|
|
59
|
+
- [x] **#136** — E2E: Reorder projects within area (depends: #126)
|
|
60
|
+
- [x] **#137** — E2E: View task details (depends: #124)
|
|
61
|
+
- [x] **#138** — E2E: Create a task in Inbox (depends: #109, #137)
|
|
62
|
+
- [x] **#139** — E2E: Create a task in a project (depends: #124, #137)
|
|
63
|
+
- [x] **#140** — E2E: Edit task (depends: #137)
|
|
64
|
+
- [x] **#141** — E2E: Complete a task (depends: #138)
|
|
65
|
+
- [x] **#142** — E2E: Uncomplete a task (depends: #141)
|
|
66
|
+
- [x] **#143** — E2E: Delete a task (depends: #137)
|
|
67
|
+
- [x] **#144** — E2E: Reorder tasks in Inbox via DnD (depends: #138)
|
|
68
|
+
- [x] **#145** — E2E: Reorder tasks in Today via DnD (depends: #111, #140)
|
|
69
|
+
- [x] **#146** — E2E: Reorder tasks within a project (depends: #139, #140)
|
|
70
|
+
- [x] **#147** — E2E: Complete task removes from active views (depends: #138, #140)
|
|
71
|
+
- [x] **#148** — E2E: Move task from Inbox to project (depends: #138, #139)
|
|
72
|
+
- [x] **#149** — E2E: Move task from Inbox to area (depends: #138, #116)
|
|
73
|
+
- [x] **#150** — E2E: Move task between projects (depends: #139, #146)
|
|
74
|
+
- [x] **#151** — E2E: Move task from project to area (depends: #139, #116)
|
|
75
|
+
- [x] **#152** — E2E: Move task to Inbox by clearing assignment (depends: #140)
|
|
76
|
+
|
|
77
|
+
## Discoveries
|
|
78
|
+
|
|
79
|
+
- E2E tests require a running MySQL database. The CI environment doesn't have one, so tests can't be executed here. The test code follows the exact same pattern as `auth.setup.ts` which was verified working in issue #100.
|
|
80
|
+
- The `Document` component in `root.tsx` calls `useLoaderData()` which returns `undefined` inside `ErrorBoundary` context, causing a crash on error pages. This is a pre-existing bug that doesn't affect happy-path flows.
|
|
81
|
+
- The `completed.tsx` route had a bug: `dateFns.format(item.completedDate as Iso.Date, ...)` fails because `completedDate` is an instant (datetime string), not a date string. `dateFns.format` from `iso-fns` requires an `Iso.Date` (e.g., `"2024-01-15"`), not a full instant. Fixed by slicing to extract the date portion: `.slice(0, 10)`.
|
|
82
|
+
- The `TaskSeed` helper used `taskDbProvider.create` which doesn't support `completedDate`. Added `taskDbProvider.seedCreate` (mirroring `projectDbProvider.seedCreate`) and updated `TaskSeed` to use it, enabling seeding tasks with any field including `completedDate` and `deletedDate`.
|
|
83
|
+
- The `createProjectForm` schema had `areaId`, `notes`, and `scheduledDate` as `.nullable()` but not `.default(null)`. The inline sidebar create form only sends `title`, so these fields were missing from FormData and parsed as `undefined`, failing Zod validation. Fixed by adding `.default(null)` to each field so missing values default to `null`.
|
|
84
|
+
- The `CompleteProject` use case was incorrectly calling `taskDbProvider.completeByProjectId(id)` inside a transaction, which completed all tasks when a project was completed. The spec and app requirements state "completing a project does not automatically complete its tasks." Removed the task completion line so only the project itself is marked complete.
|
|
85
|
+
- The `createTaskForm` schema had the same bug as `createProjectForm`: `projectId`, `areaId`, `notes`, and `scheduledDate` were `.nullable()` but not `.default(null)`. The inline create form only sends `title`, so missing fields failed Zod validation. Fixed by adding `.default(null)` to each nullable field.
|
|
86
|
+
- The Today route (`today.tsx`) was missing `onComplete` and `onUncomplete` callbacks on the `TaskList` component (same bug as Inbox). Added `useCompleteTask` and `useUncompleteTask` hooks and passed them as handlers.
|
|
87
|
+
- The `TaskDetailPanel` had no Save button. The edit form only auto-submitted on title Enter key or date change, making it impossible to save notes alone. Added a Save button to the form (matching the project form pattern) so all fields can be explicitly submitted.
|
|
88
|
+
- The Inbox route (`inbox.tsx`) was missing `onComplete` and `onUncomplete` callbacks on the `TaskList` component, so clicking a task's checkbox did nothing. Added `useCompleteTask` and `useUncompleteTask` hooks and passed them as handlers.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export default async function (env: Record<string, string | undefined>) {
|
|
2
|
+
return {
|
|
3
|
+
DB_HOST: env.DB_HOST ?? 'localhost',
|
|
4
|
+
DB_PORT: env.DB_PORT ?? '3310',
|
|
5
|
+
DB_USER: env.DB_USER ?? 'setlist',
|
|
6
|
+
DB_PASSWORD: env.DB_PASSWORD ?? '',
|
|
7
|
+
DB_DATABASE: env.DB_DATABASE ?? 'setlist'
|
|
8
|
+
}
|
|
9
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import getServicesConfig from './services.ts'
|
|
2
|
+
|
|
3
|
+
export default async function (env: Record<string, string | undefined>) {
|
|
4
|
+
const servicesConfig = await getServicesConfig(env)
|
|
5
|
+
|
|
6
|
+
return {
|
|
7
|
+
...servicesConfig,
|
|
8
|
+
QUEUE_CONCURRENCY: env.QUEUE_CONCURRENCY ?? '1',
|
|
9
|
+
QUEUE_POLL_INTERVAL: env.QUEUE_POLL_INTERVAL ?? '5000'
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export default async function (env: Record<string, string | undefined>) {
|
|
2
|
+
return {
|
|
3
|
+
DB_HOST: env.DB_HOST ?? 'localhost',
|
|
4
|
+
DB_PORT: env.DB_PORT ?? '3306',
|
|
5
|
+
DB_USER: env.DB_USER ?? 'setlist',
|
|
6
|
+
DB_PASSWORD: env.DB_PASSWORD ?? '',
|
|
7
|
+
DB_DATABASE: env.DB_DATABASE ?? 'setlist',
|
|
8
|
+
ENCRYPTION_KEY: env.ENCRYPTION_KEY,
|
|
9
|
+
HASH_KEY: env.HASH_KEY,
|
|
10
|
+
MAIL_FROM: env.MAIL_FROM ?? 'noreply@setlist.app',
|
|
11
|
+
BASE_URL: env.BASE_URL ?? 'http://localhost:3000',
|
|
12
|
+
ENV_NAME: env.ENV_NAME ?? 'local',
|
|
13
|
+
AWS_REGION: env.AWS_REGION ?? 'us-east-1',
|
|
14
|
+
TZ: 'America/Chicago'
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import getServicesConfig from './services.ts'
|
|
2
|
+
|
|
3
|
+
export default async function (env: Record<string, string | undefined>) {
|
|
4
|
+
const servicesConfig = await getServicesConfig(env)
|
|
5
|
+
|
|
6
|
+
return {
|
|
7
|
+
...servicesConfig,
|
|
8
|
+
PORT: env.PORT ?? '3000',
|
|
9
|
+
SESSION_COOKIE_NAME: 'setlist_session',
|
|
10
|
+
SESSION_COOKIE_SECURE: servicesConfig.ENV_NAME !== 'local' ? 'true' : 'false'
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import * as path from 'path'
|
|
2
|
+
import { App, Duration, Stack } from 'aws-cdk-lib'
|
|
3
|
+
import { AuroraMysqlEngineVersion } from 'aws-cdk-lib/aws-rds'
|
|
4
|
+
import { AuroraDatabase, Email, LambdaFunction, ReactRouterSsrSiteLambda, Vpc } from '@maestro-js/aws-cdk-recipes'
|
|
5
|
+
|
|
6
|
+
const app = new App()
|
|
7
|
+
const stack = new Stack(app, 'Setlist')
|
|
8
|
+
|
|
9
|
+
// VPC
|
|
10
|
+
const network = new Vpc(stack, 'Network', {
|
|
11
|
+
natGateways: 'single',
|
|
12
|
+
wireguard: true
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
// Aurora MySQL database
|
|
16
|
+
const db = new AuroraDatabase(stack, 'Database', {
|
|
17
|
+
engine: 'mysql',
|
|
18
|
+
version: AuroraMysqlEngineVersion.VER_3_08_0,
|
|
19
|
+
database: 'setlist',
|
|
20
|
+
scaling: { pauseAfter: '5 minutes' },
|
|
21
|
+
deletionProtection: false,
|
|
22
|
+
vpc: network.vpc
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
db.connections.allowDefaultPortFrom(network.securityGroup, 'WireGuard VPN access')
|
|
26
|
+
|
|
27
|
+
// SES email for magic links
|
|
28
|
+
new Email(stack, 'Email', {
|
|
29
|
+
sender: 'setlist@marcatopartners.com',
|
|
30
|
+
configurationSetName: 'setlist'
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
// React Router SSR app on Lambda + CloudFront
|
|
34
|
+
new ReactRouterSsrSiteLambda(stack, 'SsrApp', {
|
|
35
|
+
path: path.join(import.meta.dirname, '../../setlist-web'),
|
|
36
|
+
vpc: network,
|
|
37
|
+
environment: {
|
|
38
|
+
DB_HOST: db.host,
|
|
39
|
+
DB_PORT: String(db.port),
|
|
40
|
+
DB_DATABASE: 'setlist',
|
|
41
|
+
DB_USER: 'root'
|
|
42
|
+
}
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
// Queue processor Lambda
|
|
46
|
+
new LambdaFunction(stack, 'QueueProcessor', {
|
|
47
|
+
handler: 'queue-processor.handler',
|
|
48
|
+
vpc: network.vpc,
|
|
49
|
+
timeout: Duration.minutes(5),
|
|
50
|
+
environment: {
|
|
51
|
+
DB_HOST: db.host,
|
|
52
|
+
DB_PORT: String(db.port),
|
|
53
|
+
DB_DATABASE: 'setlist',
|
|
54
|
+
DB_USER: 'root'
|
|
55
|
+
}
|
|
56
|
+
})
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { DbMigrations } from '@maestro-js/db-migrate'
|
|
2
|
+
import { readFile } from 'node:fs/promises'
|
|
3
|
+
import { join, dirname } from 'node:path'
|
|
4
|
+
import { fileURLToPath } from 'node:url'
|
|
5
|
+
|
|
6
|
+
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
7
|
+
|
|
8
|
+
export async function up(db: DbMigrations.Db) {
|
|
9
|
+
const sql = await readFile(join(__dirname, 'sqls', '20260316000000_init-up.sql'), 'utf-8')
|
|
10
|
+
await db.statement(sql)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export async function down(db: DbMigrations.Db) {
|
|
14
|
+
const sql = await readFile(join(__dirname, 'sqls', '20260316000000_init-down.sql'), 'utf-8')
|
|
15
|
+
await db.statement(sql)
|
|
16
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { DbMigrations } from '@maestro-js/db-migrate'
|
|
2
|
+
import { readFile } from 'node:fs/promises'
|
|
3
|
+
import { join, dirname } from 'node:path'
|
|
4
|
+
import { fileURLToPath } from 'node:url'
|
|
5
|
+
|
|
6
|
+
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
7
|
+
|
|
8
|
+
export async function up(db: DbMigrations.Db) {
|
|
9
|
+
const sql = await readFile(
|
|
10
|
+
join(__dirname, 'sqls', '20260317000000_add-queue-and-recurring-job-tables-up.sql'),
|
|
11
|
+
'utf-8'
|
|
12
|
+
)
|
|
13
|
+
await db.statement(sql)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export async function down(db: DbMigrations.Db) {
|
|
17
|
+
const sql = await readFile(
|
|
18
|
+
join(__dirname, 'sqls', '20260317000000_add-queue-and-recurring-job-tables-down.sql'),
|
|
19
|
+
'utf-8'
|
|
20
|
+
)
|
|
21
|
+
await db.statement(sql)
|
|
22
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
CREATE TABLE users (
|
|
2
|
+
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
|
3
|
+
email VARCHAR(255) NOT NULL,
|
|
4
|
+
credentialsInvalidBefore DATETIME(3),
|
|
5
|
+
createdDate DATETIME(3) NOT NULL,
|
|
6
|
+
lastModifiedDate DATETIME(3) NOT NULL,
|
|
7
|
+
UNIQUE KEY uq_users_email (email)
|
|
8
|
+
);
|
|
9
|
+
|
|
10
|
+
CREATE TABLE magicLinks (
|
|
11
|
+
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
|
12
|
+
userId INT UNSIGNED NOT NULL,
|
|
13
|
+
selector VARCHAR(255) NOT NULL,
|
|
14
|
+
verifierHash VARCHAR(255) NOT NULL,
|
|
15
|
+
usedDate DATETIME(3),
|
|
16
|
+
expirationDate DATETIME(3) NOT NULL,
|
|
17
|
+
createdDate DATETIME(3) NOT NULL,
|
|
18
|
+
UNIQUE KEY uq_magicLinks_selector (selector),
|
|
19
|
+
CONSTRAINT fk_magicLinks_userId FOREIGN KEY (userId) REFERENCES users (id)
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
CREATE TABLE areas (
|
|
23
|
+
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
|
24
|
+
userId INT UNSIGNED NOT NULL,
|
|
25
|
+
title VARCHAR(255) NOT NULL,
|
|
26
|
+
position VARCHAR(255) NOT NULL,
|
|
27
|
+
deletedDate DATETIME(3),
|
|
28
|
+
createdDate DATETIME(3) NOT NULL,
|
|
29
|
+
lastModifiedDate DATETIME(3) NOT NULL,
|
|
30
|
+
CONSTRAINT fk_areas_userId FOREIGN KEY (userId) REFERENCES users (id)
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
CREATE TABLE projects (
|
|
34
|
+
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
|
35
|
+
userId INT UNSIGNED NOT NULL,
|
|
36
|
+
areaId BIGINT UNSIGNED,
|
|
37
|
+
title VARCHAR(255) NOT NULL,
|
|
38
|
+
notes TEXT,
|
|
39
|
+
scheduledDate DATE,
|
|
40
|
+
position VARCHAR(255) NOT NULL,
|
|
41
|
+
completedDate DATETIME(3),
|
|
42
|
+
deletedDate DATETIME(3),
|
|
43
|
+
createdDate DATETIME(3) NOT NULL,
|
|
44
|
+
lastModifiedDate DATETIME(3) NOT NULL,
|
|
45
|
+
CONSTRAINT fk_projects_userId FOREIGN KEY (userId) REFERENCES users (id),
|
|
46
|
+
CONSTRAINT fk_projects_areaId FOREIGN KEY (areaId) REFERENCES areas (id)
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
CREATE TABLE tasks (
|
|
50
|
+
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
|
51
|
+
userId INT UNSIGNED NOT NULL,
|
|
52
|
+
projectId BIGINT UNSIGNED,
|
|
53
|
+
areaId BIGINT UNSIGNED,
|
|
54
|
+
title VARCHAR(255) NOT NULL,
|
|
55
|
+
notes TEXT,
|
|
56
|
+
scheduledDate DATE,
|
|
57
|
+
listPosition VARCHAR(255) NOT NULL,
|
|
58
|
+
scheduledPosition VARCHAR(255),
|
|
59
|
+
completedDate DATETIME(3),
|
|
60
|
+
deletedDate DATETIME(3),
|
|
61
|
+
createdDate DATETIME(3) NOT NULL,
|
|
62
|
+
lastModifiedDate DATETIME(3) NOT NULL,
|
|
63
|
+
KEY idx_tasks_userId_scheduledDate (userId, scheduledDate),
|
|
64
|
+
KEY idx_tasks_userId_completedDate (userId, completedDate),
|
|
65
|
+
CONSTRAINT fk_tasks_userId FOREIGN KEY (userId) REFERENCES users (id),
|
|
66
|
+
CONSTRAINT fk_tasks_projectId FOREIGN KEY (projectId) REFERENCES projects (id),
|
|
67
|
+
CONSTRAINT fk_tasks_areaId FOREIGN KEY (areaId) REFERENCES areas (id)
|
|
68
|
+
);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
CREATE TABLE queueMessages (
|
|
2
|
+
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
3
|
+
attempt INT UNSIGNED NOT NULL DEFAULT 0,
|
|
4
|
+
queue VARCHAR(255) NOT NULL,
|
|
5
|
+
status ENUM('waiting', 'processing', 'succeeded', 'failed', 'failedPermanently') NOT NULL DEFAULT 'waiting',
|
|
6
|
+
scheduledDate DATETIME NOT NULL,
|
|
7
|
+
enqueuedDate DATETIME NOT NULL DEFAULT NOW(),
|
|
8
|
+
startedDate DATETIME,
|
|
9
|
+
completedDate DATETIME,
|
|
10
|
+
body JSON,
|
|
11
|
+
result TEXT,
|
|
12
|
+
lockId BIGINT UNSIGNED DEFAULT NULL,
|
|
13
|
+
PRIMARY KEY (id, attempt),
|
|
14
|
+
INDEX locking_pop (lockId, status, scheduledDate),
|
|
15
|
+
INDEX queue (queue)
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
CREATE TABLE recurringJobs (
|
|
19
|
+
name VARCHAR(255) NOT NULL PRIMARY KEY,
|
|
20
|
+
lastRunDate DATETIME DEFAULT NULL
|
|
21
|
+
);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@setlist/infrastructure",
|
|
3
|
+
"private": true,
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"cdk-synth": "cdk synth --app 'node ./cdk/index.ts'",
|
|
7
|
+
"cdk-diff": "cdk diff --app 'node ./cdk/index.ts'",
|
|
8
|
+
"cdk-deploy": "cdk deploy --all --app 'node ./cdk/index.ts'",
|
|
9
|
+
"cdk-destroy": "cdk destroy --app 'node ./cdk/index.ts'",
|
|
10
|
+
"aws-whoami": "aws sts get-caller-identity"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@maestro-js/aws-cdk-recipes": "^1.0.0-alpha.21",
|
|
14
|
+
"@maestro-js/db-migrate": "^1.0.0-alpha.21",
|
|
15
|
+
"aws-cdk": "^2.1106.1",
|
|
16
|
+
"aws-cdk-lib": "^2.178.0",
|
|
17
|
+
"constructs": "^10.4.2",
|
|
18
|
+
"esbuild": "^0.25.0"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"type": "module",
|
|
3
|
+
"private": true,
|
|
4
|
+
"scripts": {
|
|
5
|
+
"fks-cascade": "maestro config:run --config services -- node ./scripts/foreign-key-delete-behavior.ts cascade",
|
|
6
|
+
"fks-restrict": "maestro config:run --config services -- node ./scripts/foreign-key-delete-behavior.ts restrict"
|
|
7
|
+
},
|
|
8
|
+
"dependencies": {
|
|
9
|
+
"@maestro-js/config": "^1.0.0-alpha.21",
|
|
10
|
+
"@setlist/services": "workspace:*"
|
|
11
|
+
},
|
|
12
|
+
"devDependencies": {
|
|
13
|
+
"@maestro-js/cli": "^1.0.0-alpha.21",
|
|
14
|
+
"@maestro-js/db-migrate": "^1.0.0-alpha.21",
|
|
15
|
+
"@maestro-js/db": "^1.0.0-alpha.21",
|
|
16
|
+
"@types/node": "^22.19.11",
|
|
17
|
+
"tsx": "^4.21.0"
|
|
18
|
+
}
|
|
19
|
+
}
|