Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,21 @@
"localRoot": "${workspaceFolder}/apps/pwabuilder-google-play",
"remoteRoot": "${workspaceFolder}/apps/pwabuilder-google-play"
},
{
"name": "Attach: Meta Horizon Service",
"type": "node",
"request": "attach",
"preLaunchTask": "tasks.meta-horizon:dev",
"env": {
"NODE_ENV": "test"
},
"port": 5859,
"skipFiles": [
"<node_internals>/**"
],
"localRoot": "${workspaceFolder}/apps/pwabuilder-meta-horizon",
"remoteRoot": "${workspaceFolder}/apps/pwabuilder-meta-horizon"
},
{
"name": "launch.microsoft-package-generator",
"type": "coreclr",
Expand All @@ -68,7 +83,8 @@
"configurations": [
"launch.backend",
"launch.microsoft-package-generator",
"Attach: Google Play Service"
"Attach: Google Play Service",
"Attach: Meta Horizon Service"
]
}
]
Expand Down
23 changes: 23 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,29 @@
"NODE_ENV": "test"
}
}
},
{
"label": "tasks.meta-horizon:install",
"type": "npm",
"path": "apps/pwabuilder-meta-horizon",
"script": "install",
"isBackground": true,
"detail": "npm install for pwabuilder-meta-horizon"
},
{
"label": "tasks.meta-horizon:dev",
"type": "npm",
"path": "apps/pwabuilder-meta-horizon",
"script": "dev",
"dependsOn": "tasks.meta-horizon:install",
"isBackground": true,
"detail": "npm run dev for pwabuilder-meta-horizon",
"problemMatcher": [],
"options": {
"env": {
"NODE_ENV": "test"
}
}
}
],
"inputs": [
Expand Down
1 change: 1 addition & 0 deletions apps/pwabuilder-meta-horizon/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
147 changes: 147 additions & 0 deletions apps/pwabuilder-meta-horizon/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Runtime data
pids
*.pid
*.seed
*.pid.lock

#remove js files
**/*.js
**/*.js.map
!static/*.js

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage

# nyc test coverage
.nyc_output

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# TypeScript v1 declaration files
typings/

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variables file
.env

# next.js build output
.next

# Built application files
*.apk
*.ap_
*.aab

# Files for the ART/Dalvik VM
*.dex

# Java class files
*.class

# Generated files
bin/
gen/
out/


# Local configuration file (sdk path, etc)
local.properties

# Proguard folder generated by Eclipse
proguard/

# Log Files
*.log

# Android Studio Navigation editor temp files
.navigation/

# Android Studio captures folder
captures/

# IntelliJ
*.iml
.idea/workspace.xml
.idea/tasks.xml
.idea/gradle.xml
.idea/assetWizardSettings.xml
.idea/dictionaries
.idea/libraries
.idea/caches
# Android Studio 3 in .gitignore file.
.idea/caches/build_file_checksums.ser
.idea/modules.xml

# Keystore files
# Uncomment the following lines if you do not want to check your keystore files in.
#*.jks
#*.keystore

# External native build folder generated in Android Studio 2.2 and later
.externalNativeBuild

# Google Services (e.g. APIs or Firebase)
# google-services.json

# Freeline
freeline.py
freeline/
freeline_project_description.json

# fastlane
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots
fastlane/test_output
fastlane/readme.md

# Version control
vcs.xml

# lint
lint/intermediates/
lint/generated/
lint/outputs/
lint/tmp/
# lint/reports/

# Visual Studio
/.vs
18 changes: 18 additions & 0 deletions apps/pwabuilder-meta-horizon/.vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"program": "${workspaceFolder}/server.js",
"skipFiles": [
"<node_internals>/**"
]
}

]
}
106 changes: 106 additions & 0 deletions apps/pwabuilder-meta-horizon/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# ─── PRELIMINAR: Ubuntu base con Android/Java toolchain ───────────────────────
FROM --platform=linux/amd64 ubuntu:24.04 AS ubuntu

ARG ANDROID_SDK_TOOLS_VERSION="11076708"
ARG NODE_VERSION="20.x"
ARG JENV_RELEASE="0.5.6"

ARG DIRWORK="/tmp"
ARG SDK_PACKAGES_LIST="${DIRWORK}/packages.txt"

ENV JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
ENV PATH=${JAVA_HOME}/bin:${PATH}

ENV ANDROID_HOME="/opt/android-sdk" \
ANDROID_SDK_HOME="/opt/android-sdk" \
ANDROID_NDK="/opt/android-sdk/ndk/latest" \
ANDROID_NDK_ROOT="/opt/android-sdk/ndk/latest" \
FLUTTER_HOME="/opt/flutter" \
JENV_ROOT="/opt/jenv" \
ANDROID_SDK_MANAGER=/opt/android-sdk/cmdline-tools/latest/bin/sdkmanager \
TZ=America/Los_Angeles \
LANG="en_US.UTF-8" \
LANGUAGE="en_US.UTF-8" \
LC_ALL="en_US.UTF-8"

ENV PATH="${JENV_ROOT}/shims:${JENV_ROOT}/bin:$JAVA_HOME/bin:$PATH:$ANDROID_SDK_HOME/emulator:$ANDROID_SDK_HOME/cmdline-tools/latest/bin:$ANDROID_SDK_HOME/tools:$ANDROID_SDK_HOME/platform-tools:$ANDROID_NDK:$FLUTTER_HOME/bin:$FLUTTER_HOME/bin/cache/dart-sdk/bin"

FROM ubuntu AS pre-base
ARG TERM=dumb
ARG DEBIAN_FRONTEND=noninteractive
WORKDIR ${DIRWORK}

RUN echo export JAVA_HOME="/usr/lib/jvm/java-17-openjdk-$(uname -m)/" >> /etc/jdk.env && \
echo . /etc/jdk.env >> /etc/bash.bashrc && echo . /etc.jdk.env >> /etc/profile && \
apt-get update -qq && \
apt-get install -qq --no-install-recommends \
apt-utils locales unzip curl git git-lfs build-essential openjdk-11-jdk openjdk-17-jdk \
wget zip zipalign ruby-full python3-pip tzdata && \
locale-gen $LANG && \
git lfs install && \
ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone && \
rm -rf /var/lib/apt/lists/*


FROM pre-base AS base

RUN wget --quiet -O sdk-tools.zip \
"https://dl.google.com/android/repository/commandlinetools-linux-${ANDROID_SDK_TOOLS_VERSION}_latest.zip" && \
mkdir -p "$ANDROID_HOME/cmdline-tools" && \
unzip -q sdk-tools.zip -d "$ANDROID_HOME/cmdline-tools" && \
rm sdk-tools.zip && \
mv "$ANDROID_HOME/cmdline-tools/cmdline-tools" "$ANDROID_HOME/cmdline-tools/latest" && \
echo yes | "$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" --licenses && \
echo yes | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager "platform-tools" && \
echo yes | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager "platforms;android-31" && \
echo yes | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager "platforms;android-36" && \
echo yes | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager "build-tools;35.0.0" && \
echo yes | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager "build-tools;34.0.0" && \
echo yes | "$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" --licenses


FROM base AS jenv-base
RUN git clone --depth 1 --branch ${JENV_RELEASE} https://github.com/jenv/jenv.git ${JENV_ROOT} && \
echo 'eval "$(jenv init -)"' >> ~/.bash_profile && \
. ~/.bash_profile && . /etc/jdk.env && \
jenv add /usr/lib/jvm/java-11-openjdk-$(uname -m) && \
jenv add /usr/lib/jvm/java-17-openjdk-$(uname -m) && \
jenv global 17.0


FROM base AS pre-minimal
RUN mkdir -p "$ANDROID_HOME"/.android && \
echo '### User Sources for Android SDK Manager' > "$ANDROID_HOME"/.android/repositories.cfg && \
echo yes | ${ANDROID_SDK_MANAGER} --licenses > /dev/null && \
${ANDROID_SDK_MANAGER} --list > ${SDK_PACKAGES_LIST}


FROM pre-minimal AS node-final
RUN curl -sL https://deb.nodesource.com/setup_${NODE_VERSION} | bash - && \
apt-get update -qq && apt-get install -qq nodejs yarn && \
npm install -g npm@latest && \
npm install -g bower cordova eslint gulp-cli @ionic/cli mocha node-gyp

FROM node-final AS builder
WORKDIR /app

COPY package*.json tsconfig.json ./
COPY . .

ENV NODE_ENV=development
RUN npm install
RUN npm run build
RUN ls -la /app/server.*

FROM builder AS app
WORKDIR /app

COPY --from=builder /app/package*.json ./
RUN npm install --omit=dev --ignore-scripts

COPY --from=builder /app .

ENV PORT=5858
EXPOSE 5858

CMD npm start
13 changes: 13 additions & 0 deletions apps/pwabuilder-meta-horizon/LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
PWABuilder Meta Horizon Packaging Service

Copyright (c) Microsoft Corporation

All rights reserved.

MIT License

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
42 changes: 42 additions & 0 deletions apps/pwabuilder-meta-horizon/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Meta Horizon Packaging Service

This is PWABuilder's Meta Horizon platform that generates a Meta Horizon Store-ready app package (an `.aab` file) from a Progressive Web App using Android's Trusted Web Activity technology, configured for Meta Quest headsets.

We utilize [Meta's fork of Bubblewrap](https://github.com/meta-quest/bubblewrap) (`@meta-quest/bubblewrap-core`) to generate and sign an Android app package targeting Horizon OS. See the [Meta Horizon PWA packaging documentation](https://developers.meta.com/horizon/documentation/web/pwa-packaging/) for full guidance on the Bubblewrap CLI options used by this service.

This tool generates a zip file containing both an `.apk` file (for sideloading and testing on a Quest device) and an `.aab` file (for submission to the Meta Horizon Store).

This app uses [PWABuilder's Android Build Box](https://github.com/pwa-builder/docker-android-build-box) docker image, which contains the necessary Android SDK Build Tools to execute Bubblewrap.

## Issues

Please use our [main repository for any issues/bugs/features suggestions](https://github.com/pwa-builder/PWABuilder/issues/new/choose).

## Running Locally

Steps:

1. Configure environment files: in `apps/pwabuilder-meta-horizon/env/test.env`, set the paths for your JDK and AndroidTools.

2. Launch the service: open the Run and Debug panel in VS Code, select "Launch Program", and press F5 to start the Meta Horizon package generator API.

3. Visit `localhost` to see the testing interface.

The response will be a zip file containing the generated app.

Alternatively, you can build and run the service using Docker:

```bash
npm run docker:build
npm run docker:run
```

This will start the docker container. Open a browser to `localhost:5859` to see the testing interface.

## More info

Once a Meta Horizon Store app package has been generated, follow the steps on the [Meta Horizon PWA packaging documentation](https://developers.meta.com/horizon/documentation/web/pwa-packaging/) to publish to the Meta Horizon Store.

## Deploy

Deploys are automatically pushed to the Meta Horizon staging slot. To deploy to production, swap staging and production.
Loading