@digitaldefiance/express-suite-starter 2.3.5 → 2.3.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/package.json +2 -1
  2. package/scaffolding/api/.env.example.mustache +52 -0
  3. package/scaffolding/api/src/assets/.gitkeep +0 -0
  4. package/scaffolding/api/src/main.ts.mustache +19 -0
  5. package/scaffolding/api/src/views/index.ejs +34 -0
  6. package/scaffolding/api-lib/src/index.ts +9 -0
  7. package/scaffolding/api-lib/src/lib/application.ts +35 -0
  8. package/scaffolding/api-lib/src/lib/constants.ts.mustache +10 -0
  9. package/scaffolding/api-lib/src/lib/documents/index.ts +1 -0
  10. package/scaffolding/api-lib/src/lib/documents/user.ts +17 -0
  11. package/scaffolding/api-lib/src/lib/environment.ts +52 -0
  12. package/scaffolding/api-lib/src/lib/interfaces/constants.ts +9 -0
  13. package/scaffolding/api-lib/src/lib/interfaces/environment-aws.ts +7 -0
  14. package/scaffolding/api-lib/src/lib/interfaces/environment.ts +9 -0
  15. package/scaffolding/api-lib/src/lib/middlewares.ts.mustache +113 -0
  16. package/scaffolding/api-lib/src/lib/models/email-token.ts +12 -0
  17. package/scaffolding/api-lib/src/lib/models/mnemonic.ts +12 -0
  18. package/scaffolding/api-lib/src/lib/models/role.ts +12 -0
  19. package/scaffolding/api-lib/src/lib/models/used-direct-login-token.ts +12 -0
  20. package/scaffolding/api-lib/src/lib/models/user-role.ts +12 -0
  21. package/scaffolding/api-lib/src/lib/models/user.ts +14 -0
  22. package/scaffolding/api-lib/src/lib/routers/api.ts +23 -0
  23. package/scaffolding/api-lib/src/lib/routers/app.ts +31 -0
  24. package/scaffolding/api-lib/src/lib/routers/index.ts +2 -0
  25. package/scaffolding/api-lib/src/lib/schemas/index.ts +2 -0
  26. package/scaffolding/api-lib/src/lib/schemas/schema.ts +53 -0
  27. package/scaffolding/api-lib/src/lib/schemas/user.ts +13 -0
  28. package/scaffolding/api-lib/src/lib/services/email.ts +109 -0
  29. package/scaffolding/api-lib/src/lib/services/index.ts +1 -0
  30. package/scaffolding/api-lib/src/lib/shared-types.ts +172 -0
  31. package/scaffolding/devcontainer-mongodb/.devcontainer/.env.example +3 -0
  32. package/scaffolding/devcontainer-mongodb/.devcontainer/Dockerfile +6 -0
  33. package/scaffolding/devcontainer-mongodb/.devcontainer/devcontainer.json.mustache +31 -0
  34. package/scaffolding/devcontainer-mongodb/.devcontainer/docker-compose.yml +31 -0
  35. package/scaffolding/devcontainer-mongodb/.devcontainer/load-env.sh +20 -0
  36. package/scaffolding/devcontainer-mongodb/.devcontainer/post-create.sh.hbs +54 -0
  37. package/scaffolding/devcontainer-mongodb-replicaset/.devcontainer/.env.example +14 -0
  38. package/scaffolding/devcontainer-mongodb-replicaset/.devcontainer/Dockerfile +38 -0
  39. package/scaffolding/devcontainer-mongodb-replicaset/.devcontainer/Mongo.Dockerfile +24 -0
  40. package/scaffolding/devcontainer-mongodb-replicaset/.devcontainer/devcontainer.json +69 -0
  41. package/scaffolding/devcontainer-mongodb-replicaset/.devcontainer/docker-compose.yml +66 -0
  42. package/scaffolding/devcontainer-mongodb-replicaset/.devcontainer/entrypoint.sh +29 -0
  43. package/scaffolding/devcontainer-mongodb-replicaset/.devcontainer/load-env.sh +20 -0
  44. package/scaffolding/devcontainer-mongodb-replicaset/.devcontainer/mongodb_entrypoint.sh +124 -0
  45. package/scaffolding/devcontainer-mongodb-replicaset/.devcontainer/mongodb_healthcheck.sh +36 -0
  46. package/scaffolding/devcontainer-mongodb-replicaset/.devcontainer/post-create.sh.hbs +54 -0
  47. package/scaffolding/devcontainer-simple/.devcontainer/.env.example +4 -0
  48. package/scaffolding/devcontainer-simple/.devcontainer/devcontainer.json.mustache +60 -0
  49. package/scaffolding/devcontainer-simple/.devcontainer/post-create.sh.hbs +72 -0
  50. package/scaffolding/inituserdb/.env.example.mustache +9 -0
  51. package/scaffolding/inituserdb/src/main.ts.mustache +178 -0
  52. package/scaffolding/lib/src/index.ts.mustache +6 -0
  53. package/scaffolding/lib/src/lib/constants.ts.mustache +15 -0
  54. package/scaffolding/lib/src/lib/ecies-config.ts +10 -0
  55. package/scaffolding/lib/src/lib/enumerations/{{workspaceName}}-string-key.ts.mustache +5 -0
  56. package/scaffolding/lib/src/lib/i18n-setup.ts.mustache +99 -0
  57. package/scaffolding/lib/src/lib/interfaces/constants.ts +13 -0
  58. package/scaffolding/lib/src/lib/strings-collection.ts.mustache +45 -0
  59. package/scaffolding/react/src/app/app.tsx.mustache +170 -0
  60. package/scaffolding/react/src/app/menus/extraMenu.tsx +20 -0
  61. package/scaffolding/react/src/app/menus/index.ts +5 -0
  62. package/scaffolding/react/src/app/pages/SplashPage.tsx +60 -0
  63. package/scaffolding/react/src/app/theme.tsx.mustache +91 -0
  64. package/scaffolding/react/src/assets/albatross.ico +0 -0
  65. package/scaffolding/react/src/assets/albatross.png +0 -0
  66. package/scaffolding/react/src/assets/albatross.svg +108 -0
  67. package/scaffolding/react/src/assets/fonts/allroundgothic-xlig.otf +0 -0
  68. package/scaffolding/react/src/assets/fonts/allroundgothic-xlig.ttf +0 -0
  69. package/scaffolding/react/src/assets/fonts/allroundgothic-xlig.woff +0 -0
  70. package/scaffolding/react/src/assets/fonts/allroundgothic-xlig.woff2 +0 -0
  71. package/scaffolding/react/src/assets/gen-by-albatross.png +0 -0
  72. package/scaffolding/react/src/assets/gen-by-albatross.svg +124 -0
  73. package/scaffolding/react/src/config/ecies.ts +10 -0
  74. package/scaffolding/react/src/config/runtime-config.ts +25 -0
  75. package/scaffolding/react/src/environments/environment.prod.ts.mustache +16 -0
  76. package/scaffolding/react/src/environments/environment.ts +15 -0
  77. package/scaffolding/react/src/interfaces/environment.ts +5 -0
  78. package/scaffolding/react/src/main.tsx +22 -0
  79. package/scaffolding/react/src/styles.scss +103 -0
  80. package/scaffolding/react/src/test-setup.ts +1 -0
  81. package/scaffolding/react-lib/src/index.ts +6 -0
  82. package/scaffolding/react-lib/src/theme/theme.tsx +67 -0
  83. package/scaffolding/root/.github/dependabot.yml +11 -0
  84. package/scaffolding/root/.github/workflows/ci.yml +44 -0
  85. package/scaffolding/root/.vscode/extensions.json +9 -0
  86. package/scaffolding/root/DEPLOYMENT.md +104 -0
  87. package/scaffolding/root/do-yarn.sh +148 -0
  88. package/scaffolding/root/ensure-git-globals.sh +30 -0
  89. package/scaffolding/root/eslint.config.mjs +70 -0
  90. package/scaffolding/root/list-scripts.sh +12 -0
  91. package/scaffolding/root/npm-install-globals.sh +5 -0
  92. package/scaffolding/root/nuke-node-modules.sh +23 -0
  93. package/scaffolding/root/recover-yarn.sh +37 -0
  94. package/scaffolding/root/reset.sh.mustache +25 -0
  95. package/scaffolding/root/setup-nvm.sh +15 -0
@@ -0,0 +1,20 @@
1
+ #!/bin/bash
2
+ SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
3
+
4
+ # Check if we're in a /workspaces or /workspace path
5
+ if [[ "${PWD}" =~ ^/workspaces?/ ]]; then
6
+ WORKSPACE=$(echo "${PWD}" | grep -oP '^/workspaces?/[^/]+')
7
+ elif [ "$(basename "${PWD}")" = ".devcontainer" ]; then
8
+ WORKSPACE=$(realpath "${PWD}/..")
9
+ else
10
+ WORKSPACE=$(realpath "${SCRIPT_DIR}/..")
11
+ fi
12
+
13
+ DEVCONTAINER_DIR="${WORKSPACE}/.devcontainer"
14
+
15
+ if [ -f "${DEVCONTAINER_DIR}/.env" ]; then
16
+ echo "Loading environment variables from ${DEVCONTAINER_DIR}/.env"
17
+ set -a
18
+ source "${DEVCONTAINER_DIR}/.env"
19
+ set +a
20
+ fi
@@ -0,0 +1,124 @@
1
+ #!/bin/bash
2
+ set -e
3
+
4
+ echo "Hostname: $(hostname)"
5
+
6
+ # Environment Variables with Defaults
7
+ MONGO_LOG=${MONGO_LOG:-"/var/log/mongodb/mongod.log"}
8
+ MONGO_INITDB_ROOT_USERNAME=${MONGO_INITDB_ROOT_USERNAME}
9
+ MONGO_INITDB_ROOT_PASSWORD=${MONGO_INITDB_ROOT_PASSWORD}
10
+ MONGO_REPLICA_SET_NAME=${MONGO_REPLICA_SET_NAME:-"rs0"}
11
+ MONGO_BIND_IP=${MONGO_BIND_IP:-"0.0.0.0"}
12
+ MONGO_PORT=${MONGO_PORT:-27017}
13
+ MONGO_KEYFILE=${MONGO_KEYFILE:-"/tmp/replica.key"}
14
+ MONGO_DB_PATH=${MONGO_DB_PATH:-"/data/db"}
15
+ MAX_ATTEMPTS=30
16
+ RETRY_INTERVAL=${RETRY_INTERVAL:-30}
17
+ SETUP_COMPLETE_FILE="/data/db/.setup_complete"
18
+
19
+ start_mongo_noauth() {
20
+ echo "Starting MongoDB without authentication..."
21
+ mongod --replSet "$MONGO_REPLICA_SET_NAME" --bind_ip_all --dbpath "$MONGO_DB_PATH" --logpath "$MONGO_LOG" \
22
+ --wiredTigerCacheSizeGB 0.5 \
23
+ --fork
24
+ }
25
+
26
+ wait_for_mongo() {
27
+ echo "Waiting for MongoDB to be ready..."
28
+ for i in $(seq 1 $MAX_ATTEMPTS); do
29
+ if mongosh --quiet --eval "db.runCommand({ ping: 1 })" &>/dev/null; then
30
+ echo "MongoDB is ready."
31
+ return 0
32
+ fi
33
+ echo "Attempt $i: MongoDB not ready yet, retrying in $RETRY_INTERVAL seconds..."
34
+ sleep $RETRY_INTERVAL
35
+ done
36
+ echo "Failed to connect to MongoDB after $MAX_ATTEMPTS attempts."
37
+ return 1
38
+ }
39
+
40
+ initialize_replica_set() {
41
+ echo "Initializing replica set with localhost..."
42
+ mongosh --quiet --eval "
43
+ rs.initiate({
44
+ _id: '$MONGO_REPLICA_SET_NAME',
45
+ members: [{ _id: 0, host: 'localhost:$MONGO_PORT' }]
46
+ })
47
+ "
48
+ }
49
+
50
+ wait_for_primary() {
51
+ echo "Waiting for replica set to become PRIMARY..."
52
+ for i in $(seq 1 $MAX_ATTEMPTS); do
53
+ if [ "$1" = "auth" ]; then
54
+ status=$(mongosh admin --quiet --eval "db.auth('$MONGO_INITDB_ROOT_USERNAME', '$MONGO_INITDB_ROOT_PASSWORD'); rs.status().myState")
55
+ else
56
+ status=$(mongosh --quiet --eval "rs.status().myState")
57
+ fi
58
+ if [ "$status" = "1" ]; then
59
+ echo "Replica set is now PRIMARY."
60
+ return 0
61
+ fi
62
+ echo "Attempt $i: Replica set is not PRIMARY yet, retrying in $RETRY_INTERVAL seconds..."
63
+ sleep $RETRY_INTERVAL
64
+ done
65
+ echo "Replica set did not become PRIMARY within the expected time."
66
+ return 1
67
+ }
68
+
69
+ create_root_user() {
70
+ echo "Creating root user..."
71
+ mongosh admin --quiet --eval "
72
+ db.createUser({
73
+ user: '$MONGO_INITDB_ROOT_USERNAME',
74
+ pwd: '$MONGO_INITDB_ROOT_PASSWORD',
75
+ roles: [{ role: 'root', db: 'admin' }]
76
+ });
77
+ "
78
+ }
79
+
80
+ start_mongo_auth() {
81
+ echo "Starting MongoDB with authentication..."
82
+ mongod --auth --replSet "$MONGO_REPLICA_SET_NAME" --bind_ip_all --dbpath "$MONGO_DB_PATH" --logpath "$MONGO_LOG" --keyFile "$MONGO_KEYFILE" \
83
+ --wiredTigerCacheSizeGB 0.5 \
84
+ --fork
85
+ }
86
+
87
+ start_mongo_auth_foreground() {
88
+ echo "Starting MongoDB with authentication in the foreground..."
89
+ exec mongod --auth --replSet "$MONGO_REPLICA_SET_NAME" --bind_ip_all --dbpath "$MONGO_DB_PATH" --keyFile "$MONGO_KEYFILE" \
90
+ --wiredTigerCacheSizeGB 0.5
91
+ }
92
+
93
+ if [ -f "$SETUP_COMPLETE_FILE" ]; then
94
+ echo "Setup already completed. Starting MongoDB in foreground mode."
95
+ start_mongo_auth_foreground
96
+ exit 0
97
+ fi
98
+
99
+ # Main execution flow
100
+ echo "Starting MongoDB setup..."
101
+
102
+ start_mongo_noauth
103
+ wait_for_mongo || exit 1
104
+
105
+ echo "Initializing replica set..."
106
+ initialize_replica_set
107
+ wait_for_primary || exit 1
108
+
109
+ echo "Creating root user..."
110
+ create_root_user
111
+
112
+ echo "Shutting down MongoDB to restart with authentication..."
113
+ mongod --shutdown
114
+
115
+ echo "Starting MongoDB with authentication..."
116
+ start_mongo_auth
117
+ wait_for_mongo || exit 1
118
+ wait_for_primary "auth" || exit 1
119
+
120
+ # Mark setup as complete
121
+ touch "$SETUP_COMPLETE_FILE"
122
+
123
+ echo "MongoDB setup completed successfully. Starting MongoDB in foreground mode."
124
+ start_mongo_auth_foreground
@@ -0,0 +1,36 @@
1
+ #!/bin/bash
2
+
3
+ MAX_ATTEMPTS=30
4
+ RETRY_INTERVAL=10
5
+
6
+ # Wait for MongoDB to start
7
+ for i in $(seq 1 $MAX_ATTEMPTS); do
8
+ if mongosh --quiet --eval 'db.runCommand({ ping: 1 })' >/dev/null 2>&1; then
9
+ echo "[HC] MongoDB is responsive."
10
+ break
11
+ fi
12
+ echo "[HC] Attempt $i/$MAX_ATTEMPTS: Waiting for MongoDB to start..."
13
+ sleep $RETRY_INTERVAL
14
+ if [ $i -eq $MAX_ATTEMPTS ]; then
15
+ echo "[HC] MongoDB failed to start after $MAX_ATTEMPTS attempts."
16
+ exit 1
17
+ fi
18
+ done
19
+
20
+ # Check if MongoDB replica set is ready
21
+ for i in $(seq 1 $MAX_ATTEMPTS); do
22
+ rs_status=$(mongosh --quiet --eval 'rs.status().ok' --authenticationDatabase admin -u "$MONGO_INITDB_ROOT_USERNAME" -p "$MONGO_INITDB_ROOT_PASSWORD" || echo "0")
23
+ if [ "$rs_status" = "1" ]; then
24
+ echo "[HC] MongoDB replica set is ready."
25
+ exit 0
26
+ fi
27
+ echo "[HC] Attempt $i/$MAX_ATTEMPTS: Waiting for MongoDB replica set to be ready..."
28
+ sleep $RETRY_INTERVAL
29
+ if [ $i -eq $MAX_ATTEMPTS ]; then
30
+ echo "[HC] MongoDB replica set failed to initialize after $MAX_ATTEMPTS attempts."
31
+ exit 1
32
+ fi
33
+ done
34
+
35
+ echo "[HC] MongoDB healthcheck failed."
36
+ exit 1
@@ -0,0 +1,54 @@
1
+ #!/bin/bash
2
+ set -e
3
+ SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
4
+ WORKSPACE=$(realpath "${SCRIPT_DIR}/..")
5
+
6
+ echo "Post-create setup starting..."
7
+
8
+ cd ${WORKSPACE} && source .devcontainer/load-env.sh
9
+
10
+ # Basic git setup
11
+ git config --global --add safe.directory ${WORKSPACE} 2>/dev/null || true
12
+
13
+ cd ${WORKSPACE} && ./setup-nvm.sh
14
+ cd ${WORKSPACE} && ./ensure-git-globals.sh
15
+ cd ${WORKSPACE} && ./recover-yarn.sh
16
+
17
+ cd ${WORKSPACE} && export COREPACK_ENABLE_DOWNLOAD_PROMPT=0 && yes | corepack enable
18
+
19
+ # Setup Yarn Berry
20
+ echo "Setting up Yarn Berry..."
21
+ cd ${WORKSPACE} && corepack prepare yarn@${DEFAULT_YARN_VERSION} --activate && corepack yarn set version ${DEFAULT_YARN_VERSION} || echo "Yarn Berry setup failed"
22
+
23
+ # Install dependencies
24
+ echo "Installing dependencies..."
25
+ cd ${WORKSPACE} && corepack yarn config set nodeLinker node-modules
26
+
27
+ MAX_ATTEMPTS=5;
28
+ WAIT_TIME=2;
29
+ REGISTRY_URL=http://host.docker.internal:4873/;
30
+ ATTEMPTS=0;
31
+ echo 'Waiting for Verdaccio registry at $REGISTRY_URL (Max 10s total, 4s timeout per attempt)...';
32
+ while [ $ATTEMPTS -lt $MAX_ATTEMPTS ]; do
33
+ # Increased timeouts for cross-host networking stability: 2s connect, 4s total time.
34
+ if curl -sS -o /dev/null --fail --connect-timeout 2 --max-time 4 $REGISTRY_URL; then
35
+ echo 'Verdaccio detected. Configuring NPM and YARN.';
36
+ npm config set registry $REGISTRY_URL --location=project;
37
+ yarn config set npmRegistryServer $REGISTRY_URL;
38
+ VERDACCIO=1;
39
+ break;
40
+ fi;
41
+ sleep $WAIT_TIME;
42
+ ATTEMPTS=$((ATTEMPTS + 1));
43
+ done;
44
+ [ -z "$VERDACCIO" ] && echo 'Verdaccio not detected after 5 attempts. Using default public registry.';
45
+
46
+ cd ${WORKSPACE} && ./npm-install-globals.sh
47
+ cd ${WORKSPACE} && ./do-yarn.sh || echo "Dependency installation failed"
48
+
49
+ cd ${WORKSPACE} && /usr/local/bin/mkcert localhost 127.0.0.1 ::1 {{hostname}}
50
+
51
+ echo ""
52
+ cd ${WORKSPACE} && yarn playwright install --with-deps || echo "Playwright installation failed"
53
+
54
+ echo "Post-create setup complete"
@@ -0,0 +1,4 @@
1
+ DEFAULT_YARN_VERSION=4.11.0
2
+ DEFAULT_NVM_VERSION=22
3
+ GIT_EMAIL=your@email.com
4
+ GIT_NAME="Your Name"
@@ -0,0 +1,60 @@
1
+ {
2
+ "name": "{{workspaceName}} - Node.js",
3
+ "image": "mcr.microsoft.com/devcontainers/javascript-node:20",
4
+ "customizations": {
5
+ "vscode": {
6
+ "extensions": [
7
+ "github.vscode-github-actions",
8
+ "ms-azuretools.vscode-docker",
9
+ "esbenp.prettier-vscode",
10
+ "ms-vscode-remote.remote-containers",
11
+ "firsttris.vscode-jest-runner",
12
+ "ms-playwright.playwright",
13
+ "nrwl.angular-console",
14
+ "GitHub.copilot",
15
+ "GitHub.copilot-chat",
16
+ "bruno-api-client.bruno"
17
+ ]
18
+ }
19
+ },
20
+ "hostRequirements": {
21
+ "memory": "16gb",
22
+ "cpus": 4
23
+ },
24
+ "runArgs": [
25
+ "--memory=16g",
26
+ "--memory-swap=16g",
27
+ "--cpus=4",
28
+ "--dns=1.1.1.1",
29
+ "--dns=8.8.8.8",
30
+ "--add-host=host.docker.internal:host-gateway",
31
+ "-p",
32
+ "3000:3000",
33
+ "-p",
34
+ "3443:3443",
35
+ "-p",
36
+ "4200:4200",
37
+ ],
38
+ "mounts": [
39
+ "source=${localWorkspaceFolder}/.devcontainer/.env,target=/workspaces/${localWorkspaceFolderBasename}/.env,type=bind,consistency=cached"
40
+ ],
41
+ "forwardPorts": [3000, 3443, 4200],
42
+ "portsAttributes": {
43
+ "3443": {
44
+ "label": "HTTPS Server",
45
+ "protocol": "https",
46
+ "onAutoForward": "notify"
47
+ },
48
+ "3000": {
49
+ "label": "HTTP Server",
50
+ "protocol": "http",
51
+ "onAutoForward": "notify"
52
+ },
53
+ "4200": {
54
+ "label": "React Dev Server",
55
+ "protocol": "http",
56
+ "onAutoForward": "notify"
57
+ }
58
+ },
59
+ "postCreateCommand": "set -a && [ -f .env ] && . ./.env && set +a && .devcontainer/post-create.sh"
60
+ }
@@ -0,0 +1,72 @@
1
+ #!/bin/bash
2
+ set -e
3
+ SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
4
+ WORKSPACE=$(realpath "${SCRIPT_DIR}/..")
5
+
6
+ echo "Post-create setup starting..."
7
+
8
+ # Basic git setup
9
+ git config --global --add safe.directory ${WORKSPACE} 2>/dev/null || true
10
+
11
+ cd ${WORKSPACE} && ./setup-nvm.sh
12
+ cd ${WORKSPACE} && ./ensure-git-globals.sh
13
+ cd ${WORKSPACE} && ./recover-yarn.sh
14
+
15
+ cd ${WORKSPACE} && export COREPACK_ENABLE_DOWNLOAD_PROMPT=0 && yes | corepack enable
16
+
17
+ # Setup Yarn Berry
18
+ echo "Setting up Yarn Berry..."
19
+ cd ${WORKSPACE} && corepack prepare yarn@${DEFAULT_YARN_VERSION} --activate && corepack yarn set version ${DEFAULT_YARN_VERSION} || echo "Yarn Berry setup failed"
20
+
21
+ # Install dependencies
22
+ echo "Installing dependencies..."
23
+ cd ${WORKSPACE} && corepack yarn config set nodeLinker node-modules
24
+
25
+ MAX_ATTEMPTS=5;
26
+ WAIT_TIME=2;
27
+ REGISTRY_URL=http://host.docker.internal:4873/;
28
+ ATTEMPTS=0;
29
+ echo 'Waiting for Verdaccio registry at $REGISTRY_URL (Max 10s total, 4s timeout per attempt)...';
30
+ while [ $ATTEMPTS -lt $MAX_ATTEMPTS ]; do
31
+ # Increased timeouts for cross-host networking stability: 2s connect, 4s total time.
32
+ if curl -sS -o /dev/null --fail --connect-timeout 2 --max-time 4 $REGISTRY_URL; then
33
+ echo 'Verdaccio detected. Configuring NPM and YARN.';
34
+ npm config set registry $REGISTRY_URL --location=project;
35
+ yarn config set npmRegistryServer $REGISTRY_URL;
36
+ VERDACCIO=1;
37
+ break;
38
+ fi;
39
+ sleep $WAIT_TIME;
40
+ ATTEMPTS=$((ATTEMPTS + 1));
41
+ done;
42
+ [ -z "$VERDACCIO" ] && echo 'Verdaccio not detected after 5 attempts. Using default public registry.';
43
+
44
+ cd ${WORKSPACE} && ./npm-install-globals.sh
45
+ cd ${WORKSPACE} && ./do-yarn.sh || echo "Dependency installation failed"
46
+
47
+ # Install mkcert if not already present
48
+ if ! command -v mkcert &> /dev/null; then
49
+ echo "Installing mkcert..."
50
+ sudo apt-get update -y && sudo apt-get install golang -y
51
+
52
+ # Clean up any existing mkcert directory from failed attempts
53
+ [ -d "${WORKSPACE}/mkcert" ] && rm -rf "${WORKSPACE}/mkcert"
54
+
55
+ cd ${WORKSPACE} && \
56
+ git clone https://github.com/FiloSottile/mkcert && \
57
+ cd mkcert && \
58
+ go build -ldflags "-X main.Version=$(git describe --tags)" && \
59
+ sudo cp mkcert /usr/local/bin/ && \
60
+ cd .. && \
61
+ rm -rf mkcert
62
+
63
+ /usr/local/bin/mkcert -install
64
+ else
65
+ echo "mkcert already installed"
66
+ fi
67
+ cd ${WORKSPACE} && /usr/local/bin/mkcert localhost 127.0.0.1 ::1 {{hostname}}
68
+
69
+ echo ""
70
+ cd ${WORKSPACE} && yarn playwright install --with-deps || echo "Playwright installation failed"
71
+
72
+ echo "Post-create setup complete"
@@ -0,0 +1,9 @@
1
+ MONGO_URI=mongodb://admin:{{password}}@db:27017/{{workspaceName}}?authSource=admin&directConnection=true
2
+ JWT_SECRET={{jwtSecret}}
3
+ API_DIST_DIR=/workspaces/{{workspaceName}}/dist/{{prefix}}-api
4
+ REACT_DIST_DIR=/workspaces/{{workspaceName}}/dist/{{prefix}}-react
5
+ DEBUG=true
6
+ DETAILED_DEBUG=true
7
+ MNEMONIC_ENCRYPTION_KEY={{mnemonicEncryptionKey}}
8
+ MNEMONIC_HMAC_SECRET={{mnemonicHmacSecret}}
9
+ MONGO_USE_TRANSACTIONS=false
@@ -0,0 +1,178 @@
1
+ import {
2
+ BaseApplication,
3
+ DatabaseInitializationService,
4
+ Environment,
5
+ IServerInitResult,
6
+ getSchemaMap,
7
+ } from '@digitaldefiance/node-express-suite';
8
+
9
+ // Simple debugLog implementation
10
+ function debugLog(debug: boolean, type: 'log' | 'warn' | 'error', ...args: any[]): void {
11
+ if (debug) {
12
+ console[type](...args);
13
+ }
14
+ }
15
+ import { Constants as AppConstants } from '{{namespace}}/api-lib';
16
+ import { GlobalActiveContext, IActiveContext } from '@digitaldefiance/i18n-lib';
17
+ import { IECIESConfig } from '@digitaldefiance/ecies-lib';
18
+ import { ECIESService } from '@digitaldefiance/node-ecies-lib';
19
+ import {
20
+ CoreLanguageCode,
21
+ } from '@digitaldefiance/i18n-lib';
22
+ import { getSuiteCoreI18nEngine, getSuiteCoreTranslation, IFailableResult, SuiteCoreStringKey } from '@digitaldefiance/suite-core-lib';
23
+ import { randomBytes } from 'crypto';
24
+ import { join } from 'path';
25
+
26
+ async function main() {
27
+ const context = GlobalActiveContext.getInstance<CoreLanguageCode, IActiveContext<CoreLanguageCode>>();
28
+ context.languageContextSpace = 'admin';
29
+
30
+ const config: IECIESConfig = {
31
+ curveName: AppConstants.ECIES.CURVE_NAME,
32
+ primaryKeyDerivationPath: AppConstants.ECIES.PRIMARY_KEY_DERIVATION_PATH,
33
+ mnemonicStrength: AppConstants.ECIES.MNEMONIC_STRENGTH,
34
+ symmetricAlgorithm: AppConstants.ECIES.SYMMETRIC_ALGORITHM_CONFIGURATION,
35
+ symmetricKeyBits: AppConstants.ECIES.SYMMETRIC.KEY_BITS,
36
+ symmetricKeyMode: AppConstants.ECIES.SYMMETRIC.MODE,
37
+ };
38
+ const eciesService = new ECIESService(config);
39
+ if (process.argv.includes('--gen-system-user-mnemonic')) {
40
+ const mnemonic = eciesService.generateNewMnemonic();
41
+ process.env.ADMIN_MNEMONIC = mnemonic.value;
42
+ console.log(
43
+ `ADMIN_MNEMONIC="${mnemonic.value}"\n`,
44
+ getSuiteCoreTranslation(
45
+ SuiteCoreStringKey.Admin_MakeSureToSetItInEnv,
46
+ ),
47
+ );
48
+ }
49
+ if (process.argv.includes('--gen-member-user-mnemonic')) {
50
+ const mnemonic = eciesService.generateNewMnemonic();
51
+ process.env.MEMBER_MNEMONIC = mnemonic.value;
52
+ console.log(
53
+ `MEMBER_MNEMONIC="${mnemonic.value}"\n`,
54
+ getSuiteCoreTranslation(
55
+ SuiteCoreStringKey.Admin_MakeSureToSetItInEnv,
56
+ ),
57
+ );
58
+ }
59
+ if (process.argv.includes('--gen-mnemonic-hmac-secret')) {
60
+ const mnemonicHmacSecret = randomBytes(32).toString('hex');
61
+ process.env.MNEMONIC_HMAC_SECRET = mnemonicHmacSecret;
62
+ console.log(
63
+ `MNEMONIC_HMAC_SECRET="${mnemonicHmacSecret}"\n`,
64
+ getSuiteCoreTranslation(
65
+ SuiteCoreStringKey.Admin_MakeSureToSetItInEnv,
66
+ ),
67
+ );
68
+ }
69
+ if (process.argv.includes('--gen-mnemonic-encryption-key')) {
70
+ const mnemonicEncryptionKey = randomBytes(32).toString('hex');
71
+ process.env.MNEMONIC_ENCRYPTION_KEY = mnemonicEncryptionKey;
72
+ console.log(
73
+ `MNEMONIC_ENCRYPTION_KEY="${mnemonicEncryptionKey}"\n`,
74
+ getSuiteCoreTranslation(
75
+ SuiteCoreStringKey.Admin_MakeSureToSetItInEnv,
76
+ ),
77
+ );
78
+ }
79
+
80
+ const envDir = join(
81
+ BaseApplication.distDir,
82
+ '{{prefix}}-inituserdb',
83
+ '.env',
84
+ );
85
+ const env: Environment = new Environment(envDir, true);
86
+ const app = new BaseApplication(env, getSchemaMap, DatabaseInitializationService.initUserDb, DatabaseInitializationService.serverInitResultHash, AppConstants);
87
+ context.languageContextSpace = 'admin';
88
+ const shouldDropDatabase = process.argv.includes('--drop');
89
+ debugLog(
90
+ app.environment.detailedDebug,
91
+ 'log',
92
+ getSuiteCoreTranslation(SuiteCoreStringKey.Admin_TransactionsEnabledDisabledTemplate, {
93
+ STATE: getSuiteCoreTranslation(
94
+ app.environment.mongo.useTransactions
95
+ ? SuiteCoreStringKey.Common_Enabled
96
+ : SuiteCoreStringKey.Common_Disabled,
97
+ ),
98
+ }),
99
+ );
100
+ let exitCode = 1;
101
+ await app.start();
102
+ if (shouldDropDatabase) {
103
+ const result = await DatabaseInitializationService.dropDatabase(
104
+ app.db.connection,
105
+ );
106
+ if (result) {
107
+ debugLog(
108
+ app.environment.detailedDebug,
109
+ 'log',
110
+ getSuiteCoreTranslation(SuiteCoreStringKey.Admin_DatabaseDropped),
111
+ );
112
+ await new Promise((resolve) => setTimeout(resolve, 1000));
113
+ debugLog(
114
+ app.environment.detailedDebug,
115
+ 'log',
116
+ getSuiteCoreTranslation(SuiteCoreStringKey.Admin_ProceedingToDbInitialization),
117
+ );
118
+ } else {
119
+ debugLog(
120
+ app.environment.detailedDebug,
121
+ 'error',
122
+ getSuiteCoreTranslation(SuiteCoreStringKey.Admin_Error_FailedToDropDatabase),
123
+ );
124
+ await app.stop();
125
+ process.exit(2);
126
+ }
127
+ }
128
+ debugLog(
129
+ app.environment.detailedDebug,
130
+ 'log',
131
+ getSuiteCoreTranslation(SuiteCoreStringKey.Admin_StartingDbInitialization),
132
+ );
133
+ const result: IFailableResult<IServerInitResult> =
134
+ await DatabaseInitializationService.initUserDb(app);
135
+ if (result.success && result.data) {
136
+ debugLog(
137
+ app.environment.debug,
138
+ 'log',
139
+ getSuiteCoreTranslation(
140
+ SuiteCoreStringKey.Admin_UserDatabaseInitialized,
141
+ ),
142
+ );
143
+ if (app.environment.detailedDebug) {
144
+ DatabaseInitializationService.printServerInitResults(result.data);
145
+ // DatabaseInitializationService.setEnvFromInitResults(result.data);
146
+ // app.reloadEnvironment(envDir, true);
147
+ const initHash = DatabaseInitializationService.serverInitResultHash(
148
+ result.data,
149
+ );
150
+ debugLog(
151
+ true,
152
+ 'log',
153
+ `Database initialized with options hash: ${initHash}`,
154
+ );
155
+ }
156
+ exitCode = 0;
157
+ } else {
158
+ const engine = getSuiteCoreI18nEngine();
159
+ console.error(
160
+ engine.t(
161
+ '{{SuiteCoreStringKey.Admin_Error_FailedToInitializeUserDatabase}}:',
162
+ ),
163
+ result.error,
164
+ );
165
+ exitCode++;
166
+ }
167
+ await app.stop();
168
+ process.exit(exitCode);
169
+ }
170
+
171
+ main().catch((err) => {
172
+ const engine = getSuiteCoreI18nEngine();
173
+ console.error(
174
+ engine.t('{{SuiteCoreStringKey.Admin_Error_UnhandledErrorInMain}}:'),
175
+ err,
176
+ );
177
+ process.exit(1);
178
+ });
@@ -0,0 +1,6 @@
1
+ export * from './lib/constants';
2
+ export * from './lib/i18n-setup';
3
+ export * from './lib/enumerations/{{workspaceName}}-string-key';
4
+ export * from './lib/interfaces/constants';
5
+ export * from './lib/strings-collection';
6
+ export * from './lib/ecies-config';
@@ -0,0 +1,15 @@
1
+ import { IConstants } from './interfaces/constants';
2
+ import { Constants } from '@digitaldefiance/suite-core-lib';
3
+
4
+ export const AppConstants: IConstants = {
5
+ ...Constants,
6
+ Site: '{{siteTitle}}' as const,
7
+ SiteTagline: '{{siteTagline}}' as const,
8
+ SiteDescription: '{{siteDescription}}' as const,
9
+ SiteHostname: '{{hostname}}' as const,
10
+ PasswordRegex: /^(?=.*[A-Za-z])(?=.*\d)(?=.*[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?])[A-Za-z\d!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]{8,}$/,
11
+ UsernameMinLength: 3 as const,
12
+ UsernameMaxLength: 30 as const,
13
+ UsernameRegex: /^[A-Za-z0-9]{3,30}$/,
14
+ PasswordMinLength: 8 as const,
15
+ };
@@ -0,0 +1,10 @@
1
+ import { IECIESConfig, ECIES } from '@digitaldefiance/ecies-lib';
2
+
3
+ export const EciesConfig: IECIESConfig = {
4
+ curveName: ECIES.CURVE_NAME,
5
+ primaryKeyDerivationPath: ECIES.PRIMARY_KEY_DERIVATION_PATH,
6
+ mnemonicStrength: ECIES.MNEMONIC_STRENGTH,
7
+ symmetricAlgorithm: ECIES.SYMMETRIC_ALGORITHM_CONFIGURATION,
8
+ symmetricKeyBits: ECIES.SYMMETRIC.KEY_BITS,
9
+ symmetricKeyMode: ECIES.SYMMETRIC.MODE,
10
+ };
@@ -0,0 +1,5 @@
1
+ export enum {{WorkspaceName}}StringKey {
2
+ SiteTitle = 'siteTitle',
3
+ SiteDescription = 'siteDescription',
4
+ SiteTagline = 'siteTagline',
5
+ }