Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bb7a4c7361 | ||
|
|
17d19f9172 | ||
|
|
b35b71470d | ||
|
|
ccdc6350a1 | ||
|
|
7fea799087 | ||
|
|
e6b64b39f2 | ||
|
|
a457186f46 | ||
|
|
2d5b8b094f | ||
|
|
ef7c4e774d | ||
|
|
cc36301638 | ||
|
|
5dd632d4d3 | ||
|
|
4d70f16b69 | ||
|
|
2ddee6b8f8 | ||
|
|
aa530b0ce3 | ||
| cdd0ac32de | |||
|
|
d98ec76dc0 | ||
| 3c35e14c3d | |||
|
|
c0deea9318 | ||
| 915e995ab7 | |||
|
|
0e42e6f2a9 | ||
| 39e4bcab6c | |||
|
|
69a1046ff4 | ||
| ceaf459d97 | |||
|
|
d9a5dbafd6 | ||
|
|
86e4853709 | ||
|
|
2adf2475fa | ||
| 9dbba04408 | |||
|
|
240cdda68f | ||
|
|
ce48e54c03 |
5
.gitea/workflows/README.md
Normal file
5
.gitea/workflows/README.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
docker exec -it gitea-runner bash
|
||||||
|
# 然后在容器里安装 Node.js
|
||||||
|
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
|
||||||
|
apt-get install -y nodejs
|
||||||
|
node -v
|
||||||
104
.gitea/workflows/server-build.yml
Normal file
104
.gitea/workflows/server-build.yml
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
name: Build and Push Server Docker Image
|
||||||
|
|
||||||
|
# 手动触发 workflow:从哪个分支运行,就打包哪个分支的代码
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-and-push:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
# 1️⃣ Checkout 仓库代码
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
# 需要能 push tag(请在仓库 Secrets 配置 RUNNER_TOKEN)
|
||||||
|
token: ${{ secrets.RUNNER_TOKEN }}
|
||||||
|
persist-credentials: true
|
||||||
|
|
||||||
|
# 2️⃣ 自动递增 tag 并推送回 Gitea 仓库(默认按 vX.Y.Z 的 patch +1)
|
||||||
|
- name: Auto bump tag and push to repository
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# 配置提交信息(用于创建注释 tag)
|
||||||
|
git config user.name "gitea-actions"
|
||||||
|
git config user.email "actions@local"
|
||||||
|
|
||||||
|
# 确保本地有最新 tags
|
||||||
|
git fetch --tags --force
|
||||||
|
|
||||||
|
# 取最新的 semver tag(vX.Y.Z),按版本号排序
|
||||||
|
LATEST_TAG="$(git tag --list 'v*' --sort=-v:refname | head -n 1 || true)"
|
||||||
|
echo "LATEST_TAG=${LATEST_TAG}"
|
||||||
|
|
||||||
|
if [[ -z "${LATEST_TAG}" ]]; then
|
||||||
|
NEXT_TAG="v1.0.0"
|
||||||
|
else
|
||||||
|
if [[ "${LATEST_TAG}" =~ ^v([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then
|
||||||
|
MAJOR="${BASH_REMATCH[1]}"
|
||||||
|
MINOR="${BASH_REMATCH[2]}"
|
||||||
|
PATCH="${BASH_REMATCH[3]}"
|
||||||
|
NEXT_TAG="v${MAJOR}.${MINOR}.$((PATCH + 1))"
|
||||||
|
else
|
||||||
|
# 如果最新 tag 不符合 vX.Y.Z,回退到 v1.0.0,避免误解析
|
||||||
|
NEXT_TAG="v1.0.0"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "NEXT_TAG=${NEXT_TAG}"
|
||||||
|
|
||||||
|
# 如果 tag 已存在则直接复用(避免重复运行失败)
|
||||||
|
if git rev-parse -q --verify "refs/tags/${NEXT_TAG}" >/dev/null; then
|
||||||
|
echo "Tag ${NEXT_TAG} 已存在,跳过创建。"
|
||||||
|
else
|
||||||
|
git tag -a "${NEXT_TAG}" -m "Release ${NEXT_TAG}"
|
||||||
|
git push origin "${NEXT_TAG}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 输出给后续步骤使用
|
||||||
|
if [[ -n "${GITHUB_ENV:-}" ]]; then
|
||||||
|
echo "IMAGE_TAG=${NEXT_TAG}" >> "$GITHUB_ENV"
|
||||||
|
fi
|
||||||
|
# 兼容部分 Gitea Runner 环境变量命名
|
||||||
|
if [[ -n "${GITEA_ENV:-}" ]]; then
|
||||||
|
echo "IMAGE_TAG=${NEXT_TAG}" >> "$GITEA_ENV"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 3️⃣ 设置镜像仓库与镜像名称(自建 Registry / Docker Hub 都可)
|
||||||
|
- name: Set image variables
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
# 直接写死:推送到自建仓库
|
||||||
|
IMAGE_NAME="docker.damer.fun/damer/mindfulness-server"
|
||||||
|
|
||||||
|
if [[ -n "${GITHUB_ENV:-}" ]]; then
|
||||||
|
echo "IMAGE_NAME=$IMAGE_NAME" >> "$GITHUB_ENV"
|
||||||
|
fi
|
||||||
|
if [[ -n "${GITEA_ENV:-}" ]]; then
|
||||||
|
echo "IMAGE_NAME=$IMAGE_NAME" >> "$GITEA_ENV"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 4️⃣ 登录镜像仓库(自建 Registry / Docker Hub)
|
||||||
|
- name: Login to Docker Registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
# 与 IMAGE_NAME 的 registry 保持一致
|
||||||
|
registry: docker.damer.fun
|
||||||
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKER_TOKEN }}
|
||||||
|
|
||||||
|
# 5️⃣ 构建 Docker 镜像(使用 server/ 作为构建上下文)
|
||||||
|
- name: Build Docker Image
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
docker build -f server/Dockerfile -t "$IMAGE_NAME:$IMAGE_TAG" server
|
||||||
|
|
||||||
|
# 6️⃣ 推送 Docker 镜像到镜像仓库
|
||||||
|
- name: Push Docker Image
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
docker push "$IMAGE_NAME:$IMAGE_TAG"
|
||||||
431
.gitea/workflows/server-deploy.yml
Normal file
431
.gitea/workflows/server-deploy.yml
Normal file
@@ -0,0 +1,431 @@
|
|||||||
|
name: Deploy Server (SSH + Nginx 蓝绿)
|
||||||
|
|
||||||
|
# 手动触发:选择部署环境(dev/pro)并输入要部署的镜像 tag
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
env:
|
||||||
|
description: '部署环境'
|
||||||
|
type: choice
|
||||||
|
required: true
|
||||||
|
options:
|
||||||
|
- dev
|
||||||
|
- pro
|
||||||
|
tag:
|
||||||
|
description: '要部署的镜像 Tag(例如:v1.2.7)'
|
||||||
|
required: true
|
||||||
|
|
||||||
|
# 同一环境同一时间只允许一个部署在跑,避免互相覆盖
|
||||||
|
concurrency:
|
||||||
|
group: deploy-server-${{ github.event.inputs.env }}
|
||||||
|
cancel-in-progress: false
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
# 统一在 env 中注入变量,减少 runner 差异带来的兼容性问题
|
||||||
|
DEPLOY_ENV: ${{ github.event.inputs.env }}
|
||||||
|
DEPLOY_TAG: ${{ github.event.inputs.tag }}
|
||||||
|
|
||||||
|
# 镜像名(优先 vars.DOCKER_IMAGE;未配置则步骤里兜底)
|
||||||
|
DOCKER_IMAGE: ${{ vars.DOCKER_IMAGE }}
|
||||||
|
|
||||||
|
# 可选:明确 registry(私有仓库用)。未配置会从 DOCKER_IMAGE 推断
|
||||||
|
DOCKER_REGISTRY: ${{ vars.DOCKER_REGISTRY }}
|
||||||
|
|
||||||
|
# SSH:dev 用 secrets,pro 用 vars(按你现有用法)
|
||||||
|
SSH_HOST: ${{ github.event.inputs.env == 'dev' && secrets.DEV_SSH_HOST || vars.PRO_SSH_HOST }}
|
||||||
|
SSH_USER: ${{ github.event.inputs.env == 'dev' && secrets.DEV_SSH_USER || vars.PRO_SSH_USER }}
|
||||||
|
SSH_PORT: ${{ github.event.inputs.env == 'dev' && secrets.DEV_SSH_PORT || vars.PRO_SSH_PORT }}
|
||||||
|
SSH_KEY: ${{ github.event.inputs.env == 'dev' && secrets.DEV_SSH_KEY || secrets.PRO_SSH_KEY }}
|
||||||
|
# 推荐把私钥做成 base64(单行)存到 Secrets,避免多行变量丢换行
|
||||||
|
SSH_KEY_B64: ${{ github.event.inputs.env == 'dev' && secrets.DEV_SSH_KEY_B64 || secrets.PRO_SSH_KEY_B64 }}
|
||||||
|
|
||||||
|
# Nginx upstream 配置(建议放到 vars)
|
||||||
|
NGINX_UPSTREAM_FILE: ${{ vars.NGINX_UPSTREAM_FILE }}
|
||||||
|
NGINX_UPSTREAM_NAME: ${{ vars.NGINX_UPSTREAM_NAME }}
|
||||||
|
|
||||||
|
# 蓝绿端口(宿主机端口,建议放到 vars;未配置则脚本内有默认值)
|
||||||
|
BLUE_PORT: ${{ vars.BLUE_PORT }}
|
||||||
|
GREEN_PORT: ${{ vars.GREEN_PORT }}
|
||||||
|
|
||||||
|
# 容器内监听端口(FastAPI 常用 8000;未配置则默认 8000)
|
||||||
|
CONTAINER_PORT: ${{ vars.CONTAINER_PORT }}
|
||||||
|
|
||||||
|
# 健康检查路径(未配置则默认 /health;如果你没有 health 接口,可改为 /docs 或 /)
|
||||||
|
HEALTHCHECK_PATH: ${{ vars.HEALTHCHECK_PATH }}
|
||||||
|
|
||||||
|
# 可选:远端 env 文件路径(例如 /opt/mindfulness-server/.env.prod),存在则 docker run --env-file
|
||||||
|
REMOTE_ENV_FILE: ${{ vars.REMOTE_ENV_FILE }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: 配置 SSH Key(密钥登陆)
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# 镜像名兜底(与 .gitea/workflows/server-build.yml 的默认一致)
|
||||||
|
if [[ -z "${DOCKER_IMAGE:-}" ]]; then
|
||||||
|
DOCKER_IMAGE="docker.damer.fun/damer/mindfulness-server"
|
||||||
|
fi
|
||||||
|
if [[ -n "${GITHUB_ENV:-}" ]]; then
|
||||||
|
echo "DOCKER_IMAGE=${DOCKER_IMAGE}" >> "$GITHUB_ENV"
|
||||||
|
fi
|
||||||
|
if [[ -n "${GITEA_ENV:-}" ]]; then
|
||||||
|
echo "DOCKER_IMAGE=${DOCKER_IMAGE}" >> "$GITEA_ENV"
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p ~/.ssh
|
||||||
|
chmod 700 ~/.ssh
|
||||||
|
|
||||||
|
# 从 Secrets 写入私钥(推荐使用 *_SSH_KEY_B64)
|
||||||
|
SSH_KEY_PATH="${HOME}/.ssh/id_rsa"
|
||||||
|
if [[ -n "${SSH_KEY_B64:-}" ]]; then
|
||||||
|
# 兼容两种常见误配置:
|
||||||
|
# 1) *_SSH_KEY_B64 里其实粘贴的是“原始私钥”(包含 -----BEGIN ... PRIVATE KEY-----)
|
||||||
|
# 2) base64 值在粘贴/保存过程中混入空白或其他无关字符
|
||||||
|
if printf '%s' "${SSH_KEY_B64}" | grep -qE 'BEGIN[[:space:]].*PRIVATE[[:space:]]KEY'; then
|
||||||
|
echo "提示:检测到 *_SSH_KEY_B64 看起来是原始私钥内容,将按原始私钥写入(建议你改用真正的 base64 单行值)。"
|
||||||
|
echo "SSH_KEY_B64 字符数(原始):${#SSH_KEY_B64}"
|
||||||
|
printf '%s' "${SSH_KEY_B64}" | tr -d '\r' > "${SSH_KEY_PATH}"
|
||||||
|
else
|
||||||
|
CLEAN_B64="$(printf '%s' "${SSH_KEY_B64}" | tr -d '\r\n\t ')"
|
||||||
|
echo "SSH_KEY_B64 字符数(原始/清理后):${#SSH_KEY_B64}/${#CLEAN_B64}"
|
||||||
|
if ! printf '%s' "${CLEAN_B64}" | base64 -d -i | tr -d '\r' > "${SSH_KEY_PATH}"; then
|
||||||
|
echo "私钥 base64 解码失败:"
|
||||||
|
echo "- 请确认你在 Gitea Secrets 配置的 *_SSH_KEY_B64 是“单行 base64 字符串”,不要带引号/前后空格。"
|
||||||
|
echo "- 推荐用仓库里的脚本生成并复制:node scripts/ssh-key-to-b64.mjs ~/.ssh/你的私钥 --clipboard"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "使用 SSH_KEY(原始私钥)写入。SSH_KEY 字符数:${#SSH_KEY}"
|
||||||
|
printf '%s' "${SSH_KEY}" | tr -d '\r' > "${SSH_KEY_PATH}"
|
||||||
|
fi
|
||||||
|
chmod 600 "${SSH_KEY_PATH}"
|
||||||
|
|
||||||
|
# 自检(不输出私钥内容,仅输出元信息,方便定位是否写入了错误文件/被截断)
|
||||||
|
echo "SSH_KEY_PATH=${SSH_KEY_PATH}"
|
||||||
|
KEY_BYTES="$(wc -c < "${SSH_KEY_PATH}" | tr -d ' ')"
|
||||||
|
KEY_LINES="$(wc -l < "${SSH_KEY_PATH}" | tr -d ' ')"
|
||||||
|
echo "SSH key 字节数:${KEY_BYTES}"
|
||||||
|
echo "SSH key 行数:${KEY_LINES}"
|
||||||
|
echo "SSH key 首行:$(head -n 1 "${SSH_KEY_PATH}" | tr -d '\r')"
|
||||||
|
echo "SSH key 末行:$(tail -n 1 "${SSH_KEY_PATH}" | tr -d '\r')"
|
||||||
|
if command -v stat >/dev/null 2>&1; then
|
||||||
|
# Ubuntu runner: stat -c;不同系统做兼容
|
||||||
|
if stat -c '%a %U %G %n' "${SSH_KEY_PATH}" >/dev/null 2>&1; then
|
||||||
|
echo "SSH key 权限:$(stat -c '%a %U %G %n' "${SSH_KEY_PATH}")"
|
||||||
|
else
|
||||||
|
echo "SSH key 权限:$(stat -f '%Lp %Su %Sg %N' "${SSH_KEY_PATH}" 2>/dev/null || true)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if command -v file >/dev/null 2>&1; then
|
||||||
|
echo "file(1) 识别:$(file "${SSH_KEY_PATH}")"
|
||||||
|
fi
|
||||||
|
if command -v sha256sum >/dev/null 2>&1; then
|
||||||
|
echo "SSH key sha256(前12位):$(sha256sum "${SSH_KEY_PATH}" | awk '{print substr($1,1,12)}')"
|
||||||
|
fi
|
||||||
|
echo "ssh 版本:$(ssh -V 2>&1 || true)"
|
||||||
|
echo "ssh-keygen 版本:$(ssh-keygen -V 2>&1 || true)"
|
||||||
|
echo "openssl 版本:$(openssl version 2>&1 || true)"
|
||||||
|
|
||||||
|
# 进一步校验:OpenSSH 私钥中间的 base64 块是否可解码(不输出内容)
|
||||||
|
if grep -q '^-----BEGIN OPENSSH PRIVATE KEY-----$' "${SSH_KEY_PATH}" && grep -q '^-----END OPENSSH PRIVATE KEY-----$' "${SSH_KEY_PATH}"; then
|
||||||
|
# 注意:不要用变量名 in(是 awk 关键字,部分实现会报语法错)
|
||||||
|
OPENSSH_B64_LEN="$(
|
||||||
|
awk '
|
||||||
|
BEGIN{in_block=0; n=0}
|
||||||
|
/^-----BEGIN OPENSSH PRIVATE KEY-----$/{in_block=1; next}
|
||||||
|
/^-----END OPENSSH PRIVATE KEY-----$/{in_block=0; exit}
|
||||||
|
in_block==1{gsub(/\r/,""); n+=length($0)}
|
||||||
|
END{print n}
|
||||||
|
' "${SSH_KEY_PATH}" 2>/dev/null || true
|
||||||
|
)"
|
||||||
|
if [[ -n "${OPENSSH_B64_LEN:-}" ]]; then
|
||||||
|
echo "OpenSSH base64 块字符数(合计):${OPENSSH_B64_LEN}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 该校验仅用于提示,不应阻断部署流程
|
||||||
|
if ! awk '
|
||||||
|
BEGIN{in_block=0}
|
||||||
|
/^-----BEGIN OPENSSH PRIVATE KEY-----$/{in_block=1; next}
|
||||||
|
/^-----END OPENSSH PRIVATE KEY-----$/{in_block=0; exit}
|
||||||
|
in_block==1{gsub(/\r/,""); print}
|
||||||
|
' "${SSH_KEY_PATH}" 2>/dev/null | tr -d '\n' | base64 -d >/dev/null 2>&1; then
|
||||||
|
echo "提示:OpenSSH 私钥的 base64 块无法解码(疑似内容被截断/损坏),将继续执行 ssh-keygen 校验定位。"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 额外信息:ssh-keygen -lf 的报错(不输出私钥内容)
|
||||||
|
if ! ssh-keygen -lf "${SSH_KEY_PATH}" >/dev/null 2>~/.ssh/ssh_key_fingerprint.err; then
|
||||||
|
echo "ssh-keygen -lf 报错:"
|
||||||
|
cat ~/.ssh/ssh_key_fingerprint.err || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 快速校验私钥是否可解析(不会输出私钥内容)
|
||||||
|
if ! ssh-keygen -y -f "${SSH_KEY_PATH}" >/dev/null 2>~/.ssh/ssh_key_check.err; then
|
||||||
|
echo "SSH 私钥无法解析。下面是 ssh-keygen 的报错(不包含私钥内容):"
|
||||||
|
cat ~/.ssh/ssh_key_check.err || true
|
||||||
|
echo
|
||||||
|
echo "常见原因:"
|
||||||
|
echo "- 你填的是公钥(.pub),不是私钥"
|
||||||
|
echo "- 私钥带口令(CI 无法交互输入 passphrase)"
|
||||||
|
echo "- 内容复制丢换行/被截断/不是正确的 base64"
|
||||||
|
echo
|
||||||
|
echo "推荐:生成一把“无口令”的部署专用私钥,并用 base64 存储到 Secrets(*_SSH_KEY_B64)。"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
SSH_PORT="${SSH_PORT:-22}"
|
||||||
|
if [[ -n "${GITHUB_ENV:-}" ]]; then
|
||||||
|
echo "SSH_PORT=${SSH_PORT}" >> "$GITHUB_ENV"
|
||||||
|
fi
|
||||||
|
if [[ -n "${GITEA_ENV:-}" ]]; then
|
||||||
|
echo "SSH_PORT=${SSH_PORT}" >> "$GITEA_ENV"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 预写 known_hosts,避免交互
|
||||||
|
ssh-keyscan -p "${SSH_PORT}" -H "${SSH_HOST}" >> ~/.ssh/known_hosts 2>/dev/null
|
||||||
|
|
||||||
|
- name: 验证 SSH 连接(快速定位公钥/用户/端口问题)
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
SSH_PORT="${SSH_PORT:-22}"
|
||||||
|
ssh -p "${SSH_PORT}" \
|
||||||
|
-i ~/.ssh/id_rsa \
|
||||||
|
-o StrictHostKeyChecking=yes \
|
||||||
|
-o BatchMode=yes \
|
||||||
|
-o IdentitiesOnly=yes \
|
||||||
|
"${SSH_USER}@${SSH_HOST}" 'echo "SSH_OK $(whoami)@$(hostname)"'
|
||||||
|
|
||||||
|
- name: 远程登录 Docker Registry(如需私有镜像)
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
|
||||||
|
DOCKER_TOKEN: ${{ secrets.DOCKER_TOKEN }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# 如果镜像是公开的,可不配 DOCKER_USERNAME/DOCKER_TOKEN;此步骤会自动跳过
|
||||||
|
if [[ -z "${DOCKER_USERNAME:-}" || -z "${DOCKER_TOKEN:-}" ]]; then
|
||||||
|
echo "未配置 DOCKER_USERNAME/DOCKER_TOKEN,跳过远程 docker login。"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
SSH_PORT="${SSH_PORT:-22}"
|
||||||
|
|
||||||
|
# 推断 registry:优先使用 DOCKER_REGISTRY;否则从 DOCKER_IMAGE 的第一个段推断
|
||||||
|
REG="${DOCKER_REGISTRY:-}"
|
||||||
|
if [[ -z "${REG}" ]]; then
|
||||||
|
FIRST_SEG="${DOCKER_IMAGE%%/*}"
|
||||||
|
if [[ "${FIRST_SEG}" == *.* || "${FIRST_SEG}" == *:* || "${FIRST_SEG}" == "localhost" ]]; then
|
||||||
|
REG="${FIRST_SEG}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [[ -z "${REG}" ]]; then
|
||||||
|
echo "无法推断 registry(看起来像 Docker Hub 公有镜像),跳过 docker login。"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
ssh -p "${SSH_PORT}" -i ~/.ssh/id_rsa -o StrictHostKeyChecking=yes -o IdentitiesOnly=yes \
|
||||||
|
"${SSH_USER}@${SSH_HOST}" bash -s -- "${DOCKER_TOKEN}" "${DOCKER_USERNAME}" "${REG}" <<'REMOTE'
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
TOKEN="$1"
|
||||||
|
USERNAME="$2"
|
||||||
|
REGISTRY="$3"
|
||||||
|
|
||||||
|
SUDO=""
|
||||||
|
if [[ "$(id -u)" -ne 0 ]] && command -v sudo >/dev/null 2>&1; then
|
||||||
|
SUDO="sudo"
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf '%s' "$TOKEN" | ${SUDO} docker login "${REGISTRY}" -u "$USERNAME" --password-stdin
|
||||||
|
REMOTE
|
||||||
|
|
||||||
|
- name: SSH 部署(Nginx 蓝绿切换)
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SSH_PORT="${SSH_PORT:-22}"
|
||||||
|
NGINX_UPSTREAM_NAME="${NGINX_UPSTREAM_NAME:-mindfulness_backend}"
|
||||||
|
NGINX_UPSTREAM_FILE="${NGINX_UPSTREAM_FILE:-/etc/nginx/conf.d/api.damer.fun.conf}"
|
||||||
|
BLUE_PORT="${BLUE_PORT:-8001}"
|
||||||
|
GREEN_PORT="${GREEN_PORT:-8002}"
|
||||||
|
CONTAINER_PORT="${CONTAINER_PORT:-8000}"
|
||||||
|
HEALTHCHECK_PATH="${HEALTHCHECK_PATH:-/health}"
|
||||||
|
|
||||||
|
echo "准备部署:${DOCKER_IMAGE}:${DEPLOY_TAG} -> ${DEPLOY_ENV} (${SSH_USER}@${SSH_HOST}:${SSH_PORT})"
|
||||||
|
|
||||||
|
ssh -p "${SSH_PORT}" -i ~/.ssh/id_rsa -o StrictHostKeyChecking=yes -o IdentitiesOnly=yes "${SSH_USER}@${SSH_HOST}" bash -s -- \
|
||||||
|
"${DOCKER_IMAGE}" "${DEPLOY_TAG}" "${NGINX_UPSTREAM_FILE}" "${NGINX_UPSTREAM_NAME}" "${BLUE_PORT}" "${GREEN_PORT}" "${CONTAINER_PORT}" "${HEALTHCHECK_PATH}" "${REMOTE_ENV_FILE:-}" <<'REMOTE'
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
IMAGE="$1"
|
||||||
|
TAG="$2"
|
||||||
|
UPSTREAM_FILE="$3"
|
||||||
|
UPSTREAM_NAME="$4"
|
||||||
|
BLUE_PORT="$5"
|
||||||
|
GREEN_PORT="$6"
|
||||||
|
CONTAINER_PORT="$7"
|
||||||
|
HEALTHCHECK_PATH="$8"
|
||||||
|
REMOTE_ENV_FILE="$9"
|
||||||
|
|
||||||
|
APP_DIR="/opt/mindfulness-server"
|
||||||
|
ACTIVE_FILE="${APP_DIR}/active_color"
|
||||||
|
mkdir -p "${APP_DIR}"
|
||||||
|
|
||||||
|
# 判断 sudo(如果非 root 且存在 sudo,则使用 sudo)
|
||||||
|
SUDO=""
|
||||||
|
if [[ "$(id -u)" -ne 0 ]] && command -v sudo >/dev/null 2>&1; then
|
||||||
|
SUDO="sudo"
|
||||||
|
fi
|
||||||
|
|
||||||
|
ACTIVE_COLOR="blue"
|
||||||
|
if [[ -f "${ACTIVE_FILE}" ]]; then
|
||||||
|
ACTIVE_COLOR="$(cat "${ACTIVE_FILE}" || echo blue)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "${ACTIVE_COLOR}" == "blue" ]]; then
|
||||||
|
NEW_COLOR="green"
|
||||||
|
NEW_PORT="${GREEN_PORT}"
|
||||||
|
OLD_COLOR="blue"
|
||||||
|
OLD_PORT="${BLUE_PORT}"
|
||||||
|
else
|
||||||
|
NEW_COLOR="blue"
|
||||||
|
NEW_PORT="${BLUE_PORT}"
|
||||||
|
OLD_COLOR="green"
|
||||||
|
OLD_PORT="${GREEN_PORT}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "当前在线:${ACTIVE_COLOR}(${OLD_PORT}),准备发布:${NEW_COLOR}(${NEW_PORT})"
|
||||||
|
|
||||||
|
# 拉取镜像
|
||||||
|
${SUDO} docker pull "${IMAGE}:${TAG}"
|
||||||
|
|
||||||
|
# 启动新颜色容器
|
||||||
|
${SUDO} docker rm -f "mindfulness-server-${NEW_COLOR}" >/dev/null 2>&1 || true
|
||||||
|
|
||||||
|
ENV_FILE_ARGS=()
|
||||||
|
if [[ -n "${REMOTE_ENV_FILE}" && -f "${REMOTE_ENV_FILE}" ]]; then
|
||||||
|
ENV_FILE_ARGS=(--env-file "${REMOTE_ENV_FILE}")
|
||||||
|
echo "将使用远端 env 文件:${REMOTE_ENV_FILE}"
|
||||||
|
elif [[ -n "${REMOTE_ENV_FILE}" ]]; then
|
||||||
|
echo "提示:REMOTE_ENV_FILE 已配置但文件不存在:${REMOTE_ENV_FILE}(将忽略 env-file)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
${SUDO} docker run -d \
|
||||||
|
--name "mindfulness-server-${NEW_COLOR}" \
|
||||||
|
--restart=always \
|
||||||
|
-p "${NEW_PORT}:${CONTAINER_PORT}" \
|
||||||
|
"${ENV_FILE_ARGS[@]}" \
|
||||||
|
"${IMAGE}:${TAG}"
|
||||||
|
|
||||||
|
# 健康检查
|
||||||
|
if [[ "${HEALTHCHECK_PATH}" != /* ]]; then
|
||||||
|
HEALTHCHECK_PATH="/${HEALTHCHECK_PATH}"
|
||||||
|
fi
|
||||||
|
HEALTH_URL="http://127.0.0.1:${NEW_PORT}${HEALTHCHECK_PATH}"
|
||||||
|
echo "健康检查:${HEALTH_URL}"
|
||||||
|
|
||||||
|
for i in $(seq 1 30); do
|
||||||
|
if command -v curl >/dev/null 2>&1; then
|
||||||
|
if curl -fsS "${HEALTH_URL}" >/dev/null; then
|
||||||
|
echo "健康检查通过"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
elif command -v wget >/dev/null 2>&1; then
|
||||||
|
if wget -q -O /dev/null "${HEALTH_URL}"; then
|
||||||
|
echo "健康检查通过"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "远端缺少 curl/wget,跳过 HTTP 健康检查"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$i" -eq 30 ]]; then
|
||||||
|
echo "健康检查失败:新版本未就绪,回滚并退出"
|
||||||
|
${SUDO} docker logs --tail 200 "mindfulness-server-${NEW_COLOR}" || true
|
||||||
|
${SUDO} docker rm -f "mindfulness-server-${NEW_COLOR}" || true
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
sleep 2
|
||||||
|
done
|
||||||
|
|
||||||
|
# 切换 Nginx upstream(在同一个 conf 文件中通过 backup 做主备切换)
|
||||||
|
if [[ ! -f "${UPSTREAM_FILE}" ]]; then
|
||||||
|
echo "未找到 Nginx upstream 配置文件:${UPSTREAM_FILE}"
|
||||||
|
${SUDO} docker rm -f "mindfulness-server-${NEW_COLOR}" || true
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! ${SUDO} grep -qE "upstream[[:space:]]+${UPSTREAM_NAME}[[:space:]]*\\{" "${UPSTREAM_FILE}"; then
|
||||||
|
echo "在 ${UPSTREAM_FILE} 中未找到 upstream:${UPSTREAM_NAME}"
|
||||||
|
${SUDO} docker rm -f "mindfulness-server-${NEW_COLOR}" || true
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! ${SUDO} grep -qE "server[[:space:]]+127\\.0\\.0\\.1:${BLUE_PORT}" "${UPSTREAM_FILE}"; then
|
||||||
|
echo "在 ${UPSTREAM_FILE} 中未找到 server 127.0.0.1:${BLUE_PORT}(请先按参考配置写入 upstream)"
|
||||||
|
${SUDO} docker rm -f "mindfulness-server-${NEW_COLOR}" || true
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if ! ${SUDO} grep -qE "server[[:space:]]+127\\.0\\.0\\.1:${GREEN_PORT}" "${UPSTREAM_FILE}"; then
|
||||||
|
echo "在 ${UPSTREAM_FILE} 中未找到 server 127.0.0.1:${GREEN_PORT}(请先按参考配置写入 upstream)"
|
||||||
|
${SUDO} docker rm -f "mindfulness-server-${NEW_COLOR}" || true
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 备份(回滚用)
|
||||||
|
BACKUP_FILE="${UPSTREAM_FILE}.bak.$(date +%s)"
|
||||||
|
${SUDO} cp -f "${UPSTREAM_FILE}" "${BACKUP_FILE}"
|
||||||
|
|
||||||
|
echo "切换 upstream:${UPSTREAM_NAME}(${OLD_PORT} -> ${NEW_PORT})通过 backup 切换"
|
||||||
|
|
||||||
|
TMP_FILE="$(mktemp)"
|
||||||
|
${SUDO} awk -v name="${UPSTREAM_NAME}" -v old="${OLD_PORT}" -v new="${NEW_PORT}" '
|
||||||
|
BEGIN { in_up = 0 }
|
||||||
|
$0 ~ ("^[[:space:]]*upstream[[:space:]]+" name "[[:space:]]*\\{[[:space:]]*$") { in_up = 1 }
|
||||||
|
in_up == 1 {
|
||||||
|
# 新端口:主(去掉 backup)
|
||||||
|
if ($0 ~ ("server[[:space:]]+127\\.0\\.0\\.1:" new)) {
|
||||||
|
gsub(/[[:space:]]+backup[[:space:]]*;/, ";")
|
||||||
|
}
|
||||||
|
# 旧端口:备(确保有 backup;)
|
||||||
|
if ($0 ~ ("server[[:space:]]+127\\.0\\.0\\.1:" old)) {
|
||||||
|
gsub(/[[:space:]]+backup[[:space:]]*;/, ";")
|
||||||
|
sub(/;[[:space:]]*$/, " backup;")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
in_up == 1 && $0 ~ /^[[:space:]]*\}[[:space:]]*$/ { in_up = 0 }
|
||||||
|
{ print }
|
||||||
|
' "${UPSTREAM_FILE}" > "${TMP_FILE}"
|
||||||
|
|
||||||
|
${SUDO} cp -f "${TMP_FILE}" "${UPSTREAM_FILE}"
|
||||||
|
rm -f "${TMP_FILE}"
|
||||||
|
|
||||||
|
# 校验并 reload nginx(失败则回滚并退出)
|
||||||
|
if ${SUDO} nginx -t; then
|
||||||
|
${SUDO} nginx -s reload
|
||||||
|
else
|
||||||
|
echo "Nginx 配置校验失败,回滚 upstream 配置并退出"
|
||||||
|
${SUDO} cp -f "${BACKUP_FILE}" "${UPSTREAM_FILE}" || true
|
||||||
|
${SUDO} nginx -t && ${SUDO} nginx -s reload || true
|
||||||
|
${SUDO} docker rm -f "mindfulness-server-${NEW_COLOR}" || true
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 记录当前在线颜色
|
||||||
|
echo "${NEW_COLOR}" | ${SUDO} tee "${ACTIVE_FILE}" >/dev/null
|
||||||
|
|
||||||
|
# 下线旧容器(切流后再停旧的)
|
||||||
|
${SUDO} docker rm -f "mindfulness-server-${OLD_COLOR}" >/dev/null 2>&1 || true
|
||||||
|
|
||||||
|
echo "部署完成:${NEW_COLOR} 已上线"
|
||||||
|
REMOTE
|
||||||
|
|
||||||
@@ -13,7 +13,9 @@ git pull
|
|||||||
|
|
||||||
# 创建自己的分支
|
# 创建自己的分支
|
||||||
git checkout -b 姓名拼写
|
git checkout -b 姓名拼写
|
||||||
|
# 生产密钥
|
||||||
|
|
||||||
|
ssh-keygen -t rsa -b 4096 -m PEM -N '' -f deploy_key_rsa
|
||||||
# 目录结构
|
# 目录结构
|
||||||
|
|
||||||
/mindfulness
|
/mindfulness
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
},
|
},
|
||||||
"ios": {
|
"ios": {
|
||||||
"supportsTablet": true,
|
"supportsTablet": true,
|
||||||
"bundleIdentifier": "com.anonymous.client"
|
"bundleIdentifier": "com.damer.mindfulness"
|
||||||
},
|
},
|
||||||
"android": {
|
"android": {
|
||||||
"adaptiveIcon": {
|
"adaptiveIcon": {
|
||||||
|
|||||||
@@ -59,5 +59,13 @@ target 'client' do
|
|||||||
:mac_catalyst_enabled => false,
|
:mac_catalyst_enabled => false,
|
||||||
:ccache_enabled => ccache_enabled?(podfile_properties),
|
:ccache_enabled => ccache_enabled?(podfile_properties),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# 生成并随归档产物携带 dSYM(用于崩溃符号化与 Upload Symbols Failed 修复)
|
||||||
|
installer.pods_project.targets.each do |target|
|
||||||
|
target.build_configurations.each do |build_config|
|
||||||
|
build_config.build_settings['DEBUG_INFORMATION_FORMAT'] = 'dwarf-with-dsym'
|
||||||
|
build_config.build_settings['DWARF_DSYM_FILE_SHOULD_ACCOMPANY_PRODUCT'] = 'YES'
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -3,9 +3,6 @@ PODS:
|
|||||||
- ExpoModulesCore
|
- ExpoModulesCore
|
||||||
- EXConstants (18.0.13):
|
- EXConstants (18.0.13):
|
||||||
- ExpoModulesCore
|
- ExpoModulesCore
|
||||||
- EXJSONUtils (0.15.0)
|
|
||||||
- EXManifests (1.0.10):
|
|
||||||
- ExpoModulesCore
|
|
||||||
- EXNotifications (0.32.16):
|
- EXNotifications (0.32.16):
|
||||||
- ExpoModulesCore
|
- ExpoModulesCore
|
||||||
- Expo (54.0.32):
|
- Expo (54.0.32):
|
||||||
@@ -33,177 +30,6 @@ PODS:
|
|||||||
- ReactCommon/turbomodule/core
|
- ReactCommon/turbomodule/core
|
||||||
- ReactNativeDependencies
|
- ReactNativeDependencies
|
||||||
- Yoga
|
- Yoga
|
||||||
- expo-dev-client (6.0.20):
|
|
||||||
- EXManifests
|
|
||||||
- expo-dev-launcher
|
|
||||||
- expo-dev-menu
|
|
||||||
- expo-dev-menu-interface
|
|
||||||
- EXUpdatesInterface
|
|
||||||
- expo-dev-launcher (6.0.20):
|
|
||||||
- EXManifests
|
|
||||||
- expo-dev-launcher/Main (= 6.0.20)
|
|
||||||
- expo-dev-menu
|
|
||||||
- expo-dev-menu-interface
|
|
||||||
- ExpoModulesCore
|
|
||||||
- EXUpdatesInterface
|
|
||||||
- hermes-engine
|
|
||||||
- RCTRequired
|
|
||||||
- RCTTypeSafety
|
|
||||||
- React-Core
|
|
||||||
- React-Core-prebuilt
|
|
||||||
- React-debug
|
|
||||||
- React-Fabric
|
|
||||||
- React-featureflags
|
|
||||||
- React-graphics
|
|
||||||
- React-ImageManager
|
|
||||||
- React-jsi
|
|
||||||
- React-jsinspector
|
|
||||||
- React-NativeModulesApple
|
|
||||||
- React-RCTAppDelegate
|
|
||||||
- React-RCTFabric
|
|
||||||
- React-renderercss
|
|
||||||
- React-rendererdebug
|
|
||||||
- React-utils
|
|
||||||
- ReactAppDependencyProvider
|
|
||||||
- ReactCodegen
|
|
||||||
- ReactCommon/turbomodule/bridging
|
|
||||||
- ReactCommon/turbomodule/core
|
|
||||||
- ReactNativeDependencies
|
|
||||||
- Yoga
|
|
||||||
- expo-dev-launcher/Main (6.0.20):
|
|
||||||
- EXManifests
|
|
||||||
- expo-dev-launcher/Unsafe
|
|
||||||
- expo-dev-menu
|
|
||||||
- expo-dev-menu-interface
|
|
||||||
- ExpoModulesCore
|
|
||||||
- EXUpdatesInterface
|
|
||||||
- hermes-engine
|
|
||||||
- RCTRequired
|
|
||||||
- RCTTypeSafety
|
|
||||||
- React-Core
|
|
||||||
- React-Core-prebuilt
|
|
||||||
- React-debug
|
|
||||||
- React-Fabric
|
|
||||||
- React-featureflags
|
|
||||||
- React-graphics
|
|
||||||
- React-ImageManager
|
|
||||||
- React-jsi
|
|
||||||
- React-jsinspector
|
|
||||||
- React-NativeModulesApple
|
|
||||||
- React-RCTAppDelegate
|
|
||||||
- React-RCTFabric
|
|
||||||
- React-renderercss
|
|
||||||
- React-rendererdebug
|
|
||||||
- React-utils
|
|
||||||
- ReactAppDependencyProvider
|
|
||||||
- ReactCodegen
|
|
||||||
- ReactCommon/turbomodule/bridging
|
|
||||||
- ReactCommon/turbomodule/core
|
|
||||||
- ReactNativeDependencies
|
|
||||||
- Yoga
|
|
||||||
- expo-dev-launcher/Unsafe (6.0.20):
|
|
||||||
- EXManifests
|
|
||||||
- expo-dev-menu
|
|
||||||
- expo-dev-menu-interface
|
|
||||||
- ExpoModulesCore
|
|
||||||
- EXUpdatesInterface
|
|
||||||
- hermes-engine
|
|
||||||
- RCTRequired
|
|
||||||
- RCTTypeSafety
|
|
||||||
- React-Core
|
|
||||||
- React-Core-prebuilt
|
|
||||||
- React-debug
|
|
||||||
- React-Fabric
|
|
||||||
- React-featureflags
|
|
||||||
- React-graphics
|
|
||||||
- React-ImageManager
|
|
||||||
- React-jsi
|
|
||||||
- React-jsinspector
|
|
||||||
- React-NativeModulesApple
|
|
||||||
- React-RCTAppDelegate
|
|
||||||
- React-RCTFabric
|
|
||||||
- React-renderercss
|
|
||||||
- React-rendererdebug
|
|
||||||
- React-utils
|
|
||||||
- ReactAppDependencyProvider
|
|
||||||
- ReactCodegen
|
|
||||||
- ReactCommon/turbomodule/bridging
|
|
||||||
- ReactCommon/turbomodule/core
|
|
||||||
- ReactNativeDependencies
|
|
||||||
- Yoga
|
|
||||||
- expo-dev-menu (7.0.18):
|
|
||||||
- expo-dev-menu/Main (= 7.0.18)
|
|
||||||
- expo-dev-menu/ReactNativeCompatibles (= 7.0.18)
|
|
||||||
- hermes-engine
|
|
||||||
- RCTRequired
|
|
||||||
- RCTTypeSafety
|
|
||||||
- React-Core
|
|
||||||
- React-Core-prebuilt
|
|
||||||
- React-debug
|
|
||||||
- React-Fabric
|
|
||||||
- React-featureflags
|
|
||||||
- React-graphics
|
|
||||||
- React-ImageManager
|
|
||||||
- React-jsi
|
|
||||||
- React-NativeModulesApple
|
|
||||||
- React-RCTFabric
|
|
||||||
- React-renderercss
|
|
||||||
- React-rendererdebug
|
|
||||||
- React-utils
|
|
||||||
- ReactCodegen
|
|
||||||
- ReactCommon/turbomodule/bridging
|
|
||||||
- ReactCommon/turbomodule/core
|
|
||||||
- ReactNativeDependencies
|
|
||||||
- Yoga
|
|
||||||
- expo-dev-menu-interface (2.0.0)
|
|
||||||
- expo-dev-menu/Main (7.0.18):
|
|
||||||
- EXManifests
|
|
||||||
- expo-dev-menu-interface
|
|
||||||
- ExpoModulesCore
|
|
||||||
- hermes-engine
|
|
||||||
- RCTRequired
|
|
||||||
- RCTTypeSafety
|
|
||||||
- React-Core
|
|
||||||
- React-Core-prebuilt
|
|
||||||
- React-debug
|
|
||||||
- React-Fabric
|
|
||||||
- React-featureflags
|
|
||||||
- React-graphics
|
|
||||||
- React-ImageManager
|
|
||||||
- React-jsi
|
|
||||||
- React-jsinspector
|
|
||||||
- React-NativeModulesApple
|
|
||||||
- React-RCTFabric
|
|
||||||
- React-renderercss
|
|
||||||
- React-rendererdebug
|
|
||||||
- React-utils
|
|
||||||
- ReactCodegen
|
|
||||||
- ReactCommon/turbomodule/bridging
|
|
||||||
- ReactCommon/turbomodule/core
|
|
||||||
- ReactNativeDependencies
|
|
||||||
- Yoga
|
|
||||||
- expo-dev-menu/ReactNativeCompatibles (7.0.18):
|
|
||||||
- hermes-engine
|
|
||||||
- RCTRequired
|
|
||||||
- RCTTypeSafety
|
|
||||||
- React-Core
|
|
||||||
- React-Core-prebuilt
|
|
||||||
- React-debug
|
|
||||||
- React-Fabric
|
|
||||||
- React-featureflags
|
|
||||||
- React-graphics
|
|
||||||
- React-ImageManager
|
|
||||||
- React-jsi
|
|
||||||
- React-NativeModulesApple
|
|
||||||
- React-RCTFabric
|
|
||||||
- React-renderercss
|
|
||||||
- React-rendererdebug
|
|
||||||
- React-utils
|
|
||||||
- ReactCodegen
|
|
||||||
- ReactCommon/turbomodule/bridging
|
|
||||||
- ReactCommon/turbomodule/core
|
|
||||||
- ReactNativeDependencies
|
|
||||||
- Yoga
|
|
||||||
- ExpoAsset (12.0.12):
|
- ExpoAsset (12.0.12):
|
||||||
- ExpoModulesCore
|
- ExpoModulesCore
|
||||||
- ExpoFileSystem (19.0.21):
|
- ExpoFileSystem (19.0.21):
|
||||||
@@ -248,8 +74,6 @@ PODS:
|
|||||||
- ExpoModulesCore
|
- ExpoModulesCore
|
||||||
- ExpoWebBrowser (15.0.10):
|
- ExpoWebBrowser (15.0.10):
|
||||||
- ExpoModulesCore
|
- ExpoModulesCore
|
||||||
- EXUpdatesInterface (2.0.0):
|
|
||||||
- ExpoModulesCore
|
|
||||||
- FBLazyVector (0.81.5)
|
- FBLazyVector (0.81.5)
|
||||||
- hermes-engine (0.81.5):
|
- hermes-engine (0.81.5):
|
||||||
- hermes-engine/Pre-built (= 0.81.5)
|
- hermes-engine/Pre-built (= 0.81.5)
|
||||||
@@ -1974,28 +1798,6 @@ PODS:
|
|||||||
- ReactCommon/turbomodule/core
|
- ReactCommon/turbomodule/core
|
||||||
- ReactNativeDependencies
|
- ReactNativeDependencies
|
||||||
- Yoga
|
- Yoga
|
||||||
- RNGestureHandler (2.30.0):
|
|
||||||
- hermes-engine
|
|
||||||
- RCTRequired
|
|
||||||
- RCTTypeSafety
|
|
||||||
- React-Core
|
|
||||||
- React-Core-prebuilt
|
|
||||||
- React-debug
|
|
||||||
- React-Fabric
|
|
||||||
- React-featureflags
|
|
||||||
- React-graphics
|
|
||||||
- React-ImageManager
|
|
||||||
- React-jsi
|
|
||||||
- React-NativeModulesApple
|
|
||||||
- React-RCTFabric
|
|
||||||
- React-renderercss
|
|
||||||
- React-rendererdebug
|
|
||||||
- React-utils
|
|
||||||
- ReactCodegen
|
|
||||||
- ReactCommon/turbomodule/bridging
|
|
||||||
- ReactCommon/turbomodule/core
|
|
||||||
- ReactNativeDependencies
|
|
||||||
- Yoga
|
|
||||||
- RNReanimated (4.1.6):
|
- RNReanimated (4.1.6):
|
||||||
- hermes-engine
|
- hermes-engine
|
||||||
- RCTRequired
|
- RCTRequired
|
||||||
@@ -2238,26 +2040,19 @@ PODS:
|
|||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
- "EXApplication (from `../node_modules/.pnpm/expo-application@7.0.8_expo@54.0.32/node_modules/expo-application/ios`)"
|
- "EXApplication (from `../node_modules/.pnpm/expo-application@7.0.8_expo@54.0.32/node_modules/expo-application/ios`)"
|
||||||
- "EXConstants (from `../node_modules/.pnpm/expo-constants@18.0.13_expo@54.0.32_react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0_/node_modules/expo-constants/ios`)"
|
- "EXConstants (from `../node_modules/.pnpm/expo-constants@18.0.13_expo@54.0.32_react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0_/node_modules/expo-constants/ios`)"
|
||||||
- "EXJSONUtils (from `../node_modules/.pnpm/expo-json-utils@0.15.0/node_modules/expo-json-utils/ios`)"
|
- "EXNotifications (from `../node_modules/.pnpm/expo-notifications@0.32.16_expo@54.0.32_react-native@0.81.5_@babel+core@7.28.6_@types+react@1_nvlvke5tn7wk5pigfsu7j4ieeq/node_modules/expo-notifications/ios`)"
|
||||||
- "EXManifests (from `../node_modules/.pnpm/expo-manifests@1.0.10_expo@54.0.32/node_modules/expo-manifests/ios`)"
|
- "Expo (from `../node_modules/.pnpm/expo@54.0.32_@babel+core@7.28.6_@expo+metro-runtime@6.1.2_expo-router@6.0.22_react-native@0.8_7rhpxisdkrzvrgzbu7ct455kta/node_modules/expo`)"
|
||||||
- "EXNotifications (from `../node_modules/.pnpm/expo-notifications@0.32.16_expo@54.0.32_react-native@0.81.5_@babel+core@7.28.6_@types+r_758952db70529f49bda448def1c13c49/node_modules/expo-notifications/ios`)"
|
|
||||||
- "Expo (from `../node_modules/.pnpm/expo@54.0.32_@babel+core@7.28.6_@expo+metro-runtime@6.1.2_expo-router@6.0.22_react-nati_18ad48ba284ee86e6eb1cb0f939697b0/node_modules/expo`)"
|
|
||||||
- "expo-dev-client (from `../node_modules/.pnpm/expo-dev-client@6.0.20_expo@54.0.32/node_modules/expo-dev-client/ios`)"
|
|
||||||
- "expo-dev-launcher (from `../node_modules/.pnpm/expo-dev-launcher@6.0.20_expo@54.0.32/node_modules/expo-dev-launcher`)"
|
|
||||||
- "expo-dev-menu (from `../node_modules/.pnpm/expo-dev-menu@7.0.18_expo@54.0.32/node_modules/expo-dev-menu`)"
|
|
||||||
- "expo-dev-menu-interface (from `../node_modules/.pnpm/expo-dev-menu-interface@2.0.0_expo@54.0.32/node_modules/expo-dev-menu-interface/ios`)"
|
|
||||||
- "ExpoAsset (from `../node_modules/.pnpm/expo-asset@12.0.12_expo@54.0.32_react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0__react@19.1.0/node_modules/expo-asset/ios`)"
|
- "ExpoAsset (from `../node_modules/.pnpm/expo-asset@12.0.12_expo@54.0.32_react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0__react@19.1.0/node_modules/expo-asset/ios`)"
|
||||||
- "ExpoFileSystem (from `../node_modules/.pnpm/expo-file-system@19.0.21_expo@54.0.32_react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0_/node_modules/expo-file-system/ios`)"
|
- "ExpoFileSystem (from `../node_modules/.pnpm/expo-file-system@19.0.21_expo@54.0.32_react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0_/node_modules/expo-file-system/ios`)"
|
||||||
- "ExpoFont (from `../node_modules/.pnpm/expo-font@14.0.11_expo@54.0.32_react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0__react@19.1.0/node_modules/expo-font/ios`)"
|
- "ExpoFont (from `../node_modules/.pnpm/expo-font@14.0.11_expo@54.0.32_react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0__react@19.1.0/node_modules/expo-font/ios`)"
|
||||||
- "ExpoHead (from `../node_modules/.pnpm/expo-router@6.0.22_@expo+metro-runtime@6.1.2_@types+react@19.1.17_expo-constants@18.0.1_bd9aa16746ed7110429f931eb008e6d2/node_modules/expo-router/ios`)"
|
- "ExpoHead (from `../node_modules/.pnpm/expo-router@6.0.22_@expo+metro-runtime@6.1.2_@types+react@19.1.17_expo-constants@18.0.13_expo_rjurfbyy5kjn57nkkfxix5iqea/node_modules/expo-router/ios`)"
|
||||||
- "ExpoKeepAwake (from `../node_modules/.pnpm/expo-keep-awake@15.0.8_expo@54.0.32_react@19.1.0/node_modules/expo-keep-awake/ios`)"
|
- "ExpoKeepAwake (from `../node_modules/.pnpm/expo-keep-awake@15.0.8_expo@54.0.32_react@19.1.0/node_modules/expo-keep-awake/ios`)"
|
||||||
- "ExpoLinearGradient (from `../node_modules/.pnpm/expo-linear-gradient@15.0.8_expo@54.0.32_react-native@0.81.5_@babel+core@7.28.6_@types+_53aef72480df9baa4504f4743d9c64bb/node_modules/expo-linear-gradient/ios`)"
|
- "ExpoLinearGradient (from `../node_modules/.pnpm/expo-linear-gradient@15.0.8_expo@54.0.32_react-native@0.81.5_@babel+core@7.28.6_@types+react@_e6k2hjkd5k4lph2ersbp3gfshy/node_modules/expo-linear-gradient/ios`)"
|
||||||
- "ExpoLinking (from `../node_modules/.pnpm/expo-linking@8.0.11_expo@54.0.32_react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0__react@19.1.0/node_modules/expo-linking/ios`)"
|
- "ExpoLinking (from `../node_modules/.pnpm/expo-linking@8.0.11_expo@54.0.32_react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0__react@19.1.0/node_modules/expo-linking/ios`)"
|
||||||
- "ExpoLocalization (from `../node_modules/.pnpm/expo-localization@17.0.8_expo@54.0.32_react@19.1.0/node_modules/expo-localization/ios`)"
|
- "ExpoLocalization (from `../node_modules/.pnpm/expo-localization@17.0.8_expo@54.0.32_react@19.1.0/node_modules/expo-localization/ios`)"
|
||||||
- "ExpoModulesCore (from `../node_modules/.pnpm/expo-modules-core@3.0.29_react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0__react@19.1.0/node_modules/expo-modules-core`)"
|
- "ExpoModulesCore (from `../node_modules/.pnpm/expo-modules-core@3.0.29_react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0__react@19.1.0/node_modules/expo-modules-core`)"
|
||||||
- "ExpoSplashScreen (from `../node_modules/.pnpm/expo-splash-screen@31.0.13_expo@54.0.32/node_modules/expo-splash-screen/ios`)"
|
- "ExpoSplashScreen (from `../node_modules/.pnpm/expo-splash-screen@31.0.13_expo@54.0.32/node_modules/expo-splash-screen/ios`)"
|
||||||
- "ExpoWebBrowser (from `../node_modules/.pnpm/expo-web-browser@15.0.10_expo@54.0.32_react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0_/node_modules/expo-web-browser/ios`)"
|
- "ExpoWebBrowser (from `../node_modules/.pnpm/expo-web-browser@15.0.10_expo@54.0.32_react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0_/node_modules/expo-web-browser/ios`)"
|
||||||
- "EXUpdatesInterface (from `../node_modules/.pnpm/expo-updates-interface@2.0.0_expo@54.0.32/node_modules/expo-updates-interface/ios`)"
|
|
||||||
- "FBLazyVector (from `../node_modules/.pnpm/react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0/node_modules/react-native/Libraries/FBLazyVector`)"
|
- "FBLazyVector (from `../node_modules/.pnpm/react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0/node_modules/react-native/Libraries/FBLazyVector`)"
|
||||||
- "hermes-engine (from `../node_modules/.pnpm/react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0/node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`)"
|
- "hermes-engine (from `../node_modules/.pnpm/react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0/node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`)"
|
||||||
- "RCTDeprecation (from `../node_modules/.pnpm/react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0/node_modules/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation`)"
|
- "RCTDeprecation (from `../node_modules/.pnpm/react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0/node_modules/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation`)"
|
||||||
@@ -2294,7 +2089,7 @@ DEPENDENCIES:
|
|||||||
- "React-logger (from `../node_modules/.pnpm/react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0/node_modules/react-native/ReactCommon/logger`)"
|
- "React-logger (from `../node_modules/.pnpm/react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0/node_modules/react-native/ReactCommon/logger`)"
|
||||||
- "React-Mapbuffer (from `../node_modules/.pnpm/react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0/node_modules/react-native/ReactCommon`)"
|
- "React-Mapbuffer (from `../node_modules/.pnpm/react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0/node_modules/react-native/ReactCommon`)"
|
||||||
- "React-microtasksnativemodule (from `../node_modules/.pnpm/react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0/node_modules/react-native/ReactCommon/react/nativemodule/microtasks`)"
|
- "React-microtasksnativemodule (from `../node_modules/.pnpm/react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0/node_modules/react-native/ReactCommon/react/nativemodule/microtasks`)"
|
||||||
- "react-native-safe-area-context (from `../node_modules/.pnpm/react-native-safe-area-context@5.6.2_react-native@0.81.5_@babel+core@7.28.6_@types+reac_14122a3aa345cfabcc022a0f638ef16d/node_modules/react-native-safe-area-context`)"
|
- "react-native-safe-area-context (from `../node_modules/.pnpm/react-native-safe-area-context@5.6.2_react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1_azuxgonsvxb2yngtegtuvyxcpi/node_modules/react-native-safe-area-context`)"
|
||||||
- "React-NativeModulesApple (from `../node_modules/.pnpm/react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0/node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`)"
|
- "React-NativeModulesApple (from `../node_modules/.pnpm/react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0/node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`)"
|
||||||
- "React-oscompat (from `../node_modules/.pnpm/react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0/node_modules/react-native/ReactCommon/oscompat`)"
|
- "React-oscompat (from `../node_modules/.pnpm/react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0/node_modules/react-native/ReactCommon/oscompat`)"
|
||||||
- "React-perflogger (from `../node_modules/.pnpm/react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0/node_modules/react-native/ReactCommon/reactperflogger`)"
|
- "React-perflogger (from `../node_modules/.pnpm/react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0/node_modules/react-native/ReactCommon/reactperflogger`)"
|
||||||
@@ -2326,12 +2121,11 @@ DEPENDENCIES:
|
|||||||
- ReactCodegen (from `build/generated/ios`)
|
- ReactCodegen (from `build/generated/ios`)
|
||||||
- "ReactCommon/turbomodule/core (from `../node_modules/.pnpm/react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0/node_modules/react-native/ReactCommon`)"
|
- "ReactCommon/turbomodule/core (from `../node_modules/.pnpm/react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0/node_modules/react-native/ReactCommon`)"
|
||||||
- "ReactNativeDependencies (from `../node_modules/.pnpm/react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0/node_modules/react-native/third-party-podspecs/ReactNativeDependencies.podspec`)"
|
- "ReactNativeDependencies (from `../node_modules/.pnpm/react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0/node_modules/react-native/third-party-podspecs/ReactNativeDependencies.podspec`)"
|
||||||
- "RNCAsyncStorage (from `../node_modules/.pnpm/@react-native-async-storage+async-storage@2.2.0_react-native@0.81.5_@babel+core@7.28.6__ce3c4972004f3d6791573ec5b64bee38/node_modules/@react-native-async-storage/async-storage`)"
|
- "RNCAsyncStorage (from `../node_modules/.pnpm/@react-native-async-storage+async-storage@2.2.0_react-native@0.81.5_@babel+core@7.28.6_@types_fp4qq3a7mejmut52v6jrlvxlzi/node_modules/@react-native-async-storage/async-storage`)"
|
||||||
- "RNGestureHandler (from `../node_modules/.pnpm/react-native-gesture-handler@2.30.0_react-native@0.81.5_@babel+core@7.28.6_@types+react_39cf7da47c9c8531caaa923ee740e293/node_modules/react-native-gesture-handler`)"
|
- "RNReanimated (from `../node_modules/.pnpm/react-native-reanimated@4.1.6_@babel+core@7.28.6_react-native-worklets@0.5.1_@babel+core@7.28_ky3sbxf6i7nkyacc2hzg3xcz4q/node_modules/react-native-reanimated`)"
|
||||||
- "RNReanimated (from `../node_modules/.pnpm/react-native-reanimated@4.1.6_@babel+core@7.28.6_react-native-worklets@0.5.1_@babel+cor_c7c888bd389fb93c9cfe2d3c1c8b0777/node_modules/react-native-reanimated`)"
|
|
||||||
- "RNScreens (from `../node_modules/.pnpm/react-native-screens@4.16.0_react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0__react@19.1.0/node_modules/react-native-screens`)"
|
- "RNScreens (from `../node_modules/.pnpm/react-native-screens@4.16.0_react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0__react@19.1.0/node_modules/react-native-screens`)"
|
||||||
- "RNSVG (from `../node_modules/.pnpm/react-native-svg@15.12.1_react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0__react@19.1.0/node_modules/react-native-svg`)"
|
- "RNSVG (from `../node_modules/.pnpm/react-native-svg@15.12.1_react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0__react@19.1.0/node_modules/react-native-svg`)"
|
||||||
- "RNWorklets (from `../node_modules/.pnpm/react-native-worklets@0.5.1_@babel+core@7.28.6_react-native@0.81.5_@babel+core@7.28.6_@_40f69326ce21d3f9f6d74d3965fd9adf/node_modules/react-native-worklets`)"
|
- "RNWorklets (from `../node_modules/.pnpm/react-native-worklets@0.5.1_@babel+core@7.28.6_react-native@0.81.5_@babel+core@7.28.6_@types+_5atwepuw3zy3crkgvetf35tkve/node_modules/react-native-worklets`)"
|
||||||
- "Yoga (from `../node_modules/.pnpm/react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0/node_modules/react-native/ReactCommon/yoga`)"
|
- "Yoga (from `../node_modules/.pnpm/react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0/node_modules/react-native/ReactCommon/yoga`)"
|
||||||
|
|
||||||
EXTERNAL SOURCES:
|
EXTERNAL SOURCES:
|
||||||
@@ -2339,22 +2133,10 @@ EXTERNAL SOURCES:
|
|||||||
:path: "../node_modules/.pnpm/expo-application@7.0.8_expo@54.0.32/node_modules/expo-application/ios"
|
:path: "../node_modules/.pnpm/expo-application@7.0.8_expo@54.0.32/node_modules/expo-application/ios"
|
||||||
EXConstants:
|
EXConstants:
|
||||||
:path: "../node_modules/.pnpm/expo-constants@18.0.13_expo@54.0.32_react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0_/node_modules/expo-constants/ios"
|
:path: "../node_modules/.pnpm/expo-constants@18.0.13_expo@54.0.32_react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0_/node_modules/expo-constants/ios"
|
||||||
EXJSONUtils:
|
|
||||||
:path: "../node_modules/.pnpm/expo-json-utils@0.15.0/node_modules/expo-json-utils/ios"
|
|
||||||
EXManifests:
|
|
||||||
:path: "../node_modules/.pnpm/expo-manifests@1.0.10_expo@54.0.32/node_modules/expo-manifests/ios"
|
|
||||||
EXNotifications:
|
EXNotifications:
|
||||||
:path: "../node_modules/.pnpm/expo-notifications@0.32.16_expo@54.0.32_react-native@0.81.5_@babel+core@7.28.6_@types+r_758952db70529f49bda448def1c13c49/node_modules/expo-notifications/ios"
|
:path: "../node_modules/.pnpm/expo-notifications@0.32.16_expo@54.0.32_react-native@0.81.5_@babel+core@7.28.6_@types+react@1_nvlvke5tn7wk5pigfsu7j4ieeq/node_modules/expo-notifications/ios"
|
||||||
Expo:
|
Expo:
|
||||||
:path: "../node_modules/.pnpm/expo@54.0.32_@babel+core@7.28.6_@expo+metro-runtime@6.1.2_expo-router@6.0.22_react-nati_18ad48ba284ee86e6eb1cb0f939697b0/node_modules/expo"
|
:path: "../node_modules/.pnpm/expo@54.0.32_@babel+core@7.28.6_@expo+metro-runtime@6.1.2_expo-router@6.0.22_react-native@0.8_7rhpxisdkrzvrgzbu7ct455kta/node_modules/expo"
|
||||||
expo-dev-client:
|
|
||||||
:path: "../node_modules/.pnpm/expo-dev-client@6.0.20_expo@54.0.32/node_modules/expo-dev-client/ios"
|
|
||||||
expo-dev-launcher:
|
|
||||||
:path: "../node_modules/.pnpm/expo-dev-launcher@6.0.20_expo@54.0.32/node_modules/expo-dev-launcher"
|
|
||||||
expo-dev-menu:
|
|
||||||
:path: "../node_modules/.pnpm/expo-dev-menu@7.0.18_expo@54.0.32/node_modules/expo-dev-menu"
|
|
||||||
expo-dev-menu-interface:
|
|
||||||
:path: "../node_modules/.pnpm/expo-dev-menu-interface@2.0.0_expo@54.0.32/node_modules/expo-dev-menu-interface/ios"
|
|
||||||
ExpoAsset:
|
ExpoAsset:
|
||||||
:path: "../node_modules/.pnpm/expo-asset@12.0.12_expo@54.0.32_react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0__react@19.1.0/node_modules/expo-asset/ios"
|
:path: "../node_modules/.pnpm/expo-asset@12.0.12_expo@54.0.32_react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0__react@19.1.0/node_modules/expo-asset/ios"
|
||||||
ExpoFileSystem:
|
ExpoFileSystem:
|
||||||
@@ -2362,11 +2144,11 @@ EXTERNAL SOURCES:
|
|||||||
ExpoFont:
|
ExpoFont:
|
||||||
:path: "../node_modules/.pnpm/expo-font@14.0.11_expo@54.0.32_react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0__react@19.1.0/node_modules/expo-font/ios"
|
:path: "../node_modules/.pnpm/expo-font@14.0.11_expo@54.0.32_react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0__react@19.1.0/node_modules/expo-font/ios"
|
||||||
ExpoHead:
|
ExpoHead:
|
||||||
:path: "../node_modules/.pnpm/expo-router@6.0.22_@expo+metro-runtime@6.1.2_@types+react@19.1.17_expo-constants@18.0.1_bd9aa16746ed7110429f931eb008e6d2/node_modules/expo-router/ios"
|
:path: "../node_modules/.pnpm/expo-router@6.0.22_@expo+metro-runtime@6.1.2_@types+react@19.1.17_expo-constants@18.0.13_expo_rjurfbyy5kjn57nkkfxix5iqea/node_modules/expo-router/ios"
|
||||||
ExpoKeepAwake:
|
ExpoKeepAwake:
|
||||||
:path: "../node_modules/.pnpm/expo-keep-awake@15.0.8_expo@54.0.32_react@19.1.0/node_modules/expo-keep-awake/ios"
|
:path: "../node_modules/.pnpm/expo-keep-awake@15.0.8_expo@54.0.32_react@19.1.0/node_modules/expo-keep-awake/ios"
|
||||||
ExpoLinearGradient:
|
ExpoLinearGradient:
|
||||||
:path: "../node_modules/.pnpm/expo-linear-gradient@15.0.8_expo@54.0.32_react-native@0.81.5_@babel+core@7.28.6_@types+_53aef72480df9baa4504f4743d9c64bb/node_modules/expo-linear-gradient/ios"
|
:path: "../node_modules/.pnpm/expo-linear-gradient@15.0.8_expo@54.0.32_react-native@0.81.5_@babel+core@7.28.6_@types+react@_e6k2hjkd5k4lph2ersbp3gfshy/node_modules/expo-linear-gradient/ios"
|
||||||
ExpoLinking:
|
ExpoLinking:
|
||||||
:path: "../node_modules/.pnpm/expo-linking@8.0.11_expo@54.0.32_react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0__react@19.1.0/node_modules/expo-linking/ios"
|
:path: "../node_modules/.pnpm/expo-linking@8.0.11_expo@54.0.32_react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0__react@19.1.0/node_modules/expo-linking/ios"
|
||||||
ExpoLocalization:
|
ExpoLocalization:
|
||||||
@@ -2377,8 +2159,6 @@ EXTERNAL SOURCES:
|
|||||||
:path: "../node_modules/.pnpm/expo-splash-screen@31.0.13_expo@54.0.32/node_modules/expo-splash-screen/ios"
|
:path: "../node_modules/.pnpm/expo-splash-screen@31.0.13_expo@54.0.32/node_modules/expo-splash-screen/ios"
|
||||||
ExpoWebBrowser:
|
ExpoWebBrowser:
|
||||||
:path: "../node_modules/.pnpm/expo-web-browser@15.0.10_expo@54.0.32_react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0_/node_modules/expo-web-browser/ios"
|
:path: "../node_modules/.pnpm/expo-web-browser@15.0.10_expo@54.0.32_react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0_/node_modules/expo-web-browser/ios"
|
||||||
EXUpdatesInterface:
|
|
||||||
:path: "../node_modules/.pnpm/expo-updates-interface@2.0.0_expo@54.0.32/node_modules/expo-updates-interface/ios"
|
|
||||||
FBLazyVector:
|
FBLazyVector:
|
||||||
:path: "../node_modules/.pnpm/react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0/node_modules/react-native/Libraries/FBLazyVector"
|
:path: "../node_modules/.pnpm/react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0/node_modules/react-native/Libraries/FBLazyVector"
|
||||||
hermes-engine:
|
hermes-engine:
|
||||||
@@ -2451,7 +2231,7 @@ EXTERNAL SOURCES:
|
|||||||
React-microtasksnativemodule:
|
React-microtasksnativemodule:
|
||||||
:path: "../node_modules/.pnpm/react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0/node_modules/react-native/ReactCommon/react/nativemodule/microtasks"
|
:path: "../node_modules/.pnpm/react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0/node_modules/react-native/ReactCommon/react/nativemodule/microtasks"
|
||||||
react-native-safe-area-context:
|
react-native-safe-area-context:
|
||||||
:path: "../node_modules/.pnpm/react-native-safe-area-context@5.6.2_react-native@0.81.5_@babel+core@7.28.6_@types+reac_14122a3aa345cfabcc022a0f638ef16d/node_modules/react-native-safe-area-context"
|
:path: "../node_modules/.pnpm/react-native-safe-area-context@5.6.2_react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1_azuxgonsvxb2yngtegtuvyxcpi/node_modules/react-native-safe-area-context"
|
||||||
React-NativeModulesApple:
|
React-NativeModulesApple:
|
||||||
:path: "../node_modules/.pnpm/react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0/node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios"
|
:path: "../node_modules/.pnpm/react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0/node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios"
|
||||||
React-oscompat:
|
React-oscompat:
|
||||||
@@ -2515,43 +2295,34 @@ EXTERNAL SOURCES:
|
|||||||
ReactNativeDependencies:
|
ReactNativeDependencies:
|
||||||
:podspec: "../node_modules/.pnpm/react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0/node_modules/react-native/third-party-podspecs/ReactNativeDependencies.podspec"
|
:podspec: "../node_modules/.pnpm/react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0/node_modules/react-native/third-party-podspecs/ReactNativeDependencies.podspec"
|
||||||
RNCAsyncStorage:
|
RNCAsyncStorage:
|
||||||
:path: "../node_modules/.pnpm/@react-native-async-storage+async-storage@2.2.0_react-native@0.81.5_@babel+core@7.28.6__ce3c4972004f3d6791573ec5b64bee38/node_modules/@react-native-async-storage/async-storage"
|
:path: "../node_modules/.pnpm/@react-native-async-storage+async-storage@2.2.0_react-native@0.81.5_@babel+core@7.28.6_@types_fp4qq3a7mejmut52v6jrlvxlzi/node_modules/@react-native-async-storage/async-storage"
|
||||||
RNGestureHandler:
|
|
||||||
:path: "../node_modules/.pnpm/react-native-gesture-handler@2.30.0_react-native@0.81.5_@babel+core@7.28.6_@types+react_39cf7da47c9c8531caaa923ee740e293/node_modules/react-native-gesture-handler"
|
|
||||||
RNReanimated:
|
RNReanimated:
|
||||||
:path: "../node_modules/.pnpm/react-native-reanimated@4.1.6_@babel+core@7.28.6_react-native-worklets@0.5.1_@babel+cor_c7c888bd389fb93c9cfe2d3c1c8b0777/node_modules/react-native-reanimated"
|
:path: "../node_modules/.pnpm/react-native-reanimated@4.1.6_@babel+core@7.28.6_react-native-worklets@0.5.1_@babel+core@7.28_ky3sbxf6i7nkyacc2hzg3xcz4q/node_modules/react-native-reanimated"
|
||||||
RNScreens:
|
RNScreens:
|
||||||
:path: "../node_modules/.pnpm/react-native-screens@4.16.0_react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0__react@19.1.0/node_modules/react-native-screens"
|
:path: "../node_modules/.pnpm/react-native-screens@4.16.0_react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0__react@19.1.0/node_modules/react-native-screens"
|
||||||
RNSVG:
|
RNSVG:
|
||||||
:path: "../node_modules/.pnpm/react-native-svg@15.12.1_react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0__react@19.1.0/node_modules/react-native-svg"
|
:path: "../node_modules/.pnpm/react-native-svg@15.12.1_react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0__react@19.1.0/node_modules/react-native-svg"
|
||||||
RNWorklets:
|
RNWorklets:
|
||||||
:path: "../node_modules/.pnpm/react-native-worklets@0.5.1_@babel+core@7.28.6_react-native@0.81.5_@babel+core@7.28.6_@_40f69326ce21d3f9f6d74d3965fd9adf/node_modules/react-native-worklets"
|
:path: "../node_modules/.pnpm/react-native-worklets@0.5.1_@babel+core@7.28.6_react-native@0.81.5_@babel+core@7.28.6_@types+_5atwepuw3zy3crkgvetf35tkve/node_modules/react-native-worklets"
|
||||||
Yoga:
|
Yoga:
|
||||||
:path: "../node_modules/.pnpm/react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0/node_modules/react-native/ReactCommon/yoga"
|
:path: "../node_modules/.pnpm/react-native@0.81.5_@babel+core@7.28.6_@types+react@19.1.17_react@19.1.0/node_modules/react-native/ReactCommon/yoga"
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
EXApplication: 1e98d4b1dccdf30627f92917f4b2c5a53c330e5f
|
EXApplication: 13420f8139864183f8a04fd6099077bdf8cfb186
|
||||||
EXConstants: fce59a631a06c4151602843667f7cfe35f81e271
|
EXConstants: 3feb66fd1d94202fc1f0946d74e029d8b224b60e
|
||||||
EXJSONUtils: 1d3e4590438c3ee593684186007028a14b3686cd
|
EXNotifications: 2a3feb7af6194828d9aafda72f63a9a03866230a
|
||||||
EXManifests: a8d97683e5c7a3b026ffbd58559c64dc655b747b
|
Expo: b8d64eb9a496ebe8c71e3dae7eeb7f394b146b80
|
||||||
EXNotifications: 9eec98712cc814ceff916d876cb53859003b0597
|
ExpoAsset: d999f3bbd998a750f3b74cb913229848901b926b
|
||||||
Expo: 4e503a041c59c4e34c8be262a135848ad5cd3710
|
ExpoFileSystem: aefcd337b94b874f88752ebefc52813b84992fad
|
||||||
expo-dev-client: 425ee077d6754a98cfe3a2e2410d29b440b24c9d
|
ExpoFont: c625dbd97ed57e9089b172b2a7bb99003d074664
|
||||||
expo-dev-launcher: a4f4cdef064ab1fb8621e5b8c7c457cd6e9568c3
|
ExpoHead: b691a2ed7ab02ed820b6c6468941832d34969c29
|
||||||
expo-dev-menu: 05b18812110c175814c6af0d09dd658abcc5e00d
|
ExpoKeepAwake: 44bf6715bc1d2ddb17afe19d927cd039cda123f0
|
||||||
expo-dev-menu-interface: 600df12ea01efecdd822daaf13cc0ac091775533
|
ExpoLinearGradient: 814a21fc4056c3cf606e4f19e31e47074c5b5a86
|
||||||
ExpoAsset: f867e55ceb428aab99e1e8c082b5aee7c159ea18
|
ExpoLinking: ebf543fd411d56375cb4eee07f6ab4e31c7ad959
|
||||||
ExpoFileSystem: 858a44267a3e6e9057e0888ad7c7cfbf55d52063
|
ExpoLocalization: 6ac6f326210f0a3141ef6f58ab8f8f4ed003b485
|
||||||
ExpoFont: f543ce20a228dd702813668b1a07b46f51878d47
|
ExpoModulesCore: 77496909fd3c800f97f7f2007dd26aeac4bb3798
|
||||||
ExpoHead: 4425246bc93411f0fe7f6945f95f698e91db8780
|
ExpoSplashScreen: 72fbc6dd9d6404dd9d0725a56c9ac1383bc0b14f
|
||||||
ExpoKeepAwake: 55f75eca6499bb9e4231ebad6f3e9cb8f99c0296
|
ExpoWebBrowser: 88b116cd378d9609c776c0903fe4070fca461588
|
||||||
ExpoLinearGradient: 809102bdb979f590083af49f7fa4805cd931bd58
|
|
||||||
ExpoLinking: 8f0aaf69aa56f832913030503b6263dc6f647f37
|
|
||||||
ExpoLocalization: d9168d5300a5b03e5e78b986124d11fb6ec3ebbd
|
|
||||||
ExpoModulesCore: f3da4f1ab5a8375d0beafab763739dbee8446583
|
|
||||||
ExpoSplashScreen: bc3cffefca2716e5f22350ca109badd7e50ec14d
|
|
||||||
ExpoWebBrowser: 17b064c621789e41d4816c95c93f429b84971f52
|
|
||||||
EXUpdatesInterface: 5adf50cb41e079c861da6d9b4b954c3db9a50734
|
|
||||||
FBLazyVector: e95a291ad2dadb88e42b06e0c5fb8262de53ec12
|
FBLazyVector: e95a291ad2dadb88e42b06e0c5fb8262de53ec12
|
||||||
hermes-engine: 9f4dfe93326146a1c99eb535b1cb0b857a3cd172
|
hermes-engine: 9f4dfe93326146a1c99eb535b1cb0b857a3cd172
|
||||||
RCTDeprecation: 943572d4be82d480a48f4884f670135ae30bf990
|
RCTDeprecation: 943572d4be82d480a48f4884f670135ae30bf990
|
||||||
@@ -2559,74 +2330,73 @@ SPEC CHECKSUMS:
|
|||||||
RCTTypeSafety: 16a4144ca3f959583ab019b57d5633df10b5e97c
|
RCTTypeSafety: 16a4144ca3f959583ab019b57d5633df10b5e97c
|
||||||
React: 914f8695f9bf38e6418228c2ffb70021e559f92f
|
React: 914f8695f9bf38e6418228c2ffb70021e559f92f
|
||||||
React-callinvoker: 1c0808402aee0c6d4a0d8e7220ce6547af9fba71
|
React-callinvoker: 1c0808402aee0c6d4a0d8e7220ce6547af9fba71
|
||||||
React-Core: c61410ef0ca6055e204a963992e363227e0fd1c5
|
React-Core: 4ae98f9e8135b8ddbd7c98730afb6fdae883db90
|
||||||
React-Core-prebuilt: 02f0ad625ddd47463c009c2d0c5dd35c0d982599
|
React-Core-prebuilt: 8f4cca589c14e8cf8fc6db4587ef1c2056b5c151
|
||||||
React-CoreModules: 1f6d1744b5f9f2ec684a4bb5ced25370f87e5382
|
React-CoreModules: e878a90bb19b8f3851818af997dbae3b3b0a27ac
|
||||||
React-cxxreact: 3af79478e8187b63ffc22b794cd42d3fc1f1f2da
|
React-cxxreact: 28af9844f6dc87be1385ab521fbfb3746f19563c
|
||||||
React-debug: 6328c2228e268846161f10082e80dc69eac2e90a
|
React-debug: 6328c2228e268846161f10082e80dc69eac2e90a
|
||||||
React-defaultsnativemodule: d635ef36d755321e5d6fc065bd166b2c5a0e9833
|
React-defaultsnativemodule: afc9d809ec75780f39464a6949c07987fbea488c
|
||||||
React-domnativemodule: dd28f6d96cd21236e020be2eff6fe0b7d4ec3b66
|
React-domnativemodule: 91a233260411d41f27f67aa1358b7f9f0bfd101d
|
||||||
React-Fabric: 2e32c3fdbb1fbcf5fde54607e3abe453c6652ce2
|
React-Fabric: 21f349b5e93f305a3c38c885902683a9c79cf983
|
||||||
React-FabricComponents: 5ed0cdb81f6b91656cb4d3be432feaa28a58071a
|
React-FabricComponents: 47ac634cc9ecc64b30a9997192f510eebe4177e4
|
||||||
React-FabricImage: 2bc714f818cb24e454f5d3961864373271b2faf8
|
React-FabricImage: 21873acd6d4a51a0b97c133141051c7acb11cc86
|
||||||
React-featureflags: 847642f41fa71ad4eec5e0351badebcad4fe6171
|
React-featureflags: 653f469f0c3c9dc271d610373e3b6e66a9fd847d
|
||||||
React-featureflagsnativemodule: c868a544b2c626fa337bcbd364b1befe749f0d3f
|
React-featureflagsnativemodule: c91a8a3880e0f4838286402241ead47db43aed28
|
||||||
React-graphics: 192ec701def5b3f2a07db2814dfba5a44986cff6
|
React-graphics: b4bdb0f635b8048c652a5d2b73eb8b1ddd950f24
|
||||||
React-hermes: e875778b496c86d07ab2ccaa36a9505d248a254b
|
React-hermes: fcfad3b917400f49026f3232561e039c9d1c34bf
|
||||||
React-idlecallbacksnativemodule: 4d57965cdf82c14ee3b337189836cd8491632b76
|
React-idlecallbacksnativemodule: 8cb83207e39f8179ac1d344b6177c6ab3ccebcdc
|
||||||
React-ImageManager: bd0b99e370b13de82c9cd15f0f08144ff3de079e
|
React-ImageManager: 396128004783fc510e629124dce682d38d1088e7
|
||||||
React-jserrorhandler: a2fdef4cbcfdcdf3fa9f5d1f7190f7fd4535248d
|
React-jserrorhandler: b58b788d788cdbf8bda7db74a88ebfcffc8a0795
|
||||||
React-jsi: 89d43d1e7d4d0663f8ba67e0b39eb4e4672c27de
|
React-jsi: d2c3f8555175371c02da6dfe7ed1b64b55a9d6c0
|
||||||
React-jsiexecutor: abe4874aaab90dfee5dec480680220b2f8af07e3
|
React-jsiexecutor: ba537434eb45ee018b590ed7d29ee233fddb8669
|
||||||
React-jsinspector: a0b3e051aef842b0b2be2353790ae2b2a5a65a8f
|
React-jsinspector: f21b6654baf96cb9f71748844a32468a5f73ad51
|
||||||
React-jsinspectorcdp: 6346013b2247c6263fbf5199adf4a8751e53bd89
|
React-jsinspectorcdp: 3f8be4830694c3c1c39442e50f8db877966d43f0
|
||||||
React-jsinspectornetwork: 26281aa50d49fc1ec93abf981d934698fa95714f
|
React-jsinspectornetwork: 70e41469565712ad60e11d9c8b8f999b9f7f61eb
|
||||||
React-jsinspectortracing: 55eedf6d57540507570259a778663b90060bbd6e
|
React-jsinspectortracing: eccf9bfa4ec7f130d514f215cfb2222dc3c0e270
|
||||||
React-jsitooling: 0e001113fa56d8498aa8ac28437ac0d36348e51a
|
React-jsitooling: b376a695f5a507627f7934748533b24eed1751ca
|
||||||
React-jsitracing: b713793eb8a5bbc4d86a84e9d9e5023c0f58cbaf
|
React-jsitracing: 5c8c3273dda2d95191cc0612fb5e71c4d9018d2a
|
||||||
React-logger: 50fdb9a8236da90c0b1072da5c32ee03aeb5bf28
|
React-logger: c3e2f8a2e284341205f61eef3d4677ab5a309dfd
|
||||||
React-Mapbuffer: 9050ee10c19f4f7fca8963d0211b2854d624973e
|
React-Mapbuffer: 603c18db65844bb81dbe62fee8fcc976eaeb7108
|
||||||
React-microtasksnativemodule: f775db9e991c6f3b8ccbc02bfcde22770f96e23b
|
React-microtasksnativemodule: d77e0c426fce34c23227394c96ca1033b30c813c
|
||||||
react-native-safe-area-context: 37e680fc4cace3c0030ee46e8987d24f5d3bdab2
|
react-native-safe-area-context: 53f796cb6c814661bbe99fbdfd0585d07b996cdd
|
||||||
React-NativeModulesApple: 8969913947d5b576de4ed371a939455a8daf28aa
|
React-NativeModulesApple: 1664340b8750d64e0ef3907c5e53d9481f74bcbd
|
||||||
React-oscompat: ce47230ed20185e91de62d8c6d139ae61763d09c
|
React-oscompat: ce47230ed20185e91de62d8c6d139ae61763d09c
|
||||||
React-perflogger: 02b010e665772c7dcb859d85d44c1bfc5ac7c0e4
|
React-perflogger: b1af3cfb3f095f819b2814910000392a8e17ba9f
|
||||||
React-performancetimeline: 130db956b5a83aa4fb41ddf5ae68da89f3fb1526
|
React-performancetimeline: f9ec65b77bcadbc7bd8b47a6f4b4b697da7b1490
|
||||||
React-RCTActionSheet: 0b14875b3963e9124a5a29a45bd1b22df8803916
|
React-RCTActionSheet: 0b14875b3963e9124a5a29a45bd1b22df8803916
|
||||||
React-RCTAnimation: a7b90fd2af7bb9c084428867445a1481a8cb112e
|
React-RCTAnimation: 60f6eca214a62b9673f64db6df3830cee902b5af
|
||||||
React-RCTAppDelegate: 3262bedd01263f140ec62b7989f4355f57cec016
|
React-RCTAppDelegate: 37734b39bac108af30a0fd9d3e1149ec68b82c28
|
||||||
React-RCTBlob: c17531368702f1ebed5d0ada75a7cf5915072a53
|
React-RCTBlob: 83fbcbd57755caf021787324aac2fe9b028cc264
|
||||||
React-RCTFabric: 6409edd8cfdc3133b6cc75636d3b858fdb1d11ea
|
React-RCTFabric: a05cb1df484008db3753c8b4a71e4c6d9f1e43a6
|
||||||
React-RCTFBReactNativeSpec: c004b27b4fa3bd85878ad2cf53de3bbec85da797
|
React-RCTFBReactNativeSpec: d58d7ae9447020bbbac651e3b0674422aba18266
|
||||||
React-RCTImage: c68078a120d0123f4f07a5ac77bea3bb10242f32
|
React-RCTImage: 47aba3be7c6c64f956b7918ab933769602406aac
|
||||||
React-RCTLinking: cf8f9391fe7fe471f96da3a5f0435235eca18c5b
|
React-RCTLinking: 2dbaa4df2e4523f68baa07936bd8efdfa34d5f31
|
||||||
React-RCTNetwork: ca31f7c879355760c2d9832a06ee35f517938a20
|
React-RCTNetwork: 1fca7455f9dedf7de2b95bec438da06680f3b000
|
||||||
React-RCTRuntime: a6cf4a1e42754fc87f493e538f2ac6b820e45418
|
React-RCTRuntime: 17819dd1dfc8613efaf4cbb9d8686baae4a83e5b
|
||||||
React-RCTSettings: e0e140b2ff4bf86d34e9637f6316848fc00be035
|
React-RCTSettings: 01bf91c856862354d3d2f642ccb82f3697a4284a
|
||||||
React-RCTText: 75915bace6f7877c03a840cc7b6c622fb62bfa6b
|
React-RCTText: cb576a3797dcb64933613c522296a07eaafc0461
|
||||||
React-RCTVibration: 25f26b85e5e432bb3c256f8b384f9269e9529f25
|
React-RCTVibration: 560af8c086741f3525b8456a482cdbe27f9d098e
|
||||||
React-rendererconsistency: 2dac03f448ff337235fd5820b10f81633328870d
|
React-rendererconsistency: 2dac03f448ff337235fd5820b10f81633328870d
|
||||||
React-renderercss: 477da167bb96b5ac86d30c5d295412fb853f5453
|
React-renderercss: c5c6b7a15948dd28facca39a18ac269073718490
|
||||||
React-rendererdebug: 2a1798c6f3ef5f22d466df24c33653edbabb5b89
|
React-rendererdebug: 3c9d5e1634273f5a24d84cc5669f290ce0bdc812
|
||||||
React-RuntimeApple: 28cf4d8eb18432f6a21abbed7d801ab7f6b6f0b4
|
React-RuntimeApple: 887637d1e12ea8262df7d32bc100467df2302613
|
||||||
React-RuntimeCore: 41bf0fd56a00de5660f222415af49879fa49c4f0
|
React-RuntimeCore: 91f779835dc4f8f84777fe5dd24f1a22f96454e4
|
||||||
React-runtimeexecutor: 1afb774dde3011348e8334be69d2f57a359ea43e
|
React-runtimeexecutor: 8bb6b738f37b0ada4a6269e6f8ab1133dea0285c
|
||||||
React-RuntimeHermes: f3b158ea40e8212b1a723a68b4315e7a495c5fc6
|
React-RuntimeHermes: 4cb93de9fa8b1cc753d200dbe61a01b9ec5f5562
|
||||||
React-runtimescheduler: 3e1e2bec7300bae512533107d8e54c6e5c63fe0f
|
React-runtimescheduler: 83dc28f530bfbd2fce84ed13aa7feebdc24e5af7
|
||||||
React-timing: 6fa9883de2e41791e5dc4ec404e5e37f3f50e801
|
React-timing: 03c7217455d2bff459b27a3811be25796b600f47
|
||||||
React-utils: 6e2035b53d087927768649a11a26c4e092448e34
|
React-utils: 6d46795ae0444ec8a5d9a5f201157b286bf5250a
|
||||||
ReactAppDependencyProvider: 1bcd3527ac0390a1c898c114f81ff954be35ed79
|
ReactAppDependencyProvider: c277c5b231881ad4f00cd59e3aa0671b99d7ebee
|
||||||
ReactCodegen: fffa79906f5866f6a5ab5d98480b375191190271
|
ReactCodegen: 88a1f4643f15841573f833b895bfa2a0c6cb4e7f
|
||||||
ReactCommon: 08810150b1206cc44aecf5f6ae19af32f29151a8
|
ReactCommon: e6e232202a447d353e5531f2be82f50f47cbaa9a
|
||||||
ReactNativeDependencies: 71ce9c28beb282aa720ea7b46980fff9669f428a
|
ReactNativeDependencies: 71ce9c28beb282aa720ea7b46980fff9669f428a
|
||||||
RNCAsyncStorage: 3a4f5e2777dae1688b781a487923a08569e27fe4
|
RNCAsyncStorage: e85a99325df9eb0191a6ee2b2a842644c7eb29f4
|
||||||
RNGestureHandler: e0d0bce5599f6120b7adf90c38d2805e2935795f
|
RNReanimated: 10415bc8396eaeac0d7b2c9a1538eae7e607ec9c
|
||||||
RNReanimated: 9c6a550b41de91cf374e60afd79db93a362f1126
|
RNScreens: dd61bc3a3e6f6901ad833efa411917d44827cf51
|
||||||
RNScreens: d8d6f1792f6e7ac12b0190d33d8d390efc0c1845
|
RNSVG: 2825ee146e0f6a16221e852299943e4cceef4528
|
||||||
RNSVG: 31d6639663c249b7d5abc9728dde2041eb2a3c34
|
RNWorklets: 9ccdc8112b17af6eee2c85a233891cb80db150ad
|
||||||
RNWorklets: 1b50cb7595142f95e70518196ba247ad7f46a52e
|
|
||||||
Yoga: 5934998fbeaef7845dbf698f698518695ab4cd1a
|
Yoga: 5934998fbeaef7845dbf698f698518695ab4cd1a
|
||||||
|
|
||||||
PODFILE CHECKSUM: dfe3cc75dee014a0abd367bc9e1bdbab0ba64ee3
|
PODFILE CHECKSUM: 4d5c52f9fa870c1d398cf59e37c149f66700c061
|
||||||
|
|
||||||
COCOAPODS: 1.16.2
|
COCOAPODS: 1.16.2
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
archiveVersion = 1;
|
archiveVersion = 1;
|
||||||
classes = {
|
classes = {
|
||||||
};
|
};
|
||||||
objectVersion = 56;
|
objectVersion = 70;
|
||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
||||||
1A1DE01D4133812B2E2BA692 /* libPods-client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E3328F0E595C1F4A244DF238 /* libPods-client.a */; };
|
1A1DE01D4133812B2E2BA692 /* libPods-client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E3328F0E595C1F4A244DF238 /* libPods-client.a */; };
|
||||||
3E461D99554A48A4959DE609 /* SplashScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */; };
|
3E461D99554A48A4959DE609 /* SplashScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */; };
|
||||||
A1B2C3D4E5F60718293A4B5C /* EmotionWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C3D4E5F60718293A4B5B /* EmotionWidget.swift */; };
|
A1B2C3D4E5F60718293A4B5C /* 情绪小组件/EmotionWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C3D4E5F60718293A4B5B /* 情绪小组件/EmotionWidget.swift */; };
|
||||||
B5A7FE9A125F7C79753EC5BF /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7DB40C26E3A46F6D06769EA /* ExpoModulesProvider.swift */; };
|
B5A7FE9A125F7C79753EC5BF /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7DB40C26E3A46F6D06769EA /* ExpoModulesProvider.swift */; };
|
||||||
BB2F792D24A3F905000567C9 /* Expo.plist in Resources */ = {isa = PBXBuildFile; fileRef = BB2F792C24A3F905000567C9 /* Expo.plist */; };
|
BB2F792D24A3F905000567C9 /* Expo.plist in Resources */ = {isa = PBXBuildFile; fileRef = BB2F792C24A3F905000567C9 /* Expo.plist */; };
|
||||||
EB3DAF812F2A4B8E00450593 /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EB3DAF802F2A4B8D00450593 /* WidgetKit.framework */; };
|
EB3DAF812F2A4B8E00450593 /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EB3DAF802F2A4B8D00450593 /* WidgetKit.framework */; };
|
||||||
@@ -50,7 +50,7 @@
|
|||||||
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = client/Info.plist; sourceTree = "<group>"; };
|
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = client/Info.plist; sourceTree = "<group>"; };
|
||||||
3C76CA16D0801CBF0D731C7C /* Pods-client.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-client.release.xcconfig"; path = "Target Support Files/Pods-client/Pods-client.release.xcconfig"; sourceTree = "<group>"; };
|
3C76CA16D0801CBF0D731C7C /* Pods-client.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-client.release.xcconfig"; path = "Target Support Files/Pods-client/Pods-client.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
75F52ADE07CAE9D9736D7671 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xml; name = PrivacyInfo.xcprivacy; path = client/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
|
75F52ADE07CAE9D9736D7671 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xml; name = PrivacyInfo.xcprivacy; path = client/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
|
||||||
A1B2C3D4E5F60718293A4B5B /* EmotionWidget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "情绪小组件/EmotionWidget.swift"; sourceTree = "<group>"; };
|
A1B2C3D4E5F60718293A4B5B /* 情绪小组件/EmotionWidget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "情绪小组件/EmotionWidget.swift"; sourceTree = "<group>"; };
|
||||||
AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = SplashScreen.storyboard; path = client/SplashScreen.storyboard; sourceTree = "<group>"; };
|
AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = SplashScreen.storyboard; path = client/SplashScreen.storyboard; sourceTree = "<group>"; };
|
||||||
BB2F792C24A3F905000567C9 /* Expo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Expo.plist; sourceTree = "<group>"; };
|
BB2F792C24A3F905000567C9 /* Expo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Expo.plist; sourceTree = "<group>"; };
|
||||||
C7DB40C26E3A46F6D06769EA /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-client/ExpoModulesProvider.swift"; sourceTree = "<group>"; };
|
C7DB40C26E3A46F6D06769EA /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-client/ExpoModulesProvider.swift"; sourceTree = "<group>"; };
|
||||||
@@ -66,7 +66,7 @@
|
|||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
|
/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
|
||||||
EB3DAF952F2A4B8F00450593 /* Exceptions for "情绪小组件" folder in "情绪小组件Extension" target */ = {
|
EB3DAF952F2A4B8F00450593 /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = {
|
||||||
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
|
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
|
||||||
membershipExceptions = (
|
membershipExceptions = (
|
||||||
EmotionWidget.swift,
|
EmotionWidget.swift,
|
||||||
@@ -77,18 +77,7 @@
|
|||||||
/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */
|
/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */
|
||||||
|
|
||||||
/* Begin PBXFileSystemSynchronizedRootGroup section */
|
/* Begin PBXFileSystemSynchronizedRootGroup section */
|
||||||
EB3DAF842F2A4B8E00450593 /* 情绪小组件 */ = {
|
EB3DAF842F2A4B8E00450593 /* 情绪小组件 */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (EB3DAF952F2A4B8F00450593 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = "情绪小组件"; sourceTree = "<group>"; };
|
||||||
isa = PBXFileSystemSynchronizedRootGroup;
|
|
||||||
exceptions = (
|
|
||||||
EB3DAF952F2A4B8F00450593 /* Exceptions for "情绪小组件" folder in "情绪小组件Extension" target */,
|
|
||||||
);
|
|
||||||
explicitFileTypes = {
|
|
||||||
};
|
|
||||||
explicitFolders = (
|
|
||||||
);
|
|
||||||
path = "情绪小组件";
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
/* End PBXFileSystemSynchronizedRootGroup section */
|
/* End PBXFileSystemSynchronizedRootGroup section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
@@ -200,7 +189,7 @@
|
|||||||
EB3DAFD42F2A5FC100450593 /* Recovered References */ = {
|
EB3DAFD42F2A5FC100450593 /* Recovered References */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
A1B2C3D4E5F60718293A4B5B /* EmotionWidget.swift */,
|
A1B2C3D4E5F60718293A4B5B /* 情绪小组件/EmotionWidget.swift */,
|
||||||
);
|
);
|
||||||
name = "Recovered References";
|
name = "Recovered References";
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -374,8 +363,6 @@
|
|||||||
"${PODS_CONFIGURATION_BUILD_DIR}/RNSVG/RNSVGFilters.bundle",
|
"${PODS_CONFIGURATION_BUILD_DIR}/RNSVG/RNSVGFilters.bundle",
|
||||||
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/React-Core_privacy.bundle",
|
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/React-Core_privacy.bundle",
|
||||||
"${PODS_CONFIGURATION_BUILD_DIR}/React-cxxreact/React-cxxreact_privacy.bundle",
|
"${PODS_CONFIGURATION_BUILD_DIR}/React-cxxreact/React-cxxreact_privacy.bundle",
|
||||||
"${PODS_CONFIGURATION_BUILD_DIR}/expo-dev-launcher/EXDevLauncher.bundle",
|
|
||||||
"${PODS_CONFIGURATION_BUILD_DIR}/expo-dev-menu/EXDevMenu.bundle",
|
|
||||||
);
|
);
|
||||||
name = "[CP] Copy Pods Resources";
|
name = "[CP] Copy Pods Resources";
|
||||||
outputPaths = (
|
outputPaths = (
|
||||||
@@ -389,8 +376,6 @@
|
|||||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RNSVGFilters.bundle",
|
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RNSVGFilters.bundle",
|
||||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/React-Core_privacy.bundle",
|
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/React-Core_privacy.bundle",
|
||||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/React-cxxreact_privacy.bundle",
|
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/React-cxxreact_privacy.bundle",
|
||||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXDevLauncher.bundle",
|
|
||||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXDevMenu.bundle",
|
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
@@ -459,7 +444,7 @@
|
|||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
A1B2C3D4E5F60718293A4B5C /* EmotionWidget.swift in Sources */,
|
A1B2C3D4E5F60718293A4B5C /* 情绪小组件/EmotionWidget.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@@ -479,9 +464,11 @@
|
|||||||
baseConfigurationReference = FFF632A94C7A551AAA096858 /* Pods-client.debug.xcconfig */;
|
baseConfigurationReference = FFF632A94C7A551AAA096858 /* Pods-client.debug.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = client/client.entitlements;
|
CODE_SIGN_ENTITLEMENTS = client/client.entitlements;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 2;
|
||||||
|
DEVELOPMENT_TEAM = WS92GPX9H2;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
@@ -493,14 +480,14 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0.0;
|
||||||
OTHER_LDFLAGS = (
|
OTHER_LDFLAGS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"-ObjC",
|
"-ObjC",
|
||||||
"-lc++",
|
"-lc++",
|
||||||
);
|
);
|
||||||
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG";
|
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG";
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.anonymous.client;
|
PRODUCT_BUNDLE_IDENTIFIER = com.damer.mindfulness;
|
||||||
PRODUCT_NAME = client;
|
PRODUCT_NAME = client;
|
||||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||||
SUPPORTS_MACCATALYST = NO;
|
SUPPORTS_MACCATALYST = NO;
|
||||||
@@ -509,7 +496,7 @@
|
|||||||
SWIFT_OBJC_BRIDGING_HEADER = "client/client-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "client/client-Bridging-Header.h";
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = 1;
|
||||||
VERSIONING_SYSTEM = "apple-generic";
|
VERSIONING_SYSTEM = "apple-generic";
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
@@ -519,23 +506,27 @@
|
|||||||
baseConfigurationReference = 3C76CA16D0801CBF0D731C7C /* Pods-client.release.xcconfig */;
|
baseConfigurationReference = 3C76CA16D0801CBF0D731C7C /* Pods-client.release.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = client/client.entitlements;
|
CODE_SIGN_ENTITLEMENTS = client/client.entitlements;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 2;
|
||||||
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
|
DEVELOPMENT_TEAM = WS92GPX9H2;
|
||||||
|
DWARF_DSYM_FILE_SHOULD_ACCOMPANY_PRODUCT = YES;
|
||||||
INFOPLIST_FILE = client/Info.plist;
|
INFOPLIST_FILE = client/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 15.1;
|
IPHONEOS_DEPLOYMENT_TARGET = 15.1;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0.0;
|
||||||
OTHER_LDFLAGS = (
|
OTHER_LDFLAGS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"-ObjC",
|
"-ObjC",
|
||||||
"-lc++",
|
"-lc++",
|
||||||
);
|
);
|
||||||
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE";
|
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE";
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.anonymous.client;
|
PRODUCT_BUNDLE_IDENTIFIER = com.damer.mindfulness;
|
||||||
PRODUCT_NAME = client;
|
PRODUCT_NAME = client;
|
||||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||||
SUPPORTS_MACCATALYST = NO;
|
SUPPORTS_MACCATALYST = NO;
|
||||||
@@ -543,7 +534,7 @@
|
|||||||
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
|
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "client/client-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "client/client-Bridging-Header.h";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = 1;
|
||||||
VERSIONING_SYSTEM = "apple-generic";
|
VERSIONING_SYSTEM = "apple-generic";
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
@@ -680,8 +671,9 @@
|
|||||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 2;
|
||||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||||
|
DEVELOPMENT_TEAM = WS92GPX9H2;
|
||||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
@@ -699,7 +691,7 @@
|
|||||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||||
MTL_FAST_MATH = YES;
|
MTL_FAST_MATH = YES;
|
||||||
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG";
|
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG";
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.anonymous.client.emotionwidget;
|
PRODUCT_BUNDLE_IDENTIFIER = com.damer.mindfulness.emotionwidget;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||||
@@ -713,7 +705,7 @@
|
|||||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = 1;
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
};
|
};
|
||||||
@@ -732,8 +724,9 @@
|
|||||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 2;
|
||||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
|
DEVELOPMENT_TEAM = WS92GPX9H2;
|
||||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
@@ -750,7 +743,7 @@
|
|||||||
MARKETING_VERSION = 1.0.0;
|
MARKETING_VERSION = 1.0.0;
|
||||||
MTL_FAST_MATH = YES;
|
MTL_FAST_MATH = YES;
|
||||||
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE";
|
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE";
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.anonymous.client.emotionwidget;
|
PRODUCT_BUNDLE_IDENTIFIER = com.damer.mindfulness.emotionwidget;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||||
@@ -763,7 +756,7 @@
|
|||||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = 1;
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
};
|
};
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 142 KiB |
@@ -1,81 +1,81 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>CFBundleDevelopmentRegion</key>
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||||
<key>CFBundleDisplayName</key>
|
<key>CFBundleDisplayName</key>
|
||||||
<string>client</string>
|
<string>client</string>
|
||||||
<key>CFBundleExecutable</key>
|
<key>CFBundleExecutable</key>
|
||||||
<string>$(EXECUTABLE_NAME)</string>
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
<key>CFBundleIdentifier</key>
|
<key>CFBundleIdentifier</key>
|
||||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
<key>CFBundleInfoDictionaryVersion</key>
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
<string>6.0</string>
|
<string>6.0</string>
|
||||||
<key>CFBundleName</key>
|
<key>CFBundleName</key>
|
||||||
<string>$(PRODUCT_NAME)</string>
|
<string>$(PRODUCT_NAME)</string>
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>1.0.0</string>
|
<string>$(MARKETING_VERSION)</string>
|
||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>CFBundleURLTypes</key>
|
<key>CFBundleURLTypes</key>
|
||||||
<array>
|
<array>
|
||||||
<dict>
|
<dict>
|
||||||
<key>CFBundleURLSchemes</key>
|
<key>CFBundleURLSchemes</key>
|
||||||
<array>
|
<array>
|
||||||
<string>client</string>
|
<string>client</string>
|
||||||
<string>com.anonymous.client</string>
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
</array>
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
</array>
|
</array>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1</string>
|
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||||
<key>LSMinimumSystemVersion</key>
|
<key>LSMinimumSystemVersion</key>
|
||||||
<string>12.0</string>
|
<string>12.0</string>
|
||||||
<key>LSRequiresIPhoneOS</key>
|
<key>LSRequiresIPhoneOS</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>NSAppTransportSecurity</key>
|
<key>NSAppTransportSecurity</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>NSAllowsArbitraryLoads</key>
|
<key>NSAllowsArbitraryLoads</key>
|
||||||
<false/>
|
<false/>
|
||||||
<key>NSAllowsLocalNetworking</key>
|
<key>NSAllowsLocalNetworking</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
<key>NSUserActivityTypes</key>
|
<key>NSUserActivityTypes</key>
|
||||||
<array>
|
<array>
|
||||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER).expo.index_route</string>
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER).expo.index_route</string>
|
||||||
</array>
|
</array>
|
||||||
<key>RCTNewArchEnabled</key>
|
<key>RCTNewArchEnabled</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>UILaunchStoryboardName</key>
|
<key>UILaunchStoryboardName</key>
|
||||||
<string>SplashScreen</string>
|
<string></string>
|
||||||
<key>UIRequiredDeviceCapabilities</key>
|
<key>UIRequiredDeviceCapabilities</key>
|
||||||
<array>
|
<array>
|
||||||
<string>arm64</string>
|
<string>arm64</string>
|
||||||
</array>
|
</array>
|
||||||
<key>UIRequiresFullScreen</key>
|
<key>UIRequiresFullScreen</key>
|
||||||
<false/>
|
<false/>
|
||||||
<key>UIStatusBarStyle</key>
|
<key>UIStatusBarStyle</key>
|
||||||
<string>UIStatusBarStyleDefault</string>
|
<string>UIStatusBarStyleDefault</string>
|
||||||
<key>UISupportedInterfaceOrientations</key>
|
<key>UISupportedInterfaceOrientations</key>
|
||||||
<array>
|
<array>
|
||||||
<string>UIInterfaceOrientationPortrait</string>
|
<string>UIInterfaceOrientationPortrait</string>
|
||||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||||
</array>
|
</array>
|
||||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||||
<array>
|
<array>
|
||||||
<string>UIInterfaceOrientationPortrait</string>
|
<string>UIInterfaceOrientationPortrait</string>
|
||||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
</array>
|
</array>
|
||||||
<key>UIUserInterfaceStyle</key>
|
<key>UIUserInterfaceStyle</key>
|
||||||
<string>Automatic</string>
|
<string>Automatic</string>
|
||||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
@@ -3,6 +3,6 @@
|
|||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>aps-environment</key>
|
<key>aps-environment</key>
|
||||||
<string>development</string>
|
<string>production</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
@@ -29,7 +29,7 @@ function getApiBaseUrl(env: AppRuntimeEnv): string {
|
|||||||
const direct = process.env.EXPO_PUBLIC_API_BASE_URL;
|
const direct = process.env.EXPO_PUBLIC_API_BASE_URL;
|
||||||
if (direct && String(direct).trim()) return String(direct).trim();
|
if (direct && String(direct).trim()) return String(direct).trim();
|
||||||
|
|
||||||
// 约定:local/dev/prod 三套域名分别配置,便于后续直接切环境而不改代码
|
// 约定:local/dev/prod 三套域名分别配置, 便于后续直接切环境而不改代码
|
||||||
if (env === 'local') {
|
if (env === 'local') {
|
||||||
return getOptionalEnv('EXPO_PUBLIC_API_BASE_URL_LOCAL', 'http://localhost:8000');
|
return getOptionalEnv('EXPO_PUBLIC_API_BASE_URL_LOCAL', 'http://localhost:8000');
|
||||||
}
|
}
|
||||||
|
|||||||
89
scripts/ssh-key-to-b64.mjs
Normal file
89
scripts/ssh-key-to-b64.mjs
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
/**
|
||||||
|
* 把 SSH 私钥转换为“单行 base64”,用于放入 Gitea Secrets(例如 DEV_SSH_KEY_B64)。
|
||||||
|
*
|
||||||
|
* 用法:
|
||||||
|
* 1) 从文件读取:
|
||||||
|
* node scripts/ssh-key-to-b64.mjs ~/.ssh/deploy_key
|
||||||
|
*
|
||||||
|
* 2) 从 stdin 读取(直接粘贴私钥内容,结束后按 Ctrl+D):
|
||||||
|
* node scripts/ssh-key-to-b64.mjs -
|
||||||
|
*
|
||||||
|
* 3) 输出同时复制到剪贴板(仅 macOS,需系统自带 pbcopy):
|
||||||
|
* node scripts/ssh-key-to-b64.mjs ~/.ssh/deploy_key --clipboard
|
||||||
|
*
|
||||||
|
* 注意:
|
||||||
|
* - 请不要把输出写入仓库或提交到 git。
|
||||||
|
* - 工作流会优先使用 *_SSH_KEY_B64(更稳,避免多行换行丢失)。
|
||||||
|
*/
|
||||||
|
|
||||||
|
import fs from 'node:fs';
|
||||||
|
import { spawnSync } from 'node:child_process';
|
||||||
|
|
||||||
|
function printHelp() {
|
||||||
|
console.log(`用法:
|
||||||
|
node scripts/ssh-key-to-b64.mjs <私钥文件路径> [--clipboard] [--stdout]
|
||||||
|
node scripts/ssh-key-to-b64.mjs - [--clipboard] [--stdout]
|
||||||
|
|
||||||
|
示例:
|
||||||
|
node scripts/ssh-key-to-b64.mjs ~/.ssh/deploy_key
|
||||||
|
node scripts/ssh-key-to-b64.mjs - --clipboard
|
||||||
|
node scripts/ssh-key-to-b64.mjs ~/.ssh/deploy_key --clipboard --stdout
|
||||||
|
`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const args = process.argv.slice(2);
|
||||||
|
const clipboard = args.includes('--clipboard') || args.includes('-c');
|
||||||
|
const forceStdout = args.includes('--stdout');
|
||||||
|
const help = args.includes('--help') || args.includes('-h');
|
||||||
|
const input = args.find((a) => !a.startsWith('-'));
|
||||||
|
|
||||||
|
if (help || !input) {
|
||||||
|
printHelp();
|
||||||
|
process.exit(help ? 0 : 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function readAllStdin() {
|
||||||
|
return fs.readFileSync(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
let buf;
|
||||||
|
try {
|
||||||
|
if (input === '-') {
|
||||||
|
buf = readAllStdin();
|
||||||
|
} else {
|
||||||
|
buf = fs.readFileSync(input);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`读取失败:${String(e?.message || e)}`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重要:按“原始字节”做 base64,避免任何编码/换行处理导致私钥内容变化
|
||||||
|
// 这样工作流解码后能 100% 还原原文件内容
|
||||||
|
const asText = buf.toString('utf8');
|
||||||
|
if (!asText.includes('BEGIN') || !asText.includes('PRIVATE KEY')) {
|
||||||
|
console.error('提示:输入内容看起来不像 SSH 私钥(未检测到 PRIVATE KEY 头部)。仍会继续转换,但请确认输入正确。');
|
||||||
|
}
|
||||||
|
|
||||||
|
const b64 = buf.toString('base64');
|
||||||
|
|
||||||
|
if (clipboard) {
|
||||||
|
if (process.platform !== 'darwin') {
|
||||||
|
console.error('当前不是 macOS,无法使用 --clipboard(需要 pbcopy)。将仅输出到 stdout。');
|
||||||
|
} else {
|
||||||
|
const r = spawnSync('pbcopy', [], { input: b64, encoding: 'utf8' });
|
||||||
|
if (r.status !== 0) {
|
||||||
|
console.error(`复制到剪贴板失败:pbcopy 退出码=${r.status}`);
|
||||||
|
} else {
|
||||||
|
console.error('已复制到剪贴板:请粘贴到 Gitea Secrets(例如 DEV_SSH_KEY_B64)。');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 默认:如果使用了 --clipboard,就不再把超长 base64 打到终端(避免影响后续命令输出)。
|
||||||
|
// 如需同时打印,请加 --stdout。
|
||||||
|
if (!clipboard || forceStdout || process.platform !== 'darwin') {
|
||||||
|
process.stdout.write(b64 + '\n');
|
||||||
|
}
|
||||||
|
|
||||||
20
server/.dockerignore
Normal file
20
server/.dockerignore
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
.venv
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
*.pyo
|
||||||
|
*.pyd
|
||||||
|
.pytest_cache/
|
||||||
|
.mypy_cache/
|
||||||
|
.ruff_cache/
|
||||||
|
|
||||||
|
# 本地/测试数据
|
||||||
|
.test.db
|
||||||
|
*.db
|
||||||
|
|
||||||
|
# 测试与开发脚本(按需移除)
|
||||||
|
tests/
|
||||||
|
.env*
|
||||||
|
|
||||||
|
# Git 元数据
|
||||||
|
.git/
|
||||||
|
.gitignore
|
||||||
32
server/Dockerfile
Normal file
32
server/Dockerfile
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
FROM python:3.11-slim
|
||||||
|
|
||||||
|
# 运行时基础环境
|
||||||
|
ENV PYTHONDONTWRITEBYTECODE=1 \
|
||||||
|
PYTHONUNBUFFERED=1
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# 系统依赖(按需扩展;多数依赖为纯 Python)
|
||||||
|
RUN apt-get update \
|
||||||
|
&& apt-get install -y --no-install-recommends build-essential curl \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# 先复制依赖清单以利用 Docker layer cache
|
||||||
|
COPY requirements.txt /app/requirements.txt
|
||||||
|
RUN python -m pip install -U pip \
|
||||||
|
&& pip install --no-cache-dir -r /app/requirements.txt
|
||||||
|
|
||||||
|
# 复制后端代码与迁移配置
|
||||||
|
COPY app /app/app
|
||||||
|
COPY alembic /app/alembic
|
||||||
|
COPY alembic.ini /app/alembic.ini
|
||||||
|
|
||||||
|
EXPOSE 8000
|
||||||
|
|
||||||
|
# 注意:
|
||||||
|
# - 镜像内不会打包 `.env.dev/.env.prod`(避免把敏感信息烘焙进镜像)
|
||||||
|
# - 运行容器时请通过 `--env-file` 或 `-e` 注入 DATABASE_URL / REDIS_URL / CELERY_BROKER_URL
|
||||||
|
# - 参考文档:server/README.md
|
||||||
|
|
||||||
|
# 生产镜像默认不开启 reload
|
||||||
|
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
|
||||||
@@ -82,6 +82,11 @@ CELERY_BROKER_URL=redis://dev_user:devpassword@127.0.0.1:6379/0
|
|||||||
|
|
||||||
`.env.prod` 同理,替换为生产环境地址与密钥即可。
|
`.env.prod` 同理,替换为生产环境地址与密钥即可。
|
||||||
|
|
||||||
|
补充:
|
||||||
|
|
||||||
|
- 仓库内提供了一个不包含真实值的模板文件 `server/env.example`,可复制为 `.env.dev/.env.prod` 后再填写。
|
||||||
|
- **Docker 不会自动读取 `.env.*`**,容器运行时需要通过 `--env-file` 或 `-e` 注入环境变量(见下方 Docker 运行)。
|
||||||
|
|
||||||
### 1.1 MySQL 命名与 dev/pro 区分(约定)
|
### 1.1 MySQL 命名与 dev/pro 区分(约定)
|
||||||
|
|
||||||
- **生产库(prod)**:`mindfulness`
|
- **生产库(prod)**:`mindfulness`
|
||||||
@@ -146,6 +151,38 @@ uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
|
|||||||
- OpenAPI 文档:`/docs`
|
- OpenAPI 文档:`/docs`
|
||||||
- ReDoc:`/redoc`
|
- ReDoc:`/redoc`
|
||||||
|
|
||||||
|
## Docker 运行
|
||||||
|
|
||||||
|
后端启动至少需要以下 3 个环境变量:
|
||||||
|
|
||||||
|
- `DATABASE_URL`
|
||||||
|
- `REDIS_URL`
|
||||||
|
- `CELERY_BROKER_URL`
|
||||||
|
|
||||||
|
### 方式 A:使用 env 文件(推荐)
|
||||||
|
|
||||||
|
1) 在宿主机准备 `server/.env.prod`(或 `.env.dev`),内容为 `KEY=value`:
|
||||||
|
|
||||||
|
- 可从 `server/env.example` 复制后填写
|
||||||
|
|
||||||
|
2) 运行容器时通过 `--env-file` 注入:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run --rm -p 8000:8000 \
|
||||||
|
--env-file server/.env.prod \
|
||||||
|
mindfulness-server:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
### 方式 B:直接用 -e 注入
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run --rm -p 8000:8000 \
|
||||||
|
-e DATABASE_URL="mysql+aiomysql://用户名:密码@mysql:3306/mindfulness?charset=utf8mb4" \
|
||||||
|
-e REDIS_URL="redis://:密码@redis:6379/0" \
|
||||||
|
-e CELERY_BROKER_URL="redis://:密码@redis:6379/0" \
|
||||||
|
mindfulness-server:latest
|
||||||
|
```
|
||||||
|
|
||||||
## 数据库迁移(Alembic)
|
## 数据库迁移(Alembic)
|
||||||
|
|
||||||
> 若你采用 Alembic:建议把迁移脚本放在 `server/alembic/`,并在 `alembic.ini` 中配置数据库连接(或从环境变量读取)。
|
> 若你采用 Alembic:建议把迁移脚本放在 `server/alembic/`,并在 `alembic.ini` 中配置数据库连接(或从环境变量读取)。
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ from functools import lru_cache
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Literal, Optional
|
from typing import Literal, Optional
|
||||||
|
|
||||||
|
from pydantic import ValidationError
|
||||||
from pydantic_settings import BaseSettings, SettingsConfigDict
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||||
|
|
||||||
|
|
||||||
@@ -67,5 +68,41 @@ def get_settings() -> Settings:
|
|||||||
env = os.getenv("APP_ENV", "dev").strip() or "dev"
|
env = os.getenv("APP_ENV", "dev").strip() or "dev"
|
||||||
env_file = _guess_env_file(env)
|
env_file = _guess_env_file(env)
|
||||||
|
|
||||||
return Settings(_env_file=env_file)
|
try:
|
||||||
|
return Settings(_env_file=env_file)
|
||||||
|
except ValidationError as e:
|
||||||
|
# 给出更可执行的错误信息,避免只看到一串校验栈。
|
||||||
|
missing_fields: list[str] = []
|
||||||
|
for err in e.errors():
|
||||||
|
if err.get("type") == "missing":
|
||||||
|
loc = err.get("loc") or ()
|
||||||
|
if loc:
|
||||||
|
missing_fields.append(str(loc[0]))
|
||||||
|
|
||||||
|
# 将字段名映射为常见的环境变量名(默认规则:字段名大写)
|
||||||
|
missing_env_keys = [f.upper() for f in missing_fields] if missing_fields else []
|
||||||
|
|
||||||
|
env_file_hint = env_file or f".env.{env}(未找到,已回退到系统环境变量)"
|
||||||
|
required_hint = (
|
||||||
|
"、".join(missing_env_keys)
|
||||||
|
if missing_env_keys
|
||||||
|
else "DATABASE_URL、REDIS_URL、CELERY_BROKER_URL"
|
||||||
|
)
|
||||||
|
|
||||||
|
msg = (
|
||||||
|
"应用启动失败:缺少必填配置。\n\n"
|
||||||
|
f"- 当前 APP_ENV:{env}\n"
|
||||||
|
f"- 期望读取的 env 文件:{env_file_hint}\n"
|
||||||
|
f"- 缺少的环境变量:{required_hint}\n\n"
|
||||||
|
"修复方式(任选其一):\n"
|
||||||
|
"1) 直接注入环境变量(推荐):\n"
|
||||||
|
" - DATABASE_URL=...\n"
|
||||||
|
" - REDIS_URL=...\n"
|
||||||
|
" - CELERY_BROKER_URL=...\n"
|
||||||
|
"2) 使用 env 文件:在 `server/` 下准备 `.env.dev` 或 `.env.prod`(KEY=value 格式),\n"
|
||||||
|
" 本地可通过 `server/run.sh --env dev|prod` 自动加载;Docker 运行可用 `--env-file` 传入。\n"
|
||||||
|
)
|
||||||
|
# 不附带原始 ValidationError 的异常上下文,减少日志噪音;
|
||||||
|
# msg 已包含缺失项与修复方式,足够定位问题。
|
||||||
|
raise RuntimeError(msg) from None
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ def create_app() -> FastAPI:
|
|||||||
"""
|
"""
|
||||||
创建 FastAPI 应用实例。
|
创建 FastAPI 应用实例。
|
||||||
|
|
||||||
说明:目前仅提供最小可运行骨架(health check),后续逐步加入路由与中间件。
|
说明:目前仅提供最小可运行骨架(健康检查),后续逐步加入路由与中间件。
|
||||||
"""
|
"""
|
||||||
|
|
||||||
settings = get_settings()
|
settings = get_settings()
|
||||||
@@ -20,6 +20,13 @@ def create_app() -> FastAPI:
|
|||||||
app.include_router(user_profile_router)
|
app.include_router(user_profile_router)
|
||||||
app.include_router(reco_router)
|
app.include_router(reco_router)
|
||||||
|
|
||||||
|
@app.get("/health")
|
||||||
|
async def health() -> dict:
|
||||||
|
"""
|
||||||
|
部署健康检查(兼容常见探针路径)。
|
||||||
|
"""
|
||||||
|
return {"status": "ok", "env": settings.app_env}
|
||||||
|
|
||||||
@app.get("/healthz")
|
@app.get("/healthz")
|
||||||
async def healthz() -> dict:
|
async def healthz() -> dict:
|
||||||
return {"status": "ok", "env": settings.app_env}
|
return {"status": "ok", "env": settings.app_env}
|
||||||
|
|||||||
@@ -1,3 +1,34 @@
|
|||||||
|
# 说明:
|
||||||
|
# - 这是后端环境变量模板,请复制为 `.env.dev` 或 `.env.prod` 再填写真实值
|
||||||
|
# - 请勿把包含真实账号密码/Token 的 `.env.*` 提交到仓库
|
||||||
|
#
|
||||||
|
# 用法示例:
|
||||||
|
# - 本地:`./run.sh --env dev`
|
||||||
|
# - Docker:`docker run --env-file server/.env.prod ...`
|
||||||
|
|
||||||
|
# 运行环境
|
||||||
|
APP_ENV=dev
|
||||||
|
APP_NAME=mindfulness-server
|
||||||
|
APP_HOST=0.0.0.0
|
||||||
|
APP_PORT=8000
|
||||||
|
|
||||||
|
# 数据库(SQLAlchemy 异步连接串)
|
||||||
|
# MySQL 示例(aiomysql):
|
||||||
|
# DATABASE_URL=mysql+aiomysql://用户名:密码@127.0.0.1:3306/mindfulness_dev?charset=utf8mb4
|
||||||
|
DATABASE_URL=
|
||||||
|
|
||||||
|
# Redis(缓存/任务队列)
|
||||||
|
# 示例:
|
||||||
|
# REDIS_URL=redis://:密码@127.0.0.1:6379/0
|
||||||
|
REDIS_URL=
|
||||||
|
|
||||||
|
# Celery(建议先只配 broker;如需结果存储可另配 CELERY_RESULT_BACKEND)
|
||||||
|
# 示例:
|
||||||
|
# CELERY_BROKER_URL=redis://:密码@127.0.0.1:6379/0
|
||||||
|
CELERY_BROKER_URL=
|
||||||
|
|
||||||
|
# 可选:Celery 结果存储
|
||||||
|
# CELERY_RESULT_BACKEND=redis://:密码@127.0.0.1:6379/0
|
||||||
# 运行环境:dev 或 prod
|
# 运行环境:dev 或 prod
|
||||||
APP_ENV=dev
|
APP_ENV=dev
|
||||||
|
|
||||||
|
|||||||
@@ -46,5 +46,5 @@
|
|||||||
## 6. 风险与注意事项
|
## 6. 风险与注意事项
|
||||||
|
|
||||||
- **Expo Go 不支持**:必须用 Xcode 运行预构建后的 App(或后续 EAS Build)
|
- **Expo Go 不支持**:必须用 Xcode 运行预构建后的 App(或后续 EAS Build)
|
||||||
- **Bundle Identifier**:当前 `client/app.json` 使用 `com.anonymous.client`,仅适合本地验证;上线前需替换为真实 bundle id,并同步证书/签名
|
- **Bundle Identifier**:当前工程已统一为主 App `com.damer.mindfulness`,Widget Extension `com.damer.mindfulness.emotionwidget`;上线前仍需在 Apple Developer / App Store Connect 侧确保 App ID、证书与签名匹配
|
||||||
|
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ npx expo prebuild -p ios
|
|||||||
- **排查**:
|
- **排查**:
|
||||||
- 桌面搜索不到:通常是没有 Run 安装过主 App,或 Widget target 未加入编译
|
- 桌面搜索不到:通常是没有 Run 安装过主 App,或 Widget target 未加入编译
|
||||||
- 点击不跳转:确认 Widget 里 `widgetURL` 为 `client:///(app)/home`,且 `app.json` 的 `scheme` 为 `client`
|
- 点击不跳转:确认 Widget 里 `widgetURL` 为 `client:///(app)/home`,且 `app.json` 的 `scheme` 为 `client`
|
||||||
- 仍然搜不到:检查 Widget Extension 的 Bundle Identifier 是否有效(本仓库已修正为 `com.anonymous.client.emotionwidget`),然后 Clean + 重新安装 App
|
- 仍然搜不到:检查 Widget Extension 的 Bundle Identifier 是否有效(本仓库已修正为 `com.damer.mindfulness.emotionwidget`),然后 Clean + 重新安装 App
|
||||||
|
|
||||||
## 6. 文档补充(可选但建议)
|
## 6. 文档补充(可选但建议)
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,11 @@
|
|||||||
- 安全:真实 IP/账号/密码/Token 不写入仓库,仅提供 `.env.example` 结构
|
- 安全:真实 IP/账号/密码/Token 不写入仓库,仅提供 `.env.example` 结构
|
||||||
- **阶段产物**:
|
- **阶段产物**:
|
||||||
- `spec_kit/Project Bootstrap/spec.md`
|
- `spec_kit/Project Bootstrap/spec.md`
|
||||||
|
- **近期变更**:
|
||||||
|
- 新增后端镜像构建基础:`server/Dockerfile`、`server/.dockerignore`
|
||||||
|
- 新增后端镜像打包与推送工作流:`.gitea/workflows/server-build.yml`(自动递增 semver tag 并推送到 Docker Hub)
|
||||||
|
- 新增后端蓝绿部署工作流:`.gitea/workflows/server-deploy.yml`(SSH 上机 + Docker 蓝绿启动 + Nginx upstream 切流 + 健康检查与失败回滚)
|
||||||
|
- 后端配置缺失时报错增强:`app/core/config.py` 将缺失的必填环境变量用中文提示并给出注入方式;补充 `server/env.example` 与 Docker 运行说明
|
||||||
|
|
||||||
## Onboarding App Shell
|
## Onboarding App Shell
|
||||||
|
|
||||||
@@ -54,6 +59,10 @@
|
|||||||
- `spec_kit/iOS Widget/spec.md`
|
- `spec_kit/iOS Widget/spec.md`
|
||||||
- `spec_kit/iOS Widget/plan.md`
|
- `spec_kit/iOS Widget/plan.md`
|
||||||
- `spec_kit/iOS Widget/tasks.md`
|
- `spec_kit/iOS Widget/tasks.md`
|
||||||
|
- **近期变更**:
|
||||||
|
- iOS 主 App Bundle ID 已统一为 `com.damer.mindfulness`,Widget Extension 为 `com.damer.mindfulness.emotionwidget`
|
||||||
|
- iOS 构建号已提升到 `2`,并将 `client/ios/client/Info.plist` 改为自动跟随 `MARKETING_VERSION` / `CURRENT_PROJECT_VERSION`
|
||||||
|
- 推送 entitlements 的 `aps-environment` 已切到 `production`(用于 TestFlight/线上包)
|
||||||
|
|
||||||
## Splash Consent
|
## Splash Consent
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user