From b3efb2514bdd160f1b41d55f01e73461d4626968 Mon Sep 17 00:00:00 2001 From: =AhmedAshraf <=ahmedashrafelgendy25@gmail.com> Date: Sun, 22 Mar 2026 17:57:16 +0200 Subject: [PATCH 1/9] i fixed the conflicts feat: add memo color customization --- .dockerignore | 24 +- .github/FUNDING.yml | 2 +- .github/ISSUE_TEMPLATE/bug_report.yml | 198 +- .github/ISSUE_TEMPLATE/config.yml | 16 +- .github/ISSUE_TEMPLATE/feature_request.yml | 156 +- .github/workflows/backend-tests.yml | 182 +- .github/workflows/build-canary-image.yml | 332 +- .github/workflows/demo-deploy.yml | 34 +- .github/workflows/frontend-tests.yml | 144 +- .github/workflows/proto-linter.yml | 80 +- .github/workflows/release.yml | 704 +- .github/workflows/stale.yml | 48 +- .gitignore | 58 +- .golangci.yaml | 202 +- AGENTS.md | 204 +- CLAUDE.md | 10 +- CODEOWNERS | 4 +- LICENSE | 42 +- README.md | 240 +- SECURITY.md | 92 +- cmd/memos/main.go | 382 +- go.mod | 282 +- go.sum | 710 +- internal/base/resource_name.go | 14 +- internal/base/resource_name_test.go | 70 +- internal/profile/profile.go | 214 +- internal/util/util.go | 146 +- internal/util/util_test.go | 62 +- internal/version/version.go | 108 +- internal/version/version_test.go | 212 +- memos_prod.db | Bin 0 -> 4096 bytes memos_prod.db-shm | Bin 0 -> 32768 bytes memos_prod.db-wal | Bin 0 -> 453232 bytes node_modules/.modules.yaml | 36 + node_modules/.pnpm-workspace-state-v1.json | 26 + node_modules/.pnpm/lock.yaml | 49 + node_modules/.pnpm/node_modules/react | 1 + node_modules/.pnpm/node_modules/react-dom | 1 + node_modules/.pnpm/node_modules/scheduler | 1 + .../node_modules/react | 1 + .../react-colorful/ACKNOWLEDGMENTS | 5 + .../node_modules/react-colorful/CHANGELOG.md | 257 + .../node_modules/react-colorful/LICENSE | 21 + .../node_modules/react-colorful/README.md | 343 + .../node_modules/react-colorful/package.json | 200 + .../node_modules/react-dom | 1 + .../node_modules/react | 1 + .../node_modules/react-dom/LICENSE | 21 + .../node_modules/react-dom/README.md | 60 + .../cjs/react-dom-client.development.js | 28121 +++++++++++++++ .../cjs/react-dom-client.production.js | 16049 +++++++++ .../cjs/react-dom-profiling.development.js | 28503 ++++++++++++++++ .../cjs/react-dom-profiling.profiling.js | 18068 ++++++++++ ...t-dom-server-legacy.browser.development.js | 9877 ++++++ ...ct-dom-server-legacy.browser.production.js | 6603 ++++ ...eact-dom-server-legacy.node.development.js | 9877 ++++++ ...react-dom-server-legacy.node.production.js | 6692 ++++ .../react-dom-server.browser.development.js | 10601 ++++++ .../react-dom-server.browser.production.js | 7410 ++++ .../cjs/react-dom-server.bun.development.js | 9605 ++++++ .../cjs/react-dom-server.bun.production.js | 6745 ++++ .../cjs/react-dom-server.edge.development.js | 10620 ++++++ .../cjs/react-dom-server.edge.production.js | 7512 ++++ .../cjs/react-dom-server.node.development.js | 10802 ++++++ .../cjs/react-dom-server.node.production.js | 7707 +++++ .../cjs/react-dom-test-utils.development.js | 24 + .../cjs/react-dom-test-utils.production.js | 21 + .../react-dom/cjs/react-dom.development.js | 424 + .../react-dom/cjs/react-dom.production.js | 210 + .../cjs/react-dom.react-server.development.js | 340 + .../cjs/react-dom.react-server.production.js | 152 + .../node_modules/react-dom/client.js | 38 + .../react-dom/client.react-server.js | 5 + .../node_modules/react-dom/index.js | 38 + .../node_modules/react-dom/package.json | 117 + .../node_modules/react-dom/profiling.js | 38 + .../react-dom/profiling.react-server.js | 5 + .../react-dom/react-dom.react-server.js | 7 + .../node_modules/react-dom/server.browser.js | 16 + .../node_modules/react-dom/server.bun.js | 17 + .../node_modules/react-dom/server.edge.js | 17 + .../node_modules/react-dom/server.js | 3 + .../node_modules/react-dom/server.node.js | 18 + .../react-dom/server.react-server.js | 5 + .../node_modules/react-dom/static.browser.js | 12 + .../node_modules/react-dom/static.edge.js | 12 + .../node_modules/react-dom/static.js | 3 + .../node_modules/react-dom/static.node.js | 14 + .../react-dom/static.react-server.js | 5 + .../node_modules/react-dom/test-utils.js | 7 + .../node_modules/scheduler | 1 + .../react@19.2.4/node_modules/react/LICENSE | 21 + .../react@19.2.4/node_modules/react/README.md | 37 + .../cjs/react-compiler-runtime.development.js | 24 + .../cjs/react-compiler-runtime.production.js | 16 + .../cjs/react-compiler-runtime.profiling.js | 16 + .../cjs/react-jsx-dev-runtime.development.js | 338 + .../cjs/react-jsx-dev-runtime.production.js | 14 + .../cjs/react-jsx-dev-runtime.profiling.js | 14 + ...sx-dev-runtime.react-server.development.js | 370 + ...jsx-dev-runtime.react-server.production.js | 40 + .../cjs/react-jsx-runtime.development.js | 352 + .../react/cjs/react-jsx-runtime.production.js | 34 + .../react/cjs/react-jsx-runtime.profiling.js | 34 + ...ct-jsx-runtime.react-server.development.js | 370 + ...act-jsx-runtime.react-server.production.js | 40 + .../react/cjs/react.development.js | 1284 + .../react/cjs/react.production.js | 542 + .../cjs/react.react-server.development.js | 848 + .../cjs/react.react-server.production.js | 423 + .../node_modules/react/compiler-runtime.js | 14 + .../react@19.2.4/node_modules/react/index.js | 7 + .../node_modules/react/jsx-dev-runtime.js | 7 + .../react/jsx-dev-runtime.react-server.js | 7 + .../node_modules/react/jsx-runtime.js | 7 + .../react/jsx-runtime.react-server.js | 7 + .../node_modules/react/package.json | 51 + .../node_modules/react/react.react-server.js | 7 + .../node_modules/scheduler/LICENSE | 21 + .../node_modules/scheduler/README.md | 9 + .../scheduler-unstable_mock.development.js | 414 + .../cjs/scheduler-unstable_mock.production.js | 406 + ...cheduler-unstable_post_task.development.js | 150 + ...scheduler-unstable_post_task.production.js | 140 + .../scheduler/cjs/scheduler.development.js | 364 + .../cjs/scheduler.native.development.js | 350 + .../cjs/scheduler.native.production.js | 330 + .../scheduler/cjs/scheduler.production.js | 340 + .../node_modules/scheduler/index.js | 7 + .../node_modules/scheduler/index.native.js | 7 + .../node_modules/scheduler/package.json | 27 + .../node_modules/scheduler/unstable_mock.js | 7 + .../scheduler/unstable_post_task.js | 7 + node_modules/react-colorful | 1 + plugin/cron/README.md | 2 +- plugin/cron/chain.go | 192 +- plugin/cron/chain_test.go | 504 +- plugin/cron/constantdelay.go | 54 +- plugin/cron/constantdelay_test.go | 110 +- plugin/cron/cron.go | 698 +- plugin/cron/cron_test.go | 1410 +- plugin/cron/logger.go | 172 +- plugin/cron/option.go | 90 +- plugin/cron/option_test.go | 86 +- plugin/cron/parser.go | 892 +- plugin/cron/parser_test.go | 768 +- plugin/cron/spec.go | 376 +- plugin/cron/spec_test.go | 602 +- plugin/email/README.md | 1014 +- plugin/email/client.go | 286 +- plugin/email/client_test.go | 242 +- plugin/email/config.go | 94 +- plugin/email/config_test.go | 160 +- plugin/email/doc.go | 196 +- plugin/email/email.go | 86 +- plugin/email/email_test.go | 254 +- plugin/email/message.go | 182 +- plugin/email/message_test.go | 362 +- plugin/filter/MAINTENANCE.md | 100 +- plugin/filter/README.md | 126 +- plugin/filter/engine.go | 382 +- plugin/filter/helpers.go | 50 +- plugin/filter/ir.go | 318 +- plugin/filter/parser.go | 1172 +- plugin/filter/render.go | 1496 +- plugin/filter/schema.go | 638 +- plugin/httpgetter/html_meta.go | 332 +- plugin/httpgetter/html_meta_test.go | 64 +- plugin/httpgetter/http_getter.go | 2 +- plugin/httpgetter/image.go | 90 +- plugin/httpgetter/util.go | 30 +- plugin/idp/idp.go | 16 +- plugin/idp/oauth2/oauth2.go | 268 +- plugin/idp/oauth2/oauth2_test.go | 328 +- plugin/markdown/ast/tag.go | 56 +- plugin/markdown/extensions/tag.go | 48 +- plugin/markdown/markdown.go | 910 +- plugin/markdown/markdown_test.go | 1188 +- plugin/markdown/parser/tag.go | 300 +- plugin/markdown/parser/tag_test.go | 526 +- plugin/markdown/renderer/markdown_renderer.go | 532 +- .../renderer/markdown_renderer_test.go | 352 +- plugin/scheduler/README.md | 734 +- plugin/scheduler/doc.go | 70 +- plugin/scheduler/example_test.go | 330 +- plugin/scheduler/integration_test.go | 786 +- plugin/scheduler/job.go | 116 +- plugin/scheduler/job_test.go | 180 +- plugin/scheduler/middleware.go | 240 +- plugin/scheduler/middleware_test.go | 292 +- plugin/scheduler/parser.go | 458 +- plugin/scheduler/parser_test.go | 254 +- plugin/scheduler/scheduler.go | 404 +- plugin/scheduler/scheduler_test.go | 330 +- plugin/storage/s3/s3.go | 226 +- plugin/webhook/validate.go | 166 +- plugin/webhook/webhook.go | 240 +- plugin/webhook/webhook_test.go | 2 +- pnpm-lock.yaml | 49 + proto/README.md | 34 +- proto/api/v1/README.md | 6 +- proto/api/v1/attachment_service.proto | 300 +- proto/api/v1/auth_service.proto | 230 +- proto/api/v1/common.proto | 46 +- proto/api/v1/idp_service.proto | 294 +- proto/api/v1/instance_service.proto | 2 - proto/api/v1/memo_service.proto | 1194 +- proto/api/v1/shortcut_service.proto | 248 +- proto/api/v1/user_service.proto | 1368 +- proto/buf.gen.yaml | 60 +- proto/buf.lock | 12 +- proto/buf.yaml | 38 +- .../attachment_service.connect.go | 472 +- .../v1/apiv1connect/auth_service.connect.go | 434 +- .../v1/apiv1connect/idp_service.connect.go | 474 +- .../apiv1connect/instance_service.connect.go | 346 +- .../v1/apiv1connect/memo_service.connect.go | 1272 +- .../apiv1connect/shortcut_service.connect.go | 472 +- .../v1/apiv1connect/user_service.connect.go | 1412 +- proto/gen/api/v1/attachment_service.pb.go | 1224 +- proto/gen/api/v1/attachment_service.pb.gw.go | 1042 +- .../gen/api/v1/attachment_service_grpc.pb.go | 568 +- proto/gen/api/v1/auth_service.pb.go | 1256 +- proto/gen/api/v1/auth_service.pb.gw.go | 686 +- proto/gen/api/v1/auth_service_grpc.pb.go | 516 +- proto/gen/api/v1/common.pb.go | 488 +- proto/gen/api/v1/idp_service.pb.go | 1610 +- proto/gen/api/v1/idp_service.pb.gw.go | 1014 +- proto/gen/api/v1/idp_service_grpc.pb.go | 570 +- proto/gen/api/v1/instance_service.pb.go | 26 +- proto/gen/api/v1/instance_service.pb.gw.go | 698 +- proto/gen/api/v1/instance_service_grpc.pb.go | 406 +- proto/gen/api/v1/memo_service.pb.go | 4954 +-- proto/gen/api/v1/memo_service.pb.gw.go | 3298 +- proto/gen/api/v1/memo_service_grpc.pb.go | 1612 +- proto/gen/api/v1/shortcut_service.pb.go | 992 +- proto/gen/api/v1/shortcut_service.pb.gw.go | 1086 +- proto/gen/api/v1/shortcut_service_grpc.pb.go | 568 +- proto/gen/api/v1/user_service.pb.go | 5984 ++-- proto/gen/api/v1/user_service.pb.gw.go | 3762 +- proto/gen/api/v1/user_service_grpc.pb.go | 1788 +- proto/gen/openapi.yaml | 8 - proto/gen/store/attachment.pb.go | 574 +- proto/gen/store/idp.pb.go | 952 +- proto/gen/store/inbox.pb.go | 542 +- proto/gen/store/instance_setting.pb.go | 24 +- proto/gen/store/memo.pb.go | 586 +- proto/gen/store/user_setting.pb.go | 2010 +- proto/store/attachment.proto | 66 +- proto/store/idp.proto | 84 +- proto/store/inbox.proto | 48 +- proto/store/instance_setting.proto | 2 - proto/store/memo.proto | 58 +- proto/store/user_setting.proto | 226 +- scripts/Dockerfile | 112 +- scripts/build.sh | 64 +- scripts/compose.yaml | 16 +- scripts/entrypoint.sh | 90 +- scripts/entrypoint_test.sh | 262 +- scripts/install.sh | 592 +- server/auth/authenticator.go | 398 +- server/auth/context.go | 198 +- server/auth/extract.go | 66 +- server/auth/token.go | 498 +- server/auth/token_test.go | 612 +- server/router/api/v1/acl_config.go | 90 +- server/router/api/v1/acl_config_test.go | 172 +- server/router/api/v1/attachment_exif_test.go | 382 +- server/router/api/v1/attachment_service.go | 1308 +- server/router/api/v1/auth_service.go | 1232 +- .../api/v1/auth_service_client_info_test.go | 358 +- server/router/api/v1/common.go | 136 +- server/router/api/v1/connect_handler.go | 158 +- server/router/api/v1/connect_interceptors.go | 474 +- server/router/api/v1/connect_services.go | 1008 +- server/router/api/v1/header_carrier.go | 248 +- server/router/api/v1/health_service.go | 50 +- server/router/api/v1/idp_service.go | 506 +- server/router/api/v1/instance_service.go | 2 - .../router/api/v1/memo_attachment_service.go | 272 +- server/router/api/v1/memo_relation_service.go | 362 +- server/router/api/v1/memo_service.go | 1820 +- .../router/api/v1/memo_service_converter.go | 486 +- server/router/api/v1/memo_service_filter.go | 2 +- server/router/api/v1/memo_share_service.go | 444 +- server/router/api/v1/reaction_service.go | 330 +- server/router/api/v1/resource_name.go | 320 +- server/router/api/v1/shortcut_service.go | 692 +- server/router/api/v1/sse_handler.go | 186 +- server/router/api/v1/sse_hub.go | 198 +- server/router/api/v1/sse_hub_test.go | 140 +- .../api/v1/test/attachment_service_test.go | 118 +- server/router/api/v1/test/auth_test.go | 1310 +- server/router/api/v1/test/idp_service_test.go | 1104 +- .../api/v1/test/instance_admin_cache_test.go | 108 +- .../api/v1/test/instance_service_test.go | 676 +- .../v1/test/memo_attachment_service_test.go | 332 +- .../api/v1/test/memo_relation_service_test.go | 338 +- .../router/api/v1/test/memo_service_test.go | 738 +- .../api/v1/test/memo_share_service_test.go | 218 +- .../api/v1/test/reaction_service_test.go | 388 +- .../api/v1/test/shortcut_service_test.go | 1638 +- server/router/api/v1/test/sse_handler_test.go | 156 +- server/router/api/v1/test/test_helper.go | 178 +- .../api/v1/test/user_notification_test.go | 286 +- .../v1/test/user_service_registration_test.go | 346 +- .../api/v1/test/user_service_stats_test.go | 210 +- server/router/api/v1/user_service.go | 2978 +- server/router/api/v1/user_service_stats.go | 472 +- server/router/api/v1/v1.go | 300 +- server/router/fileserver/README.md | 614 +- server/router/fileserver/fileserver.go | 1204 +- server/router/fileserver/fileserver_test.go | 336 +- server/router/frontend/dist/index.html | 39 +- server/router/frontend/frontend.go | 136 +- server/router/mcp/README.md | 252 +- server/router/mcp/mcp.go | 130 +- server/router/mcp/prompts.go | 384 +- server/router/mcp/resources_memo.go | 170 +- server/router/mcp/tools_attachment.go | 544 +- server/router/mcp/tools_memo.go | 1198 +- server/router/mcp/tools_reaction.go | 342 +- server/router/mcp/tools_relation.go | 422 +- server/router/mcp/tools_tag.go | 156 +- server/router/rss/rss.go | 858 +- server/runner/memopayload/runner.go | 176 +- server/runner/s3presign/runner.go | 268 +- server/server.go | 376 +- store/attachment.go | 344 +- store/cache.go | 18 +- store/cache/cache.go | 654 +- store/cache/cache_test.go | 418 +- store/common.go | 48 +- store/db/db.go | 64 +- store/db/mysql/attachment.go | 482 +- store/db/mysql/common.go | 20 +- store/db/mysql/idp.go | 260 +- store/db/mysql/inbox.go | 300 +- store/db/mysql/instance_setting.go | 130 +- store/db/mysql/memo.go | 538 +- store/db/mysql/memo_relation.go | 244 +- store/db/mysql/memo_share.go | 236 +- store/db/mysql/mysql.go | 136 +- store/db/mysql/reaction.go | 226 +- store/db/mysql/user.go | 358 +- store/db/mysql/user_setting.go | 186 +- store/db/postgres/attachment.go | 442 +- store/db/postgres/common.go | 52 +- store/db/postgres/idp.go | 246 +- store/db/postgres/inbox.go | 302 +- store/db/postgres/instance_setting.go | 144 +- store/db/postgres/memo.go | 508 +- store/db/postgres/memo_relation.go | 296 +- store/db/postgres/memo_share.go | 272 +- store/db/postgres/postgres.go | 114 +- store/db/postgres/reaction.go | 202 +- store/db/postgres/user.go | 360 +- store/db/postgres/user_setting.go | 242 +- store/db/postgres/user_setting_test.go | 580 +- store/db/sqlite/attachment.go | 442 +- store/db/sqlite/common.go | 18 +- store/db/sqlite/functions.go | 88 +- store/db/sqlite/idp.go | 246 +- store/db/sqlite/inbox.go | 282 +- store/db/sqlite/instance_setting.go | 144 +- store/db/sqlite/memo.go | 494 +- store/db/sqlite/memo_relation.go | 270 +- store/db/sqlite/memo_share.go | 276 +- store/db/sqlite/reaction.go | 272 +- store/db/sqlite/sqlite.go | 150 +- store/db/sqlite/user.go | 378 +- store/db/sqlite/user_setting.go | 218 +- store/driver.go | 144 +- store/idp.go | 372 +- store/inbox.go | 150 +- store/instance_setting.go | 598 +- store/memo.go | 318 +- store/memo_relation.go | 94 +- store/memo_share.go | 92 +- store/migration/mysql/0.17/00__inbox.sql | 18 +- .../mysql/0.17/01__delete_activity.sql | 2 +- .../migration/mysql/0.18/00__extend_text.sql | 6 +- store/migration/mysql/0.18/01__webhook.sql | 20 +- .../migration/mysql/0.18/02__user_setting.sql | 8 +- .../mysql/0.19/00__add_resource_name.sql | 30 +- store/migration/mysql/0.20/00__reaction.sql | 18 +- .../mysql/0.21/00__user_description.sql | 2 +- store/migration/mysql/0.21/01__rename_uid.sql | 6 +- .../mysql/0.22/00__resource_storage_type.sql | 22 +- store/migration/mysql/0.22/01__memo_tags.sql | 6 +- .../migration/mysql/0.22/02__memo_payload.sql | 6 +- store/migration/mysql/0.22/03__drop_tag.sql | 2 +- store/migration/mysql/0.23/00__reactions.sql | 24 +- store/migration/mysql/0.24/00__memo.sql | 2 +- .../migration/mysql/0.24/01__memo_pinned.sql | 16 +- .../mysql/0.24/02__s3_reference_length.sql | 4 +- .../mysql/0.25/00__remove_webhook.sql | 2 +- .../00__rename_resource_to_attachment.sql | 2 +- .../mysql/0.26/01__drop_memo_organizer.sql | 2 +- .../mysql/0.26/02__migrate_host_to_admin.sql | 2 +- .../0.27/00__migrate_storage_setting.sql | 12 +- .../migration/mysql/0.27/01__add_idp_uid.sql | 16 +- .../02__migrate_inbox_message_payload.sql | 28 +- .../mysql/0.27/03__drop_activity.sql | 2 +- store/migration/mysql/0.27/04__memo_share.sql | 28 +- store/migration/mysql/LATEST.sql | 222 +- .../postgres/0.19/00__add_resource_name.sql | 30 +- .../migration/postgres/0.20/00__reaction.sql | 18 +- .../postgres/0.21/00__user_description.sql | 2 +- .../postgres/0.21/01__rename_uid.sql | 6 +- .../0.22/00__resource_storage_type.sql | 22 +- .../migration/postgres/0.22/01__memo_tags.sql | 2 +- .../postgres/0.22/02__memo_payload.sql | 2 +- .../migration/postgres/0.22/03__drop_tag.sql | 2 +- .../migration/postgres/0.23/00__reactions.sql | 24 +- store/migration/postgres/0.24/00__memo.sql | 2 +- .../postgres/0.24/01__memo_pinned.sql | 14 +- .../postgres/0.25/00__remove_webhook.sql | 2 +- .../00__rename_resource_to_attachment.sql | 2 +- .../postgres/0.26/01__drop_memo_organizer.sql | 2 +- .../0.26/02__migrate_host_to_admin.sql | 2 +- .../0.27/00__migrate_storage_setting.sql | 10 +- .../postgres/0.27/01__add_idp_uid.sql | 16 +- .../02__migrate_inbox_message_payload.sql | 26 +- .../postgres/0.27/03__drop_activity.sql | 2 +- .../postgres/0.27/04__memo_share.sql | 28 +- store/migration/postgres/LATEST.sql | 222 +- store/migration/sqlite/0.10/00__activity.sql | 16 +- .../migration/sqlite/0.11/00__user_avatar.sql | 6 +- store/migration/sqlite/0.11/01__idp.sql | 14 +- store/migration/sqlite/0.11/02__storage.sql | 12 +- .../sqlite/0.12/00__user_setting.sql | 10 +- .../sqlite/0.12/01__system_setting.sql | 136 +- .../0.12/03__resource_internal_path.sql | 6 +- .../sqlite/0.12/04__resource_public_id.sql | 34 +- .../sqlite/0.13/00__memo_relation.sql | 12 +- .../0.13/01__remove_memo_organizer_id.sql | 42 +- .../0.14/00__drop_resource_public_id.sql | 50 +- .../sqlite/0.14/01__create_indexes.sql | 10 +- .../sqlite/0.15/00__drop_user_open_id.sql | 50 +- .../0.16/00__add_memo_id_to_resource.sql | 26 +- .../sqlite/0.16/01__drop_shortcut_table.sql | 2 +- store/migration/sqlite/0.17/00__inbox.sql | 18 +- .../sqlite/0.17/01__delete_activities.sql | 2 +- store/migration/sqlite/0.18/00__webhook.sql | 24 +- .../sqlite/0.18/01__user_setting.sql | 8 +- .../sqlite/0.19/00__add_resource_name.sql | 22 +- store/migration/sqlite/0.2/00__user_role.sql | 118 +- .../sqlite/0.2/01__memo_visibility.sql | 6 +- store/migration/sqlite/0.20/00__reaction.sql | 18 +- .../sqlite/0.21/00__user_description.sql | 2 +- .../migration/sqlite/0.21/01__rename_uid.sql | 6 +- .../sqlite/0.22/00__resource_storage_type.sql | 34 +- store/migration/sqlite/0.22/01__memo_tags.sql | 6 +- .../sqlite/0.22/02__memo_payload.sql | 2 +- store/migration/sqlite/0.23/00__reactions.sql | 24 +- store/migration/sqlite/0.24/00__memo.sql | 12 +- .../migration/sqlite/0.24/01__memo_pinned.sql | 22 +- .../sqlite/0.25/00__remove_webhook.sql | 2 +- .../00__rename_resource_to_attachment.sql | 10 +- .../sqlite/0.26/01__drop_memo_organizer.sql | 2 +- .../sqlite/0.26/02__drop_indexes.sql | 8 +- .../sqlite/0.26/03__alter_user_role.sql | 48 +- .../sqlite/0.26/04__migrate_host_to_admin.sql | 2 +- .../0.27/00__migrate_storage_setting.sql | 10 +- .../migration/sqlite/0.27/01__add_idp_uid.sql | 16 +- .../02__migrate_inbox_message_payload.sql | 50 +- .../sqlite/0.27/03__drop_activity.sql | 2 +- .../migration/sqlite/0.27/04__memo_share.sql | 28 +- .../0.3/00__memo_visibility_protected.sql | 84 +- .../migration/sqlite/0.4/00__user_setting.sql | 16 +- .../0.5/00__regenerate_foreign_keys.sql | 432 +- .../sqlite/0.5/01__memo_resource.sql | 18 +- .../sqlite/0.5/02__system_setting.sql | 12 +- .../sqlite/0.5/03__resource_extermal_link.sql | 6 +- .../sqlite/0.6/00__recreate_triggers.sql | 116 +- store/migration/sqlite/0.7/00__remove_fk.sql | 380 +- .../sqlite/0.7/01__remove_triggers.sql | 12 +- .../sqlite/0.8/00__migration_history.sql | 8 +- .../sqlite/0.8/01__user_username.sql | 98 +- store/migration/sqlite/0.9/00__tag.sql | 10 +- store/migration/sqlite/LATEST.sql | 224 +- store/migrator.go | 810 +- store/reaction.go | 82 +- store/seed/DEMO_DATA_GUIDE.md | 410 +- store/seed/sqlite/01__dump.sql | 106 +- store/store.go | 114 +- store/test/README.md | 26 +- store/test/attachment_filter_test.go | 750 +- store/test/attachment_test.go | 494 +- store/test/containers.go | 636 +- store/test/filter_helpers_test.go | 580 +- store/test/idp_test.go | 936 +- store/test/inbox_test.go | 1226 +- store/test/instance_setting_test.go | 772 +- store/test/main_test.go | 100 +- store/test/memo_filter_test.go | 1878 +- store/test/memo_relation_test.go | 1892 +- store/test/memo_test.go | 956 +- store/test/migrator_test.go | 400 +- store/test/reaction_test.go | 378 +- store/test/store.go | 222 +- store/test/user_setting_test.go | 1986 +- store/test/user_test.go | 572 +- store/user.go | 318 +- store/user_setting.go | 972 +- web/.gitignore | 14 +- web/biome.json | 402 +- web/components.json | 40 +- web/docs/auth-architecture.md | 110 +- web/index.html | 48 +- web/public/site.webmanifest | 28 +- web/src/App.tsx | 132 +- web/src/auth-state.ts | 256 +- .../ActivityCalendar/CalendarCell.tsx | 164 +- .../ActivityCalendar/MonthCalendar.tsx | 152 +- .../ActivityCalendar/YearCalendar.tsx | 232 +- .../components/ActivityCalendar/constants.ts | 70 +- web/src/components/ActivityCalendar/hooks.ts | 46 +- web/src/components/ActivityCalendar/index.ts | 8 +- web/src/components/ActivityCalendar/types.ts | 78 +- .../ActivityCalendar/useCalendar.ts | 188 +- web/src/components/ActivityCalendar/utils.ts | 144 +- web/src/components/AttachmentIcon.tsx | 216 +- web/src/components/AuthFooter.tsx | 70 +- .../components/ChangeMemberPasswordDialog.tsx | 228 +- web/src/components/ConfirmDialog/README.md | 262 +- web/src/components/ConfirmDialog/index.tsx | 118 +- .../components/CreateAccessTokenDialog.tsx | 366 +- .../CreateIdentityProviderDialog.tsx | 1064 +- web/src/components/CreateShortcutDialog.tsx | 316 +- web/src/components/CreateUserDialog.tsx | 300 +- web/src/components/CreateWebhookDialog.tsx | 332 +- web/src/components/DateTimeInput.tsx | 86 +- web/src/components/Empty.tsx | 22 +- web/src/components/ErrorBoundary.tsx | 206 +- .../components/Inbox/MemoCommentMessage.tsx | 452 +- web/src/components/LearnMore.tsx | 62 +- web/src/components/LocaleSelect.tsx | 82 +- .../MemoActionMenu/MemoActionMenu.tsx | 270 +- web/src/components/MemoActionMenu/hooks.ts | 252 +- web/src/components/MemoActionMenu/index.ts | 6 +- web/src/components/MemoActionMenu/types.ts | 40 +- web/src/components/MemoContent/CodeBlock.tsx | 312 +- .../MemoContent/ConditionalComponent.tsx | 72 +- .../components/MemoContent/MermaidBlock.tsx | 176 +- web/src/components/MemoContent/Table.tsx | 152 +- web/src/components/MemoContent/Tag.tsx | 4 +- .../components/MemoContent/TaskListItem.tsx | 140 +- web/src/components/MemoContent/constants.ts | 160 +- web/src/components/MemoContent/hooks.ts | 56 +- web/src/components/MemoContent/index.tsx | 67 +- .../MemoContent/markdown/Blockquote.tsx | 34 +- .../MemoContent/markdown/Heading.tsx | 5 +- .../MemoContent/markdown/HorizontalRule.tsx | 22 +- .../components/MemoContent/markdown/Image.tsx | 38 +- .../MemoContent/markdown/InlineCode.tsx | 34 +- .../components/MemoContent/markdown/Link.tsx | 54 +- .../components/MemoContent/markdown/List.tsx | 142 +- .../MemoContent/markdown/Paragraph.tsx | 34 +- .../components/MemoContent/markdown/README.md | 194 +- .../components/MemoContent/markdown/index.ts | 16 +- .../components/MemoContent/markdown/types.ts | 18 +- web/src/components/MemoContent/types.ts | 24 +- web/src/components/MemoContent/utils.ts | 50 +- .../MemoDetailSidebar/MemoDetailSidebar.tsx | 140 +- .../MemoDetailSidebarDrawer.tsx | 5 +- .../MemoDetailSidebar/MemoSharePanel.tsx | 316 +- web/src/components/MemoDetailSidebar/index.ts | 8 +- web/src/components/MemoDisplaySettingMenu.tsx | 98 +- .../MemoEditor/Editor/SlashCommands.tsx | 90 +- .../MemoEditor/Editor/SuggestionsPopup.tsx | 98 +- .../MemoEditor/Editor/TagSuggestions.tsx | 100 +- .../components/MemoEditor/Editor/commands.ts | 56 +- .../components/MemoEditor/Editor/index.tsx | 436 +- .../components/MemoEditor/Editor/shortcuts.ts | 140 +- .../MemoEditor/Editor/useListCompletion.ts | 164 +- .../MemoEditor/Editor/useSuggestions.ts | 316 +- web/src/components/MemoEditor/README.md | 146 +- .../MemoEditor/Toolbar/InsertMenu.tsx | 432 +- .../MemoEditor/Toolbar/VisibilitySelector.tsx | 84 +- .../components/MemoEditor/Toolbar/index.ts | 6 +- .../MemoEditor/components/EditorContent.tsx | 150 +- .../MemoEditor/components/EditorMetadata.tsx | 58 +- .../MemoEditor/components/EditorToolbar.tsx | 112 +- .../components/FocusModeOverlay.tsx | 40 +- .../components/TimestampPopover.tsx | 178 +- .../components/MemoEditor/components/index.ts | 14 +- web/src/components/MemoEditor/constants.ts | 28 +- web/src/components/MemoEditor/hooks/index.ts | 20 +- .../MemoEditor/hooks/useAutoSave.ts | 18 +- .../MemoEditor/hooks/useBlobUrls.ts | 56 +- .../MemoEditor/hooks/useDragAndDrop.ts | 42 +- .../MemoEditor/hooks/useFileUpload.ts | 68 +- .../MemoEditor/hooks/useFocusMode.ts | 20 +- .../MemoEditor/hooks/useKeyboard.ts | 64 +- .../MemoEditor/hooks/useLinkMemo.ts | 170 +- .../MemoEditor/hooks/useLocation.ts | 174 +- .../MemoEditor/hooks/useMemoInit.ts | 80 +- web/src/components/MemoEditor/index.tsx | 320 +- .../MemoEditor/services/cacheService.ts | 50 +- .../MemoEditor/services/errorService.ts | 28 +- .../components/MemoEditor/services/index.ts | 10 +- .../MemoEditor/services/memoService.ts | 294 +- .../MemoEditor/services/uploadService.ts | 56 +- .../MemoEditor/services/validationService.ts | 64 +- .../components/MemoEditor/state/actions.ts | 156 +- .../components/MemoEditor/state/context.tsx | 80 +- web/src/components/MemoEditor/state/index.ts | 8 +- .../components/MemoEditor/state/reducer.ts | 260 +- web/src/components/MemoEditor/state/types.ts | 142 +- .../components/MemoEditor/types/attachment.ts | 162 +- .../components/MemoEditor/types/components.ts | 154 +- web/src/components/MemoEditor/types/index.ts | 32 +- .../MemoEditor/types/insert-menu.ts | 16 +- .../components/MemoExplorer/MemoExplorer.tsx | 174 +- .../MemoExplorer/MemoExplorerDrawer.tsx | 84 +- .../MemoExplorer/ShortcutsSection.tsx | 270 +- .../components/MemoExplorer/TagsSection.tsx | 200 +- web/src/components/MemoExplorer/index.ts | 10 +- web/src/components/MemoFilters.tsx | 212 +- .../Attachment/AttachmentCard.tsx | 76 +- .../Attachment/AttachmentListEditor.tsx | 334 +- .../Attachment/AttachmentListView.tsx | 346 +- .../MemoMetadata/Attachment/index.ts | 6 +- .../MemoMetadata/Location/LocationDialog.tsx | 226 +- .../Location/LocationDisplayEditor.tsx | 96 +- .../Location/LocationDisplayView.tsx | 104 +- .../components/MemoMetadata/Location/index.ts | 6 +- .../MemoMetadata/Relation/LinkMemoDialog.tsx | 184 +- .../MemoMetadata/Relation/RelationCard.tsx | 32 +- .../Relation/RelationListEditor.tsx | 188 +- .../Relation/RelationListView.tsx | 168 +- .../components/MemoMetadata/Relation/index.ts | 8 +- .../components/MemoMetadata/SectionHeader.tsx | 96 +- web/src/components/MemoMetadata/index.ts | 12 +- .../components/MemoPreview/MemoPreview.tsx | 87 +- web/src/components/MemoPreview/index.ts | 2 +- .../MemoReactionListView.tsx | 68 +- .../MemoReactionListView/ReactionSelector.tsx | 126 +- .../MemoReactionListView/ReactionView.tsx | 116 +- .../components/MemoReactionListView/hooks.ts | 164 +- .../components/MemoReactionListView/index.ts | 6 +- .../MemoRelationForceGraph.tsx | 62 + .../MemoRelationForceGraph/index.ts | 5 + .../MemoRelationForceGraph/types.ts | 10 + .../MemoRelationForceGraph/utils.ts | 36 + web/src/components/MemoView/MemoView.tsx | 311 +- .../components/MemoView/MemoViewContext.tsx | 8 +- .../MemoView/components/MemoBody.tsx | 10 +- .../components/MemoCommentListView.tsx | 25 +- .../components/MemoCustomizeColor.tsx | 286 + .../MemoView/components/MemoHeader.tsx | 292 +- .../MemoView/components/MemoSnippetLink.tsx | 68 +- .../components/MemoView/components/index.ts | 6 +- web/src/components/MemoView/constants.ts | 8 +- web/src/components/MemoView/hooks/index.ts | 6 +- .../MemoView/hooks/useImagePreview.ts | 54 +- .../MemoView/hooks/useMemoActions.ts | 26 +- .../MemoView/hooks/useMemoHandlers.ts | 78 +- web/src/components/MemoView/index.ts | 4 +- web/src/components/MemoView/types.ts | 46 +- web/src/components/MemosLogo.tsx | 52 +- web/src/components/MobileHeader.tsx | 66 +- web/src/components/Navigation.tsx | 250 +- web/src/components/NavigationDrawer.tsx | 76 +- .../PagedMemoList/PagedMemoList.tsx | 437 +- web/src/components/PagedMemoList/index.ts | 6 +- web/src/components/PasswordSignInForm.tsx | 240 +- web/src/components/PreviewImageDialog.tsx | 202 +- web/src/components/RequiredBadge.tsx | 22 +- web/src/components/SearchBar.tsx | 102 +- .../Settings/AccessTokenSection.tsx | 290 +- .../components/Settings/InstanceSection.tsx | 360 +- web/src/components/Settings/MemberSection.tsx | 418 +- .../Settings/MemoRelatedSettings.tsx | 272 +- .../components/Settings/MyAccountSection.tsx | 128 +- .../Settings/PreferencesSection.tsx | 214 +- web/src/components/Settings/SSOSection.tsx | 298 +- .../components/Settings/SectionMenuItem.tsx | 50 +- web/src/components/Settings/SettingGroup.tsx | 60 +- web/src/components/Settings/SettingRow.tsx | 82 +- .../components/Settings/SettingSection.tsx | 62 +- web/src/components/Settings/SettingTable.tsx | 142 +- .../components/Settings/StorageSection.tsx | 472 +- web/src/components/Settings/TagsSection.tsx | 72 +- .../components/Settings/WebhookSection.tsx | 242 +- web/src/components/Skeleton.tsx | 102 +- .../StatisticsView/MonthNavigator.tsx | 180 +- .../StatisticsView/StatisticsView.tsx | 68 +- web/src/components/StatisticsView/index.ts | 2 +- web/src/components/TagTree.tsx | 320 +- web/src/components/ThemeSelect.tsx | 102 +- web/src/components/UpdateAccountDialog.tsx | 446 +- .../UpdateCustomizedProfileDialog.tsx | 308 +- web/src/components/UserAvatar.tsx | 46 +- .../components/UserMemoMap/UserMemoMap.tsx | 246 +- web/src/components/UserMemoMap/index.ts | 2 +- web/src/components/UserMenu.tsx | 356 +- web/src/components/VisibilityIcon.tsx | 56 +- web/src/components/kit/OverflowTip.tsx | 80 +- web/src/components/kit/SquareDiv.tsx | 90 +- web/src/components/map/LocationPicker.tsx | 486 +- web/src/components/map/index.ts | 6 +- web/src/components/map/map-utils.tsx | 72 +- web/src/components/map/useReverseGeocoding.ts | 78 +- web/src/components/ui/badge.tsx | 68 +- web/src/components/ui/button.tsx | 90 +- web/src/components/ui/checkbox.tsx | 56 +- web/src/components/ui/dialog.tsx | 244 +- web/src/components/ui/dropdown-menu.tsx | 546 +- web/src/components/ui/input.tsx | 36 +- web/src/components/ui/label.tsx | 36 +- web/src/components/ui/popover.tsx | 104 +- web/src/components/ui/radio-group.tsx | 54 +- web/src/components/ui/select.tsx | 296 +- web/src/components/ui/separator.tsx | 50 +- web/src/components/ui/sheet.tsx | 256 +- web/src/components/ui/switch.tsx | 50 +- web/src/components/ui/textarea.tsx | 34 +- web/src/components/ui/tooltip.tsx | 118 +- web/src/components/ui/visually-hidden.tsx | 38 +- web/src/connect.ts | 402 +- web/src/contexts/AuthContext.tsx | 366 +- web/src/contexts/InstanceContext.tsx | 322 +- web/src/contexts/MemoFilterContext.tsx | 320 +- web/src/contexts/ViewContext.tsx | 128 +- web/src/helpers/consts.ts | 10 +- web/src/helpers/resource-names.ts | 112 +- web/src/helpers/utils.ts | 78 +- web/src/hooks/index.ts | 22 +- web/src/hooks/useAsyncEffect.ts | 18 +- web/src/hooks/useAttachmentQueries.ts | 114 +- web/src/hooks/useCurrentUser.ts | 16 +- web/src/hooks/useDateFilterNavigation.ts | 38 +- web/src/hooks/useDialog.ts | 150 +- web/src/hooks/useFilteredMemoStats.ts | 174 +- web/src/hooks/useInstanceQueries.ts | 160 +- web/src/hooks/useLiveMemoRefresh.ts | 422 +- web/src/hooks/useLoading.ts | 70 +- web/src/hooks/useMediaQuery.ts | 68 +- web/src/hooks/useMemoFilters.ts | 200 +- web/src/hooks/useMemoQueries.ts | 317 +- web/src/hooks/useMemoShareQueries.ts | 9 - web/src/hooks/useMemoSorting.ts | 96 +- web/src/hooks/useNavigateTo.ts | 48 +- web/src/hooks/useTokenRefreshOnFocus.ts | 98 +- web/src/hooks/useUserLocale.ts | 70 +- web/src/hooks/useUserQueries.ts | 492 +- web/src/hooks/useUserTheme.ts | 74 +- web/src/i18n.ts | 172 +- web/src/index.css | 104 +- web/src/layouts/MainLayout.tsx | 188 +- web/src/layouts/RootLayout.tsx | 120 +- web/src/lib/calendar-utils.ts | 46 +- web/src/lib/color.ts | 42 +- web/src/lib/error.ts | 76 +- web/src/lib/query-client.ts | 58 +- web/src/lib/tag.ts | 128 +- web/src/lib/utils.ts | 12 +- web/src/locales/ar.json | 6 +- web/src/locales/ca.json | 6 +- web/src/locales/cs.json | 6 +- web/src/locales/de.json | 6 +- web/src/locales/en-GB.json | 38 +- web/src/locales/en.json | 8 +- web/src/locales/es.json | 6 +- web/src/locales/fa.json | 6 +- web/src/locales/fr.json | 6 +- web/src/locales/gl.json | 6 +- web/src/locales/hi.json | 6 +- web/src/locales/hr.json | 6 +- web/src/locales/hu.json | 6 +- web/src/locales/id.json | 6 +- web/src/locales/it.json | 6 +- web/src/locales/ja.json | 6 +- web/src/locales/ka-GE.json | 6 +- web/src/locales/ko.json | 6 +- web/src/locales/mr.json | 6 +- web/src/locales/nb.json | 6 +- web/src/locales/nl.json | 6 +- web/src/locales/pl.json | 6 +- web/src/locales/pt-BR.json | 6 +- web/src/locales/pt-PT.json | 6 +- web/src/locales/ru.json | 6 +- web/src/locales/sl.json | 6 +- web/src/locales/sv.json | 6 +- web/src/locales/th.json | 6 +- web/src/locales/tr.json | 6 +- web/src/locales/uk.json | 6 +- web/src/locales/vi.json | 6 +- web/src/locales/zh-Hans.json | 6 +- web/src/locales/zh-Hant.json | 6 +- web/src/main.tsx | 164 +- web/src/pages/AdminSignIn.tsx | 46 +- web/src/pages/Archived.tsx | 70 +- web/src/pages/Attachments.tsx | 584 +- web/src/pages/AuthCallback.tsx | 252 +- web/src/pages/Explore.tsx | 82 +- web/src/pages/Home.tsx | 74 +- web/src/pages/Inboxes.tsx | 244 +- web/src/pages/MemoDetail.tsx | 304 +- web/src/pages/NotFound.tsx | 30 +- web/src/pages/PermissionDenied.tsx | 30 +- web/src/pages/Setting.tsx | 324 +- web/src/pages/SharedMemo.tsx | 85 + web/src/pages/SignIn.tsx | 270 +- web/src/pages/SignUp.tsx | 324 +- web/src/pages/UserProfile.tsx | 312 +- web/src/router/index.tsx | 4 +- web/src/router/routes.ts | 26 +- web/src/themes/COLOR_GUIDE.md | 598 +- web/src/themes/default-dark.css | 86 +- web/src/themes/default.css | 166 +- web/src/themes/paper.css | 64 +- web/src/types/common.d.ts | 2 +- web/src/types/common.ts | 26 +- web/src/types/i18n.d.ts | 2 +- web/src/types/markdown.ts | 88 +- web/src/types/modules/setting.d.ts | 2 +- .../proto/api/v1/attachment_service_pb.ts | 644 +- web/src/types/proto/api/v1/auth_service_pb.ts | 600 +- web/src/types/proto/api/v1/common_pb.ts | 180 +- web/src/types/proto/api/v1/idp_service_pb.ts | 752 +- .../types/proto/api/v1/instance_service_pb.ts | 14 +- web/src/types/proto/api/v1/memo_service_pb.ts | 2646 +- .../types/proto/api/v1/shortcut_service_pb.ts | 500 +- web/src/types/proto/api/v1/user_service_pb.ts | 3124 +- .../types/proto/google/api/annotations_pb.ts | 78 +- web/src/types/proto/google/api/client_pb.ts | 1906 +- .../proto/google/api/field_behavior_pb.ts | 314 +- web/src/types/proto/google/api/http_pb.ts | 948 +- .../types/proto/google/api/launch_stage_pb.ts | 236 +- web/src/types/proto/google/api/resource_pb.ts | 708 +- web/src/types/proto/google/type/color_pb.ts | 408 +- web/src/types/statistics.ts | 26 +- web/src/types/view.d.ts | 10 +- web/src/utils/attachment.ts | 108 +- web/src/utils/auth-redirect.ts | 150 +- web/src/utils/format.ts | 150 +- web/src/utils/i18n.ts | 248 +- web/src/utils/markdown-list-detection.ts | 134 +- web/src/utils/memo.ts | 54 +- web/src/utils/oauth.ts | 296 +- .../remark-plugins/remark-disable-setext.ts | 28 +- .../remark-plugins/remark-preserve-type.ts | 44 +- web/src/utils/remark-plugins/remark-tag.ts | 224 +- web/src/utils/theme.ts | 498 +- web/src/utils/user.ts | 10 +- web/src/utils/uuid.ts | 10 +- web/tsconfig.json | 3 +- web/vite.config.mts | 110 +- 852 files changed, 303670 insertions(+), 98297 deletions(-) create mode 100644 memos_prod.db create mode 100644 memos_prod.db-shm create mode 100644 memos_prod.db-wal create mode 100644 node_modules/.modules.yaml create mode 100644 node_modules/.pnpm-workspace-state-v1.json create mode 100644 node_modules/.pnpm/lock.yaml create mode 120000 node_modules/.pnpm/node_modules/react create mode 120000 node_modules/.pnpm/node_modules/react-dom create mode 120000 node_modules/.pnpm/node_modules/scheduler create mode 120000 node_modules/.pnpm/react-colorful@5.6.1_react-_30faa463c7a46a636667ecc41211c837/node_modules/react create mode 100644 node_modules/.pnpm/react-colorful@5.6.1_react-_30faa463c7a46a636667ecc41211c837/node_modules/react-colorful/ACKNOWLEDGMENTS create mode 100644 node_modules/.pnpm/react-colorful@5.6.1_react-_30faa463c7a46a636667ecc41211c837/node_modules/react-colorful/CHANGELOG.md create mode 100644 node_modules/.pnpm/react-colorful@5.6.1_react-_30faa463c7a46a636667ecc41211c837/node_modules/react-colorful/LICENSE create mode 100644 node_modules/.pnpm/react-colorful@5.6.1_react-_30faa463c7a46a636667ecc41211c837/node_modules/react-colorful/README.md create mode 100644 node_modules/.pnpm/react-colorful@5.6.1_react-_30faa463c7a46a636667ecc41211c837/node_modules/react-colorful/package.json create mode 120000 node_modules/.pnpm/react-colorful@5.6.1_react-_30faa463c7a46a636667ecc41211c837/node_modules/react-dom create mode 120000 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/LICENSE create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/README.md create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/cjs/react-dom-client.development.js create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/cjs/react-dom-client.production.js create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/cjs/react-dom-profiling.development.js create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/cjs/react-dom-profiling.profiling.js create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/cjs/react-dom-server-legacy.browser.development.js create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/cjs/react-dom-server-legacy.browser.production.js create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/cjs/react-dom-server-legacy.node.production.js create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/cjs/react-dom-server.browser.development.js create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/cjs/react-dom-server.browser.production.js create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/cjs/react-dom-server.bun.development.js create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/cjs/react-dom-server.bun.production.js create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/cjs/react-dom-server.edge.development.js create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/cjs/react-dom-server.edge.production.js create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/cjs/react-dom-server.node.development.js create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/cjs/react-dom-server.node.production.js create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/cjs/react-dom-test-utils.development.js create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/cjs/react-dom-test-utils.production.js create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/cjs/react-dom.development.js create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/cjs/react-dom.production.js create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/cjs/react-dom.react-server.development.js create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/cjs/react-dom.react-server.production.js create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/client.js create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/client.react-server.js create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/index.js create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/package.json create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/profiling.js create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/profiling.react-server.js create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/react-dom.react-server.js create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/server.browser.js create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/server.bun.js create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/server.edge.js create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/server.js create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/server.node.js create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/server.react-server.js create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/static.browser.js create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/static.edge.js create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/static.js create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/static.node.js create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/static.react-server.js create mode 100644 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/test-utils.js create mode 120000 node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/scheduler create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/LICENSE create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/README.md create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/cjs/react-compiler-runtime.development.js create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/cjs/react-compiler-runtime.production.js create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/cjs/react-compiler-runtime.profiling.js create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/cjs/react-jsx-dev-runtime.development.js create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/cjs/react-jsx-dev-runtime.production.js create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/cjs/react-jsx-dev-runtime.profiling.js create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/cjs/react-jsx-dev-runtime.react-server.development.js create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/cjs/react-jsx-dev-runtime.react-server.production.js create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/cjs/react-jsx-runtime.development.js create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/cjs/react-jsx-runtime.production.js create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/cjs/react-jsx-runtime.profiling.js create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/cjs/react-jsx-runtime.react-server.development.js create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/cjs/react-jsx-runtime.react-server.production.js create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/cjs/react.development.js create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/cjs/react.production.js create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/cjs/react.react-server.development.js create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/cjs/react.react-server.production.js create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/compiler-runtime.js create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/index.js create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/jsx-dev-runtime.js create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/jsx-dev-runtime.react-server.js create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/jsx-runtime.js create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/jsx-runtime.react-server.js create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/package.json create mode 100644 node_modules/.pnpm/react@19.2.4/node_modules/react/react.react-server.js create mode 100644 node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/LICENSE create mode 100644 node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/README.md create mode 100644 node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/cjs/scheduler-unstable_mock.development.js create mode 100644 node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/cjs/scheduler-unstable_mock.production.js create mode 100644 node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/cjs/scheduler-unstable_post_task.development.js create mode 100644 node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/cjs/scheduler-unstable_post_task.production.js create mode 100644 node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/cjs/scheduler.development.js create mode 100644 node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/cjs/scheduler.native.development.js create mode 100644 node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/cjs/scheduler.native.production.js create mode 100644 node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/cjs/scheduler.production.js create mode 100644 node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/index.js create mode 100644 node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/index.native.js create mode 100644 node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/package.json create mode 100644 node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/unstable_mock.js create mode 100644 node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/unstable_post_task.js create mode 120000 node_modules/react-colorful create mode 100644 pnpm-lock.yaml create mode 100644 web/src/components/MemoRelationForceGraph/MemoRelationForceGraph.tsx create mode 100644 web/src/components/MemoRelationForceGraph/index.ts create mode 100644 web/src/components/MemoRelationForceGraph/types.ts create mode 100644 web/src/components/MemoRelationForceGraph/utils.ts create mode 100644 web/src/components/MemoView/components/MemoCustomizeColor.tsx create mode 100644 web/src/pages/SharedMemo.tsx diff --git a/.dockerignore b/.dockerignore index d465134d4..944184ae7 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,13 +1,13 @@ -web/node_modules -web/dist -.git -.github -build/ -tmp/ -memos -*.md -.gitignore -.golangci.yaml -.dockerignore -docs/ +web/node_modules +web/dist +.git +.github +build/ +tmp/ +memos +*.md +.gitignore +.golangci.yaml +.dockerignore +docs/ .DS_Store \ No newline at end of file diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index f9af2381b..e4a2c915f 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1 +1 @@ -github: usememos +github: usememos diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 75f0b5850..e034c8d1b 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -1,99 +1,99 @@ -name: Bug Report -description: Something isn't working as expected -type: Bug -body: - - type: markdown - attributes: - value: | - Thanks for reporting a bug! Please fill out the form below so we can reproduce and fix the issue. - - **Before submitting**, please search [existing issues](https://github.com/usememos/memos/issues) to avoid duplicates. - - - type: checkboxes - id: pre-check - attributes: - label: Pre-submission Checklist - options: - - label: I have searched existing issues and confirmed this bug has not been reported - required: true - - label: I can reproduce this bug on the latest version or the [demo site](https://demo.usememos.com) - required: true - - label: This is a bug, not a question (use [Discussions](https://github.com/usememos/memos/discussions) for questions) - required: true - - - type: input - id: version - attributes: - label: Memos Version - description: Find this in **Settings > System > About** or via the `--version` flag - placeholder: "v0.25.2" - validations: - required: true - - - type: dropdown - id: deployment - attributes: - label: Deployment Method - options: - - Docker - - Pre-built binary - - Built from source - validations: - required: true - - - type: dropdown - id: database - attributes: - label: Database - options: - - SQLite - - PostgreSQL - - MySQL - validations: - required: true - - - type: input - id: browser-os - attributes: - label: Browser & OS - description: e.g. Chrome 120 on macOS 15, Firefox 130 on Ubuntu 24.04 - placeholder: "Chrome 120 on macOS 15" - validations: - required: false - - - type: textarea - id: bug-description - attributes: - label: Bug Description - description: A clear and concise description of what the bug is - placeholder: When I try to..., the application... - validations: - required: true - - - type: textarea - id: reproduction-steps - attributes: - label: Steps to Reproduce - description: Minimal steps to reliably reproduce the issue - placeholder: | - 1. Go to '...' - 2. Click on '...' - 3. See error - validations: - required: true - - - type: textarea - id: expected-behavior - attributes: - label: Expected Behavior - description: What did you expect to happen instead? - placeholder: I expected... - validations: - required: true - - - type: textarea - id: additional-context - attributes: - label: Screenshots, Logs & Additional Context - description: Attach screenshots, browser console errors, or server logs if available - placeholder: Drag and drop images here, or paste error logs... +name: Bug Report +description: Something isn't working as expected +type: Bug +body: + - type: markdown + attributes: + value: | + Thanks for reporting a bug! Please fill out the form below so we can reproduce and fix the issue. + + **Before submitting**, please search [existing issues](https://github.com/usememos/memos/issues) to avoid duplicates. + + - type: checkboxes + id: pre-check + attributes: + label: Pre-submission Checklist + options: + - label: I have searched existing issues and confirmed this bug has not been reported + required: true + - label: I can reproduce this bug on the latest version or the [demo site](https://demo.usememos.com) + required: true + - label: This is a bug, not a question (use [Discussions](https://github.com/usememos/memos/discussions) for questions) + required: true + + - type: input + id: version + attributes: + label: Memos Version + description: Find this in **Settings > System > About** or via the `--version` flag + placeholder: "v0.25.2" + validations: + required: true + + - type: dropdown + id: deployment + attributes: + label: Deployment Method + options: + - Docker + - Pre-built binary + - Built from source + validations: + required: true + + - type: dropdown + id: database + attributes: + label: Database + options: + - SQLite + - PostgreSQL + - MySQL + validations: + required: true + + - type: input + id: browser-os + attributes: + label: Browser & OS + description: e.g. Chrome 120 on macOS 15, Firefox 130 on Ubuntu 24.04 + placeholder: "Chrome 120 on macOS 15" + validations: + required: false + + - type: textarea + id: bug-description + attributes: + label: Bug Description + description: A clear and concise description of what the bug is + placeholder: When I try to..., the application... + validations: + required: true + + - type: textarea + id: reproduction-steps + attributes: + label: Steps to Reproduce + description: Minimal steps to reliably reproduce the issue + placeholder: | + 1. Go to '...' + 2. Click on '...' + 3. See error + validations: + required: true + + - type: textarea + id: expected-behavior + attributes: + label: Expected Behavior + description: What did you expect to happen instead? + placeholder: I expected... + validations: + required: true + + - type: textarea + id: additional-context + attributes: + label: Screenshots, Logs & Additional Context + description: Attach screenshots, browser console errors, or server logs if available + placeholder: Drag and drop images here, or paste error logs... diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 99c57ecd1..7b50bcfc4 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,8 +1,8 @@ -blank_issues_enabled: false -contact_links: - - name: Questions & Support - url: https://github.com/usememos/memos/discussions - about: Ask questions or get help in GitHub Discussions — please don't open issues for questions - - name: Documentation - url: https://www.usememos.com/docs - about: Check the documentation before opening an issue +blank_issues_enabled: false +contact_links: + - name: Questions & Support + url: https://github.com/usememos/memos/discussions + about: Ask questions or get help in GitHub Discussions — please don't open issues for questions + - name: Documentation + url: https://www.usememos.com/docs + about: Check the documentation before opening an issue diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml index ec1ff0cfe..9f113a370 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -1,78 +1,78 @@ -name: Feature Request -description: Suggest a new feature or improvement -type: Feature -body: - - type: markdown - attributes: - value: | - Thanks for suggesting a feature! Please fill out the form below so we can understand your idea. - - **Before submitting**, please search [existing issues](https://github.com/usememos/memos/issues?q=label%3Aenhancement) to avoid duplicates. - - - type: checkboxes - id: pre-check - attributes: - label: Pre-submission Checklist - options: - - label: I have searched existing issues and confirmed this feature has not been requested - required: true - - label: This is a feature request, not a bug report or question - required: true - - - type: dropdown - id: feature-type - attributes: - label: Feature Area - options: - - User Interface (UI) - - User Experience (UX) - - API / Backend - - Integrations / Plugins - - Security / Privacy - - Performance - - Other - validations: - required: true - - - type: textarea - id: problem-statement - attributes: - label: Problem or Use Case - description: What problem does this feature solve? Why do you need it? - placeholder: | - I often need to... but currently there's no way to... - validations: - required: true - - - type: textarea - id: proposed-solution - attributes: - label: Proposed Solution - description: Describe what you'd like to happen - placeholder: | - It would be great if Memos could... - validations: - required: true - - - type: textarea - id: alternatives - attributes: - label: Alternatives Considered - description: Have you considered any workarounds or alternative approaches? - placeholder: | - I've tried... but it doesn't work well because... - - - type: textarea - id: additional-context - attributes: - label: Additional Context - description: Mockups, screenshots, examples from other apps, or any other context - placeholder: Drag and drop images here... - - - type: checkboxes - id: contribution - attributes: - label: Contribution - description: Would you be willing to help implement this feature? - options: - - label: I'm willing to submit a pull request for this feature +name: Feature Request +description: Suggest a new feature or improvement +type: Feature +body: + - type: markdown + attributes: + value: | + Thanks for suggesting a feature! Please fill out the form below so we can understand your idea. + + **Before submitting**, please search [existing issues](https://github.com/usememos/memos/issues?q=label%3Aenhancement) to avoid duplicates. + + - type: checkboxes + id: pre-check + attributes: + label: Pre-submission Checklist + options: + - label: I have searched existing issues and confirmed this feature has not been requested + required: true + - label: This is a feature request, not a bug report or question + required: true + + - type: dropdown + id: feature-type + attributes: + label: Feature Area + options: + - User Interface (UI) + - User Experience (UX) + - API / Backend + - Integrations / Plugins + - Security / Privacy + - Performance + - Other + validations: + required: true + + - type: textarea + id: problem-statement + attributes: + label: Problem or Use Case + description: What problem does this feature solve? Why do you need it? + placeholder: | + I often need to... but currently there's no way to... + validations: + required: true + + - type: textarea + id: proposed-solution + attributes: + label: Proposed Solution + description: Describe what you'd like to happen + placeholder: | + It would be great if Memos could... + validations: + required: true + + - type: textarea + id: alternatives + attributes: + label: Alternatives Considered + description: Have you considered any workarounds or alternative approaches? + placeholder: | + I've tried... but it doesn't work well because... + + - type: textarea + id: additional-context + attributes: + label: Additional Context + description: Mockups, screenshots, examples from other apps, or any other context + placeholder: Drag and drop images here... + + - type: checkboxes + id: contribution + attributes: + label: Contribution + description: Would you be willing to help implement this feature? + options: + - label: I'm willing to submit a pull request for this feature diff --git a/.github/workflows/backend-tests.yml b/.github/workflows/backend-tests.yml index dfdd5ac1f..7384f5d60 100644 --- a/.github/workflows/backend-tests.yml +++ b/.github/workflows/backend-tests.yml @@ -1,91 +1,91 @@ -name: Backend Tests - -on: - push: - branches: [main] - pull_request: - branches: [main] - paths: - - "go.mod" - - "go.sum" - - "**.go" - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -env: - GO_VERSION: "1.26.1" - -jobs: - static-checks: - name: Static Checks - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v6 - - - name: Setup Go - uses: actions/setup-go@v6 - with: - go-version: ${{ env.GO_VERSION }} - cache: true - cache-dependency-path: go.sum - - - name: Verify go.mod is tidy - run: | - go mod tidy -go=${{ env.GO_VERSION }} - git diff --exit-code - - - name: Run golangci-lint - uses: golangci/golangci-lint-action@v9 - with: - version: v2.11.3 - args: --timeout=3m - - tests: - name: Tests (${{ matrix.test-group }}) - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - test-group: [store, server, plugin, other] - steps: - - name: Checkout code - uses: actions/checkout@v6 - - - name: Setup Go - uses: actions/setup-go@v6 - with: - go-version: ${{ env.GO_VERSION }} - cache: true - cache-dependency-path: go.sum - - - name: Run tests - run: | - case "${{ matrix.test-group }}" in - store) - # Run store tests for all drivers (sqlite, mysql, postgres) - go test -v -coverprofile=coverage.out -covermode=atomic ./store/... - ;; - server) - go test -v -race -coverprofile=coverage.out -covermode=atomic ./server/... - ;; - plugin) - go test -v -race -coverprofile=coverage.out -covermode=atomic ./plugin/... - ;; - other) - go test -v -race -coverprofile=coverage.out -covermode=atomic \ - ./cmd/... ./internal/... ./proto/... - ;; - esac - env: - DRIVER: ${{ matrix.test-group == 'store' && '' || 'sqlite' }} - - - name: Upload coverage - if: github.event_name == 'push' && github.ref == 'refs/heads/main' - uses: codecov/codecov-action@v5 - with: - files: ./coverage.out - flags: ${{ matrix.test-group }} - fail_ci_if_error: false +name: Backend Tests + +on: + push: + branches: [main] + pull_request: + branches: [main] + paths: + - "go.mod" + - "go.sum" + - "**.go" + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + GO_VERSION: "1.26.1" + +jobs: + static-checks: + name: Static Checks + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Setup Go + uses: actions/setup-go@v6 + with: + go-version: ${{ env.GO_VERSION }} + cache: true + cache-dependency-path: go.sum + + - name: Verify go.mod is tidy + run: | + go mod tidy -go=${{ env.GO_VERSION }} + git diff --exit-code + + - name: Run golangci-lint + uses: golangci/golangci-lint-action@v9 + with: + version: v2.11.3 + args: --timeout=3m + + tests: + name: Tests (${{ matrix.test-group }}) + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + test-group: [store, server, plugin, other] + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Setup Go + uses: actions/setup-go@v6 + with: + go-version: ${{ env.GO_VERSION }} + cache: true + cache-dependency-path: go.sum + + - name: Run tests + run: | + case "${{ matrix.test-group }}" in + store) + # Run store tests for all drivers (sqlite, mysql, postgres) + go test -v -coverprofile=coverage.out -covermode=atomic ./store/... + ;; + server) + go test -v -race -coverprofile=coverage.out -covermode=atomic ./server/... + ;; + plugin) + go test -v -race -coverprofile=coverage.out -covermode=atomic ./plugin/... + ;; + other) + go test -v -race -coverprofile=coverage.out -covermode=atomic \ + ./cmd/... ./internal/... ./proto/... + ;; + esac + env: + DRIVER: ${{ matrix.test-group == 'store' && '' || 'sqlite' }} + + - name: Upload coverage + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + uses: codecov/codecov-action@v5 + with: + files: ./coverage.out + flags: ${{ matrix.test-group }} + fail_ci_if_error: false diff --git a/.github/workflows/build-canary-image.yml b/.github/workflows/build-canary-image.yml index de8f5919a..eceaa8d32 100644 --- a/.github/workflows/build-canary-image.yml +++ b/.github/workflows/build-canary-image.yml @@ -1,166 +1,166 @@ -name: Build Canary Image - -on: - push: - branches: [main] - -concurrency: - group: ${{ github.workflow }}-${{ github.repository }} - cancel-in-progress: true - -jobs: - build-frontend: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v6 - - - uses: pnpm/action-setup@v4.2.0 - with: - version: 10 - - uses: actions/setup-node@v6 - with: - node-version: "24" - cache: pnpm - cache-dependency-path: "web/pnpm-lock.yaml" - - name: Get pnpm store directory - id: pnpm-cache - shell: bash - run: echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT - - name: Setup pnpm cache - uses: actions/cache@v5 - with: - path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('web/pnpm-lock.yaml') }} - restore-keys: ${{ runner.os }}-pnpm-store- - - run: pnpm install --frozen-lockfile - working-directory: web - - name: Run frontend build - run: pnpm release - working-directory: web - - - name: Upload frontend artifacts - uses: actions/upload-artifact@v6 - with: - name: frontend-dist - path: server/router/frontend/dist - retention-days: 1 - - build-push: - needs: build-frontend - runs-on: ubuntu-latest - permissions: - contents: read - packages: write - strategy: - fail-fast: false - matrix: - platform: - - linux/amd64 - - linux/arm64 - steps: - - uses: actions/checkout@v6 - - - name: Download frontend artifacts - uses: actions/download-artifact@v7 - with: - name: frontend-dist - path: server/router/frontend/dist - - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Login to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKER_HUB_USERNAME }} - password: ${{ secrets.DOCKER_HUB_TOKEN }} - - - name: Login to GitHub Container Registry - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ github.token }} - - - name: Build and push by digest - id: build - uses: docker/build-push-action@v6 - with: - context: . - file: ./scripts/Dockerfile - platforms: ${{ matrix.platform }} - cache-from: type=gha,scope=build-${{ matrix.platform }} - cache-to: type=gha,mode=max,scope=build-${{ matrix.platform }} - outputs: type=image,name=neosmemo/memos,push-by-digest=true,name-canonical=true,push=true - - - name: Export digest - run: | - mkdir -p /tmp/digests - digest="${{ steps.build.outputs.digest }}" - touch "/tmp/digests/${digest#sha256:}" - - - name: Upload digest - uses: actions/upload-artifact@v6 - with: - name: digests-${{ strategy.job-index }} - path: /tmp/digests/* - if-no-files-found: error - retention-days: 1 - - merge: - needs: build-push - runs-on: ubuntu-latest - permissions: - contents: read - packages: write - steps: - - name: Download digests - uses: actions/download-artifact@v7 - with: - pattern: digests-* - merge-multiple: true - path: /tmp/digests - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Docker meta - id: meta - uses: docker/metadata-action@v5 - with: - images: | - neosmemo/memos - ghcr.io/usememos/memos - flavor: | - latest=false - tags: | - type=raw,value=canary - - - name: Login to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKER_HUB_USERNAME }} - password: ${{ secrets.DOCKER_HUB_TOKEN }} - - - name: Login to GitHub Container Registry - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ github.token }} - - - name: Create manifest list and push - working-directory: /tmp/digests - run: | - docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ - $(printf 'neosmemo/memos@sha256:%s ' *) - env: - DOCKER_METADATA_OUTPUT_JSON: ${{ steps.meta.outputs.json }} - - - name: Inspect images - run: | - docker buildx imagetools inspect neosmemo/memos:canary - docker buildx imagetools inspect ghcr.io/usememos/memos:canary +name: Build Canary Image + +on: + push: + branches: [main] + +concurrency: + group: ${{ github.workflow }}-${{ github.repository }} + cancel-in-progress: true + +jobs: + build-frontend: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + + - uses: pnpm/action-setup@v4.2.0 + with: + version: 10 + - uses: actions/setup-node@v6 + with: + node-version: "24" + cache: pnpm + cache-dependency-path: "web/pnpm-lock.yaml" + - name: Get pnpm store directory + id: pnpm-cache + shell: bash + run: echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT + - name: Setup pnpm cache + uses: actions/cache@v5 + with: + path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('web/pnpm-lock.yaml') }} + restore-keys: ${{ runner.os }}-pnpm-store- + - run: pnpm install --frozen-lockfile + working-directory: web + - name: Run frontend build + run: pnpm release + working-directory: web + + - name: Upload frontend artifacts + uses: actions/upload-artifact@v6 + with: + name: frontend-dist + path: server/router/frontend/dist + retention-days: 1 + + build-push: + needs: build-frontend + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + strategy: + fail-fast: false + matrix: + platform: + - linux/amd64 + - linux/arm64 + steps: + - uses: actions/checkout@v6 + + - name: Download frontend artifacts + uses: actions/download-artifact@v7 + with: + name: frontend-dist + path: server/router/frontend/dist + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_HUB_USERNAME }} + password: ${{ secrets.DOCKER_HUB_TOKEN }} + + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ github.token }} + + - name: Build and push by digest + id: build + uses: docker/build-push-action@v6 + with: + context: . + file: ./scripts/Dockerfile + platforms: ${{ matrix.platform }} + cache-from: type=gha,scope=build-${{ matrix.platform }} + cache-to: type=gha,mode=max,scope=build-${{ matrix.platform }} + outputs: type=image,name=neosmemo/memos,push-by-digest=true,name-canonical=true,push=true + + - name: Export digest + run: | + mkdir -p /tmp/digests + digest="${{ steps.build.outputs.digest }}" + touch "/tmp/digests/${digest#sha256:}" + + - name: Upload digest + uses: actions/upload-artifact@v6 + with: + name: digests-${{ strategy.job-index }} + path: /tmp/digests/* + if-no-files-found: error + retention-days: 1 + + merge: + needs: build-push + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - name: Download digests + uses: actions/download-artifact@v7 + with: + pattern: digests-* + merge-multiple: true + path: /tmp/digests + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Docker meta + id: meta + uses: docker/metadata-action@v5 + with: + images: | + neosmemo/memos + ghcr.io/usememos/memos + flavor: | + latest=false + tags: | + type=raw,value=canary + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_HUB_USERNAME }} + password: ${{ secrets.DOCKER_HUB_TOKEN }} + + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ github.token }} + + - name: Create manifest list and push + working-directory: /tmp/digests + run: | + docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ + $(printf 'neosmemo/memos@sha256:%s ' *) + env: + DOCKER_METADATA_OUTPUT_JSON: ${{ steps.meta.outputs.json }} + + - name: Inspect images + run: | + docker buildx imagetools inspect neosmemo/memos:canary + docker buildx imagetools inspect ghcr.io/usememos/memos:canary diff --git a/.github/workflows/demo-deploy.yml b/.github/workflows/demo-deploy.yml index 4ff6a3742..fba639683 100644 --- a/.github/workflows/demo-deploy.yml +++ b/.github/workflows/demo-deploy.yml @@ -1,17 +1,17 @@ -name: Demo Deploy - -on: - workflow_dispatch: - -jobs: - deploy-demo: - runs-on: ubuntu-latest - steps: - - name: Trigger Render Deploy - run: | - curl -X POST "${{ secrets.RENDER_DEPLOY_HOOK }}" \ - -H "Content-Type: application/json" \ - -d '{"trigger": "github_action"}' - - - name: Deployment Status - run: echo "Demo deployment triggered successfully on Render" +name: Demo Deploy + +on: + workflow_dispatch: + +jobs: + deploy-demo: + runs-on: ubuntu-latest + steps: + - name: Trigger Render Deploy + run: | + curl -X POST "${{ secrets.RENDER_DEPLOY_HOOK }}" \ + -H "Content-Type: application/json" \ + -d '{"trigger": "github_action"}' + + - name: Deployment Status + run: echo "Demo deployment triggered successfully on Render" diff --git a/.github/workflows/frontend-tests.yml b/.github/workflows/frontend-tests.yml index d1fe8a613..3b294e750 100644 --- a/.github/workflows/frontend-tests.yml +++ b/.github/workflows/frontend-tests.yml @@ -1,72 +1,72 @@ -name: Frontend Tests - -on: - push: - branches: [main] - pull_request: - branches: [main] - paths: - - "web/**" - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -env: - NODE_VERSION: "24" - PNPM_VERSION: "10" - -jobs: - lint: - name: Lint - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v6 - - - name: Setup pnpm - uses: pnpm/action-setup@v4.2.0 - with: - version: ${{ env.PNPM_VERSION }} - - - name: Setup Node.js - uses: actions/setup-node@v6 - with: - node-version: ${{ env.NODE_VERSION }} - cache: pnpm - cache-dependency-path: web/pnpm-lock.yaml - - - name: Install dependencies - working-directory: web - run: pnpm install --frozen-lockfile - - - name: Run lint - working-directory: web - run: pnpm lint - - build: - name: Build - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v6 - - - name: Setup pnpm - uses: pnpm/action-setup@v4.2.0 - with: - version: ${{ env.PNPM_VERSION }} - - - name: Setup Node.js - uses: actions/setup-node@v6 - with: - node-version: ${{ env.NODE_VERSION }} - cache: pnpm - cache-dependency-path: web/pnpm-lock.yaml - - - name: Install dependencies - working-directory: web - run: pnpm install --frozen-lockfile - - - name: Build frontend - working-directory: web - run: pnpm build +name: Frontend Tests + +on: + push: + branches: [main] + pull_request: + branches: [main] + paths: + - "web/**" + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + NODE_VERSION: "24" + PNPM_VERSION: "10" + +jobs: + lint: + name: Lint + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Setup pnpm + uses: pnpm/action-setup@v4.2.0 + with: + version: ${{ env.PNPM_VERSION }} + + - name: Setup Node.js + uses: actions/setup-node@v6 + with: + node-version: ${{ env.NODE_VERSION }} + cache: pnpm + cache-dependency-path: web/pnpm-lock.yaml + + - name: Install dependencies + working-directory: web + run: pnpm install --frozen-lockfile + + - name: Run lint + working-directory: web + run: pnpm lint + + build: + name: Build + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Setup pnpm + uses: pnpm/action-setup@v4.2.0 + with: + version: ${{ env.PNPM_VERSION }} + + - name: Setup Node.js + uses: actions/setup-node@v6 + with: + node-version: ${{ env.NODE_VERSION }} + cache: pnpm + cache-dependency-path: web/pnpm-lock.yaml + + - name: Install dependencies + working-directory: web + run: pnpm install --frozen-lockfile + + - name: Build frontend + working-directory: web + run: pnpm build diff --git a/.github/workflows/proto-linter.yml b/.github/workflows/proto-linter.yml index a6422349c..bbc9b3dce 100644 --- a/.github/workflows/proto-linter.yml +++ b/.github/workflows/proto-linter.yml @@ -1,40 +1,40 @@ -name: Proto Linter - -on: - push: - branches: [main] - pull_request: - branches: [main] - paths: - - "proto/**" - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - lint: - name: Lint Protos - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v6 - with: - fetch-depth: 0 - - - name: Setup buf - uses: bufbuild/buf-setup-action@v1 - with: - github_token: ${{ github.token }} - - - name: Run buf lint - uses: bufbuild/buf-lint-action@v1 - with: - input: proto - - - name: Check buf format - run: | - if [[ $(buf format -d) ]]; then - echo "❌ Proto files are not formatted. Run 'buf format -w' to fix." - exit 1 - fi +name: Proto Linter + +on: + push: + branches: [main] + pull_request: + branches: [main] + paths: + - "proto/**" + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + lint: + name: Lint Protos + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Setup buf + uses: bufbuild/buf-setup-action@v1 + with: + github_token: ${{ github.token }} + + - name: Run buf lint + uses: bufbuild/buf-lint-action@v1 + with: + input: proto + + - name: Check buf format + run: | + if [[ $(buf format -d) ]]; then + echo "❌ Proto files are not formatted. Run 'buf format -w' to fix." + exit 1 + fi diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7e946a7b9..3b5ec0853 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,352 +1,352 @@ -name: Release - -on: - push: - tags: - - "v*.*.*" - workflow_dispatch: - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -env: - GO_VERSION: "1.26.1" - NODE_VERSION: "24" - PNPM_VERSION: "10" - ARTIFACT_RETENTION_DAYS: 60 - ARTIFACT_PREFIX: memos - -jobs: - prepare: - name: Extract Version - runs-on: ubuntu-latest - outputs: - version: ${{ steps.version.outputs.version }} - tag: ${{ steps.version.outputs.tag }} - steps: - - name: Extract version - id: version - env: - REF_NAME: ${{ github.ref_name }} - EVENT_NAME: ${{ github.event_name }} - run: | - if [ "$EVENT_NAME" = "workflow_dispatch" ]; then - echo "tag=" >> "$GITHUB_OUTPUT" - echo "version=manual-${GITHUB_SHA::7}" >> "$GITHUB_OUTPUT" - exit 0 - fi - - echo "tag=${REF_NAME}" >> "$GITHUB_OUTPUT" - echo "version=${REF_NAME#v}" >> "$GITHUB_OUTPUT" - - build-frontend: - name: Build Frontend - needs: prepare - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v6 - - - name: Setup pnpm - uses: pnpm/action-setup@v4.2.0 - with: - version: ${{ env.PNPM_VERSION }} - - - name: Setup Node.js - uses: actions/setup-node@v6 - with: - node-version: ${{ env.NODE_VERSION }} - cache: pnpm - cache-dependency-path: web/pnpm-lock.yaml - - - name: Get pnpm store directory - id: pnpm-cache - shell: bash - run: echo "STORE_PATH=$(pnpm store path)" >> "$GITHUB_OUTPUT" - - - name: Setup pnpm cache - uses: actions/cache@v4 - with: - path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('web/pnpm-lock.yaml') }} - restore-keys: ${{ runner.os }}-pnpm-store- - - - name: Install dependencies - working-directory: web - run: pnpm install --frozen-lockfile - - - name: Build frontend release assets - working-directory: web - run: pnpm release - - - name: Upload frontend artifacts - uses: actions/upload-artifact@v4 - with: - name: frontend-dist - path: server/router/frontend/dist - retention-days: 1 - - build-binaries: - name: Build ${{ matrix.goos }}-${{ matrix.goarch }}${{ matrix.goarm && format('v{0}', matrix.goarm) || '' }} - needs: [prepare, build-frontend] - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - include: - - goos: linux - goarch: amd64 - - goos: linux - goarch: arm64 - - goos: linux - goarch: arm - goarm: "7" - - goos: darwin - goarch: amd64 - - goos: darwin - goarch: arm64 - - goos: windows - goarch: amd64 - steps: - - name: Checkout code - uses: actions/checkout@v6 - - - name: Setup Go - uses: actions/setup-go@v6 - with: - go-version: ${{ env.GO_VERSION }} - cache: true - - - name: Download frontend artifacts - uses: actions/download-artifact@v4 - with: - name: frontend-dist - path: server/router/frontend/dist - - - name: Build binary - env: - GOOS: ${{ matrix.goos }} - GOARCH: ${{ matrix.goarch }} - GOARM: ${{ matrix.goarm }} - CGO_ENABLED: "0" - run: | - output_name="memos" - if [ "$GOOS" = "windows" ]; then - output_name="memos.exe" - fi - - mkdir -p build - - go build \ - -trimpath \ - -ldflags="-s -w -X github.com/usememos/memos/internal/version.Version=${{ needs.prepare.outputs.version }} -extldflags '-static'" \ - -tags netgo,osusergo \ - -o "build/${output_name}" \ - ./cmd/memos - - - name: Package binary - env: - VERSION: ${{ needs.prepare.outputs.version }} - GOOS: ${{ matrix.goos }} - GOARCH: ${{ matrix.goarch }} - GOARM: ${{ matrix.goarm }} - run: | - cd build - - package_name="${ARTIFACT_PREFIX}_${VERSION}_${GOOS}_${GOARCH}" - if [ -n "$GOARM" ]; then - package_name="${package_name}v${GOARM}" - fi - - if [ "$GOOS" = "windows" ]; then - artifact_name="${package_name}.zip" - zip -q "${artifact_name}" memos.exe - else - artifact_name="${package_name}.tar.gz" - tar czf "${artifact_name}" memos - fi - - echo "artifact_name=${artifact_name}" >> "$GITHUB_ENV" - - - name: Upload binary artifact - uses: actions/upload-artifact@v4 - with: - name: ${{ env.artifact_name }} - path: build/${{ env.artifact_name }} - retention-days: ${{ env.ARTIFACT_RETENTION_DAYS }} - - checksums: - name: Generate Checksums - needs: [prepare, build-binaries] - runs-on: ubuntu-latest - steps: - - name: Download binary artifacts - uses: actions/download-artifact@v4 - with: - path: artifacts - pattern: ${{ env.ARTIFACT_PREFIX }}_* - merge-multiple: true - - - name: Generate checksums - working-directory: artifacts - run: sha256sum * > checksums.txt - - - name: Upload checksum artifact - uses: actions/upload-artifact@v4 - with: - name: checksums - path: artifacts/checksums.txt - retention-days: ${{ env.ARTIFACT_RETENTION_DAYS }} - - release: - name: Publish GitHub Release - needs: [prepare, build-binaries, checksums] - if: github.event_name != 'workflow_dispatch' - runs-on: ubuntu-latest - permissions: - contents: write - steps: - - name: Download binary artifacts - uses: actions/download-artifact@v4 - with: - path: artifacts - pattern: ${{ env.ARTIFACT_PREFIX }}_* - merge-multiple: true - - - name: Download checksum artifact - uses: actions/download-artifact@v4 - with: - name: checksums - path: artifacts - - - name: Publish release assets - uses: softprops/action-gh-release@v2 - with: - tag_name: ${{ needs.prepare.outputs.tag }} - name: ${{ needs.prepare.outputs.tag }} - generate_release_notes: true - files: artifacts/* - - build-push: - name: Build Image ${{ matrix.platform }} - needs: [prepare, build-frontend] - if: github.event_name != 'workflow_dispatch' - runs-on: ubuntu-latest - permissions: - contents: read - packages: write - strategy: - fail-fast: false - matrix: - platform: - - linux/amd64 - - linux/arm/v7 - - linux/arm64 - steps: - - name: Checkout code - uses: actions/checkout@v6 - - - name: Download frontend artifacts - uses: actions/download-artifact@v4 - with: - name: frontend-dist - path: server/router/frontend/dist - - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Login to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKER_HUB_USERNAME }} - password: ${{ secrets.DOCKER_HUB_TOKEN }} - - - name: Login to GitHub Container Registry - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ github.token }} - - - name: Build and push by digest - id: build - uses: docker/build-push-action@v6 - with: - context: . - file: ./scripts/Dockerfile - platforms: ${{ matrix.platform }} - build-args: | - VERSION=${{ needs.prepare.outputs.version }} - COMMIT=${{ github.sha }} - cache-from: type=gha,scope=release-${{ matrix.platform }} - cache-to: type=gha,mode=max,scope=release-${{ matrix.platform }} - outputs: type=image,name=neosmemo/memos,push-by-digest=true,name-canonical=true,push=true - - - name: Export digest - run: | - mkdir -p /tmp/digests - digest="${{ steps.build.outputs.digest }}" - touch "/tmp/digests/${digest#sha256:}" - - - name: Upload digest - uses: actions/upload-artifact@v4 - with: - name: digests-${{ strategy.job-index }} - path: /tmp/digests/* - if-no-files-found: error - retention-days: 1 - - merge-images: - name: Publish Stable Image Tags - needs: [prepare, build-push] - if: github.event_name != 'workflow_dispatch' - runs-on: ubuntu-latest - permissions: - contents: read - packages: write - steps: - - name: Download digests - uses: actions/download-artifact@v4 - with: - pattern: digests-* - merge-multiple: true - path: /tmp/digests - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Login to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKER_HUB_USERNAME }} - password: ${{ secrets.DOCKER_HUB_TOKEN }} - - - name: Login to GitHub Container Registry - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ github.token }} - - - name: Create manifest list and push - working-directory: /tmp/digests - run: | - version="${{ needs.prepare.outputs.version }}" - major_minor=$(echo "$version" | cut -d. -f1,2) - docker buildx imagetools create \ - -t "neosmemo/memos:${version}" \ - -t "neosmemo/memos:${major_minor}" \ - -t "neosmemo/memos:stable" \ - -t "ghcr.io/usememos/memos:${version}" \ - -t "ghcr.io/usememos/memos:${major_minor}" \ - -t "ghcr.io/usememos/memos:stable" \ - $(printf 'neosmemo/memos@sha256:%s ' *) - - - name: Inspect images - run: | - docker buildx imagetools inspect neosmemo/memos:${{ needs.prepare.outputs.version }} - docker buildx imagetools inspect neosmemo/memos:stable +name: Release + +on: + push: + tags: + - "v*.*.*" + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + GO_VERSION: "1.26.1" + NODE_VERSION: "24" + PNPM_VERSION: "10" + ARTIFACT_RETENTION_DAYS: 60 + ARTIFACT_PREFIX: memos + +jobs: + prepare: + name: Extract Version + runs-on: ubuntu-latest + outputs: + version: ${{ steps.version.outputs.version }} + tag: ${{ steps.version.outputs.tag }} + steps: + - name: Extract version + id: version + env: + REF_NAME: ${{ github.ref_name }} + EVENT_NAME: ${{ github.event_name }} + run: | + if [ "$EVENT_NAME" = "workflow_dispatch" ]; then + echo "tag=" >> "$GITHUB_OUTPUT" + echo "version=manual-${GITHUB_SHA::7}" >> "$GITHUB_OUTPUT" + exit 0 + fi + + echo "tag=${REF_NAME}" >> "$GITHUB_OUTPUT" + echo "version=${REF_NAME#v}" >> "$GITHUB_OUTPUT" + + build-frontend: + name: Build Frontend + needs: prepare + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Setup pnpm + uses: pnpm/action-setup@v4.2.0 + with: + version: ${{ env.PNPM_VERSION }} + + - name: Setup Node.js + uses: actions/setup-node@v6 + with: + node-version: ${{ env.NODE_VERSION }} + cache: pnpm + cache-dependency-path: web/pnpm-lock.yaml + + - name: Get pnpm store directory + id: pnpm-cache + shell: bash + run: echo "STORE_PATH=$(pnpm store path)" >> "$GITHUB_OUTPUT" + + - name: Setup pnpm cache + uses: actions/cache@v4 + with: + path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('web/pnpm-lock.yaml') }} + restore-keys: ${{ runner.os }}-pnpm-store- + + - name: Install dependencies + working-directory: web + run: pnpm install --frozen-lockfile + + - name: Build frontend release assets + working-directory: web + run: pnpm release + + - name: Upload frontend artifacts + uses: actions/upload-artifact@v4 + with: + name: frontend-dist + path: server/router/frontend/dist + retention-days: 1 + + build-binaries: + name: Build ${{ matrix.goos }}-${{ matrix.goarch }}${{ matrix.goarm && format('v{0}', matrix.goarm) || '' }} + needs: [prepare, build-frontend] + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + - goos: linux + goarch: amd64 + - goos: linux + goarch: arm64 + - goos: linux + goarch: arm + goarm: "7" + - goos: darwin + goarch: amd64 + - goos: darwin + goarch: arm64 + - goos: windows + goarch: amd64 + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Setup Go + uses: actions/setup-go@v6 + with: + go-version: ${{ env.GO_VERSION }} + cache: true + + - name: Download frontend artifacts + uses: actions/download-artifact@v4 + with: + name: frontend-dist + path: server/router/frontend/dist + + - name: Build binary + env: + GOOS: ${{ matrix.goos }} + GOARCH: ${{ matrix.goarch }} + GOARM: ${{ matrix.goarm }} + CGO_ENABLED: "0" + run: | + output_name="memos" + if [ "$GOOS" = "windows" ]; then + output_name="memos.exe" + fi + + mkdir -p build + + go build \ + -trimpath \ + -ldflags="-s -w -X github.com/usememos/memos/internal/version.Version=${{ needs.prepare.outputs.version }} -extldflags '-static'" \ + -tags netgo,osusergo \ + -o "build/${output_name}" \ + ./cmd/memos + + - name: Package binary + env: + VERSION: ${{ needs.prepare.outputs.version }} + GOOS: ${{ matrix.goos }} + GOARCH: ${{ matrix.goarch }} + GOARM: ${{ matrix.goarm }} + run: | + cd build + + package_name="${ARTIFACT_PREFIX}_${VERSION}_${GOOS}_${GOARCH}" + if [ -n "$GOARM" ]; then + package_name="${package_name}v${GOARM}" + fi + + if [ "$GOOS" = "windows" ]; then + artifact_name="${package_name}.zip" + zip -q "${artifact_name}" memos.exe + else + artifact_name="${package_name}.tar.gz" + tar czf "${artifact_name}" memos + fi + + echo "artifact_name=${artifact_name}" >> "$GITHUB_ENV" + + - name: Upload binary artifact + uses: actions/upload-artifact@v4 + with: + name: ${{ env.artifact_name }} + path: build/${{ env.artifact_name }} + retention-days: ${{ env.ARTIFACT_RETENTION_DAYS }} + + checksums: + name: Generate Checksums + needs: [prepare, build-binaries] + runs-on: ubuntu-latest + steps: + - name: Download binary artifacts + uses: actions/download-artifact@v4 + with: + path: artifacts + pattern: ${{ env.ARTIFACT_PREFIX }}_* + merge-multiple: true + + - name: Generate checksums + working-directory: artifacts + run: sha256sum * > checksums.txt + + - name: Upload checksum artifact + uses: actions/upload-artifact@v4 + with: + name: checksums + path: artifacts/checksums.txt + retention-days: ${{ env.ARTIFACT_RETENTION_DAYS }} + + release: + name: Publish GitHub Release + needs: [prepare, build-binaries, checksums] + if: github.event_name != 'workflow_dispatch' + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Download binary artifacts + uses: actions/download-artifact@v4 + with: + path: artifacts + pattern: ${{ env.ARTIFACT_PREFIX }}_* + merge-multiple: true + + - name: Download checksum artifact + uses: actions/download-artifact@v4 + with: + name: checksums + path: artifacts + + - name: Publish release assets + uses: softprops/action-gh-release@v2 + with: + tag_name: ${{ needs.prepare.outputs.tag }} + name: ${{ needs.prepare.outputs.tag }} + generate_release_notes: true + files: artifacts/* + + build-push: + name: Build Image ${{ matrix.platform }} + needs: [prepare, build-frontend] + if: github.event_name != 'workflow_dispatch' + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + strategy: + fail-fast: false + matrix: + platform: + - linux/amd64 + - linux/arm/v7 + - linux/arm64 + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Download frontend artifacts + uses: actions/download-artifact@v4 + with: + name: frontend-dist + path: server/router/frontend/dist + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_HUB_USERNAME }} + password: ${{ secrets.DOCKER_HUB_TOKEN }} + + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ github.token }} + + - name: Build and push by digest + id: build + uses: docker/build-push-action@v6 + with: + context: . + file: ./scripts/Dockerfile + platforms: ${{ matrix.platform }} + build-args: | + VERSION=${{ needs.prepare.outputs.version }} + COMMIT=${{ github.sha }} + cache-from: type=gha,scope=release-${{ matrix.platform }} + cache-to: type=gha,mode=max,scope=release-${{ matrix.platform }} + outputs: type=image,name=neosmemo/memos,push-by-digest=true,name-canonical=true,push=true + + - name: Export digest + run: | + mkdir -p /tmp/digests + digest="${{ steps.build.outputs.digest }}" + touch "/tmp/digests/${digest#sha256:}" + + - name: Upload digest + uses: actions/upload-artifact@v4 + with: + name: digests-${{ strategy.job-index }} + path: /tmp/digests/* + if-no-files-found: error + retention-days: 1 + + merge-images: + name: Publish Stable Image Tags + needs: [prepare, build-push] + if: github.event_name != 'workflow_dispatch' + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - name: Download digests + uses: actions/download-artifact@v4 + with: + pattern: digests-* + merge-multiple: true + path: /tmp/digests + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_HUB_USERNAME }} + password: ${{ secrets.DOCKER_HUB_TOKEN }} + + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ github.token }} + + - name: Create manifest list and push + working-directory: /tmp/digests + run: | + version="${{ needs.prepare.outputs.version }}" + major_minor=$(echo "$version" | cut -d. -f1,2) + docker buildx imagetools create \ + -t "neosmemo/memos:${version}" \ + -t "neosmemo/memos:${major_minor}" \ + -t "neosmemo/memos:stable" \ + -t "ghcr.io/usememos/memos:${version}" \ + -t "ghcr.io/usememos/memos:${major_minor}" \ + -t "ghcr.io/usememos/memos:stable" \ + $(printf 'neosmemo/memos@sha256:%s ' *) + + - name: Inspect images + run: | + docker buildx imagetools inspect neosmemo/memos:${{ needs.prepare.outputs.version }} + docker buildx imagetools inspect neosmemo/memos:stable diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 18991fec3..ca75e318e 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -1,24 +1,24 @@ -name: Close Stale - -on: - schedule: - - cron: "0 */8 * * *" # Every 8 hours - -jobs: - close-stale: - name: Close Stale Issues and PRs - runs-on: ubuntu-latest - permissions: - issues: write - pull-requests: write - steps: - - name: Mark and close stale issues and PRs - uses: actions/stale@v10.1.1 - with: - # Issues: mark stale after 14 days of inactivity, close after 3 more days - days-before-issue-stale: 14 - days-before-issue-close: 3 - - # Pull requests: mark stale after 14 days of inactivity, close after 3 more days - days-before-pr-stale: 14 - days-before-pr-close: 3 +name: Close Stale + +on: + schedule: + - cron: "0 */8 * * *" # Every 8 hours + +jobs: + close-stale: + name: Close Stale Issues and PRs + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + steps: + - name: Mark and close stale issues and PRs + uses: actions/stale@v10.1.1 + with: + # Issues: mark stale after 14 days of inactivity, close after 3 more days + days-before-issue-stale: 14 + days-before-issue-close: 3 + + # Pull requests: mark stale after 14 days of inactivity, close after 3 more days + days-before-pr-stale: 14 + days-before-pr-close: 3 diff --git a/.gitignore b/.gitignore index abd9d94fc..f6b5a2396 100644 --- a/.gitignore +++ b/.gitignore @@ -1,29 +1,29 @@ -# temp folder -tmp - -# Frontend asset -web/dist - -# Build artifacts -build/ -bin/ -memos - -# Plan/design documents -docs/plans/ - -.DS_Store - -# Jetbrains -.idea - -# Docker Compose Environment File -.env - -dist - -# VSCode settings -.vscode - -# Git worktrees -.worktrees/ +# temp folder +tmp + +# Frontend asset +web/dist + +# Build artifacts +build/ +bin/ +memos + +# Plan/design documents +docs/plans/ + +.DS_Store + +# Jetbrains +.idea + +# Docker Compose Environment File +.env + +dist + +# VSCode settings +.vscode + +# Git worktrees +.worktrees/ diff --git a/.golangci.yaml b/.golangci.yaml index b97938f08..3c4f6f9f6 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -1,101 +1,101 @@ -version: "2" - -linters: - enable: - - revive - - govet - - staticcheck - - misspell - - gocritic - - sqlclosecheck - - rowserrcheck - - nilerr - - godot - - forbidigo - - mirror - - bodyclose - disable: - - errcheck - settings: - exhaustive: - explicit-exhaustive-switch: false - staticcheck: - checks: - - all - - -ST1000 - - -ST1003 - - -ST1021 - - -QF1003 - revive: - # Default to run all linters so that new rules in the future could automatically be added to the static check. - enable-all-rules: true - rules: - # The following rules are too strict and make coding harder. We do not enable them for now. - - name: file-header - disabled: true - - name: line-length-limit - disabled: true - - name: function-length - disabled: true - - name: max-public-structs - disabled: true - - name: function-result-limit - disabled: true - - name: banned-characters - disabled: true - - name: argument-limit - disabled: true - - name: cognitive-complexity - disabled: true - - name: cyclomatic - disabled: true - - name: confusing-results - disabled: true - - name: add-constant - disabled: true - - name: flag-parameter - disabled: true - - name: nested-structs - disabled: true - - name: import-shadowing - disabled: true - - name: early-return - disabled: true - - name: use-any - disabled: true - - name: exported - disabled: true - - name: unhandled-error - disabled: true - - name: if-return - disabled: true - - name: max-control-nesting - disabled: true - - name: redefines-builtin-id - disabled: true - - name: package-comments - disabled: true - gocritic: - disabled-checks: - - ifElseChain - govet: - settings: - printf: # The name of the analyzer, run `go tool vet help` to see the list of all analyzers - funcs: # Run `go tool vet help printf` to see the full configuration of `printf`. - - common.Errorf - enable-all: true - disable: - - fieldalignment - - shadow - forbidigo: - forbid: - - pattern: 'fmt\.Errorf(# Please use errors\.Wrap\|Wrapf\|Errorf instead)?' - - pattern: 'ioutil\.ReadDir(# Please use os\.ReadDir)?' - -formatters: - enable: - - goimports - settings: - goimports: - local-prefixes: - - github.com/usememos/memos +version: "2" + +linters: + enable: + - revive + - govet + - staticcheck + - misspell + - gocritic + - sqlclosecheck + - rowserrcheck + - nilerr + - godot + - forbidigo + - mirror + - bodyclose + disable: + - errcheck + settings: + exhaustive: + explicit-exhaustive-switch: false + staticcheck: + checks: + - all + - -ST1000 + - -ST1003 + - -ST1021 + - -QF1003 + revive: + # Default to run all linters so that new rules in the future could automatically be added to the static check. + enable-all-rules: true + rules: + # The following rules are too strict and make coding harder. We do not enable them for now. + - name: file-header + disabled: true + - name: line-length-limit + disabled: true + - name: function-length + disabled: true + - name: max-public-structs + disabled: true + - name: function-result-limit + disabled: true + - name: banned-characters + disabled: true + - name: argument-limit + disabled: true + - name: cognitive-complexity + disabled: true + - name: cyclomatic + disabled: true + - name: confusing-results + disabled: true + - name: add-constant + disabled: true + - name: flag-parameter + disabled: true + - name: nested-structs + disabled: true + - name: import-shadowing + disabled: true + - name: early-return + disabled: true + - name: use-any + disabled: true + - name: exported + disabled: true + - name: unhandled-error + disabled: true + - name: if-return + disabled: true + - name: max-control-nesting + disabled: true + - name: redefines-builtin-id + disabled: true + - name: package-comments + disabled: true + gocritic: + disabled-checks: + - ifElseChain + govet: + settings: + printf: # The name of the analyzer, run `go tool vet help` to see the list of all analyzers + funcs: # Run `go tool vet help printf` to see the full configuration of `printf`. + - common.Errorf + enable-all: true + disable: + - fieldalignment + - shadow + forbidigo: + forbid: + - pattern: 'fmt\.Errorf(# Please use errors\.Wrap\|Wrapf\|Errorf instead)?' + - pattern: 'ioutil\.ReadDir(# Please use os\.ReadDir)?' + +formatters: + enable: + - goimports + settings: + goimports: + local-prefixes: + - github.com/usememos/memos diff --git a/AGENTS.md b/AGENTS.md index 892553282..332f27b2e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,102 +1,102 @@ -# AGENTS.md - -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. - -Self-hosted note-taking tool. Go 1.26 backend (Echo v5, Connect RPC + gRPC-Gateway), React 18 + TypeScript 5.9 + Vite 7 frontend, Protocol Buffers API, SQLite/MySQL/PostgreSQL. - -## Commands - -```bash -# Backend -go run ./cmd/memos --port 8081 # Start dev server -go test ./... # Run all tests -go test -v ./store/... # Run store tests (all 3 DB drivers via TestContainers) -go test -v -race ./server/... # Run server tests with race detection -go test -v -run TestFoo ./pkg/... # Run a single test -golangci-lint run # Lint (v2, config: .golangci.yaml) -golangci-lint run --fix # Auto-fix lint issues (includes goimports) - -# Frontend (cd web) -pnpm install # Install deps -pnpm dev # Dev server (:3001, proxies API to :8081) -pnpm lint # Type check + Biome lint -pnpm lint:fix # Auto-fix lint issues -pnpm format # Format code -pnpm build # Production build -pnpm release # Build to server/router/frontend/dist - -# Protocol Buffers (cd proto) -buf generate # Regenerate Go + TypeScript + OpenAPI -buf lint # Lint proto files -buf format -w # Format proto files -``` - -## Architecture - -``` -cmd/memos/main.go # Cobra CLI + Viper config, server init - -server/ -├── server.go # Echo v5 HTTP server, background runners -├── auth/ # JWT access (15min) + refresh (30d) tokens, PAT -├── router/ -│ ├── api/v1/ # 8 gRPC services (Connect + Gateway) -│ │ ├── acl_config.go # Public endpoints whitelist -│ │ ├── sse_hub.go # Server-Sent Events (live updates) -│ │ └── mcp/ # MCP server for AI assistants -│ ├── frontend/ # SPA static file serving -│ ├── fileserver/ # Native HTTP file server (thumbnails, range requests) -│ └── rss/ # RSS feeds -└── runner/ # Background: memo payload processing, S3 presign refresh - -store/ -├── driver.go # Database driver interface -├── store.go # Store wrapper + in-memory cache (TTL 10min, max 1000) -├── migrator.go # Migration logic (LATEST.sql for fresh, incremental for upgrades) -└── db/{sqlite,mysql,postgres}/ # Driver implementations - -proto/ -├── api/v1/ # Service definitions -├── store/ # Internal storage messages -└── gen/ # Generated Go, TypeScript, OpenAPI - -plugin/ # scheduler, cron, email, filter (CEL), webhook, - # markdown (Goldmark), httpgetter, idp (OAuth2), storage/s3 - -web/src/ -├── connect.ts # Connect RPC client + auth interceptor + token refresh -├── auth-state.ts # Token storage (localStorage + BroadcastChannel cross-tab) -├── contexts/ # AuthContext, InstanceContext, ViewContext, MemoFilterContext -├── hooks/ # React Query hooks (useMemoQueries, useUserQueries, etc.) -├── lib/query-client.ts # React Query v5 (staleTime: 30s, gcTime: 5min) -├── router/index.tsx # Route definitions -├── components/ # UI components (Radix UI primitives, MemoEditor, Settings, etc.) -├── themes/ # CSS themes (default, dark, paper) — OKLch color tokens -└── pages/ # Page components -``` - -## Conventions - -### Go -- **Errors:** `errors.Wrap(err, "context")` from `github.com/pkg/errors`. Never `fmt.Errorf` (lint-enforced via forbidigo). -- **gRPC errors:** `status.Errorf(codes.X, "message")` from service methods. -- **Imports:** stdlib, then third-party, then local (`github.com/usememos/memos`). Enforced by goimports (runs as golangci-lint formatter). -- **Comments:** All exported functions must have doc comments (godot enforced). - -### Frontend -- **Imports:** Use `@/` alias for absolute imports. -- **Formatting:** Biome — 140 char lines, double quotes, always semicolons, 2-space indent. -- **State:** Server data via React Query hooks (`hooks/`). Client state via React Context (`contexts/`). -- **Styling:** Tailwind CSS v4 (`@tailwindcss/vite`), `cn()` utility (clsx + tailwind-merge), CVA for variants. - -### Database & Proto -- **DB changes:** Migration files for all 3 drivers + update `LATEST.sql`. -- **Proto changes:** Run `buf generate`. Generated code: `proto/gen/` and `web/src/types/proto/`. -- **Public endpoints:** Add to `server/router/api/v1/acl_config.go`. - -## CI/CD - -- **backend-tests.yml:** Go 1.26.1, golangci-lint v2.4.0, tests parallelized by group (store, server, plugin, other) -- **frontend-tests.yml:** Node 24, pnpm 10, lint + build -- **proto-linter.yml:** buf lint + format check -- **Docker:** Multi-stage (`scripts/Dockerfile`), Alpine 3.21, non-root user, port 5230, multi-arch (amd64/arm64/arm/v7) +# AGENTS.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +Self-hosted note-taking tool. Go 1.26 backend (Echo v5, Connect RPC + gRPC-Gateway), React 18 + TypeScript 5.9 + Vite 7 frontend, Protocol Buffers API, SQLite/MySQL/PostgreSQL. + +## Commands + +```bash +# Backend +go run ./cmd/memos --port 8081 # Start dev server +go test ./... # Run all tests +go test -v ./store/... # Run store tests (all 3 DB drivers via TestContainers) +go test -v -race ./server/... # Run server tests with race detection +go test -v -run TestFoo ./pkg/... # Run a single test +golangci-lint run # Lint (v2, config: .golangci.yaml) +golangci-lint run --fix # Auto-fix lint issues (includes goimports) + +# Frontend (cd web) +pnpm install # Install deps +pnpm dev # Dev server (:3001, proxies API to :8081) +pnpm lint # Type check + Biome lint +pnpm lint:fix # Auto-fix lint issues +pnpm format # Format code +pnpm build # Production build +pnpm release # Build to server/router/frontend/dist + +# Protocol Buffers (cd proto) +buf generate # Regenerate Go + TypeScript + OpenAPI +buf lint # Lint proto files +buf format -w # Format proto files +``` + +## Architecture + +``` +cmd/memos/main.go # Cobra CLI + Viper config, server init + +server/ +├── server.go # Echo v5 HTTP server, background runners +├── auth/ # JWT access (15min) + refresh (30d) tokens, PAT +├── router/ +│ ├── api/v1/ # 8 gRPC services (Connect + Gateway) +│ │ ├── acl_config.go # Public endpoints whitelist +│ │ ├── sse_hub.go # Server-Sent Events (live updates) +│ │ └── mcp/ # MCP server for AI assistants +│ ├── frontend/ # SPA static file serving +│ ├── fileserver/ # Native HTTP file server (thumbnails, range requests) +│ └── rss/ # RSS feeds +└── runner/ # Background: memo payload processing, S3 presign refresh + +store/ +├── driver.go # Database driver interface +├── store.go # Store wrapper + in-memory cache (TTL 10min, max 1000) +├── migrator.go # Migration logic (LATEST.sql for fresh, incremental for upgrades) +└── db/{sqlite,mysql,postgres}/ # Driver implementations + +proto/ +├── api/v1/ # Service definitions +├── store/ # Internal storage messages +└── gen/ # Generated Go, TypeScript, OpenAPI + +plugin/ # scheduler, cron, email, filter (CEL), webhook, + # markdown (Goldmark), httpgetter, idp (OAuth2), storage/s3 + +web/src/ +├── connect.ts # Connect RPC client + auth interceptor + token refresh +├── auth-state.ts # Token storage (localStorage + BroadcastChannel cross-tab) +├── contexts/ # AuthContext, InstanceContext, ViewContext, MemoFilterContext +├── hooks/ # React Query hooks (useMemoQueries, useUserQueries, etc.) +├── lib/query-client.ts # React Query v5 (staleTime: 30s, gcTime: 5min) +├── router/index.tsx # Route definitions +├── components/ # UI components (Radix UI primitives, MemoEditor, Settings, etc.) +├── themes/ # CSS themes (default, dark, paper) — OKLch color tokens +└── pages/ # Page components +``` + +## Conventions + +### Go +- **Errors:** `errors.Wrap(err, "context")` from `github.com/pkg/errors`. Never `fmt.Errorf` (lint-enforced via forbidigo). +- **gRPC errors:** `status.Errorf(codes.X, "message")` from service methods. +- **Imports:** stdlib, then third-party, then local (`github.com/usememos/memos`). Enforced by goimports (runs as golangci-lint formatter). +- **Comments:** All exported functions must have doc comments (godot enforced). + +### Frontend +- **Imports:** Use `@/` alias for absolute imports. +- **Formatting:** Biome — 140 char lines, double quotes, always semicolons, 2-space indent. +- **State:** Server data via React Query hooks (`hooks/`). Client state via React Context (`contexts/`). +- **Styling:** Tailwind CSS v4 (`@tailwindcss/vite`), `cn()` utility (clsx + tailwind-merge), CVA for variants. + +### Database & Proto +- **DB changes:** Migration files for all 3 drivers + update `LATEST.sql`. +- **Proto changes:** Run `buf generate`. Generated code: `proto/gen/` and `web/src/types/proto/`. +- **Public endpoints:** Add to `server/router/api/v1/acl_config.go`. + +## CI/CD + +- **backend-tests.yml:** Go 1.26.1, golangci-lint v2.4.0, tests parallelized by group (store, server, plugin, other) +- **frontend-tests.yml:** Node 24, pnpm 10, lint + build +- **proto-linter.yml:** buf lint + format check +- **Docker:** Multi-stage (`scripts/Dockerfile`), Alpine 3.21, non-root user, port 5230, multi-arch (amd64/arm64/arm/v7) diff --git a/CLAUDE.md b/CLAUDE.md index 4e1576140..e9e0d7505 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,5 +1,5 @@ -# CLAUDE.md - -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. - -See `AGENTS.md` for full architecture, workflows, conventions, and patterns. +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +See `AGENTS.md` for full architecture, workflows, conventions, and patterns. diff --git a/CODEOWNERS b/CODEOWNERS index b75ef1700..c9321e3cb 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1,2 +1,2 @@ -# These owners will be the default owners for everything in the repo. -* @usememos/moderators +# These owners will be the default owners for everything in the repo. +* @usememos/moderators diff --git a/LICENSE b/LICENSE index ad324eef2..bb1ffb327 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,21 @@ -MIT License - -Copyright (c) 2025 Memos - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +MIT License + +Copyright (c) 2025 Memos + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index a71e7f891..730841645 100644 --- a/README.md +++ b/README.md @@ -1,120 +1,120 @@ -
-

- Featured Sponsor: - - Warp - — The AI-powered terminal built for speed and collaboration - -

- - Warp sponsorship - -
- -# Memos - -Memos - -Open-source, self-hosted note-taking tool built for quick capture. Markdown-native, lightweight, and fully yours. - -[![Home](https://img.shields.io/badge/🏠-usememos.com-blue?style=flat-square)](https://usememos.com) -[![Live Demo](https://img.shields.io/badge/✨-Try%20Demo-orange?style=flat-square)](https://demo.usememos.com/) -[![Docs](https://img.shields.io/badge/📚-Documentation-green?style=flat-square)](https://usememos.com/docs) -[![Discord](https://img.shields.io/badge/💬-Discord-5865f2?style=flat-square&logo=discord&logoColor=white)](https://discord.gg/tfPJa4UmAv) -[![Docker Pulls](https://img.shields.io/docker/pulls/neosmemo/memos?style=flat-square&logo=docker)](https://hub.docker.com/r/neosmemo/memos) - -Memos Demo Screenshot - -### 💎 Featured Sponsors - -[**Warp** — The AI-powered terminal built for speed and collaboration](https://go.warp.dev/memos) - - - Warp - The AI-powered terminal built for speed and collaboration - - -

- -[**TestMu AI** - The world’s first full-stack Agentic AI Quality Engineering platform](https://www.testmuai.com/?utm_medium=sponsor&utm_source=memos) - - - TestMu AI - - -

- -[**SSD Nodes** - Affordable VPS hosting for self-hosters](https://ssdnodes.com/?utm_source=memos&utm_medium=sponsor) - - - SSD Nodes - - -## Features - -- **Instant Capture** — Timeline-first UI. Open, write, done — no folders to navigate. -- **Total Data Ownership** — Self-hosted on your infrastructure. Notes stored in Markdown, always portable. Zero telemetry. -- **Radical Simplicity** — Single Go binary, ~20MB Docker image. One command to deploy with SQLite, MySQL, or PostgreSQL. -- **Open & Extensible** — MIT-licensed with full REST and gRPC APIs for integration. - -## Quick Start - -### Docker (Recommended) - -```bash -docker run -d \ - --name memos \ - -p 5230:5230 \ - -v ~/.memos:/var/opt/memos \ - neosmemo/memos:stable -``` - -Open `http://localhost:5230` and start writing! - -### Native Binary - -```bash -curl -fsSL https://raw.githubusercontent.com/usememos/memos/main/scripts/install.sh | sh -``` - -### Try the Live Demo - -Don't want to install yet? Try our [live demo](https://demo.usememos.com/) first! - -### Other Installation Methods - -- **Docker Compose** - Recommended for production deployments -- **Pre-built Binaries** - Available for Linux, macOS, and Windows -- **Kubernetes** - Helm charts and manifests available -- **Build from Source** - For development and customization - -See our [installation guide](https://usememos.com/docs/deploy) for detailed instructions. - -## Contributing - -Contributions are welcome — bug reports, feature suggestions, pull requests, documentation, and translations. - -- [Report bugs](https://github.com/usememos/memos/issues/new?template=bug_report.md) -- [Suggest features](https://github.com/usememos/memos/issues/new?template=feature_request.md) -- [Submit pull requests](https://github.com/usememos/memos/pulls) -- [Improve documentation](https://github.com/usememos/dotcom) -- [Help with translations](https://github.com/usememos/memos/tree/main/web/src/locales) - -## Sponsors - -Love Memos? [Sponsor us on GitHub](https://github.com/sponsors/usememos) to help keep the project growing! - -## Star History - -[![Star History Chart](https://api.star-history.com/svg?repos=usememos/memos&type=Date)](https://star-history.com/#usememos/memos&Date) - -## License - -Memos is open-source software licensed under the [MIT License](LICENSE). See our [Privacy Policy](https://usememos.com/privacy) for details on data handling. - ---- - -**[Website](https://usememos.com)** • **[Documentation](https://usememos.com/docs)** • **[Demo](https://demo.usememos.com/)** • **[Discord](https://discord.gg/tfPJa4UmAv)** • **[X/Twitter](https://x.com/usememos)** - - - Vercel OSS Program - +
+

+ Featured Sponsor: + + Warp + — The AI-powered terminal built for speed and collaboration + +

+ + Warp sponsorship + +
+ +# Memos + +Memos + +Open-source, self-hosted note-taking tool built for quick capture. Markdown-native, lightweight, and fully yours. + +[![Home](https://img.shields.io/badge/🏠-usememos.com-blue?style=flat-square)](https://usememos.com) +[![Live Demo](https://img.shields.io/badge/✨-Try%20Demo-orange?style=flat-square)](https://demo.usememos.com/) +[![Docs](https://img.shields.io/badge/📚-Documentation-green?style=flat-square)](https://usememos.com/docs) +[![Discord](https://img.shields.io/badge/💬-Discord-5865f2?style=flat-square&logo=discord&logoColor=white)](https://discord.gg/tfPJa4UmAv) +[![Docker Pulls](https://img.shields.io/docker/pulls/neosmemo/memos?style=flat-square&logo=docker)](https://hub.docker.com/r/neosmemo/memos) + +Memos Demo Screenshot + +### 💎 Featured Sponsors + +[**Warp** — The AI-powered terminal built for speed and collaboration](https://go.warp.dev/memos) + + + Warp - The AI-powered terminal built for speed and collaboration + + +

+ +[**TestMu AI** - The world’s first full-stack Agentic AI Quality Engineering platform](https://www.testmuai.com/?utm_medium=sponsor&utm_source=memos) + + + TestMu AI + + +

+ +[**SSD Nodes** - Affordable VPS hosting for self-hosters](https://ssdnodes.com/?utm_source=memos&utm_medium=sponsor) + + + SSD Nodes + + +## Features + +- **Instant Capture** — Timeline-first UI. Open, write, done — no folders to navigate. +- **Total Data Ownership** — Self-hosted on your infrastructure. Notes stored in Markdown, always portable. Zero telemetry. +- **Radical Simplicity** — Single Go binary, ~20MB Docker image. One command to deploy with SQLite, MySQL, or PostgreSQL. +- **Open & Extensible** — MIT-licensed with full REST and gRPC APIs for integration. + +## Quick Start + +### Docker (Recommended) + +```bash +docker run -d \ + --name memos \ + -p 5230:5230 \ + -v ~/.memos:/var/opt/memos \ + neosmemo/memos:stable +``` + +Open `http://localhost:5230` and start writing! + +### Native Binary + +```bash +curl -fsSL https://raw.githubusercontent.com/usememos/memos/main/scripts/install.sh | sh +``` + +### Try the Live Demo + +Don't want to install yet? Try our [live demo](https://demo.usememos.com/) first! + +### Other Installation Methods + +- **Docker Compose** - Recommended for production deployments +- **Pre-built Binaries** - Available for Linux, macOS, and Windows +- **Kubernetes** - Helm charts and manifests available +- **Build from Source** - For development and customization + +See our [installation guide](https://usememos.com/docs/deploy) for detailed instructions. + +## Contributing + +Contributions are welcome — bug reports, feature suggestions, pull requests, documentation, and translations. + +- [Report bugs](https://github.com/usememos/memos/issues/new?template=bug_report.md) +- [Suggest features](https://github.com/usememos/memos/issues/new?template=feature_request.md) +- [Submit pull requests](https://github.com/usememos/memos/pulls) +- [Improve documentation](https://github.com/usememos/dotcom) +- [Help with translations](https://github.com/usememos/memos/tree/main/web/src/locales) + +## Sponsors + +Love Memos? [Sponsor us on GitHub](https://github.com/sponsors/usememos) to help keep the project growing! + +## Star History + +[![Star History Chart](https://api.star-history.com/svg?repos=usememos/memos&type=Date)](https://star-history.com/#usememos/memos&Date) + +## License + +Memos is open-source software licensed under the [MIT License](LICENSE). See our [Privacy Policy](https://usememos.com/privacy) for details on data handling. + +--- + +**[Website](https://usememos.com)** • **[Documentation](https://usememos.com/docs)** • **[Demo](https://demo.usememos.com/)** • **[Discord](https://discord.gg/tfPJa4UmAv)** • **[X/Twitter](https://x.com/usememos)** + + + Vercel OSS Program + diff --git a/SECURITY.md b/SECURITY.md index 1818991e9..d7b81bee2 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,46 +1,46 @@ -# Security Policy - -## Project Status - -Memos is currently in beta (v0.x). While we take security seriously, we are not yet ready for formal CVE assignments or coordinated disclosure programs. - -## Reporting Security Issues - -### For All Security Concerns: -Please report via **email only**: dev@usememos.com - -**DO NOT open public GitHub issues for security vulnerabilities.** - -Include in your report: -- Description of the issue -- Steps to reproduce -- Affected versions -- Your assessment of severity - -### What to Expect: -- We will acknowledge your report as soon as we can -- Fixes will be included in regular releases without special security advisories -- No CVEs will be assigned during the beta phase -- Credit will be given in release notes if you wish - -### For Non-Security Bugs: -Use GitHub issues for functionality bugs, feature requests, and general questions. - -## Philosophy - -As a beta project, we prioritize: -1. **Rapid iteration** over lengthy disclosure timelines -2. **Quick patches** over formal security processes -3. **Transparency** about our beta status - -We plan to implement formal vulnerability disclosure and CVE handling after reaching v1.0 stable. - -## Self-Hosting Security - -Since Memos is self-hosted software: -- Keep your instance updated to the latest release -- Don't expose your instance directly to the internet without authentication -- Use reverse proxies (nginx, Caddy) with rate limiting -- Review the deployment documentation for security best practices - -Thank you for helping improve Memos! +# Security Policy + +## Project Status + +Memos is currently in beta (v0.x). While we take security seriously, we are not yet ready for formal CVE assignments or coordinated disclosure programs. + +## Reporting Security Issues + +### For All Security Concerns: +Please report via **email only**: dev@usememos.com + +**DO NOT open public GitHub issues for security vulnerabilities.** + +Include in your report: +- Description of the issue +- Steps to reproduce +- Affected versions +- Your assessment of severity + +### What to Expect: +- We will acknowledge your report as soon as we can +- Fixes will be included in regular releases without special security advisories +- No CVEs will be assigned during the beta phase +- Credit will be given in release notes if you wish + +### For Non-Security Bugs: +Use GitHub issues for functionality bugs, feature requests, and general questions. + +## Philosophy + +As a beta project, we prioritize: +1. **Rapid iteration** over lengthy disclosure timelines +2. **Quick patches** over formal security processes +3. **Transparency** about our beta status + +We plan to implement formal vulnerability disclosure and CVE handling after reaching v1.0 stable. + +## Self-Hosting Security + +Since Memos is self-hosted software: +- Keep your instance updated to the latest release +- Don't expose your instance directly to the internet without authentication +- Use reverse proxies (nginx, Caddy) with rate limiting +- Review the deployment documentation for security best practices + +Thank you for helping improve Memos! diff --git a/cmd/memos/main.go b/cmd/memos/main.go index bf0a67373..48ea74610 100644 --- a/cmd/memos/main.go +++ b/cmd/memos/main.go @@ -1,191 +1,191 @@ -package main - -import ( - "context" - "fmt" - "log/slog" - "net/http" - "os" - "os/signal" - "strings" - "syscall" - - "github.com/spf13/cobra" - "github.com/spf13/viper" - - "github.com/usememos/memos/internal/profile" - "github.com/usememos/memos/internal/version" - "github.com/usememos/memos/plugin/webhook" - "github.com/usememos/memos/server" - "github.com/usememos/memos/store" - "github.com/usememos/memos/store/db" -) - -var ( - rootCmd = &cobra.Command{ - Use: "memos", - Short: `An open source, lightweight note-taking service. Easily capture and share your great thoughts.`, - Run: func(_ *cobra.Command, _ []string) { - instanceProfile := &profile.Profile{ - Demo: viper.GetBool("demo"), - Addr: viper.GetString("addr"), - Port: viper.GetInt("port"), - UNIXSock: viper.GetString("unix-sock"), - Data: viper.GetString("data"), - Driver: viper.GetString("driver"), - DSN: viper.GetString("dsn"), - InstanceURL: viper.GetString("instance-url"), - } - instanceProfile.Version = version.GetCurrentVersion() - webhook.AllowPrivateIPs = viper.GetBool("allow-private-webhooks") - - if err := instanceProfile.Validate(); err != nil { - slog.Error("failed to validate profile", "error", err) - return - } - - ctx, cancel := context.WithCancel(context.Background()) - dbDriver, err := db.NewDBDriver(instanceProfile) - if err != nil { - cancel() - slog.Error("failed to create db driver", "error", err) - return - } - - storeInstance := store.New(dbDriver, instanceProfile) - if err := storeInstance.Migrate(ctx); err != nil { - cancel() - slog.Error("failed to migrate", "error", err) - return - } - - s, err := server.NewServer(ctx, instanceProfile, storeInstance) - if err != nil { - cancel() - slog.Error("failed to create server", "error", err) - return - } - - c := make(chan os.Signal, 1) - // Trigger graceful shutdown on SIGINT or SIGTERM. - // The default signal sent by the `kill` command is SIGTERM, - // which is taken as the graceful shutdown signal for many systems, eg., Kubernetes, Gunicorn. - signal.Notify(c, os.Interrupt, syscall.SIGTERM) - - if err := s.Start(ctx); err != nil { - if err != http.ErrServerClosed { - slog.Error("failed to start server", "error", err) - cancel() - return - } - } - - printGreetings(instanceProfile) - - go func() { - <-c - s.Shutdown(ctx) - cancel() - }() - - // Wait for CTRL-C. - <-ctx.Done() - }, - } - versionCmd = &cobra.Command{ - Use: "version", - Short: "Print the current Memos version", - Run: func(_ *cobra.Command, _ []string) { - fmt.Println(version.GetCurrentVersion()) - }, - } -) - -func init() { - viper.SetDefault("demo", false) - viper.SetDefault("driver", "sqlite") - viper.SetDefault("port", 8081) - - rootCmd.PersistentFlags().Bool("demo", false, "enable demo mode") - rootCmd.PersistentFlags().String("addr", "", "address of server") - rootCmd.PersistentFlags().Int("port", 8081, "port of server") - rootCmd.PersistentFlags().String("unix-sock", "", "path to the unix socket, overrides --addr and --port") - rootCmd.PersistentFlags().String("data", "", "data directory") - rootCmd.PersistentFlags().String("driver", "sqlite", "database driver") - rootCmd.PersistentFlags().String("dsn", "", "database source name(aka. DSN)") - rootCmd.PersistentFlags().String("instance-url", "", "the url of your memos instance") - rootCmd.PersistentFlags().Bool("allow-private-webhooks", false, "allow webhook URLs to resolve to private/reserved IP addresses") - - if err := viper.BindPFlag("demo", rootCmd.PersistentFlags().Lookup("demo")); err != nil { - panic(err) - } - if err := viper.BindPFlag("addr", rootCmd.PersistentFlags().Lookup("addr")); err != nil { - panic(err) - } - if err := viper.BindPFlag("port", rootCmd.PersistentFlags().Lookup("port")); err != nil { - panic(err) - } - if err := viper.BindPFlag("unix-sock", rootCmd.PersistentFlags().Lookup("unix-sock")); err != nil { - panic(err) - } - if err := viper.BindPFlag("data", rootCmd.PersistentFlags().Lookup("data")); err != nil { - panic(err) - } - if err := viper.BindPFlag("driver", rootCmd.PersistentFlags().Lookup("driver")); err != nil { - panic(err) - } - if err := viper.BindPFlag("dsn", rootCmd.PersistentFlags().Lookup("dsn")); err != nil { - panic(err) - } - if err := viper.BindPFlag("instance-url", rootCmd.PersistentFlags().Lookup("instance-url")); err != nil { - panic(err) - } - if err := viper.BindPFlag("allow-private-webhooks", rootCmd.PersistentFlags().Lookup("allow-private-webhooks")); err != nil { - panic(err) - } - - viper.SetEnvPrefix("memos") - viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_")) - viper.AutomaticEnv() - - rootCmd.AddCommand(versionCmd) -} - -func printGreetings(profile *profile.Profile) { - fmt.Printf("Memos %s started successfully!\n", profile.Version) - - if profile.Demo { - fmt.Fprint(os.Stderr, "Development mode is enabled\n") - if profile.DSN != "" { - fmt.Fprintf(os.Stderr, "Database: %s\n", profile.DSN) - } - } - - // Server information - fmt.Printf("Data directory: %s\n", profile.Data) - fmt.Printf("Database driver: %s\n", profile.Driver) - - // Connection information - if len(profile.UNIXSock) == 0 { - if len(profile.Addr) == 0 { - fmt.Printf("Server running on port %d\n", profile.Port) - fmt.Printf("Access your memos at: http://localhost:%d\n", profile.Port) - } else { - fmt.Printf("Server running on %s:%d\n", profile.Addr, profile.Port) - fmt.Printf("Access your memos at: http://%s:%d\n", profile.Addr, profile.Port) - } - } else { - fmt.Printf("Server running on unix socket: %s\n", profile.UNIXSock) - } - - fmt.Println() - fmt.Printf("Documentation: %s\n", "https://usememos.com") - fmt.Printf("Source code: %s\n", "https://github.com/usememos/memos") - fmt.Println("\nHappy note-taking!") -} - -func main() { - if err := rootCmd.Execute(); err != nil { - os.Exit(1) - } -} +package main + +import ( + "context" + "fmt" + "log/slog" + "net/http" + "os" + "os/signal" + "strings" + "syscall" + + "github.com/spf13/cobra" + "github.com/spf13/viper" + + "github.com/usememos/memos/internal/profile" + "github.com/usememos/memos/internal/version" + "github.com/usememos/memos/plugin/webhook" + "github.com/usememos/memos/server" + "github.com/usememos/memos/store" + "github.com/usememos/memos/store/db" +) + +var ( + rootCmd = &cobra.Command{ + Use: "memos", + Short: `An open source, lightweight note-taking service. Easily capture and share your great thoughts.`, + Run: func(_ *cobra.Command, _ []string) { + instanceProfile := &profile.Profile{ + Demo: viper.GetBool("demo"), + Addr: viper.GetString("addr"), + Port: viper.GetInt("port"), + UNIXSock: viper.GetString("unix-sock"), + Data: viper.GetString("data"), + Driver: viper.GetString("driver"), + DSN: viper.GetString("dsn"), + InstanceURL: viper.GetString("instance-url"), + } + instanceProfile.Version = version.GetCurrentVersion() + webhook.AllowPrivateIPs = viper.GetBool("allow-private-webhooks") + + if err := instanceProfile.Validate(); err != nil { + slog.Error("failed to validate profile", "error", err) + return + } + + ctx, cancel := context.WithCancel(context.Background()) + dbDriver, err := db.NewDBDriver(instanceProfile) + if err != nil { + cancel() + slog.Error("failed to create db driver", "error", err) + return + } + + storeInstance := store.New(dbDriver, instanceProfile) + if err := storeInstance.Migrate(ctx); err != nil { + cancel() + slog.Error("failed to migrate", "error", err) + return + } + + s, err := server.NewServer(ctx, instanceProfile, storeInstance) + if err != nil { + cancel() + slog.Error("failed to create server", "error", err) + return + } + + c := make(chan os.Signal, 1) + // Trigger graceful shutdown on SIGINT or SIGTERM. + // The default signal sent by the `kill` command is SIGTERM, + // which is taken as the graceful shutdown signal for many systems, eg., Kubernetes, Gunicorn. + signal.Notify(c, os.Interrupt, syscall.SIGTERM) + + if err := s.Start(ctx); err != nil { + if err != http.ErrServerClosed { + slog.Error("failed to start server", "error", err) + cancel() + return + } + } + + printGreetings(instanceProfile) + + go func() { + <-c + s.Shutdown(ctx) + cancel() + }() + + // Wait for CTRL-C. + <-ctx.Done() + }, + } + versionCmd = &cobra.Command{ + Use: "version", + Short: "Print the current Memos version", + Run: func(_ *cobra.Command, _ []string) { + fmt.Println(version.GetCurrentVersion()) + }, + } +) + +func init() { + viper.SetDefault("demo", false) + viper.SetDefault("driver", "sqlite") + viper.SetDefault("port", 8081) + + rootCmd.PersistentFlags().Bool("demo", false, "enable demo mode") + rootCmd.PersistentFlags().String("addr", "", "address of server") + rootCmd.PersistentFlags().Int("port", 8081, "port of server") + rootCmd.PersistentFlags().String("unix-sock", "", "path to the unix socket, overrides --addr and --port") + rootCmd.PersistentFlags().String("data", "", "data directory") + rootCmd.PersistentFlags().String("driver", "sqlite", "database driver") + rootCmd.PersistentFlags().String("dsn", "", "database source name(aka. DSN)") + rootCmd.PersistentFlags().String("instance-url", "", "the url of your memos instance") + rootCmd.PersistentFlags().Bool("allow-private-webhooks", false, "allow webhook URLs to resolve to private/reserved IP addresses") + + if err := viper.BindPFlag("demo", rootCmd.PersistentFlags().Lookup("demo")); err != nil { + panic(err) + } + if err := viper.BindPFlag("addr", rootCmd.PersistentFlags().Lookup("addr")); err != nil { + panic(err) + } + if err := viper.BindPFlag("port", rootCmd.PersistentFlags().Lookup("port")); err != nil { + panic(err) + } + if err := viper.BindPFlag("unix-sock", rootCmd.PersistentFlags().Lookup("unix-sock")); err != nil { + panic(err) + } + if err := viper.BindPFlag("data", rootCmd.PersistentFlags().Lookup("data")); err != nil { + panic(err) + } + if err := viper.BindPFlag("driver", rootCmd.PersistentFlags().Lookup("driver")); err != nil { + panic(err) + } + if err := viper.BindPFlag("dsn", rootCmd.PersistentFlags().Lookup("dsn")); err != nil { + panic(err) + } + if err := viper.BindPFlag("instance-url", rootCmd.PersistentFlags().Lookup("instance-url")); err != nil { + panic(err) + } + if err := viper.BindPFlag("allow-private-webhooks", rootCmd.PersistentFlags().Lookup("allow-private-webhooks")); err != nil { + panic(err) + } + + viper.SetEnvPrefix("memos") + viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_")) + viper.AutomaticEnv() + + rootCmd.AddCommand(versionCmd) +} + +func printGreetings(profile *profile.Profile) { + fmt.Printf("Memos %s started successfully!\n", profile.Version) + + if profile.Demo { + fmt.Fprint(os.Stderr, "Development mode is enabled\n") + if profile.DSN != "" { + fmt.Fprintf(os.Stderr, "Database: %s\n", profile.DSN) + } + } + + // Server information + fmt.Printf("Data directory: %s\n", profile.Data) + fmt.Printf("Database driver: %s\n", profile.Driver) + + // Connection information + if len(profile.UNIXSock) == 0 { + if len(profile.Addr) == 0 { + fmt.Printf("Server running on port %d\n", profile.Port) + fmt.Printf("Access your memos at: http://localhost:%d\n", profile.Port) + } else { + fmt.Printf("Server running on %s:%d\n", profile.Addr, profile.Port) + fmt.Printf("Access your memos at: http://%s:%d\n", profile.Addr, profile.Port) + } + } else { + fmt.Printf("Server running on unix socket: %s\n", profile.UNIXSock) + } + + fmt.Println() + fmt.Printf("Documentation: %s\n", "https://usememos.com") + fmt.Printf("Source code: %s\n", "https://github.com/usememos/memos") + fmt.Println("\nHappy note-taking!") +} + +func main() { + if err := rootCmd.Execute(); err != nil { + os.Exit(1) + } +} diff --git a/go.mod b/go.mod index 64ccbfc03..938fa9f33 100644 --- a/go.mod +++ b/go.mod @@ -1,141 +1,141 @@ -module github.com/usememos/memos - -go 1.26.1 - -require ( - connectrpc.com/connect v1.19.1 - github.com/aws/aws-sdk-go-v2 v1.41.4 - github.com/aws/aws-sdk-go-v2/config v1.32.12 - github.com/aws/aws-sdk-go-v2/credentials v1.19.12 - github.com/aws/aws-sdk-go-v2/service/s3 v1.97.1 - github.com/docker/docker v28.5.2+incompatible - github.com/go-sql-driver/mysql v1.9.3 - github.com/google/cel-go v0.27.0 - github.com/google/uuid v1.6.0 - github.com/gorilla/feeds v1.2.0 - github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 - github.com/joho/godotenv v1.5.1 - github.com/labstack/echo/v5 v5.0.4 - github.com/lib/pq v1.11.2 - github.com/lithammer/shortuuid/v4 v4.2.0 - github.com/mark3labs/mcp-go v0.45.0 - github.com/pkg/errors v0.9.1 - github.com/spf13/cobra v1.10.2 - github.com/spf13/viper v1.21.0 - github.com/stretchr/testify v1.11.1 - github.com/testcontainers/testcontainers-go v0.41.0 - github.com/testcontainers/testcontainers-go/modules/mysql v0.41.0 - github.com/testcontainers/testcontainers-go/modules/postgres v0.41.0 - github.com/yuin/goldmark v1.7.16 - golang.org/x/crypto v0.49.0 - golang.org/x/mod v0.34.0 - golang.org/x/net v0.52.0 - golang.org/x/oauth2 v0.36.0 - golang.org/x/sync v0.20.0 - google.golang.org/genproto v0.0.0-20260316180232-0b37fe3546d5 - google.golang.org/genproto/googleapis/api v0.0.0-20260316172706-e463d84ca32d - google.golang.org/grpc v1.79.2 - modernc.org/sqlite v1.46.1 -) - -require ( - cel.dev/expr v0.25.1 // indirect - dario.cat/mergo v1.0.2 // indirect - filippo.io/edwards25519 v1.1.0 // indirect - github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect - github.com/Microsoft/go-winio v0.6.2 // indirect - github.com/antlr4-go/antlr/v4 v4.13.1 // indirect - github.com/aws/aws-sdk-go-v2/service/signin v1.0.8 // indirect - github.com/bahlo/generic-list-go v0.2.0 // indirect - github.com/buger/jsonparser v1.1.1 // indirect - github.com/cenkalti/backoff/v4 v4.3.0 // indirect - github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/containerd/errdefs v1.0.0 // indirect - github.com/containerd/errdefs/pkg v0.3.0 // indirect - github.com/containerd/log v0.1.0 // indirect - github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.2 // indirect - github.com/distribution/reference v0.6.0 // indirect - github.com/docker/go-connections v0.6.0 // indirect - github.com/docker/go-units v0.5.0 // indirect - github.com/dustin/go-humanize v1.0.1 // indirect - github.com/ebitengine/purego v0.10.0 // indirect - github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/fsnotify/fsnotify v1.9.0 // indirect - github.com/go-logr/logr v1.4.3 // indirect - github.com/go-logr/stdr v1.2.2 // indirect - github.com/go-ole/go-ole v1.2.6 // indirect - github.com/go-viper/mapstructure/v2 v2.4.0 // indirect - github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/invopop/jsonschema v0.13.0 // indirect - github.com/klauspost/compress v1.18.2 // indirect - github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect - github.com/magiconair/properties v1.8.10 // indirect - github.com/mailru/easyjson v0.7.7 // indirect - github.com/moby/docker-image-spec v1.3.1 // indirect - github.com/moby/go-archive v0.2.0 // indirect - github.com/moby/patternmatcher v0.6.0 // indirect - github.com/moby/sys/sequential v0.6.0 // indirect - github.com/moby/sys/user v0.4.0 // indirect - github.com/moby/sys/userns v0.1.0 // indirect - github.com/moby/term v0.5.2 // indirect - github.com/morikuni/aec v1.0.0 // indirect - github.com/ncruces/go-strftime v1.0.0 // indirect - github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.1.1 // indirect - github.com/pelletier/go-toml/v2 v2.2.4 // indirect - github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect - github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect - github.com/sagikazarmark/locafero v0.11.0 // indirect - github.com/shirou/gopsutil/v4 v4.26.2 // indirect - github.com/sirupsen/logrus v1.9.3 // indirect - github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect - github.com/spf13/afero v1.15.0 // indirect - github.com/spf13/cast v1.10.0 // indirect - github.com/spf13/pflag v1.0.10 // indirect - github.com/subosito/gotenv v1.6.0 // indirect - github.com/tklauser/go-sysconf v0.3.16 // indirect - github.com/tklauser/numcpus v0.11.0 // indirect - github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect - github.com/yosida95/uritemplate/v3 v3.0.2 // indirect - github.com/yusufpapurcu/wmi v1.2.4 // indirect - go.opentelemetry.io/auto/sdk v1.2.1 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect - go.opentelemetry.io/otel v1.41.0 // indirect - go.opentelemetry.io/otel/metric v1.41.0 // indirect - go.opentelemetry.io/otel/trace v1.41.0 // indirect - go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 // indirect - golang.org/x/image v0.30.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260311181403-84a4fc48630c // indirect - modernc.org/libc v1.67.6 // indirect - modernc.org/mathutil v1.7.1 // indirect - modernc.org/memory v1.11.0 // indirect -) - -require ( - github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.7 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.20 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.20 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.20 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6 // indirect - github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.21 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.12 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.20 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.20 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.30.13 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.17 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.41.9 // indirect - github.com/aws/smithy-go v1.24.2 // indirect - github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/disintegration/imaging v1.6.2 - github.com/golang-jwt/jwt/v5 v5.3.1 - github.com/mattn/go-isatty v0.0.20 // indirect - github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - golang.org/x/sys v0.42.0 // indirect - golang.org/x/text v0.35.0 - golang.org/x/time v0.14.0 // indirect - google.golang.org/protobuf v1.36.11 - gopkg.in/yaml.v3 v3.0.1 // indirect -) +module github.com/usememos/memos + +go 1.26.1 + +require ( + connectrpc.com/connect v1.19.1 + github.com/aws/aws-sdk-go-v2 v1.41.4 + github.com/aws/aws-sdk-go-v2/config v1.32.12 + github.com/aws/aws-sdk-go-v2/credentials v1.19.12 + github.com/aws/aws-sdk-go-v2/service/s3 v1.97.1 + github.com/docker/docker v28.5.2+incompatible + github.com/go-sql-driver/mysql v1.9.3 + github.com/google/cel-go v0.27.0 + github.com/google/uuid v1.6.0 + github.com/gorilla/feeds v1.2.0 + github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 + github.com/joho/godotenv v1.5.1 + github.com/labstack/echo/v5 v5.0.4 + github.com/lib/pq v1.11.2 + github.com/lithammer/shortuuid/v4 v4.2.0 + github.com/mark3labs/mcp-go v0.45.0 + github.com/pkg/errors v0.9.1 + github.com/spf13/cobra v1.10.2 + github.com/spf13/viper v1.21.0 + github.com/stretchr/testify v1.11.1 + github.com/testcontainers/testcontainers-go v0.41.0 + github.com/testcontainers/testcontainers-go/modules/mysql v0.41.0 + github.com/testcontainers/testcontainers-go/modules/postgres v0.41.0 + github.com/yuin/goldmark v1.7.16 + golang.org/x/crypto v0.49.0 + golang.org/x/mod v0.34.0 + golang.org/x/net v0.52.0 + golang.org/x/oauth2 v0.36.0 + golang.org/x/sync v0.20.0 + google.golang.org/genproto v0.0.0-20260316180232-0b37fe3546d5 + google.golang.org/genproto/googleapis/api v0.0.0-20260316172706-e463d84ca32d + google.golang.org/grpc v1.79.2 + modernc.org/sqlite v1.46.1 +) + +require ( + cel.dev/expr v0.25.1 // indirect + dario.cat/mergo v1.0.2 // indirect + filippo.io/edwards25519 v1.1.0 // indirect + github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/antlr4-go/antlr/v4 v4.13.1 // indirect + github.com/aws/aws-sdk-go-v2/service/signin v1.0.8 // indirect + github.com/bahlo/generic-list-go v0.2.0 // indirect + github.com/buger/jsonparser v1.1.1 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/containerd/errdefs v1.0.0 // indirect + github.com/containerd/errdefs/pkg v0.3.0 // indirect + github.com/containerd/log v0.1.0 // indirect + github.com/containerd/platforms v0.2.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect + github.com/distribution/reference v0.6.0 // indirect + github.com/docker/go-connections v0.6.0 // indirect + github.com/docker/go-units v0.5.0 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/ebitengine/purego v0.10.0 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/fsnotify/fsnotify v1.9.0 // indirect + github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-viper/mapstructure/v2 v2.4.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/invopop/jsonschema v0.13.0 // indirect + github.com/klauspost/compress v1.18.2 // indirect + github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect + github.com/magiconair/properties v1.8.10 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/moby/docker-image-spec v1.3.1 // indirect + github.com/moby/go-archive v0.2.0 // indirect + github.com/moby/patternmatcher v0.6.0 // indirect + github.com/moby/sys/sequential v0.6.0 // indirect + github.com/moby/sys/user v0.4.0 // indirect + github.com/moby/sys/userns v0.1.0 // indirect + github.com/moby/term v0.5.2 // indirect + github.com/morikuni/aec v1.0.0 // indirect + github.com/ncruces/go-strftime v1.0.0 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.1.1 // indirect + github.com/pelletier/go-toml/v2 v2.2.4 // indirect + github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect + github.com/sagikazarmark/locafero v0.11.0 // indirect + github.com/shirou/gopsutil/v4 v4.26.2 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect + github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect + github.com/spf13/afero v1.15.0 // indirect + github.com/spf13/cast v1.10.0 // indirect + github.com/spf13/pflag v1.0.10 // indirect + github.com/subosito/gotenv v1.6.0 // indirect + github.com/tklauser/go-sysconf v0.3.16 // indirect + github.com/tklauser/numcpus v0.11.0 // indirect + github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect + github.com/yosida95/uritemplate/v3 v3.0.2 // indirect + github.com/yusufpapurcu/wmi v1.2.4 // indirect + go.opentelemetry.io/auto/sdk v1.2.1 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect + go.opentelemetry.io/otel v1.41.0 // indirect + go.opentelemetry.io/otel/metric v1.41.0 // indirect + go.opentelemetry.io/otel/trace v1.41.0 // indirect + go.yaml.in/yaml/v3 v3.0.4 // indirect + golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 // indirect + golang.org/x/image v0.30.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260311181403-84a4fc48630c // indirect + modernc.org/libc v1.67.6 // indirect + modernc.org/mathutil v1.7.1 // indirect + modernc.org/memory v1.11.0 // indirect +) + +require ( + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.7 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.20 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.20 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.20 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.21 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.12 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.20 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.20 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.30.13 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.17 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.41.9 // indirect + github.com/aws/smithy-go v1.24.2 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/disintegration/imaging v1.6.2 + github.com/golang-jwt/jwt/v5 v5.3.1 + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + golang.org/x/sys v0.42.0 // indirect + golang.org/x/text v0.35.0 + golang.org/x/time v0.14.0 // indirect + google.golang.org/protobuf v1.36.11 + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/go.sum b/go.sum index 1ed2415ca..e12a14dda 100644 --- a/go.sum +++ b/go.sum @@ -1,355 +1,355 @@ -cel.dev/expr v0.25.1 h1:1KrZg61W6TWSxuNZ37Xy49ps13NUovb66QLprthtwi4= -cel.dev/expr v0.25.1/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4= -connectrpc.com/connect v1.19.1 h1:R5M57z05+90EfEvCY1b7hBxDVOUl45PrtXtAV2fOC14= -connectrpc.com/connect v1.19.1/go.mod h1:tN20fjdGlewnSFeZxLKb0xwIZ6ozc3OQs2hTXy4du9w= -dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= -dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= -filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= -filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= -github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk= -github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= -github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg= -github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= -github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= -github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= -github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ= -github.com/antlr4-go/antlr/v4 v4.13.1/go.mod h1:GKmUxMtwp6ZgGwZSva4eWPC5mS6vUAmOABFgjdkM7Nw= -github.com/aws/aws-sdk-go-v2 v1.41.4 h1:10f50G7WyU02T56ox1wWXq+zTX9I1zxG46HYuG1hH/k= -github.com/aws/aws-sdk-go-v2 v1.41.4/go.mod h1:mwsPRE8ceUUpiTgF7QmQIJ7lgsKUPQOUl3o72QBrE1o= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.7 h1:3kGOqnh1pPeddVa/E37XNTaWJ8W6vrbYV9lJEkCnhuY= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.7/go.mod h1:lyw7GFp3qENLh7kwzf7iMzAxDn+NzjXEAGjKS2UOKqI= -github.com/aws/aws-sdk-go-v2/config v1.32.12 h1:O3csC7HUGn2895eNrLytOJQdoL2xyJy0iYXhoZ1OmP0= -github.com/aws/aws-sdk-go-v2/config v1.32.12/go.mod h1:96zTvoOFR4FURjI+/5wY1vc1ABceROO4lWgWJuxgy0g= -github.com/aws/aws-sdk-go-v2/credentials v1.19.12 h1:oqtA6v+y5fZg//tcTWahyN9PEn5eDU/Wpvc2+kJ4aY8= -github.com/aws/aws-sdk-go-v2/credentials v1.19.12/go.mod h1:U3R1RtSHx6NB0DvEQFGyf/0sbrpJrluENHdPy1j/3TE= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.20 h1:zOgq3uezl5nznfoK3ODuqbhVg1JzAGDUhXOsU0IDCAo= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.20/go.mod h1:z/MVwUARehy6GAg/yQ1GO2IMl0k++cu1ohP9zo887wE= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.20 h1:CNXO7mvgThFGqOFgbNAP2nol2qAWBOGfqR/7tQlvLmc= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.20/go.mod h1:oydPDJKcfMhgfcgBUZaG+toBbwy8yPWubJXBVERtI4o= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.20 h1:tN6W/hg+pkM+tf9XDkWUbDEjGLb+raoBMFsTodcoYKw= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.20/go.mod h1:YJ898MhD067hSHA6xYCx5ts/jEd8BSOLtQDL3iZsvbc= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6 h1:qYQ4pzQ2Oz6WpQ8T3HvGHnZydA72MnLuFK9tJwmrbHw= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6/go.mod h1:O3h0IK87yXci+kg6flUKzJnWeziQUKciKrLjcatSNcY= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.21 h1:SwGMTMLIlvDNyhMteQ6r8IJSBPlRdXX5d4idhIGbkXA= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.21/go.mod h1:UUxgWxofmOdAMuqEsSppbDtGKLfR04HGsD0HXzvhI1k= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7 h1:5EniKhLZe4xzL7a+fU3C2tfUN4nWIqlLesfrjkuPFTY= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7/go.mod h1:x0nZssQ3qZSnIcePWLvcoFisRXJzcTVvYpAAdYX8+GI= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.12 h1:qtJZ70afD3ISKWnoX3xB0J2otEqu3LqicRcDBqsj0hQ= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.12/go.mod h1:v2pNpJbRNl4vEUWEh5ytQok0zACAKfdmKS51Hotc3pQ= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.20 h1:2HvVAIq+YqgGotK6EkMf+KIEqTISmTYh5zLpYyeTo1Y= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.20/go.mod h1:V4X406Y666khGa8ghKmphma/7C0DAtEQYhkq9z4vpbk= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.20 h1:siU1A6xjUZ2N8zjTHSXFhB9L/2OY8Dqs0xXiLjF30jA= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.20/go.mod h1:4TLZCmVJDM3FOu5P5TJP0zOlu9zWgDWU7aUxWbr+rcw= -github.com/aws/aws-sdk-go-v2/service/s3 v1.97.1 h1:csi9NLpFZXb9fxY7rS1xVzgPRGMt7MSNWeQ6eo247kE= -github.com/aws/aws-sdk-go-v2/service/s3 v1.97.1/go.mod h1:qXVal5H0ChqXP63t6jze5LmFalc7+ZE7wOdLtZ0LCP0= -github.com/aws/aws-sdk-go-v2/service/signin v1.0.8 h1:0GFOLzEbOyZABS3PhYfBIx2rNBACYcKty+XGkTgw1ow= -github.com/aws/aws-sdk-go-v2/service/signin v1.0.8/go.mod h1:LXypKvk85AROkKhOG6/YEcHFPoX+prKTowKnVdcaIxE= -github.com/aws/aws-sdk-go-v2/service/sso v1.30.13 h1:kiIDLZ005EcKomYYITtfsjn7dtOwHDOFy7IbPXKek2o= -github.com/aws/aws-sdk-go-v2/service/sso v1.30.13/go.mod h1:2h/xGEowcW/g38g06g3KpRWDlT+OTfxxI0o1KqayAB8= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.17 h1:jzKAXIlhZhJbnYwHbvUQZEB8KfgAEuG0dc08Bkda7NU= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.17/go.mod h1:Al9fFsXjv4KfbzQHGe6V4NZSZQXecFcvaIF4e70FoRA= -github.com/aws/aws-sdk-go-v2/service/sts v1.41.9 h1:Cng+OOwCHmFljXIxpEVXAGMnBia8MSU6Ch5i9PgBkcU= -github.com/aws/aws-sdk-go-v2/service/sts v1.41.9/go.mod h1:LrlIndBDdjA/EeXeyNBle+gyCwTlizzW5ycgWnvIxkk= -github.com/aws/smithy-go v1.24.2 h1:FzA3bu/nt/vDvmnkg+R8Xl46gmzEDam6mZ1hzmwXFng= -github.com/aws/smithy-go v1.24.2/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc= -github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk= -github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg= -github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= -github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= -github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= -github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= -github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= -github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= -github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= -github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= -github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= -github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE= -github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk= -github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= -github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= -github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= -github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= -github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= -github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= -github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= -github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c= -github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4= -github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= -github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v28.5.2+incompatible h1:DBX0Y0zAjZbSrm1uzOkdr1onVghKaftjlSWt4AFexzM= -github.com/docker/docker v28.5.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94= -github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE= -github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= -github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= -github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= -github.com/ebitengine/purego v0.10.0 h1:QIw4xfpWT6GWTzaW5XEKy3HXoqrJGx1ijYHzTF0/ISU= -github.com/ebitengine/purego v0.10.0/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= -github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= -github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= -github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= -github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= -github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= -github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= -github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo= -github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU= -github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= -github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= -github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63YCY= -github.com/golang-jwt/jwt/v5 v5.3.1/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= -github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= -github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/cel-go v0.27.0 h1:e7ih85+4qVrBuqQWTW4FKSqZYokVuc3HnhH5keboFTo= -github.com/google/cel-go v0.27.0/go.mod h1:tTJ11FWqnhw5KKpnWpvW9CJC3Y9GK4EIS0WXnBbebzw= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= -github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs= -github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gorilla/feeds v1.2.0 h1:O6pBiXJ5JHhPvqy53NsjKOThq+dNFm8+DFrxBEdzSCc= -github.com/gorilla/feeds v1.2.0/go.mod h1:WMib8uJP3BbY+X8Szd1rA5Pzhdfh+HCCAYT2z7Fza6Y= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 h1:HWRh5R2+9EifMyIHV7ZV+MIZqgz+PMpZ14Jynv3O2Zs= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0/go.mod h1:JfhWUomR1baixubs02l85lZYYOm7LV6om4ceouMv45c= -github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= -github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= -github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= -github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/invopop/jsonschema v0.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E= -github.com/invopop/jsonschema v0.13.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0= -github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= -github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= -github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= -github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= -github.com/jackc/pgx/v5 v5.5.4 h1:Xp2aQS8uXButQdnCMWNmvx6UysWQQC+u1EoizjguY+8= -github.com/jackc/pgx/v5 v5.5.4/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A= -github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk= -github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= -github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= -github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= -github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/klauspost/compress v1.18.2 h1:iiPHWW0YrcFgpBYhsA6D1+fqHssJscY/Tm/y2Uqnapk= -github.com/klauspost/compress v1.18.2/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/labstack/echo/v5 v5.0.4 h1:ll3I/O8BifjMztj9dD1vx/peZQv8cR2CTUdQK6QxGGc= -github.com/labstack/echo/v5 v5.0.4/go.mod h1:SyvlSdObGjRXeQfCCXW/sybkZdOOQZBmpKF0bvALaeo= -github.com/lib/pq v1.11.2 h1:x6gxUeu39V0BHZiugWe8LXZYZ+Utk7hSJGThs8sdzfs= -github.com/lib/pq v1.11.2/go.mod h1:/p+8NSbOcwzAEI7wiMXFlgydTwcgTr3OSKMsD2BitpA= -github.com/lithammer/shortuuid/v4 v4.2.0 h1:LMFOzVB3996a7b8aBuEXxqOBflbfPQAiVzkIcHO0h8c= -github.com/lithammer/shortuuid/v4 v4.2.0/go.mod h1:D5noHZ2oFw/YaKCfGy0YxyE7M0wMbezmMjPdhyEFe6Y= -github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= -github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= -github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE= -github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= -github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= -github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mark3labs/mcp-go v0.45.0 h1:s0S8qR/9fWaQ3pHxz7pm1uQ0DrswoSnRIxKIjbiQtkc= -github.com/mark3labs/mcp-go v0.45.0/go.mod h1:YnJfOL382MIWDx1kMY+2zsRHU/q78dBg9aFb8W6Thdw= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mdelapenya/tlscert v0.2.0 h1:7H81W6Z/4weDvZBNOfQte5GpIMo0lGYEeWbkGp5LJHI= -github.com/mdelapenya/tlscert v0.2.0/go.mod h1:O4njj3ELLnJjGdkN7M/vIVCpZ+Cf0L6muqOG4tLSl8o= -github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= -github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= -github.com/moby/go-archive v0.2.0 h1:zg5QDUM2mi0JIM9fdQZWC7U8+2ZfixfTYoHL7rWUcP8= -github.com/moby/go-archive v0.2.0/go.mod h1:mNeivT14o8xU+5q1YnNrkQVpK+dnNe/K6fHqnTg4qPU= -github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= -github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= -github.com/moby/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw= -github.com/moby/sys/atomicwriter v0.1.0/go.mod h1:Ul8oqv2ZMNHOceF643P6FKPXeCmYtlQMvpizfsSoaWs= -github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= -github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko= -github.com/moby/sys/user v0.4.0 h1:jhcMKit7SA80hivmFJcbB1vqmw//wU61Zdui2eQXuMs= -github.com/moby/sys/user v0.4.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs= -github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g= -github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28= -github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ= -github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc= -github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= -github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= -github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w= -github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= -github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= -github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= -github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= -github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= -github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU= -github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= -github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= -github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= -github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= -github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc= -github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik= -github.com/shirou/gopsutil/v4 v4.26.2 h1:X8i6sicvUFih4BmYIGT1m2wwgw2VG9YgrDTi7cIRGUI= -github.com/shirou/gopsutil/v4 v4.26.2/go.mod h1:LZ6ewCSkBqUpvSOf+LsTGnRinC6iaNUNMGBtDkJBaLQ= -github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= -github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw= -github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U= -github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= -github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg= -github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= -github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= -github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= -github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= -github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= -github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU= -github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= -github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= -github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= -github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= -github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= -github.com/testcontainers/testcontainers-go v0.41.0 h1:mfpsD0D36YgkxGj2LrIyxuwQ9i2wCKAD+ESsYM1wais= -github.com/testcontainers/testcontainers-go v0.41.0/go.mod h1:pdFrEIfaPl24zmBjerWTTYaY0M6UHsqA1YSvsoU40MI= -github.com/testcontainers/testcontainers-go/modules/mysql v0.41.0 h1:5rwejaJr5nIfw8NK99eKPX7O6k27lnSMklTj5DbYybM= -github.com/testcontainers/testcontainers-go/modules/mysql v0.41.0/go.mod h1:iMO/aFWnbjYkqHw8VPsJB3rVTOD9hKDsUtV0PvzD0DA= -github.com/testcontainers/testcontainers-go/modules/postgres v0.41.0 h1:AOtFXssrDlLm84A2sTTR/AhvJiYbrIuCO59d+Ro9Tb0= -github.com/testcontainers/testcontainers-go/modules/postgres v0.41.0/go.mod h1:k2a09UKhgSp6vNpliIY0QSgm4Hi7GXVTzWvWgUemu/8= -github.com/tklauser/go-sysconf v0.3.16 h1:frioLaCQSsF5Cy1jgRBrzr6t502KIIwQ0MArYICU0nA= -github.com/tklauser/go-sysconf v0.3.16/go.mod h1:/qNL9xxDhc7tx3HSRsLWNnuzbVfh3e7gh/BmM179nYI= -github.com/tklauser/numcpus v0.11.0 h1:nSTwhKH5e1dMNsCdVBukSZrURJRoHbSEQjdEbY+9RXw= -github.com/tklauser/numcpus v0.11.0/go.mod h1:z+LwcLq54uWZTX0u/bGobaV34u6V7KNlTZejzM6/3MQ= -github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc= -github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw= -github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4= -github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4= -github.com/yuin/goldmark v1.7.16 h1:n+CJdUxaFMiDUNnWC3dMWCIQJSkxH4uz3ZwQBkAlVNE= -github.com/yuin/goldmark v1.7.16/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg= -github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= -github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= -go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 h1:TT4fX+nBOA/+LUkobKGW1ydGcn+G3vRw9+g5HwCphpk= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8= -go.opentelemetry.io/otel v1.41.0 h1:YlEwVsGAlCvczDILpUXpIpPSL/VPugt7zHThEMLce1c= -go.opentelemetry.io/otel v1.41.0/go.mod h1:Yt4UwgEKeT05QbLwbyHXEwhnjxNO6D8L5PQP51/46dE= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.41.0 h1:inYW9ZhgqiDqh6BioM7DVHHzEGVq76Db5897WLGZ5Go= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.41.0/go.mod h1:Izur+Wt8gClgMJqO/cZ8wdeeMryJ/xxiOVgFSSfpDTY= -go.opentelemetry.io/otel/metric v1.41.0 h1:rFnDcs4gRzBcsO9tS8LCpgR0dxg4aaxWlJxCno7JlTQ= -go.opentelemetry.io/otel/metric v1.41.0/go.mod h1:xPvCwd9pU0VN8tPZYzDZV/BMj9CM9vs00GuBjeKhJps= -go.opentelemetry.io/otel/sdk v1.41.0 h1:YPIEXKmiAwkGl3Gu1huk1aYWwtpRLeskpV+wPisxBp8= -go.opentelemetry.io/otel/sdk v1.41.0/go.mod h1:ahFdU0G5y8IxglBf0QBJXgSe7agzjE4GiTJ6HT9ud90= -go.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2WKg+sEJTtB8= -go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew= -go.opentelemetry.io/otel/trace v1.41.0 h1:Vbk2co6bhj8L59ZJ6/xFTskY+tGAbOnCtQGVVa9TIN0= -go.opentelemetry.io/otel/trace v1.41.0/go.mod h1:U1NU4ULCoxeDKc09yCWdWe+3QoyweJcISEVa1RBzOis= -go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= -go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= -go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= -go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= -golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= -golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= -golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 h1:mgKeJMpvi0yx/sU5GsxQ7p6s2wtOnGAHZWCHUM4KGzY= -golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70= -golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.30.0 h1:jD5RhkmVAnjqaCUXfbGBrn3lpxbknfN9w2UhHHU+5B4= -golang.org/x/image v0.30.0/go.mod h1:SAEUTxCCMWSrJcCy/4HwavEsfZZJlYxeHLc6tTiAe/c= -golang.org/x/mod v0.34.0 h1:xIHgNUUnW6sYkcM5Jleh05DvLOtwc6RitGHbDk4akRI= -golang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY= -golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0= -golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw= -golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= -golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= -golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= -golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo= -golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= -golang.org/x/term v0.41.0 h1:QCgPso/Q3RTJx2Th4bDLqML4W6iJiaXFq2/ftQF13YU= -golang.org/x/term v0.41.0/go.mod h1:3pfBgksrReYfZ5lvYM0kSO0LIkAl4Yl2bXOkKP7Ec2A= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8= -golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA= -golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI= -golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= -golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k= -golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= -gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= -google.golang.org/genproto v0.0.0-20260316180232-0b37fe3546d5 h1:JNfk58HZ8lfmXbYK2vx/UvsqIL59TzByCxPIX4TDmsE= -google.golang.org/genproto v0.0.0-20260316180232-0b37fe3546d5/go.mod h1:x5julN69+ED4PcFk/XWayw35O0lf/nGa4aNgODCmNmw= -google.golang.org/genproto/googleapis/api v0.0.0-20260316172706-e463d84ca32d h1:RdWlPmVySdTF0IBIZzvZJvSD0ZocPBNUsnE+uGBxj+4= -google.golang.org/genproto/googleapis/api v0.0.0-20260316172706-e463d84ca32d/go.mod h1:X2gu9Qwng7Nn009s/r3RUxqkzQNqOrAy79bluY7ojIg= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260311181403-84a4fc48630c h1:xgCzyF2LFIO/0X2UAoVRiXKU5Xg6VjToG4i2/ecSswk= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260311181403-84a4fc48630c/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= -google.golang.org/grpc v1.79.2 h1:fRMD94s2tITpyJGtBBn7MkMseNpOZU8ZxgC3MMBaXRU= -google.golang.org/grpc v1.79.2/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= -google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= -google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q= -gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA= -modernc.org/cc/v4 v4.27.1 h1:9W30zRlYrefrDV2JE2O8VDtJ1yPGownxciz5rrbQZis= -modernc.org/cc/v4 v4.27.1/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0= -modernc.org/ccgo/v4 v4.30.1 h1:4r4U1J6Fhj98NKfSjnPUN7Ze2c6MnAdL0hWw6+LrJpc= -modernc.org/ccgo/v4 v4.30.1/go.mod h1:bIOeI1JL54Utlxn+LwrFyjCx2n2RDiYEaJVSrgdrRfM= -modernc.org/fileutil v1.3.40 h1:ZGMswMNc9JOCrcrakF1HrvmergNLAmxOPjizirpfqBA= -modernc.org/fileutil v1.3.40/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc= -modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI= -modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito= -modernc.org/gc/v3 v3.1.1 h1:k8T3gkXWY9sEiytKhcgyiZ2L0DTyCQ/nvX+LoCljoRE= -modernc.org/gc/v3 v3.1.1/go.mod h1:HFK/6AGESC7Ex+EZJhJ2Gni6cTaYpSMmU/cT9RmlfYY= -modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks= -modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI= -modernc.org/libc v1.67.6 h1:eVOQvpModVLKOdT+LvBPjdQqfrZq+pC39BygcT+E7OI= -modernc.org/libc v1.67.6/go.mod h1:JAhxUVlolfYDErnwiqaLvUqc8nfb2r6S6slAgZOnaiE= -modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU= -modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg= -modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI= -modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw= -modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8= -modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns= -modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w= -modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE= -modernc.org/sqlite v1.46.1 h1:eFJ2ShBLIEnUWlLy12raN0Z1plqmFX9Qe3rjQTKt6sU= -modernc.org/sqlite v1.46.1/go.mod h1:CzbrU2lSB1DKUusvwGz7rqEKIq+NUd8GWuBBZDs9/nA= -modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0= -modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A= -modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= -modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= +cel.dev/expr v0.25.1 h1:1KrZg61W6TWSxuNZ37Xy49ps13NUovb66QLprthtwi4= +cel.dev/expr v0.25.1/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4= +connectrpc.com/connect v1.19.1 h1:R5M57z05+90EfEvCY1b7hBxDVOUl45PrtXtAV2fOC14= +connectrpc.com/connect v1.19.1/go.mod h1:tN20fjdGlewnSFeZxLKb0xwIZ6ozc3OQs2hTXy4du9w= +dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= +dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= +github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg= +github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ= +github.com/antlr4-go/antlr/v4 v4.13.1/go.mod h1:GKmUxMtwp6ZgGwZSva4eWPC5mS6vUAmOABFgjdkM7Nw= +github.com/aws/aws-sdk-go-v2 v1.41.4 h1:10f50G7WyU02T56ox1wWXq+zTX9I1zxG46HYuG1hH/k= +github.com/aws/aws-sdk-go-v2 v1.41.4/go.mod h1:mwsPRE8ceUUpiTgF7QmQIJ7lgsKUPQOUl3o72QBrE1o= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.7 h1:3kGOqnh1pPeddVa/E37XNTaWJ8W6vrbYV9lJEkCnhuY= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.7/go.mod h1:lyw7GFp3qENLh7kwzf7iMzAxDn+NzjXEAGjKS2UOKqI= +github.com/aws/aws-sdk-go-v2/config v1.32.12 h1:O3csC7HUGn2895eNrLytOJQdoL2xyJy0iYXhoZ1OmP0= +github.com/aws/aws-sdk-go-v2/config v1.32.12/go.mod h1:96zTvoOFR4FURjI+/5wY1vc1ABceROO4lWgWJuxgy0g= +github.com/aws/aws-sdk-go-v2/credentials v1.19.12 h1:oqtA6v+y5fZg//tcTWahyN9PEn5eDU/Wpvc2+kJ4aY8= +github.com/aws/aws-sdk-go-v2/credentials v1.19.12/go.mod h1:U3R1RtSHx6NB0DvEQFGyf/0sbrpJrluENHdPy1j/3TE= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.20 h1:zOgq3uezl5nznfoK3ODuqbhVg1JzAGDUhXOsU0IDCAo= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.20/go.mod h1:z/MVwUARehy6GAg/yQ1GO2IMl0k++cu1ohP9zo887wE= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.20 h1:CNXO7mvgThFGqOFgbNAP2nol2qAWBOGfqR/7tQlvLmc= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.20/go.mod h1:oydPDJKcfMhgfcgBUZaG+toBbwy8yPWubJXBVERtI4o= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.20 h1:tN6W/hg+pkM+tf9XDkWUbDEjGLb+raoBMFsTodcoYKw= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.20/go.mod h1:YJ898MhD067hSHA6xYCx5ts/jEd8BSOLtQDL3iZsvbc= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6 h1:qYQ4pzQ2Oz6WpQ8T3HvGHnZydA72MnLuFK9tJwmrbHw= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6/go.mod h1:O3h0IK87yXci+kg6flUKzJnWeziQUKciKrLjcatSNcY= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.21 h1:SwGMTMLIlvDNyhMteQ6r8IJSBPlRdXX5d4idhIGbkXA= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.21/go.mod h1:UUxgWxofmOdAMuqEsSppbDtGKLfR04HGsD0HXzvhI1k= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7 h1:5EniKhLZe4xzL7a+fU3C2tfUN4nWIqlLesfrjkuPFTY= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7/go.mod h1:x0nZssQ3qZSnIcePWLvcoFisRXJzcTVvYpAAdYX8+GI= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.12 h1:qtJZ70afD3ISKWnoX3xB0J2otEqu3LqicRcDBqsj0hQ= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.12/go.mod h1:v2pNpJbRNl4vEUWEh5ytQok0zACAKfdmKS51Hotc3pQ= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.20 h1:2HvVAIq+YqgGotK6EkMf+KIEqTISmTYh5zLpYyeTo1Y= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.20/go.mod h1:V4X406Y666khGa8ghKmphma/7C0DAtEQYhkq9z4vpbk= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.20 h1:siU1A6xjUZ2N8zjTHSXFhB9L/2OY8Dqs0xXiLjF30jA= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.20/go.mod h1:4TLZCmVJDM3FOu5P5TJP0zOlu9zWgDWU7aUxWbr+rcw= +github.com/aws/aws-sdk-go-v2/service/s3 v1.97.1 h1:csi9NLpFZXb9fxY7rS1xVzgPRGMt7MSNWeQ6eo247kE= +github.com/aws/aws-sdk-go-v2/service/s3 v1.97.1/go.mod h1:qXVal5H0ChqXP63t6jze5LmFalc7+ZE7wOdLtZ0LCP0= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.8 h1:0GFOLzEbOyZABS3PhYfBIx2rNBACYcKty+XGkTgw1ow= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.8/go.mod h1:LXypKvk85AROkKhOG6/YEcHFPoX+prKTowKnVdcaIxE= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.13 h1:kiIDLZ005EcKomYYITtfsjn7dtOwHDOFy7IbPXKek2o= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.13/go.mod h1:2h/xGEowcW/g38g06g3KpRWDlT+OTfxxI0o1KqayAB8= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.17 h1:jzKAXIlhZhJbnYwHbvUQZEB8KfgAEuG0dc08Bkda7NU= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.17/go.mod h1:Al9fFsXjv4KfbzQHGe6V4NZSZQXecFcvaIF4e70FoRA= +github.com/aws/aws-sdk-go-v2/service/sts v1.41.9 h1:Cng+OOwCHmFljXIxpEVXAGMnBia8MSU6Ch5i9PgBkcU= +github.com/aws/aws-sdk-go-v2/service/sts v1.41.9/go.mod h1:LrlIndBDdjA/EeXeyNBle+gyCwTlizzW5ycgWnvIxkk= +github.com/aws/smithy-go v1.24.2 h1:FzA3bu/nt/vDvmnkg+R8Xl46gmzEDam6mZ1hzmwXFng= +github.com/aws/smithy-go v1.24.2/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc= +github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk= +github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg= +github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= +github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= +github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= +github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= +github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE= +github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk= +github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= +github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= +github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= +github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= +github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= +github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c= +github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4= +github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= +github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/docker/docker v28.5.2+incompatible h1:DBX0Y0zAjZbSrm1uzOkdr1onVghKaftjlSWt4AFexzM= +github.com/docker/docker v28.5.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94= +github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/ebitengine/purego v0.10.0 h1:QIw4xfpWT6GWTzaW5XEKy3HXoqrJGx1ijYHzTF0/ISU= +github.com/ebitengine/purego v0.10.0/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= +github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo= +github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU= +github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= +github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63YCY= +github.com/golang-jwt/jwt/v5 v5.3.1/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/cel-go v0.27.0 h1:e7ih85+4qVrBuqQWTW4FKSqZYokVuc3HnhH5keboFTo= +github.com/google/cel-go v0.27.0/go.mod h1:tTJ11FWqnhw5KKpnWpvW9CJC3Y9GK4EIS0WXnBbebzw= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs= +github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/feeds v1.2.0 h1:O6pBiXJ5JHhPvqy53NsjKOThq+dNFm8+DFrxBEdzSCc= +github.com/gorilla/feeds v1.2.0/go.mod h1:WMib8uJP3BbY+X8Szd1rA5Pzhdfh+HCCAYT2z7Fza6Y= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 h1:HWRh5R2+9EifMyIHV7ZV+MIZqgz+PMpZ14Jynv3O2Zs= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0/go.mod h1:JfhWUomR1baixubs02l85lZYYOm7LV6om4ceouMv45c= +github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= +github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/invopop/jsonschema v0.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E= +github.com/invopop/jsonschema v0.13.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgx/v5 v5.5.4 h1:Xp2aQS8uXButQdnCMWNmvx6UysWQQC+u1EoizjguY+8= +github.com/jackc/pgx/v5 v5.5.4/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A= +github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk= +github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= +github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= +github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/klauspost/compress v1.18.2 h1:iiPHWW0YrcFgpBYhsA6D1+fqHssJscY/Tm/y2Uqnapk= +github.com/klauspost/compress v1.18.2/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/labstack/echo/v5 v5.0.4 h1:ll3I/O8BifjMztj9dD1vx/peZQv8cR2CTUdQK6QxGGc= +github.com/labstack/echo/v5 v5.0.4/go.mod h1:SyvlSdObGjRXeQfCCXW/sybkZdOOQZBmpKF0bvALaeo= +github.com/lib/pq v1.11.2 h1:x6gxUeu39V0BHZiugWe8LXZYZ+Utk7hSJGThs8sdzfs= +github.com/lib/pq v1.11.2/go.mod h1:/p+8NSbOcwzAEI7wiMXFlgydTwcgTr3OSKMsD2BitpA= +github.com/lithammer/shortuuid/v4 v4.2.0 h1:LMFOzVB3996a7b8aBuEXxqOBflbfPQAiVzkIcHO0h8c= +github.com/lithammer/shortuuid/v4 v4.2.0/go.mod h1:D5noHZ2oFw/YaKCfGy0YxyE7M0wMbezmMjPdhyEFe6Y= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE= +github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mark3labs/mcp-go v0.45.0 h1:s0S8qR/9fWaQ3pHxz7pm1uQ0DrswoSnRIxKIjbiQtkc= +github.com/mark3labs/mcp-go v0.45.0/go.mod h1:YnJfOL382MIWDx1kMY+2zsRHU/q78dBg9aFb8W6Thdw= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mdelapenya/tlscert v0.2.0 h1:7H81W6Z/4weDvZBNOfQte5GpIMo0lGYEeWbkGp5LJHI= +github.com/mdelapenya/tlscert v0.2.0/go.mod h1:O4njj3ELLnJjGdkN7M/vIVCpZ+Cf0L6muqOG4tLSl8o= +github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= +github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= +github.com/moby/go-archive v0.2.0 h1:zg5QDUM2mi0JIM9fdQZWC7U8+2ZfixfTYoHL7rWUcP8= +github.com/moby/go-archive v0.2.0/go.mod h1:mNeivT14o8xU+5q1YnNrkQVpK+dnNe/K6fHqnTg4qPU= +github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= +github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= +github.com/moby/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw= +github.com/moby/sys/atomicwriter v0.1.0/go.mod h1:Ul8oqv2ZMNHOceF643P6FKPXeCmYtlQMvpizfsSoaWs= +github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= +github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko= +github.com/moby/sys/user v0.4.0 h1:jhcMKit7SA80hivmFJcbB1vqmw//wU61Zdui2eQXuMs= +github.com/moby/sys/user v0.4.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs= +github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g= +github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28= +github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ= +github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w= +github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= +github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= +github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= +github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU= +github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc= +github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik= +github.com/shirou/gopsutil/v4 v4.26.2 h1:X8i6sicvUFih4BmYIGT1m2wwgw2VG9YgrDTi7cIRGUI= +github.com/shirou/gopsutil/v4 v4.26.2/go.mod h1:LZ6ewCSkBqUpvSOf+LsTGnRinC6iaNUNMGBtDkJBaLQ= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw= +github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U= +github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= +github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg= +github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= +github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= +github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= +github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= +github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= +github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU= +github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/testcontainers/testcontainers-go v0.41.0 h1:mfpsD0D36YgkxGj2LrIyxuwQ9i2wCKAD+ESsYM1wais= +github.com/testcontainers/testcontainers-go v0.41.0/go.mod h1:pdFrEIfaPl24zmBjerWTTYaY0M6UHsqA1YSvsoU40MI= +github.com/testcontainers/testcontainers-go/modules/mysql v0.41.0 h1:5rwejaJr5nIfw8NK99eKPX7O6k27lnSMklTj5DbYybM= +github.com/testcontainers/testcontainers-go/modules/mysql v0.41.0/go.mod h1:iMO/aFWnbjYkqHw8VPsJB3rVTOD9hKDsUtV0PvzD0DA= +github.com/testcontainers/testcontainers-go/modules/postgres v0.41.0 h1:AOtFXssrDlLm84A2sTTR/AhvJiYbrIuCO59d+Ro9Tb0= +github.com/testcontainers/testcontainers-go/modules/postgres v0.41.0/go.mod h1:k2a09UKhgSp6vNpliIY0QSgm4Hi7GXVTzWvWgUemu/8= +github.com/tklauser/go-sysconf v0.3.16 h1:frioLaCQSsF5Cy1jgRBrzr6t502KIIwQ0MArYICU0nA= +github.com/tklauser/go-sysconf v0.3.16/go.mod h1:/qNL9xxDhc7tx3HSRsLWNnuzbVfh3e7gh/BmM179nYI= +github.com/tklauser/numcpus v0.11.0 h1:nSTwhKH5e1dMNsCdVBukSZrURJRoHbSEQjdEbY+9RXw= +github.com/tklauser/numcpus v0.11.0/go.mod h1:z+LwcLq54uWZTX0u/bGobaV34u6V7KNlTZejzM6/3MQ= +github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc= +github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw= +github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4= +github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4= +github.com/yuin/goldmark v1.7.16 h1:n+CJdUxaFMiDUNnWC3dMWCIQJSkxH4uz3ZwQBkAlVNE= +github.com/yuin/goldmark v1.7.16/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg= +github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= +github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 h1:TT4fX+nBOA/+LUkobKGW1ydGcn+G3vRw9+g5HwCphpk= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8= +go.opentelemetry.io/otel v1.41.0 h1:YlEwVsGAlCvczDILpUXpIpPSL/VPugt7zHThEMLce1c= +go.opentelemetry.io/otel v1.41.0/go.mod h1:Yt4UwgEKeT05QbLwbyHXEwhnjxNO6D8L5PQP51/46dE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.41.0 h1:inYW9ZhgqiDqh6BioM7DVHHzEGVq76Db5897WLGZ5Go= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.41.0/go.mod h1:Izur+Wt8gClgMJqO/cZ8wdeeMryJ/xxiOVgFSSfpDTY= +go.opentelemetry.io/otel/metric v1.41.0 h1:rFnDcs4gRzBcsO9tS8LCpgR0dxg4aaxWlJxCno7JlTQ= +go.opentelemetry.io/otel/metric v1.41.0/go.mod h1:xPvCwd9pU0VN8tPZYzDZV/BMj9CM9vs00GuBjeKhJps= +go.opentelemetry.io/otel/sdk v1.41.0 h1:YPIEXKmiAwkGl3Gu1huk1aYWwtpRLeskpV+wPisxBp8= +go.opentelemetry.io/otel/sdk v1.41.0/go.mod h1:ahFdU0G5y8IxglBf0QBJXgSe7agzjE4GiTJ6HT9ud90= +go.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2WKg+sEJTtB8= +go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew= +go.opentelemetry.io/otel/trace v1.41.0 h1:Vbk2co6bhj8L59ZJ6/xFTskY+tGAbOnCtQGVVa9TIN0= +go.opentelemetry.io/otel/trace v1.41.0/go.mod h1:U1NU4ULCoxeDKc09yCWdWe+3QoyweJcISEVa1RBzOis= +go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= +go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= +go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= +golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= +golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= +golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 h1:mgKeJMpvi0yx/sU5GsxQ7p6s2wtOnGAHZWCHUM4KGzY= +golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70= +golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.30.0 h1:jD5RhkmVAnjqaCUXfbGBrn3lpxbknfN9w2UhHHU+5B4= +golang.org/x/image v0.30.0/go.mod h1:SAEUTxCCMWSrJcCy/4HwavEsfZZJlYxeHLc6tTiAe/c= +golang.org/x/mod v0.34.0 h1:xIHgNUUnW6sYkcM5Jleh05DvLOtwc6RitGHbDk4akRI= +golang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY= +golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0= +golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw= +golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= +golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= +golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= +golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo= +golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/term v0.41.0 h1:QCgPso/Q3RTJx2Th4bDLqML4W6iJiaXFq2/ftQF13YU= +golang.org/x/term v0.41.0/go.mod h1:3pfBgksrReYfZ5lvYM0kSO0LIkAl4Yl2bXOkKP7Ec2A= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8= +golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA= +golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI= +golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= +golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k= +golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= +gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= +google.golang.org/genproto v0.0.0-20260316180232-0b37fe3546d5 h1:JNfk58HZ8lfmXbYK2vx/UvsqIL59TzByCxPIX4TDmsE= +google.golang.org/genproto v0.0.0-20260316180232-0b37fe3546d5/go.mod h1:x5julN69+ED4PcFk/XWayw35O0lf/nGa4aNgODCmNmw= +google.golang.org/genproto/googleapis/api v0.0.0-20260316172706-e463d84ca32d h1:RdWlPmVySdTF0IBIZzvZJvSD0ZocPBNUsnE+uGBxj+4= +google.golang.org/genproto/googleapis/api v0.0.0-20260316172706-e463d84ca32d/go.mod h1:X2gu9Qwng7Nn009s/r3RUxqkzQNqOrAy79bluY7ojIg= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260311181403-84a4fc48630c h1:xgCzyF2LFIO/0X2UAoVRiXKU5Xg6VjToG4i2/ecSswk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260311181403-84a4fc48630c/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/grpc v1.79.2 h1:fRMD94s2tITpyJGtBBn7MkMseNpOZU8ZxgC3MMBaXRU= +google.golang.org/grpc v1.79.2/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q= +gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA= +modernc.org/cc/v4 v4.27.1 h1:9W30zRlYrefrDV2JE2O8VDtJ1yPGownxciz5rrbQZis= +modernc.org/cc/v4 v4.27.1/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0= +modernc.org/ccgo/v4 v4.30.1 h1:4r4U1J6Fhj98NKfSjnPUN7Ze2c6MnAdL0hWw6+LrJpc= +modernc.org/ccgo/v4 v4.30.1/go.mod h1:bIOeI1JL54Utlxn+LwrFyjCx2n2RDiYEaJVSrgdrRfM= +modernc.org/fileutil v1.3.40 h1:ZGMswMNc9JOCrcrakF1HrvmergNLAmxOPjizirpfqBA= +modernc.org/fileutil v1.3.40/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc= +modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI= +modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito= +modernc.org/gc/v3 v3.1.1 h1:k8T3gkXWY9sEiytKhcgyiZ2L0DTyCQ/nvX+LoCljoRE= +modernc.org/gc/v3 v3.1.1/go.mod h1:HFK/6AGESC7Ex+EZJhJ2Gni6cTaYpSMmU/cT9RmlfYY= +modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks= +modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI= +modernc.org/libc v1.67.6 h1:eVOQvpModVLKOdT+LvBPjdQqfrZq+pC39BygcT+E7OI= +modernc.org/libc v1.67.6/go.mod h1:JAhxUVlolfYDErnwiqaLvUqc8nfb2r6S6slAgZOnaiE= +modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU= +modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg= +modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI= +modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw= +modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8= +modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns= +modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w= +modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE= +modernc.org/sqlite v1.46.1 h1:eFJ2ShBLIEnUWlLy12raN0Z1plqmFX9Qe3rjQTKt6sU= +modernc.org/sqlite v1.46.1/go.mod h1:CzbrU2lSB1DKUusvwGz7rqEKIq+NUd8GWuBBZDs9/nA= +modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0= +modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A= +modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= +modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= diff --git a/internal/base/resource_name.go b/internal/base/resource_name.go index 828bfa366..504faec43 100644 --- a/internal/base/resource_name.go +++ b/internal/base/resource_name.go @@ -1,7 +1,7 @@ -package base - -import "regexp" - -var ( - UIDMatcher = regexp.MustCompile("^[a-zA-Z0-9]([a-zA-Z0-9-]{0,30}[a-zA-Z0-9])?$") -) +package base + +import "regexp" + +var ( + UIDMatcher = regexp.MustCompile("^[a-zA-Z0-9]([a-zA-Z0-9-]{0,30}[a-zA-Z0-9])?$") +) diff --git a/internal/base/resource_name_test.go b/internal/base/resource_name_test.go index cef922ac0..76bddf37f 100644 --- a/internal/base/resource_name_test.go +++ b/internal/base/resource_name_test.go @@ -1,35 +1,35 @@ -package base - -import ( - "testing" -) - -func TestUIDMatcher(t *testing.T) { - tests := []struct { - input string - expected bool - }{ - {"", false}, - {"-abc123", false}, - {"012345678901234567890123456789", true}, - {"1abc-123", true}, - {"A123B456C789", true}, - {"a", true}, - {"ab", true}, - {"a*b&c", false}, - {"a--b", true}, - {"a-1b-2c", true}, - {"a1234567890123456789012345678901", true}, - {"abc123", true}, - {"abc123-", false}, - } - - for _, test := range tests { - t.Run(test.input, func(*testing.T) { - result := UIDMatcher.MatchString(test.input) - if result != test.expected { - t.Errorf("For input '%s', expected %v but got %v", test.input, test.expected, result) - } - }) - } -} +package base + +import ( + "testing" +) + +func TestUIDMatcher(t *testing.T) { + tests := []struct { + input string + expected bool + }{ + {"", false}, + {"-abc123", false}, + {"012345678901234567890123456789", true}, + {"1abc-123", true}, + {"A123B456C789", true}, + {"a", true}, + {"ab", true}, + {"a*b&c", false}, + {"a--b", true}, + {"a-1b-2c", true}, + {"a1234567890123456789012345678901", true}, + {"abc123", true}, + {"abc123-", false}, + } + + for _, test := range tests { + t.Run(test.input, func(*testing.T) { + result := UIDMatcher.MatchString(test.input) + if result != test.expected { + t.Errorf("For input '%s', expected %v but got %v", test.input, test.expected, result) + } + }) + } +} diff --git a/internal/profile/profile.go b/internal/profile/profile.go index 30579a313..fddeb96cb 100644 --- a/internal/profile/profile.go +++ b/internal/profile/profile.go @@ -1,107 +1,107 @@ -package profile - -import ( - "fmt" - "log/slog" - "os" - "path/filepath" - "runtime" - "strings" - - "github.com/pkg/errors" -) - -// Profile is the configuration to start main server. -type Profile struct { - // Demo indicates if the server is in demo mode - Demo bool - // Addr is the binding address for server - Addr string - // Port is the binding port for server - Port int - // UNIXSock is the IPC binding path. Overrides Addr and Port - UNIXSock string - // Data is the data directory - Data string - // DSN points to where memos stores its own data - DSN string - // Driver is the database driver - // sqlite, mysql - Driver string - // Version is the current version of server - Version string - // InstanceURL is the url of your memos instance. - InstanceURL string -} - -func checkDataDir(dataDir string) (string, error) { - // Convert to absolute path if relative path is supplied. - if !filepath.IsAbs(dataDir) { - // Use current working directory, not the binary's directory - // This ensures we use the actual working directory where the process runs - absDir, err := filepath.Abs(dataDir) - if err != nil { - return "", err - } - dataDir = absDir - } - - // Trim trailing \ or / in case user supplies - dataDir = strings.TrimRight(dataDir, "\\/") - if _, err := os.Stat(dataDir); err != nil { - return "", errors.Wrapf(err, "unable to access data folder %s", dataDir) - } - return dataDir, nil -} - -func (p *Profile) Validate() error { - // Set default data directory if not specified - if p.Data == "" { - if runtime.GOOS == "windows" { - p.Data = filepath.Join(os.Getenv("ProgramData"), "memos") - } else { - // On Linux/macOS, check if /var/opt/memos exists and is writable (Docker scenario) - if info, err := os.Stat("/var/opt/memos"); err == nil && info.IsDir() { - // Check if we can write to this directory - testFile := filepath.Join("/var/opt/memos", ".write-test") - if err := os.WriteFile(testFile, []byte("test"), 0600); err == nil { - os.Remove(testFile) - p.Data = "/var/opt/memos" - } else { - // /var/opt/memos exists but is not writable, use current directory - slog.Warn("/var/opt/memos is not writable, using current directory") - p.Data = "." - } - } else { - // /var/opt/memos doesn't exist, use current directory (local development) - p.Data = "." - } - } - } - - // Create data directory if it doesn't exist - if _, err := os.Stat(p.Data); os.IsNotExist(err) { - if err := os.MkdirAll(p.Data, 0770); err != nil { - slog.Error("failed to create data directory", slog.String("data", p.Data), slog.String("error", err.Error())) - return err - } - } - - dataDir, err := checkDataDir(p.Data) - if err != nil { - slog.Error("failed to check dsn", slog.String("data", dataDir), slog.String("error", err.Error())) - return err - } - - p.Data = dataDir - if p.Driver == "sqlite" && p.DSN == "" { - mode := "prod" - if p.Demo { - mode = "demo" - } - dbFile := fmt.Sprintf("memos_%s.db", mode) - p.DSN = filepath.Join(dataDir, dbFile) - } - - return nil -} +package profile + +import ( + "fmt" + "log/slog" + "os" + "path/filepath" + "runtime" + "strings" + + "github.com/pkg/errors" +) + +// Profile is the configuration to start main server. +type Profile struct { + // Demo indicates if the server is in demo mode + Demo bool + // Addr is the binding address for server + Addr string + // Port is the binding port for server + Port int + // UNIXSock is the IPC binding path. Overrides Addr and Port + UNIXSock string + // Data is the data directory + Data string + // DSN points to where memos stores its own data + DSN string + // Driver is the database driver + // sqlite, mysql + Driver string + // Version is the current version of server + Version string + // InstanceURL is the url of your memos instance. + InstanceURL string +} + +func checkDataDir(dataDir string) (string, error) { + // Convert to absolute path if relative path is supplied. + if !filepath.IsAbs(dataDir) { + // Use current working directory, not the binary's directory + // This ensures we use the actual working directory where the process runs + absDir, err := filepath.Abs(dataDir) + if err != nil { + return "", err + } + dataDir = absDir + } + + // Trim trailing \ or / in case user supplies + dataDir = strings.TrimRight(dataDir, "\\/") + if _, err := os.Stat(dataDir); err != nil { + return "", errors.Wrapf(err, "unable to access data folder %s", dataDir) + } + return dataDir, nil +} + +func (p *Profile) Validate() error { + // Set default data directory if not specified + if p.Data == "" { + if runtime.GOOS == "windows" { + p.Data = filepath.Join(os.Getenv("ProgramData"), "memos") + } else { + // On Linux/macOS, check if /var/opt/memos exists and is writable (Docker scenario) + if info, err := os.Stat("/var/opt/memos"); err == nil && info.IsDir() { + // Check if we can write to this directory + testFile := filepath.Join("/var/opt/memos", ".write-test") + if err := os.WriteFile(testFile, []byte("test"), 0600); err == nil { + os.Remove(testFile) + p.Data = "/var/opt/memos" + } else { + // /var/opt/memos exists but is not writable, use current directory + slog.Warn("/var/opt/memos is not writable, using current directory") + p.Data = "." + } + } else { + // /var/opt/memos doesn't exist, use current directory (local development) + p.Data = "." + } + } + } + + // Create data directory if it doesn't exist + if _, err := os.Stat(p.Data); os.IsNotExist(err) { + if err := os.MkdirAll(p.Data, 0770); err != nil { + slog.Error("failed to create data directory", slog.String("data", p.Data), slog.String("error", err.Error())) + return err + } + } + + dataDir, err := checkDataDir(p.Data) + if err != nil { + slog.Error("failed to check dsn", slog.String("data", dataDir), slog.String("error", err.Error())) + return err + } + + p.Data = dataDir + if p.Driver == "sqlite" && p.DSN == "" { + mode := "prod" + if p.Demo { + mode = "demo" + } + dbFile := fmt.Sprintf("memos_%s.db", mode) + p.DSN = filepath.Join(dataDir, dbFile) + } + + return nil +} diff --git a/internal/util/util.go b/internal/util/util.go index cdb211fb6..6091c30ab 100644 --- a/internal/util/util.go +++ b/internal/util/util.go @@ -1,73 +1,73 @@ -package util //nolint:revive // util namespace is intentional for shared helpers - -import ( - "crypto/rand" - "math/big" - "net/mail" - "strconv" - "strings" - - "github.com/google/uuid" -) - -// ConvertStringToInt32 converts a string to int32. -func ConvertStringToInt32(src string) (int32, error) { - parsed, err := strconv.ParseInt(src, 10, 32) - if err != nil { - return 0, err - } - return int32(parsed), nil -} - -// HasPrefixes returns true if the string s has any of the given prefixes. -func HasPrefixes(src string, prefixes ...string) bool { - for _, prefix := range prefixes { - if strings.HasPrefix(src, prefix) { - return true - } - } - return false -} - -// ValidateEmail validates the email. -func ValidateEmail(email string) bool { - if _, err := mail.ParseAddress(email); err != nil { - return false - } - return true -} - -func GenUUID() string { - return uuid.New().String() -} - -var letters = []rune("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") - -// RandomString returns a random string with length n. -func RandomString(n int) (string, error) { - var sb strings.Builder - sb.Grow(n) - for i := 0; i < n; i++ { - // The reason for using crypto/rand instead of math/rand is that - // the former relies on hardware to generate random numbers and - // thus has a stronger source of random numbers. - randNum, err := rand.Int(rand.Reader, big.NewInt(int64(len(letters)))) - if err != nil { - return "", err - } - if _, err := sb.WriteRune(letters[randNum.Uint64()]); err != nil { - return "", err - } - } - return sb.String(), nil -} - -// ReplaceString replaces all occurrences of old in slice with new. -func ReplaceString(slice []string, old, new string) []string { - for i, s := range slice { - if s == old { - slice[i] = new - } - } - return slice -} +package util //nolint:revive // util namespace is intentional for shared helpers + +import ( + "crypto/rand" + "math/big" + "net/mail" + "strconv" + "strings" + + "github.com/google/uuid" +) + +// ConvertStringToInt32 converts a string to int32. +func ConvertStringToInt32(src string) (int32, error) { + parsed, err := strconv.ParseInt(src, 10, 32) + if err != nil { + return 0, err + } + return int32(parsed), nil +} + +// HasPrefixes returns true if the string s has any of the given prefixes. +func HasPrefixes(src string, prefixes ...string) bool { + for _, prefix := range prefixes { + if strings.HasPrefix(src, prefix) { + return true + } + } + return false +} + +// ValidateEmail validates the email. +func ValidateEmail(email string) bool { + if _, err := mail.ParseAddress(email); err != nil { + return false + } + return true +} + +func GenUUID() string { + return uuid.New().String() +} + +var letters = []rune("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") + +// RandomString returns a random string with length n. +func RandomString(n int) (string, error) { + var sb strings.Builder + sb.Grow(n) + for i := 0; i < n; i++ { + // The reason for using crypto/rand instead of math/rand is that + // the former relies on hardware to generate random numbers and + // thus has a stronger source of random numbers. + randNum, err := rand.Int(rand.Reader, big.NewInt(int64(len(letters)))) + if err != nil { + return "", err + } + if _, err := sb.WriteRune(letters[randNum.Uint64()]); err != nil { + return "", err + } + } + return sb.String(), nil +} + +// ReplaceString replaces all occurrences of old in slice with new. +func ReplaceString(slice []string, old, new string) []string { + for i, s := range slice { + if s == old { + slice[i] = new + } + } + return slice +} diff --git a/internal/util/util_test.go b/internal/util/util_test.go index 9dbdd34b3..d8ee5f83d 100644 --- a/internal/util/util_test.go +++ b/internal/util/util_test.go @@ -1,31 +1,31 @@ -package util //nolint:revive // util is an appropriate package name for utility functions - -import ( - "testing" -) - -func TestValidateEmail(t *testing.T) { - tests := []struct { - email string - want bool - }{ - { - email: "t@gmail.com", - want: true, - }, - { - email: "@usememos.com", - want: false, - }, - { - email: "1@gmail", - want: true, - }, - } - for _, test := range tests { - result := ValidateEmail(test.email) - if result != test.want { - t.Errorf("Validate Email %s: got result %v, want %v.", test.email, result, test.want) - } - } -} +package util //nolint:revive // util is an appropriate package name for utility functions + +import ( + "testing" +) + +func TestValidateEmail(t *testing.T) { + tests := []struct { + email string + want bool + }{ + { + email: "t@gmail.com", + want: true, + }, + { + email: "@usememos.com", + want: false, + }, + { + email: "1@gmail", + want: true, + }, + } + for _, test := range tests { + result := ValidateEmail(test.email) + if result != test.want { + t.Errorf("Validate Email %s: got result %v, want %v.", test.email, result, test.want) + } + } +} diff --git a/internal/version/version.go b/internal/version/version.go index 685f0c979..64d0a82aa 100644 --- a/internal/version/version.go +++ b/internal/version/version.go @@ -1,54 +1,54 @@ -package version - -import ( - "fmt" - "strings" - - "golang.org/x/mod/semver" -) - -// Version is the service current released version. -// Semantic versioning: https://semver.org/ -var Version = "0.27.0" - -func GetCurrentVersion() string { - return Version -} - -// GetMinorVersion extracts the minor version (e.g., "0.25") from a full version string (e.g., "0.25.1"). -// Returns the minor version string or empty string if the version format is invalid. -// Version format should be "major.minor.patch" (e.g., "0.25.1"). -func GetMinorVersion(version string) string { - versionList := strings.Split(version, ".") - if len(versionList) < 2 { - return "" - } - // Return major.minor only (first two components) - return versionList[0] + "." + versionList[1] -} - -// IsVersionGreaterOrEqualThan returns true if version is greater than or equal to target. -func IsVersionGreaterOrEqualThan(version, target string) bool { - return semver.Compare(fmt.Sprintf("v%s", version), fmt.Sprintf("v%s", target)) > -1 -} - -// IsVersionGreaterThan returns true if version is greater than target. -func IsVersionGreaterThan(version, target string) bool { - return semver.Compare(fmt.Sprintf("v%s", version), fmt.Sprintf("v%s", target)) > 0 -} - -type SortVersion []string - -func (s SortVersion) Len() int { - return len(s) -} - -func (s SortVersion) Swap(i, j int) { - s[i], s[j] = s[j], s[i] -} - -func (s SortVersion) Less(i, j int) bool { - v1 := fmt.Sprintf("v%s", s[i]) - v2 := fmt.Sprintf("v%s", s[j]) - return semver.Compare(v1, v2) == -1 -} +package version + +import ( + "fmt" + "strings" + + "golang.org/x/mod/semver" +) + +// Version is the service current released version. +// Semantic versioning: https://semver.org/ +var Version = "0.27.0" + +func GetCurrentVersion() string { + return Version +} + +// GetMinorVersion extracts the minor version (e.g., "0.25") from a full version string (e.g., "0.25.1"). +// Returns the minor version string or empty string if the version format is invalid. +// Version format should be "major.minor.patch" (e.g., "0.25.1"). +func GetMinorVersion(version string) string { + versionList := strings.Split(version, ".") + if len(versionList) < 2 { + return "" + } + // Return major.minor only (first two components) + return versionList[0] + "." + versionList[1] +} + +// IsVersionGreaterOrEqualThan returns true if version is greater than or equal to target. +func IsVersionGreaterOrEqualThan(version, target string) bool { + return semver.Compare(fmt.Sprintf("v%s", version), fmt.Sprintf("v%s", target)) > -1 +} + +// IsVersionGreaterThan returns true if version is greater than target. +func IsVersionGreaterThan(version, target string) bool { + return semver.Compare(fmt.Sprintf("v%s", version), fmt.Sprintf("v%s", target)) > 0 +} + +type SortVersion []string + +func (s SortVersion) Len() int { + return len(s) +} + +func (s SortVersion) Swap(i, j int) { + s[i], s[j] = s[j], s[i] +} + +func (s SortVersion) Less(i, j int) bool { + v1 := fmt.Sprintf("v%s", s[i]) + v2 := fmt.Sprintf("v%s", s[j]) + return semver.Compare(v1, v2) == -1 +} diff --git a/internal/version/version_test.go b/internal/version/version_test.go index 0222748d2..8d23ea96a 100644 --- a/internal/version/version_test.go +++ b/internal/version/version_test.go @@ -1,106 +1,106 @@ -package version - -import ( - "slices" - "testing" - - "github.com/stretchr/testify/assert" - "golang.org/x/mod/semver" -) - -func TestIsVersionGreaterOrEqualThan(t *testing.T) { - tests := []struct { - version string - target string - want bool - }{ - { - version: "0.9.1", - target: "0.9.1", - want: true, - }, - { - version: "0.10.0", - target: "0.9.1", - want: true, - }, - { - version: "0.9.0", - target: "0.9.1", - want: false, - }, - } - for _, test := range tests { - result := IsVersionGreaterOrEqualThan(test.version, test.target) - if result != test.want { - t.Errorf("got result %v, want %v.", result, test.want) - } - } -} - -func TestIsVersionGreaterThan(t *testing.T) { - tests := []struct { - version string - target string - want bool - }{ - { - version: "0.9.1", - target: "0.9.1", - want: false, - }, - { - version: "0.10.0", - target: "0.8.0", - want: true, - }, - { - version: "0.23", - target: "0.22", - want: true, - }, - { - version: "0.8.0", - target: "0.10.0", - want: false, - }, - { - version: "0.9.0", - target: "0.9.1", - want: false, - }, - { - version: "0.22", - target: "0.22", - want: false, - }, - } - for _, test := range tests { - result := IsVersionGreaterThan(test.version, test.target) - if result != test.want { - t.Errorf("got result %v, want %v.", result, test.want) - } - } -} - -func TestSortVersion(t *testing.T) { - tests := []struct { - versionList []string - want []string - }{ - { - versionList: []string{"0.9.1", "0.10.0", "0.8.0"}, - want: []string{"0.8.0", "0.9.1", "0.10.0"}, - }, - { - versionList: []string{"1.9.1", "0.9.1", "0.10.0", "0.8.0"}, - want: []string{"0.8.0", "0.9.1", "0.10.0", "1.9.1"}, - }, - } - for _, test := range tests { - slices.SortFunc(test.versionList, func(a, b string) int { - return semver.Compare("v"+a, "v"+b) - }) - assert.Equal(t, test.versionList, test.want) - } -} +package version + +import ( + "slices" + "testing" + + "github.com/stretchr/testify/assert" + "golang.org/x/mod/semver" +) + +func TestIsVersionGreaterOrEqualThan(t *testing.T) { + tests := []struct { + version string + target string + want bool + }{ + { + version: "0.9.1", + target: "0.9.1", + want: true, + }, + { + version: "0.10.0", + target: "0.9.1", + want: true, + }, + { + version: "0.9.0", + target: "0.9.1", + want: false, + }, + } + for _, test := range tests { + result := IsVersionGreaterOrEqualThan(test.version, test.target) + if result != test.want { + t.Errorf("got result %v, want %v.", result, test.want) + } + } +} + +func TestIsVersionGreaterThan(t *testing.T) { + tests := []struct { + version string + target string + want bool + }{ + { + version: "0.9.1", + target: "0.9.1", + want: false, + }, + { + version: "0.10.0", + target: "0.8.0", + want: true, + }, + { + version: "0.23", + target: "0.22", + want: true, + }, + { + version: "0.8.0", + target: "0.10.0", + want: false, + }, + { + version: "0.9.0", + target: "0.9.1", + want: false, + }, + { + version: "0.22", + target: "0.22", + want: false, + }, + } + for _, test := range tests { + result := IsVersionGreaterThan(test.version, test.target) + if result != test.want { + t.Errorf("got result %v, want %v.", result, test.want) + } + } +} + +func TestSortVersion(t *testing.T) { + tests := []struct { + versionList []string + want []string + }{ + { + versionList: []string{"0.9.1", "0.10.0", "0.8.0"}, + want: []string{"0.8.0", "0.9.1", "0.10.0"}, + }, + { + versionList: []string{"1.9.1", "0.9.1", "0.10.0", "0.8.0"}, + want: []string{"0.8.0", "0.9.1", "0.10.0", "1.9.1"}, + }, + } + for _, test := range tests { + slices.SortFunc(test.versionList, func(a, b string) int { + return semver.Compare("v"+a, "v"+b) + }) + assert.Equal(t, test.versionList, test.want) + } +} diff --git a/memos_prod.db b/memos_prod.db new file mode 100644 index 0000000000000000000000000000000000000000..159e90adb13561c0365c22e76084c658383a62f1 GIT binary patch literal 4096 zcmWFz^vNtqRY=P(%1ta$FlG>7U}9o$P*7lCU|@t|AVoG{WYFvV#S79dK(-m98b?E5 nGz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nC=3Arqf-Z% literal 0 HcmV?d00001 diff --git a/memos_prod.db-shm b/memos_prod.db-shm new file mode 100644 index 0000000000000000000000000000000000000000..ad56e3d1518a97455c9c74ddb8980f0fdb0e32c7 GIT binary patch literal 32768 zcmeI*$8OY66o>JTWYPnKgc5r1Frn9w&>TL#uOHvP znHZ~%f9e0n{#fcqrFE;3Z@=p2zrTOu*)&C(Bb7)?q&3nOX^(V7IwM_??#T4WjL6JL zPh?i4H_{iG9hnoE8<`hL^JHtMW4-m$v$AKTXV&I#*J}G}&uj0=-Z{ITu4V7~=Xv%H z***2v`JeuaQ7i=%P(T3%6i`3`1r$&~0R-Q3tQR7c6P9j{aLF= z1qvq6&a#3{)FK-PI8(HjB}F-9`Y>j0`@7;umYW|WCOc7$_Qt;$W?AJ z$s?XO>_on}0(k|x*uybSah6M5<2Ltr%v9c+?Ngwk1-jYGaYi}EWv+9F`#d4-$zdr_ ze1WuEjHN(11=2oAmICDzNIQgC3Y1eI?Tu$CP)>ogE2O1BIR$z-z`=5k?$o6h=wpaO YrB@K3oC0YNY)gT13Z&iNtvmwX0V;n$p#T5? literal 0 HcmV?d00001 diff --git a/memos_prod.db-wal b/memos_prod.db-wal new file mode 100644 index 0000000000000000000000000000000000000000..63af6c02669a0eff2cc5087a0fb102af05850e34 GIT binary patch literal 453232 zcmeI*3w&HP*Q4w8HZp*&!^PI`tl9`lV zXfFMo<|Jp%{rR5foSFIeIsfClvhZMz>G^YVa?Z$+-G)b6o*7+x@oV>)k8JVxe9I?B z=~BnP_v*j&|G$U+>(%ZpZGot291Mj=m8j7smd?%1dB4#p=FJtoSYM(m6+`)nS5xat zd7Wu6H)qYq-zX4MbcQ$O^m7bvF8O)crKJ;Pl|_Fn?bQFK=z)SO_4nti1^s#Ly5Hr! zTlb*u!AvV+T$+IG?81tsmAafj(68=|>>3fra6lQ4hP2lMqv~jAATq3k)d5R#c-cYI znfi(qD|ClUQN=r=hE>HE4TOU6zh}9-JoP;uV^4iUo5vU*Yg}DkVl)Q)#+HsAPm`z1 z*xA+6Uf;FN*y`D4tncmF+|nVIYxi{Y)W{iqV!5d5ABaYb4J}P#8Dqz0(f78s88>wDXJjH@Hj@L)7Bs;;hD6{)H*Rs}&!G-ZPclCji{ocWM>VlJ~gm=mKh>ZB|09-U^=QsBFfM- z?Zlz3+PA+-Kpq%dqOVxGRCiTV%*8(z@Q)eNP5fiWC^A014j5y{SE~v^Wpvs;X`{1L zjDTO%slZ@B01O63qG~w3pvmG?#Vg@pU?|%>u_CWB6jr#FW~)1*_yZR4>x@ITGJVC$ zmAb1fnv4>SD!$=Su{X(~@-(O9_>;+%JS7sRdHQL0VrTXEnEymB3gVckGY{zWqv9P2 zd5sNin;Q}nVNv}vTyYW$Pi-Nr z4vH&o&^N7GPM>W|nHUKv)2?pGnPQd8RzBO+KUqZvEXm;|2U<$>6;)NbgIlz!rj;hF zjwtdiAniqIT7^rS6svR7AQD%2O+;IzcmtSqrYz^-)CGEKQF%ocyO&&7jZrQqugtE} z!ix5)Y-d;6E>FD!#!Fgu=&~Yx#j<6(YnCS%8qr2JTZZ)n> zncmW2TwT?%xvRatO}=y2ce$Hewt6;-x9?;fjZfA-4#eJHvt27=C*STsB;XB*&oC3y z=9}7n%5-h}oxKfhEpEB}&aTZp9(Rw}0qsT0R`K~IZC}KP6>XeWHOB(Mpql(36Tia6 ziJOAI-saaKASh0TDtTj{nNLF&-!a{w;s#Us!2CW{BN5q>?M2$uR z!J*V)eOkRtof4~`+L+`;Dg9jBsZJBs7N9FY-8C*Rg413Wrj>Hq#MScJUn7>RKC~uJJ9n?X zBw;4En4h+^9CM84?g@TqJ;ArPl+!EiGi|(Hrc6K9(@$Dtc;`&{pcD>`OsfmY6S=qB z(-k{I)lnrdGVSDyf1ICse+veDJ2Px*+FWBwB(f(I_74mzk>T_eYIRWAtwfdZzqI1~j>gZ&NZPC1 zwAz+FEmrSlGR%73y`8e8o}hB|^2A)9TUfEVI@^hvzGDNH^w)W@Zu~32>qC)@y1Q0*~0R#|0009ILKmdWoDWJs&;_V0?e5?9_x6b>@ z<0Z1J#03`T5vNoLAbo%;xq zKnx*(00IagfB*srAb8AzkmM^K7Zul zA=(Qhffzyn0R#|0009ILKmY**5I|rN3usLP;&FlZeX272+aLbNb+i{)#7CT>A%Fk^ z2q1s}0tg_000IagkQ7)V2jg*pQs*tdH$A+wj`jjcAchb?009ILKmY**5I_I{1Q1xn z0tQ*OcwFH63qEl7weE+8XfLpck2pm`009ILKmY**5I_I{1Q0+VDR71yjK>8W6%{qV zc;Mi3v=>MMF@yjD2q1s}0tg_000IagfWRUaI8&A_9v8Uy;`ZMMF@yjD2q1s}0tg_000IagfWRUaSSHIBj|(Vw9NBU316%%q_5zFe zh*LBK5I_I{1Q0*~0R#|0009J&0`HQ8@wmW!+s6u@{I~9(l()zQ#EWLOEO44v)n^3?Zuj6L-YZ60HC4&&FBAE3yde1=<)RT$b~yL_ZT~R+uDr19W7gWJ=$#Ac4D)} z*BhTro9+v%N;DK65VK^TuKEX}5o1G3lb9uCGaEgP^}TI9#?_H%crY3mRaaN7id5AY ztAe3DRn^tn`qjN-fv_4$T|T~;+*NI!#?4)xmZlD^psS~LxZ2p|Y4mh?I^3Ra4QqA4 zUv1pnVch6x^9V(EeYd-Qqo=&2T7Q4u<4r4dIf0;G-5c385{Rk;%6K%Sy&gz94_K1J z%MO~()K{!np*v*Kj+a32MFXK={O?(5$0|NHairo>vmYUiHjOSWFA8yVxuYJLP%x?n zqw>gU6(GKHjWoW?1JQ{wHN*5+4OyMsMvc*zSYM4XZSiUiIoIc2kqtR9yCpuf^x(2H z^c58qxA5RaBJh6+W!`)WGgpW{58KisC_~e< z6NkEL-~K8Ad0=dbzGCT8-BnF77ynqmKW0cb@sAy&h`bi0)q&J2Ku{T-woh6O$x<-_ zeo?0ag8>0B7#NAF;b|+5*W9WqZ7rhG3%@Zr~Dnns~YiYK+BZ@y@5x>qjWGmAy zp;ucp86_H3e8Zz+Z<0ghX->)UCzC6AO1#|*V*JEQ9O~JwhvQ>@C3^f91#wK&nFlnn z<*B3M9SM1j4Q-nn5)%^F+L?zvG0)V(k-(%nqv(m5%-Ug(zpG4L2(@t$@iro=e}*eg zV&SPRgw;VctOkA4s^#?A#*~SXkTShyCn{j9av5IBab&;xC#%SSB{{t0Kud|fqN+-F zaEn&ew98@FxV36|{&nWcibAE+Gdj>LH z;EnEPkGs{lI%RrGhjDdP$L6l~`ZoEQr@qVG+_KfPQGD=8R^<3(`GIZf{WaUQGIl-P z9f$O&x8K>dxyR$~5j&v0XxS=0Yo_gs_^_gl)2i24 zAQ)6YX`l)6U)mef~8odtyz7hR;=rj>8%GipTLH7+lL(_R*)m2%p|)$-b3BbKZ_v?fnG zcdx!AVJ5ejpSH9dbByQi34Ulj!MC@R(<}Y+%!!|V(jvnf_olW* zoNCvh{n6TqR!sd@T1&@9PrqmlnrUv?{4u#iqNSwm?81udO<q&I-1!RlN!SY3No zVa2hvrKGW{XwLlh8>`axbgCVAqQ${6HN-p(o2c5#XS;+ZTMnkRA{1|Fx$|qDWUCsEh+8iz*HxO=Sel+#Z_=h zg8%{uAbr>2wN}ai~#yDGhfqdx^zmMQYPwLdzo%F6>sZdxPz*n?go<3mbV@ydrO zSZnJywzqU#U{x-#m@jB`weGPgo1CNL6P`7Vb(3Rz$A-6#Z&MnZ+%0=u?p^(D+nTrg zb~%UoJ6dXMJDaxjjSRVkQ-QRK#|5ryHhJ$d=YBnQAHmBxhL;z#Bs-4)0tg_000Iag zfB*srAbm*H+Oj&yFA^^13jBtJssWqD#PkvSd9$#gm$XINaeaq_fgBB%lVP zEy2N1<+^>9@~d+FkQgDh)E=4)jEpF29c#?S)qUbYt)V>;V@HqCVqRljZxkbH?dy$u zYwgv>`mwPQwNLf72BK>nHs=~!t#Ng0b5DC)jd3KfQ#CfJzMY|JqkA|U8dcX??6qse zD#Tj5l|dyOh%e&t4<)C`f&|9u{eDqy!B%Mzj}MRwS>y!2x;x-gdnU$IF~zS&c1A;E za(qb68Q)Wjd96j8+Zz@;u7<@Vu?5wb*nH*w{g=z<5fq6&(O$s1^4U8txozwpWA_of zlw)}5=!c#;5I_I{1Q0*~0R#|0009ILKwtp~oRwc(U7Q}c5qmA~BS^Ft`1NJ49KQ5> zKiwzW3*;JpFP>8F6ihuwD2q1s}0tg_000IagfWV><=+u?wxQfN23eI0% zbdjsA!M$TsbA!9zI%#uRqur6ocAqL9T(DmDv4YU5zm{?_izRTx%P&4w`IsuhnEXdli${tT;>#zr&(B zymdai!z%OXWzRckbFQ=5*4Uj^v$@XUv>YYxU~+DotJY~I@1T} zbiEcA;CTe|^xDU6A%Fk^2q1s}0tg_0KumzRz`RO;e>~44ATBT;o=1=t7dV_heB)1U z{`f~|FTiyc0R#|0009ILKmY**=D)!4#0B^wI>%o`)7uNEiej&|dmSd#?{JvxgAS|7 zTkCL{oMyjW9aJ1Xo6A0XdjW@io!Pv`VXL**xvaHyM`nKmY**5I_I{1P~xDu;AMZ5Eq!^FpYK}LE3W)mFuqB zko!RGQW+P>HM}IBQ}`0s8UzqP009ILKmY**5I_I{1Q1vR0!896g*y3|!rZLSDYVa*|)p9w=ZzyutoNgDS6h7xXXYEs4g1?r}DaoeIcb$*k} zTxT(PEe^lcWp~;K&5qgf4%V$R*R8X<*3_CU4ztr~uAMdSVCvk?I;+dda|&lZr|`!; zANaxg(p&SixB$;7JcZXYHiZBJ2q1s}0tg_000PG@KwMzK=N%+2Fvnq8@_M~ylh@@P^ws&jR>fzXy}f|dvd(5-&)g_yN&h& zGvflk+Vbh&-uaJ@JxhCmQ++*Sdk7$a00IagfB*srAaLvg#03_7djaACa~!6b85dak z?SuQa+fC!N7dZAS5=$U}00IagfB*srAb`NB7C4@`0AEDs_={+IdjX5;Fk9-(s%cQQ znoV}qZ!;-%s?FqZsSc;l@AnNlEwi^5usPS+ENg5|r`>9;wOEdlUm!VmU7gcvr@g?; zxWFBM{hnLj{N%e=(q7HyEiIZdwGI-g0j9#E|!V}RFZJ4$;2hk2d7c8$g9vf3@qx})V6NY3qYxtu(YVE@dx zz@t}w?QatPxWF8TX=cU+Ui^t= z?ehP4d@bz-j{SahfbHi=)m_YqL6hv$hv-tuxok_5!s|r`2II+Z?mz7f6}gW_7ykF7gY^ zj0^l~UqR2Me;9s~_5!E+ddBt;KmY**5I_I{1Q0;r*ae6SEco^U#0BO!OrymG3gx-C z;gObSM%P~a+Gkh(_{Q&!-)59?fn38&IfhroFFFJeKmY**5I_I{1Q0*~0R#|O_yR?_ zdCPR8>S!oWughCjJRVWQqEN-MVDY%XU+(^!+{U5}Ka+8RJj2;JhPw=xi9d7*Ab)Q zFPDAC=C1boHl?$xWovzpXJ6%5I5eh)qZ5_u_U+%_nLD+f^Tm3s{e!_Kf8$nnWRtto z-xr+h+uhyU7dUd*BKz2ShLuE@WsSO&HM-gw+&eZkH@N$)lQx$%+8vo}_o;y+H?5a_ zY>nHLkrBn{Rf9@N<~53gS|a*$;&FjHzWJ96{Hxw7mm~8Gcjp+MFuWlC&>?^T0tg_0 z00IagfB*srAb`L;5I8T-rOOs| z@(URLm?M7Z5I_I{1Q0*~0R#|0009ILKwz;5lW8;?9G+Y9K33oMqSPB{=j009ILKmY**5I_I{1Q3V`EGZCSf#TG-fL=^U#0Bn~ zyzS;|KQ{0wt-V0m!#U!I4gmxZKmY**5I_I{1Q3{~0>|?_0utcQaRU7G=M*{>#iH73 zZKgrHx7K7A&l)r-KC|6a>#Fq+TFk1?R$EtDW2{v7js?PMq&`}?uF`6@)|$jTR!fiB zwa#i@XRljhx4RsU+B)meo>Q2Z+v%vQv)Xx1;mqe0e&-`ME&coEzpv2Z0!vzQ#19<; z2q1s}0tg_000IagFi!=D3oQ8O6cQJh<1o$4=M=uDu`p6UQK!WP@(j;v&nXmt=ny~v z0R#|0009ILKmY**5I|r73Y6yMttbwwiZ2=n1v5XV@GM!Zc;3PF-#hY(?wVGAEbrix zIff?}V4>M%1Q0*~0R#|0009ILKmY**PFsN*U13gsvFF^tk^6o=s*Z*tYcoH;;Q3o_ zfBCDQ5KK!&pU5w8{&Sxm{KAX-|0QH?1xEk@1Q0*~0R#|0009ILKw!ZN zR27KOK=Ip(3lz#i#@h>+dM~yqefR!Wwin1VJQKT*;F$%>z>Xt;00IagfB*srAb&WciW>x$>5dj0$UWZs2-;s<`Ky0<&ixqo5zLRn&0ZjY z00IagfB*srAbxUnfae@3L z-_9}IWw^|6wiuv8009ILKmY**5I_I{1Q0-A{tC3_m*%*N^YhO=cX`o88+#Og>(=qz z!+TuKt!nqKUbTK=R0$k;;J;!i(Pjdn*S+kI-_$W7~IA6w%#Wn@G#dexv( zl6j5dkjh&I63-*3zxbLTU8n!f&2nVE;f5T;6NVQIHyG}ozlWYZLjVB;5I_I{1Q0*~ z0R#|0V37%&m*>)D4sPVjNtr_xd2&+b=tJ(gd9LEjVFV#pD)r*+1#bOb+v=;X`^mmo z-ofW{41Y8{zsPhc4gv@ufB*srAb&@By}7;J)6r9|lP~k) zF9k%I=o9S)4(v>WJkXd``v%o;!`OC@KO7AbTcexy_H~3jeM7r9I{F)%$M-aJhzx;$mVIiLz&&9#sAf)|N8Z7cly~s;H=e%n zmv4S@t-Oz*z%UulJ2*+^!IM+?^T0tg_000IagfB*srAb`L^5Qya&Ohg6pjxq0G z@w;Dq^ETVp4v}|oAslS>5dj1cKmY**5I_I{1Q0*~fmsEzdKmY**5I_I{1Q0*~ z0R#|0VEzfj@(Lz`0{JJHcW`Lg(}gR(_QFc?4$i+r%^o3u00IagfB*srAba*q@eDRB4{L-%uzxqBI7tojgS6bdd@sbV!1Q0*~0R#|0009ILKwu#XH0o3G z1@`yu9p32ai0<9f<=xV?v%Y(KPkpFI-B=2DNcwnf(vnLcda_{A`k8vqk zvIOR)WC^tP4+fk3ja%K3P3}(ryv;lKi4Rrwe(2UqN9BD4dc(%lyn`FbJh%`~e)bsw z1Q0*~0R#|0009ILK;WGgkQoFsM_cp@F7M!-q1#`}fBw2r*009IL zKmY**5I_I{1Q0*~f%za%ULX?<>Jy0uPh#G|4{d0@;=A|Vy-v0lC@|cU$U7(o=@38w z0R#|0009ILKmY**5I|tA1!8#x6ET5;lbm<(t^Q?O?s@uyP2?S%>jTa95kLR|1Q0*~ z0R#|0009ILIAMV-c?XNK<{d0sQm(t^&sTY6T%f4@mT7qh#RxhC5I_I{1Q0*~0R#|0 z0D)5{&{&j`FVHbGUaJO&Mu$R;jrLugf$)kyn~~PQ2KA#Po)YR zR>Z%|`2rjBQrNd|>D(J?>e%J8dYrcLMW1)@fA4fu4Lv^kRe2vlk)c}V9jrFIV7S3B zX&5k&dGOSo`)mmT1Q0*~0R#|0009ILKwy3e$P9v+Lo-E-DevHC{`~oGKDzamOJsY2 zLc<*?c?ZP{Is_0v009ILKmY**5I_I{1Q3`5f$~C`Xs{@eXz-oOJNV)^{&4dKV_17m zVWHu0O5Q>7f(`)$5I_I{1Q0*~0R#|0009I}tw1cVU?LI)3-78&sVSN5~# z3ncGgYL>t~VKt~`P8HaiKP7(d@}i42_9*_=t>e3g_qdu{)$U!rYW)Ox2Q$Nosw`6s zp0nYRmS;xSUi{kgckYN>diERpuG_bNf2S@5&ehi7-m$5S=ig#RxhC5I_I{ z1Q0*~0R#|0009ILIOziAMKaM~Ng~nUT;&~n^ueb-{*{LxyGFJbC^8(FmUmE$phExw z1Q0*~0R#|0009ILKmdW0ClJdkmueCI0(G*VN{2U;ISCti2Vb8x zUtnWlN?yk9@%}FN#!c47=E)&tW7BBJwWDF%PLV6{RoTzF9`X+M1twHLou{KosE@4oAjAItUv#fFI)c?ZQPIs_0v z009ILKmY**5I_I{1Q0k;f%0ORXs|SqXmFn79W4EF`#mpT^}!cpdx2uZt{Hg;#V9%i z5I_I{1Q0*~0R#|0009ILI9`ERUcp2>pm?6;9lWZ&I(*yMP|J_WkJ zckl2$0DHJ>(r64-7SU_JjgQ?!8?0F)k%bmcZO8 z_VYzPOl$vOu*u)J)g9U7?)1;wyn{QQyyZ$=^b22?_YssWc{EGjK{0_20R#|0009IL zKmY**5I_Kdxfalp3ucTbm63NaCHjziZl0^y)z;wNv8lPi-EW;G@8Ii0j*b8Fcfb3- zY%fq^*pVUcpcqMq00IagfB*srAb>y&ULq3>mL(Dm&d=16.8.0' + react-dom: '>=16.8.0' + + react-dom@19.2.4: + resolution: {integrity: sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==} + peerDependencies: + react: ^19.2.4 + + react@19.2.4: + resolution: {integrity: sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==} + engines: {node: '>=0.10.0'} + + scheduler@0.27.0: + resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} + +snapshots: + + react-colorful@5.6.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4): + dependencies: + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + react-dom@19.2.4(react@19.2.4): + dependencies: + react: 19.2.4 + scheduler: 0.27.0 + + react@19.2.4: {} + + scheduler@0.27.0: {} diff --git a/node_modules/.pnpm/node_modules/react b/node_modules/.pnpm/node_modules/react new file mode 120000 index 000000000..f3ed04ceb --- /dev/null +++ b/node_modules/.pnpm/node_modules/react @@ -0,0 +1 @@ +/mnt/d/OPEN SOURCE PROJECTS/memos/node_modules/.pnpm/react@19.2.4/node_modules/react/ \ No newline at end of file diff --git a/node_modules/.pnpm/node_modules/react-dom b/node_modules/.pnpm/node_modules/react-dom new file mode 120000 index 000000000..379e71009 --- /dev/null +++ b/node_modules/.pnpm/node_modules/react-dom @@ -0,0 +1 @@ +/mnt/d/OPEN SOURCE PROJECTS/memos/node_modules/.pnpm/react-dom@19.2.4_react@19.2.4/node_modules/react-dom/ \ No newline at end of file diff --git a/node_modules/.pnpm/node_modules/scheduler b/node_modules/.pnpm/node_modules/scheduler new file mode 120000 index 000000000..eff7d0290 --- /dev/null +++ b/node_modules/.pnpm/node_modules/scheduler @@ -0,0 +1 @@ +/mnt/d/OPEN SOURCE PROJECTS/memos/node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/ \ No newline at end of file diff --git a/node_modules/.pnpm/react-colorful@5.6.1_react-_30faa463c7a46a636667ecc41211c837/node_modules/react b/node_modules/.pnpm/react-colorful@5.6.1_react-_30faa463c7a46a636667ecc41211c837/node_modules/react new file mode 120000 index 000000000..f3ed04ceb --- /dev/null +++ b/node_modules/.pnpm/react-colorful@5.6.1_react-_30faa463c7a46a636667ecc41211c837/node_modules/react @@ -0,0 +1 @@ +/mnt/d/OPEN SOURCE PROJECTS/memos/node_modules/.pnpm/react@19.2.4/node_modules/react/ \ No newline at end of file diff --git a/node_modules/.pnpm/react-colorful@5.6.1_react-_30faa463c7a46a636667ecc41211c837/node_modules/react-colorful/ACKNOWLEDGMENTS b/node_modules/.pnpm/react-colorful@5.6.1_react-_30faa463c7a46a636667ecc41211c837/node_modules/react-colorful/ACKNOWLEDGMENTS new file mode 100644 index 000000000..235b4c312 --- /dev/null +++ b/node_modules/.pnpm/react-colorful@5.6.1_react-_30faa463c7a46a636667ecc41211c837/node_modules/react-colorful/ACKNOWLEDGMENTS @@ -0,0 +1,5 @@ +## Acknowledgements + +- Special thanks @RyanChristian4427 who has rewritten the library in TypeScript. +- In order to avoid tree-shaking problems, and provide better TS support, `rgbToHex` and `hexToRgb` methods were copied from [@swiftcarrot/color-fns](https://github.com/swiftcarrot/color-fns) (MIT License). +- `hsvToRgb` modified from https://axonflux.com/handy-rgb-to-hsl-and-rgb-to-hsv-color-model-c. diff --git a/node_modules/.pnpm/react-colorful@5.6.1_react-_30faa463c7a46a636667ecc41211c837/node_modules/react-colorful/CHANGELOG.md b/node_modules/.pnpm/react-colorful@5.6.1_react-_30faa463c7a46a636667ecc41211c837/node_modules/react-colorful/CHANGELOG.md new file mode 100644 index 000000000..8b77466d9 --- /dev/null +++ b/node_modules/.pnpm/react-colorful@5.6.1_react-_30faa463c7a46a636667ecc41211c837/node_modules/react-colorful/CHANGELOG.md @@ -0,0 +1,257 @@ +### 5.6.1 + +- Update export settings to fix Jet 28 issues (via #191) + +### 5.6.0 + +- Add new `HexAlphaColorPicker` component (via #186) +- Fix types export for TYpeScript 4.7. Thanks to @AnotherHermit (via #189) +- Improve ARIA attribute values for sliders. Thanks to @aitchiss (via #177) + +### 5.5.1 + +- Fix embedding into `