feat(deploy): production deployment setup and fixes

- Debian-based api image (bookworm-slim), docker/debian mirrors, prisma
  binaryTargets for openssl 3.0
- nginx: admin SPA under /admin, TLS via acme.sh (ZeroSSL) + auto-renewal
  cron, http->https redirect
- prisma: add origin_goods.delisted migration, sync missing schema
  (good_image/tag_font_color/good_tags), fix users.createdAt Timestamptz
- api: CORS wildcard reflection, helmet CORP cross-origin, price
  backfill in persistProductDetail, categoryIcon ancestor fallback,
  mediaByColor per-color gallery in public goods detail
- admin: /admin base path (vite + router)
- import-data.mjs: udt_name casting, serial sequence advance fix
This commit is contained in:
yeuimu
2026-08-26 14:23:09 +08:00
parent be0b90e68f
commit 6c61a4e871
982 changed files with 74156 additions and 179393 deletions
@@ -1,109 +0,0 @@
# Use Global Properties Sparingly in Plugins
## Rule
When using `app.config.globalProperties` in Vue plugins, use them sparingly and with clear naming conventions. Excessive global properties lead to confusion, naming conflicts, and debugging difficulties.
## Why This Matters
1. **Implicit dependencies**: Global properties make component dependencies invisible, making code harder to understand and maintain.
2. **Naming collisions**: Multiple plugins may try to use the same property name (e.g., `$http`, `$api`), causing silent overwrites.
3. **Debugging difficulty**: When issues arise, tracing back to which plugin provides a global property is challenging.
4. **IDE limitations**: Global properties may not have proper autocomplete or type checking without careful configuration.
5. **Testing complexity**: Global state is harder to mock and isolate in unit tests.
## Bad Practice
```typescript
// Too many global properties from various plugins
app.config.globalProperties.$http = axios
app.config.globalProperties.$api = apiClient
app.config.globalProperties.$auth = authService
app.config.globalProperties.$translate = i18n.translate
app.config.globalProperties.$format = formatters
app.config.globalProperties.$utils = utilities
app.config.globalProperties.$config = appConfig
app.config.globalProperties.$logger = logger
// In component - where did all these come from?
export default {
mounted() {
this.$logger.info('Mounted')
const data = await this.$http.get(this.$config.apiUrl)
this.$api.process(this.$utils.transform(data))
}
}
```
## Good Practice
```typescript
// Use provide/inject for most functionality
export default {
install(app, options) {
// Provide services via injection
app.provide('api', apiClient)
app.provide('auth', authService)
app.provide('i18n', i18n)
// Reserve globalProperties for truly global template helpers
// that are used extensively in templates across the app
app.config.globalProperties.$t = i18n.translate // Common convention
}
}
// In component - explicit dependencies
<script setup>
import { inject } from 'vue'
const api = inject('api')
const auth = inject('auth')
</script>
<template>
<!-- $t is acceptable for common template-only usage -->
<h1>{{ $t('welcome') }}</h1>
</template>
```
## Naming Conventions
If you do use globalProperties:
1. **Use `$` prefix**: This is the Vue convention and avoids conflicts with component data/methods
2. **Use unique prefixes for your library**: e.g., `$myLib_translate` for third-party plugins
3. **Document all global properties**: Keep a central registry of what each plugin provides
```typescript
// Good: namespaced to avoid conflicts
app.config.globalProperties.$myPlugin = {
translate: (key) => /* ... */,
format: (value) => /* ... */
}
// Usage
{{ $myPlugin.translate('key') }}
```
## Auditing Global Properties
You can inspect all global properties for debugging:
```typescript
console.log(app.config.globalProperties)
```
## When Global Properties Are Acceptable
1. **Template-only utilities** used very frequently (like `$t` for translations)
2. **Legacy migration** when transitioning from Vue 2
3. **Libraries that need Options API compatibility** (but prefer also providing inject)
## References
- [Vue.js Plugins Documentation](https://vuejs.org/guide/reusability/plugins.html)
- [Vue.js Global Properties](https://vuejs.org/api/application.html#app-config-globalproperties)