commit fb4d6837d00a73053fe575e8fae3164c24cc15e0 Author: Thomas E Lackey Date: Thu Dec 14 16:02:00 2023 +0000 Initial commit diff --git a/.gitea/workflows/publish.yaml b/.gitea/workflows/publish.yaml new file mode 100644 index 0000000..6275913 --- /dev/null +++ b/.gitea/workflows/publish.yaml @@ -0,0 +1,34 @@ +name: Publish ApplicationRecord to Registry +on: + release: + types: [published] +jobs: + cns_publish: + runs-on: ubuntu-latest + steps: + - name: "Clone project repository" + uses: actions/checkout@v3 + - name: Use Node.js + uses: actions/setup-node@v3 + with: + node-version: 18 + - name: "Install Yarn" + run: npm install -g yarn + - name: "Install registry CLI" + run: | + npm config set @cerc-io:registry https://git.vdb.to/api/packages/cerc-io/npm/ + yarn global add @cerc-io/laconic-registry-cli + - name: "Install jq" + run: apt -y update && apt -y install jq + - name: "Publish Application Record" + env: + CERC_REGISTRY_USER_KEY: ${{ secrets.CICD_CERCIO_USER_KEY }} + CERC_REGISTRY_BOND_ID: ${{ secrets.CICD_CERCIO_BOND_ID }} + CERC_REGISTRY_APP_CRN: "crn://cerc-io/applications/test-progressive-web-app" + run: scripts/publish-app-record.sh + - name: "Request Deployment" + env: + CERC_REGISTRY_USER_KEY: ${{ secrets.CICD_LACONIC_USER_KEY }} + CERC_REGISTRY_BOND_ID: ${{ secrets.CICD_LACONIC_BOND_ID }} + CERC_REGISTRY_APP_CRN: "crn://cerc-io/applications/test-progressive-web-app" + run: scripts/request-app-deployment.sh diff --git a/README.md b/README.md new file mode 100644 index 0000000..669d643 --- /dev/null +++ b/README.md @@ -0,0 +1,12 @@ +# progressive-web-app-template + +A template repo from which progressive-web-apps deployable on Laconic can be made. + +## Usage + +After creating a repository from this template, search for occurrences of "UPDATE-ME-FROM-TEMPLATE" and replace with strings appropriate to the new repository. + +Run `npm install` then commit the file `package-lock.json` to the repository. + +Add the secrets `CICD_LACONIC_USER_KEY` and `CICD_LACONIC_BOND_ID` to the repository or organization. + diff --git a/next.config.js b/next.config.js new file mode 100644 index 0000000..bc3bd17 --- /dev/null +++ b/next.config.js @@ -0,0 +1,12 @@ +/** @type {import('next').NextConfig} */ +const withPWA = require('next-pwa')({ + dest: 'public', +}) + +module.exports = withPWA({ + env: { + CERC_TEST_WEBAPP_CONFIG1: process.env.CERC_TEST_WEBAPP_CONFIG1, + CERC_TEST_WEBAPP_CONFIG2: process.env.CERC_TEST_WEBAPP_CONFIG2, + CERC_WEBAPP_DEBUG: process.env.CERC_WEBAPP_DEBUG, + }, +}) diff --git a/package.json b/package.json new file mode 100644 index 0000000..6e1cfc9 --- /dev/null +++ b/package.json @@ -0,0 +1,22 @@ +{ + "private": true, + "name": "UPDATE-ME-FROM-TEMPLATE", + "version": "0.1.0", + "repository": "https://UPDATE-ME-FROM-TEMPLATE", + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start" + }, + "dependencies": { + "next": "latest", + "next-pwa": "^5.6.0", + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@types/node": "17.0.4", + "@types/react": "17.0.38", + "typescript": "4.5.4" + } +} diff --git a/pages/_app.tsx b/pages/_app.tsx new file mode 100644 index 0000000..a9ff536 --- /dev/null +++ b/pages/_app.tsx @@ -0,0 +1,38 @@ +import Head from 'next/head' +import '../styles/globals.css' +import { AppProps } from 'next/app' + +export default function MyApp({ Component, pageProps }: AppProps) { + return ( + <> + + + + + + + Laconic Test PWA + + + + + + + + + + ) +} diff --git a/pages/api/hello.ts b/pages/api/hello.ts new file mode 100644 index 0000000..a42f463 --- /dev/null +++ b/pages/api/hello.ts @@ -0,0 +1,8 @@ +// Next.js API route support: https://nextjs.org/docs/api-routes/introduction +import { NextApiRequest, NextApiResponse } from 'next' + +const hello = (req: NextApiRequest, res: NextApiResponse) => { + res.status(200).json({ name: 'John Doe' }) +} + +export default hello diff --git a/pages/index.tsx b/pages/index.tsx new file mode 100644 index 0000000..96e5929 --- /dev/null +++ b/pages/index.tsx @@ -0,0 +1,50 @@ +import styles from '../styles/Home.module.css' + +export default function Home() { + return ( +
+
+

+ Welcome to Laconic! +

+ +
+ +

+ CONFIG1 has value: {process.env.CERC_TEST_WEBAPP_CONFIG1} +

+ +

+ CONFIG2 has value: {process.env.CERC_TEST_WEBAPP_CONFIG2} +

+ +

+ WEBAPP_DEBUG has value: {process.env.CERC_WEBAPP_DEBUG} +

+ +
+ +
+ + +
+ ) +} diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..be8a3fc Binary files /dev/null and b/public/favicon.ico differ diff --git a/public/icons/icon-128x128.png b/public/icons/icon-128x128.png new file mode 100644 index 0000000..b6f3bde Binary files /dev/null and b/public/icons/icon-128x128.png differ diff --git a/public/icons/icon-144x144.png b/public/icons/icon-144x144.png new file mode 100644 index 0000000..35529f7 Binary files /dev/null and b/public/icons/icon-144x144.png differ diff --git a/public/icons/icon-152x152.png b/public/icons/icon-152x152.png new file mode 100644 index 0000000..3543e09 Binary files /dev/null and b/public/icons/icon-152x152.png differ diff --git a/public/icons/icon-16x16.png b/public/icons/icon-16x16.png new file mode 100644 index 0000000..144f30d Binary files /dev/null and b/public/icons/icon-16x16.png differ diff --git a/public/icons/icon-192x192.png b/public/icons/icon-192x192.png new file mode 100644 index 0000000..b6cc9df Binary files /dev/null and b/public/icons/icon-192x192.png differ diff --git a/public/icons/icon-32x32.png b/public/icons/icon-32x32.png new file mode 100644 index 0000000..c29c45b Binary files /dev/null and b/public/icons/icon-32x32.png differ diff --git a/public/icons/icon-384x384.png b/public/icons/icon-384x384.png new file mode 100644 index 0000000..4c3ba7f Binary files /dev/null and b/public/icons/icon-384x384.png differ diff --git a/public/icons/icon-512x512.png b/public/icons/icon-512x512.png new file mode 100644 index 0000000..6b1e998 Binary files /dev/null and b/public/icons/icon-512x512.png differ diff --git a/public/icons/icon-72x72.png b/public/icons/icon-72x72.png new file mode 100644 index 0000000..b6bddb4 Binary files /dev/null and b/public/icons/icon-72x72.png differ diff --git a/public/icons/icon-96x96.png b/public/icons/icon-96x96.png new file mode 100644 index 0000000..d5bfcf4 Binary files /dev/null and b/public/icons/icon-96x96.png differ diff --git a/public/manifest.json b/public/manifest.json new file mode 100644 index 0000000..4164668 --- /dev/null +++ b/public/manifest.json @@ -0,0 +1,53 @@ +{ + "name": "Laconic Test Progressive Web App", + "short_name": "Test PWA", + "theme_color": "#ffffff", + "background_color": "#004740", + "display": "fullscreen", + "orientation": "portrait", + "scope": "/", + "start_url": "/", + "icons": [ + { + "src": "icons/icon-72x72.png", + "sizes": "72x72", + "type": "image/png" + }, + { + "src": "icons/icon-96x96.png", + "sizes": "96x96", + "type": "image/png" + }, + { + "src": "icons/icon-128x128.png", + "sizes": "128x128", + "type": "image/png" + }, + { + "src": "icons/icon-144x144.png", + "sizes": "144x144", + "type": "image/png" + }, + { + "src": "icons/icon-152x152.png", + "sizes": "152x152", + "type": "image/png" + }, + { + "src": "icons/icon-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/icon-384x384.png", + "sizes": "384x384", + "type": "image/png" + }, + { + "src": "icons/icon-512x512.png", + "sizes": "512x512", + "type": "image/png" + } + ], + "splash_pages": null +} diff --git a/public/vercel.svg b/public/vercel.svg new file mode 100644 index 0000000..fbf0e25 --- /dev/null +++ b/public/vercel.svg @@ -0,0 +1,4 @@ + + + \ No newline at end of file diff --git a/scripts/publish-app-record.sh b/scripts/publish-app-record.sh new file mode 100755 index 0000000..66a621e --- /dev/null +++ b/scripts/publish-app-record.sh @@ -0,0 +1,66 @@ +#!/bin/bash + +set -e + +RECORD_FILE=tmp.rf.$$ +CONFIG_FILE=`mktemp` + +CERC_APP_TYPE=${CERC_APP_TYPE:-"webapp"} +CERC_REPO_REF=${CERC_REPO_REF:-${GITHUB_SHA:-`git log -1 --format="%H"`}} +CERC_IS_LATEST_RELEASE=${CERC_IS_LATEST_RELEASE:-"true"} + +rcd_name=$(jq -r '.name' package.json | sed 's/null//') +rcd_desc=$(jq -r '.description' package.json | sed 's/null//') +rcd_repository=$(jq -r '.repository' package.json | sed 's/null//') +rcd_homepage=$(jq -r '.homepage' package.json | sed 's/null//') +rcd_license=$(jq -r '.license' package.json | sed 's/null//') +rcd_author=$(jq -r '.author' package.json | sed 's/null//') +rcd_app_version=$(jq -r '.version' package.json | sed 's/null//') + +cat < "$CONFIG_FILE" +services: + cns: + restEndpoint: '${CERC_REGISTRY_REST_ENDPOINT:-http://console.laconic.com:1317}' + gqlEndpoint: '${CERC_REGISTRY_GQL_ENDPOINT:-http://console.laconic.com:9473/api}' + chainId: ${CERC_REGISTRY_CHAIN_ID:-laconic_9000-1} + gas: 550000 + fees: 200000aphoton +EOF + +next_ver=$(laconic -c $CONFIG_FILE cns record list --type ApplicationRecord --all --name "$rcd_name" 2>/dev/null | jq -r -s ".[] | sort_by(.createTime) | reverse | [ .[] | select(.bondId == \"$CERC_REGISTRY_BOND_ID\") ] | .[0].attributes.version" | awk -F. -v OFS=. '{$NF += 1 ; print}') + +if [ -z "$next_ver" ] || [ "1" == "$next_ver" ]; then + next_ver=0.0.1 +fi + +cat < "$RECORD_FILE" +record: + type: ApplicationRecord + version: ${next_ver} + name: "$rcd_name" + description: "$rcd_desc" + homepage: "$rcd_homepage" + license: "$rcd_license" + author: "$rcd_author" + repository: + - "$rcd_repository" + repository_ref: "$CERC_REPO_REF" + app_version: "$rcd_app_version" + app_type: "$CERC_APP_TYPE" +EOF + + +cat $RECORD_FILE +RECORD_ID=$(laconic -c $CONFIG_FILE cns record publish --filename $RECORD_FILE --user-key "${CERC_REGISTRY_USER_KEY}" --bond-id ${CERC_REGISTRY_BOND_ID} | jq -r '.id') +echo $RECORD_ID + +if [ -n "$CERC_REGISTRY_APP_CRN" ]; then + laconic -c $CONFIG_FILE cns name set --user-key "${CERC_REGISTRY_USER_KEY}" --bond-id ${CERC_REGISTRY_BOND_ID} "$CERC_REGISTRY_APP_CRN@${rcd_app_version}" "$RECORD_ID" + laconic -c $CONFIG_FILE cns name set --user-key "${CERC_REGISTRY_USER_KEY}" --bond-id ${CERC_REGISTRY_BOND_ID} "$CERC_REGISTRY_APP_CRN@${CERC_REPO_REF}" "$RECORD_ID" + if [ "true" == "$CERC_IS_LATEST_RELEASE" ]; then + laconic -c $CONFIG_FILE cns name set --user-key "${CERC_REGISTRY_USER_KEY}" --bond-id ${CERC_REGISTRY_BOND_ID} "$CERC_REGISTRY_APP_CRN" "$RECORD_ID" + laconic -c $CONFIG_FILE cns name set --user-key "${CERC_REGISTRY_USER_KEY}" --bond-id ${CERC_REGISTRY_BOND_ID} "$CERC_REGISTRY_APP_CRN@latest" "$RECORD_ID" + fi +fi + +rm -f $RECORD_FILE $CONFIG_FILE diff --git a/scripts/request-app-deployment.sh b/scripts/request-app-deployment.sh new file mode 100755 index 0000000..d4500f1 --- /dev/null +++ b/scripts/request-app-deployment.sh @@ -0,0 +1,50 @@ +#!/bin/bash + +set -e + +RECORD_FILE=tmp.rf.$$ +CONFIG_FILE=`mktemp` + +rcd_name=$(jq -r '.name' package.json | sed 's/null//' | sed 's/^@//') +rcd_app_version=$(jq -r '.version' package.json | sed 's/null//') + +cat < "$CONFIG_FILE" +services: + cns: + restEndpoint: '${CERC_REGISTRY_REST_ENDPOINT:-http://console.laconic.com:1317}' + gqlEndpoint: '${CERC_REGISTRY_GQL_ENDPOINT:-http://console.laconic.com:9473/api}' + chainId: ${CERC_REGISTRY_CHAIN_ID:-laconic_9000-1} + gas: 550000 + fees: 200000aphoton +EOF + +if [ -z "$CERC_REGISTRY_APP_CRN" ]; then + echo "CERC_REGISTRY_APP_CRN is required." 1>&2 + exit 1 +fi + +APP_RECORD=$(laconic -c $CONFIG_FILE cns name resolve "$CERC_REGISTRY_APP_CRN" | jq '.[0]') +if [ -z "$APP_RECORD" ] || [ "null" == "$APP_RECORD" ]; then + echo "No record found for $CERC_REGISTRY_APP_CRN." + exit 1 +fi + +cat < "$RECORD_FILE" +record: + type: ApplicationDeploymentRequest + version: 1.0.0 + name: "$rcd_name@$rcd_app_version" + application: "$CERC_REGISTRY_APP_CRN@$rcd_app_version" + dns: "$CERC_REGISTRY_DEPLOYMENT_SHORT_HOSTNAME" + deployment: "$CERC_REGISTRY_DEPLOYMENT_CRN" + meta: + note: "Added by CI" + repository: "`git remote get-url origin`" + repository_ref: "${GITHUB_SHA:-`git log -1 --format="%H"`}" +EOF + +cat $RECORD_FILE +RECORD_ID=$(laconic -c $CONFIG_FILE cns record publish --filename $RECORD_FILE --user-key "${CERC_REGISTRY_USER_KEY}" --bond-id ${CERC_REGISTRY_BOND_ID} | jq -r '.id') +echo $RECORD_ID + +rm -f $RECORD_FILE $CONFIG_FILE diff --git a/styles/Home.module.css b/styles/Home.module.css new file mode 100644 index 0000000..b55cee6 --- /dev/null +++ b/styles/Home.module.css @@ -0,0 +1,123 @@ +.container { + min-height: 100vh; + padding: 0 0.5rem; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} + +.main { + padding: 5rem 0; + flex: 1; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} + +.footer { + width: 100%; + height: 100px; + border-top: 1px solid #eaeaea; + display: flex; + justify-content: center; + align-items: center; +} + +.footer img { + margin-left: 0.5rem; +} + +.footer a { + display: flex; + justify-content: center; + align-items: center; +} + +.title a { + color: #0070f3; + text-decoration: none; +} + +.title a:hover, +.title a:focus, +.title a:active { + text-decoration: underline; +} + +.title { + margin: 0; + line-height: 1.15; + font-size: 4rem; +} + +.title, +.description { + text-align: center; +} + +.description { + line-height: 1.5; + font-size: 1.5rem; +} + +.code { + background: #fafafa; + border-radius: 5px; + padding: 0.75rem; + font-size: 1.1rem; + font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, + Bitstream Vera Sans Mono, Courier New, monospace; +} + +.grid { + display: flex; + align-items: center; + justify-content: center; + flex-wrap: wrap; + + max-width: 800px; + margin-top: 3rem; +} + +.card { + margin: 1rem; + flex-basis: 45%; + padding: 1.5rem; + text-align: left; + color: inherit; + text-decoration: none; + border: 1px solid #eaeaea; + border-radius: 10px; + transition: color 0.15s ease, border-color 0.15s ease; +} + +.card:hover, +.card:focus, +.card:active { + color: #0070f3; + border-color: #0070f3; +} + +.card h3 { + margin: 0 0 1rem 0; + font-size: 1.5rem; +} + +.card p { + margin: 0; + font-size: 1.25rem; + line-height: 1.5; +} + +.logo { + height: 1em; +} + +@media (max-width: 600px) { + .grid { + width: 100%; + flex-direction: column; + } +} diff --git a/styles/globals.css b/styles/globals.css new file mode 100644 index 0000000..e5e2dcc --- /dev/null +++ b/styles/globals.css @@ -0,0 +1,16 @@ +html, +body { + padding: 0; + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, + Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; +} + +a { + color: inherit; + text-decoration: none; +} + +* { + box-sizing: border-box; +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..99710e8 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], + "exclude": ["node_modules"] +}