@donotdev/cli 0.0.13 → 0.0.15
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.
- package/dependencies-matrix.json +357 -89
- package/dist/bin/commands/agent-setup.d.ts +6 -0
- package/dist/bin/commands/agent-setup.d.ts.map +1 -0
- package/dist/bin/commands/agent-setup.js +629 -0
- package/dist/bin/commands/agent-setup.js.map +1 -0
- package/dist/bin/commands/build.js +131 -50
- package/dist/bin/commands/bump.js +137 -49
- package/dist/bin/commands/cacheout.js +50 -21
- package/dist/bin/commands/create-app.js +270 -261
- package/dist/bin/commands/create-project.js +418 -197
- package/dist/bin/commands/deploy.js +1752 -712
- package/dist/bin/commands/dev.js +151 -35
- package/dist/bin/commands/emu.js +228 -70
- package/dist/bin/commands/format.js +50 -21
- package/dist/bin/commands/lint.js +50 -21
- package/dist/bin/commands/preview.js +155 -35
- package/dist/bin/commands/supabase-setup.d.ts +6 -0
- package/dist/bin/commands/supabase-setup.d.ts.map +1 -0
- package/dist/bin/commands/supabase-setup.js +7 -0
- package/dist/bin/commands/supabase-setup.js.map +1 -0
- package/dist/bin/commands/sync-secrets.js +224 -46
- package/dist/bin/commands/type-check.d.ts +14 -0
- package/dist/bin/commands/type-check.d.ts.map +1 -0
- package/dist/bin/commands/type-check.js +314 -0
- package/dist/bin/commands/type-check.js.map +1 -0
- package/dist/bin/commands/wai.js +7399 -11
- package/dist/bin/dndev.js +27 -2
- package/dist/bin/donotdev.js +27 -2
- package/dist/index.js +3960 -2996
- package/package.json +2 -2
- package/templates/app-demo/src/App.tsx.example +1 -0
- package/templates/app-demo/src/pages/FullPage.tsx.example +2 -2
- package/templates/app-demo/src/pages/components/DemoLayout.tsx.example +2 -2
- package/templates/app-demo/src/themes.css.example +5 -12
- package/templates/app-expo/.env.example +64 -0
- package/templates/app-expo/.expo/README.md.example +5 -0
- package/templates/app-expo/.gitignore.example +36 -0
- package/templates/app-expo/README.md.example +58 -0
- package/templates/app-expo/app/.gitkeep +2 -0
- package/templates/app-expo/app/_layout.tsx.example +41 -0
- package/templates/app-expo/app/form.tsx.example +52 -0
- package/templates/app-expo/app/index.tsx.example +89 -0
- package/templates/app-expo/app/list.tsx.example +32 -0
- package/templates/app-expo/app/profile.tsx.example +76 -0
- package/templates/app-expo/app/signin.tsx.example +53 -0
- package/templates/app-expo/app.json.example +39 -0
- package/templates/app-expo/babel.config.js.example +10 -0
- package/templates/app-expo/eas.json.example +20 -0
- package/templates/app-expo/expo-env.d.ts.example +4 -0
- package/templates/app-expo/metro.config.js.example +20 -0
- package/templates/app-expo/service-account-key.json.example +12 -0
- package/templates/app-expo/tsconfig.json.example +19 -0
- package/templates/app-next/.env.example +4 -33
- package/templates/app-next/src/app/ClientLayout.tsx.example +2 -0
- package/templates/app-next/src/app/layout.tsx.example +7 -6
- package/templates/app-next/src/globals.css.example +2 -11
- package/templates/app-next/src/pages/HomePage.tsx.example +1 -1
- package/templates/app-next/src/themes.css.example +10 -13
- package/templates/app-vite/.env.example +3 -32
- package/templates/app-vite/index.html.example +2 -24
- package/templates/app-vite/src/App.tsx.example +2 -0
- package/templates/app-vite/src/globals.css.example +2 -12
- package/templates/app-vite/src/pages/FormPageExample.tsx.example +1 -2
- package/templates/app-vite/src/pages/HomePage.tsx.example +1 -1
- package/templates/app-vite/src/themes.css.example +109 -79
- package/templates/app-vite/vercel.json.example +11 -0
- package/templates/functions-firebase/build.mjs.example +2 -72
- package/templates/functions-firebase/functions-firebase/.env.example.example +23 -25
- package/templates/functions-firebase/functions-firebase/build.mjs.example +2 -72
- package/templates/functions-firebase/functions-firebase/tsconfig.json.example +1 -1
- package/templates/functions-supabase/supabase/functions/cancel-subscription/index.ts.example +7 -0
- package/templates/functions-supabase/supabase/functions/change-plan/index.ts.example +11 -0
- package/templates/functions-supabase/supabase/functions/create-checkout-session/index.ts.example +11 -0
- package/templates/functions-supabase/supabase/functions/create-customer-portal/index.ts.example +7 -0
- package/templates/functions-supabase/supabase/functions/crud/index.ts.example +16 -0
- package/templates/functions-supabase/supabase/functions/delete-account/index.ts.example +7 -0
- package/templates/functions-supabase/supabase/functions/get-custom-claims/index.ts.example +7 -0
- package/templates/functions-supabase/supabase/functions/get-user-auth-status/index.ts.example +7 -0
- package/templates/functions-supabase/supabase/functions/refresh-subscription-status/index.ts.example +7 -0
- package/templates/functions-supabase/supabase/functions/remove-custom-claims/index.ts.example +7 -0
- package/templates/functions-supabase/supabase/functions/set-custom-claims/index.ts.example +7 -0
- package/templates/functions-supabase/supabase/migrations/20250101000000_idempotency.sql +24 -0
- package/templates/functions-supabase/supabase/migrations/20250101000001_rate_limits.sql +22 -0
- package/templates/functions-supabase/supabase/migrations/20250101000002_cleanup_jobs.sql +28 -0
- package/templates/functions-supabase/supabase/migrations/20250101000003_operation_metrics.sql +28 -0
- package/templates/functions-vercel/functions-vercel/tsconfig.json.example +1 -1
- package/templates/functions-vercel/functions-vercel/vercel.json.example +1 -1
- package/templates/functions-vercel/vercel.json.example +1 -1
- package/templates/github/github/workflows/firebase-deploy.yml.example +1 -1
- package/templates/github/workflows/firebase-deploy.yml.example +1 -1
- package/templates/overlay-firebase/env.fragment.example +34 -0
- package/templates/overlay-firebase/env.fragment.expo.example +34 -0
- package/templates/overlay-firebase/env.fragment.nextjs.example +34 -0
- package/templates/overlay-firebase/src/config/providers.expo.ts.example +49 -0
- package/templates/overlay-firebase/src/config/providers.ts.example +23 -0
- package/templates/overlay-supabase/env.fragment.example +7 -0
- package/templates/overlay-supabase/env.fragment.expo.example +7 -0
- package/templates/overlay-supabase/env.fragment.nextjs.example +7 -0
- package/templates/overlay-supabase/src/config/providers.expo.ts.example +35 -0
- package/templates/overlay-supabase/src/config/providers.ts.example +33 -0
- package/templates/overlay-supabase/vercel.headers.example +23 -0
- package/templates/overlay-supabase/vercel.json.example +22 -0
- package/templates/overlay-vercel/env.fragment.example +34 -0
- package/templates/overlay-vercel/env.fragment.nextjs.example +34 -0
- package/templates/overlay-vercel/src/config/providers.ts.example +24 -0
- package/templates/root-consumer/.claude/agents/architect.md.example +2 -310
- package/templates/root-consumer/.claude/agents/builder.md.example +2 -326
- package/templates/root-consumer/.claude/agents/coder.md.example +2 -83
- package/templates/root-consumer/.claude/agents/extractor.md.example +2 -231
- package/templates/root-consumer/.claude/agents/polisher.md.example +2 -132
- package/templates/root-consumer/.claude/agents/prompt-engineer.md.example +2 -81
- package/templates/root-consumer/.claude/commands/brainstorm.md.example +1 -1
- package/templates/root-consumer/.claude/commands/build.md.example +1 -1
- package/templates/root-consumer/.claude/commands/design.md.example +1 -1
- package/templates/root-consumer/.claude/commands/grill.md.example +30 -0
- package/templates/root-consumer/.claude/commands/polish.md.example +1 -1
- package/templates/root-consumer/.claude/commands/techdebt.md.example +28 -0
- package/templates/root-consumer/.clinerules.example +1 -0
- package/templates/root-consumer/.cursor/rules/no-docs.mdc.example +15 -0
- package/templates/root-consumer/.cursorrules.example +1 -0
- package/templates/root-consumer/.dndev/args.json.example +6 -0
- package/templates/root-consumer/.gemini/settings.json.example +2 -2
- package/templates/root-consumer/.github/copilot-instructions.md.example +1 -0
- package/templates/root-consumer/.windsurfrules.example +1 -0
- package/templates/root-consumer/AI.md.example +25 -108
- package/templates/root-consumer/CLAUDE.md.example +1 -128
- package/templates/root-consumer/CONVENTIONS.md.example +1 -0
- package/templates/root-consumer/GEMINI.md.example +1 -0
- package/templates/root-consumer/firebase.json.example +1 -1
- package/templates/root-consumer/guides/dndev/AGENT_START_HERE.md.example +54 -0
- package/templates/root-consumer/guides/dndev/COMPONENTS_ADV.md.example +0 -18
- package/templates/root-consumer/guides/dndev/COMPONENTS_UI.md.example +1 -1
- package/templates/root-consumer/guides/dndev/ENV_SETUP.md.example +99 -30
- package/templates/root-consumer/guides/dndev/GOTCHAS.md.example +186 -0
- package/templates/root-consumer/guides/dndev/INDEX.md.example +4 -1
- package/templates/root-consumer/guides/dndev/SETUP_CRUD.md.example +143 -12
- package/templates/root-consumer/guides/dndev/SETUP_FIREBASE.md.example +9 -3
- package/templates/root-consumer/guides/dndev/SETUP_FUNCTIONS.md.example +12 -7
- package/templates/root-consumer/guides/dndev/SETUP_SOC2.md.example +234 -0
- package/templates/root-consumer/guides/dndev/SETUP_SUPABASE.md.example +124 -0
- package/templates/root-consumer/guides/dndev/SETUP_THEMES.md.example +6 -2
- package/templates/root-consumer/guides/dndev/SETUP_VERCEL.md.example +176 -0
- package/templates/root-consumer/guides/dndev/USE_ROUTING.md.example +5 -9
- package/templates/root-consumer/guides/dndev/essences_reference.css.example +174 -0
- package/templates/root-consumer/guides/wai-way/agents/builder.md.example +10 -0
- package/templates/root-consumer/guides/wai-way/agents/extractor.md.example +25 -5
- package/templates/root-consumer/guides/wai-way/agents/polisher.md.example +13 -2
- package/templates/root-consumer/guides/wai-way/blueprints/0_brainstorm.md.example +2 -2
- package/templates/root-consumer/guides/wai-way/blueprints/1_scaffold.md.example +47 -11
- package/templates/root-consumer/guides/wai-way/blueprints/3_compose.md.example +15 -4
- package/templates/root-consumer/guides/wai-way/spec_template.md.example +7 -6
- package/templates/app-payload/.env.example +0 -28
- package/templates/app-payload/README.md.example +0 -233
- package/templates/app-payload/collections/Company.ts.example +0 -125
- package/templates/app-payload/collections/Hero.ts.example +0 -62
- package/templates/app-payload/collections/Media.ts.example +0 -41
- package/templates/app-payload/collections/Products.ts.example +0 -115
- package/templates/app-payload/collections/Services.ts.example +0 -104
- package/templates/app-payload/collections/Testimonials.ts.example +0 -92
- package/templates/app-payload/collections/Users.ts.example +0 -35
- package/templates/app-payload/src/server.ts.example +0 -79
- package/templates/app-payload/tsconfig.json.example +0 -24
|
@@ -1,75 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
* @fileoverview Build script for {{APP_NAME}} functions
|
|
4
|
-
* @description Bundles @donotdev/types and imports framework functions
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { build } from 'esbuild';
|
|
8
|
-
import { writeFileSync } from 'fs';
|
|
9
|
-
import { createAppFunctionsConfig, generateFunctionsYamlWithInfo, filterEnvSecrets } from '@donotdev/core/functions';
|
|
2
|
+
import { buildFunctions } from '@donotdev/core/functions';
|
|
10
3
|
import { functionsConfig } from './functions.config.js';
|
|
11
4
|
|
|
12
|
-
|
|
13
|
-
console.log('🔨 Building {{APP_NAME}} functions...');
|
|
14
|
-
|
|
15
|
-
try {
|
|
16
|
-
const config = createAppFunctionsConfig({
|
|
17
|
-
entry: 'src/index.ts',
|
|
18
|
-
outDir: 'lib',
|
|
19
|
-
minify: process.env.NODE_ENV === 'production',
|
|
20
|
-
sourcemap: true,
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
console.log('📦 Bundling @donotdev/types and importing framework functions...');
|
|
24
|
-
|
|
25
|
-
const result = await build(config);
|
|
26
|
-
|
|
27
|
-
if (result.errors.length > 0) {
|
|
28
|
-
console.error('❌ Build errors:', result.errors);
|
|
29
|
-
process.exit(1);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
if (result.warnings.length > 0) {
|
|
33
|
-
console.warn('⚠️ Build warnings:', result.warnings);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
console.log('✅ {{APP_NAME}} functions built successfully!');
|
|
37
|
-
console.log('📁 Output directory: lib/');
|
|
38
|
-
|
|
39
|
-
// Generate functions.yaml from config + auto-detection
|
|
40
|
-
// Auto-detects: exported functions from src/index.ts + secrets from .env
|
|
41
|
-
const { yaml, staticFunctions, crudFunctions, autoDetected, autoSecrets } = generateFunctionsYamlWithInfo(
|
|
42
|
-
functionsConfig,
|
|
43
|
-
{ entryFile: 'src/index.ts', envPath: '.env' }
|
|
44
|
-
);
|
|
45
|
-
writeFileSync('functions.yaml', yaml);
|
|
46
|
-
console.log(`📄 Generated functions.yaml: ${staticFunctions.length} static + ${crudFunctions.length} CRUD functions`);
|
|
47
|
-
if (autoDetected.length > 0) {
|
|
48
|
-
console.log(`🔍 Auto-detected ${autoDetected.length} function(s) from src/index.ts: ${autoDetected.join(', ')}`);
|
|
49
|
-
}
|
|
50
|
-
if (autoSecrets.length > 0) {
|
|
51
|
-
console.log(`🔑 Auto-detected ${autoSecrets.length} secret(s) from .env: ${autoSecrets.join(', ')}`);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// Filter .env: move secret keys to .env.local (emulator-only, never deployed)
|
|
55
|
-
const { stripped } = filterEnvSecrets(functionsConfig);
|
|
56
|
-
if (stripped.length > 0) {
|
|
57
|
-
console.log(`🔒 Filtered ${stripped.length} secret(s) from .env → .env.local`);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Log bundle info if metafile is available
|
|
61
|
-
if (result.metafile) {
|
|
62
|
-
const { analyzeMetafile } = await import('esbuild');
|
|
63
|
-
const analysis = await analyzeMetafile(result.metafile);
|
|
64
|
-
console.log('\n📊 Bundle analysis:');
|
|
65
|
-
console.log(analysis);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
} catch (error) {
|
|
69
|
-
console.error('❌ Build failed:', error);
|
|
70
|
-
process.exit(1);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// Run the build
|
|
75
|
-
buildFunctions();
|
|
5
|
+
buildFunctions(functionsConfig);
|
|
@@ -1,45 +1,43 @@
|
|
|
1
1
|
# =============================================================================
|
|
2
|
-
# {{APP_NAME}}
|
|
2
|
+
# {{APP_NAME}} Server-Side Environment Variables
|
|
3
3
|
# =============================================================================
|
|
4
|
-
# Copy this file to .env in the functions directory and
|
|
4
|
+
# Copy this file to .env in the functions directory and fill in your values.
|
|
5
|
+
#
|
|
6
|
+
# IMPORTANT: These are SECRET keys. Never put them in VITE_* or NEXT_PUBLIC_*
|
|
7
|
+
# variables. Never commit this file to git.
|
|
8
|
+
#
|
|
9
|
+
# Sync to runtime: dndev sync-secrets
|
|
10
|
+
# Sync to GitHub: dndev sync-secrets --target github
|
|
5
11
|
|
|
6
12
|
# =============================================================================
|
|
7
13
|
# Stripe Configuration
|
|
14
|
+
# Get keys from: https://dashboard.stripe.com/apikeys
|
|
8
15
|
# =============================================================================
|
|
9
|
-
|
|
10
|
-
|
|
16
|
+
STRIPE_SECRET_KEY=sk_test_...
|
|
17
|
+
STRIPE_WEBHOOK_SECRET=whsec_...
|
|
11
18
|
|
|
12
|
-
#
|
|
13
|
-
|
|
19
|
+
# =============================================================================
|
|
20
|
+
# Supabase (server-side only — if using Supabase backend)
|
|
21
|
+
# Get from: https://supabase.com/dashboard → Settings → API
|
|
22
|
+
# =============================================================================
|
|
23
|
+
# SUPABASE_SERVICE_ROLE_KEY=eyJ...
|
|
14
24
|
|
|
15
25
|
# =============================================================================
|
|
16
26
|
# GitHub Configuration
|
|
17
|
-
#
|
|
18
|
-
# GitHub Personal Access Token (for repository access management)
|
|
27
|
+
# Get token from: https://github.com/settings/tokens
|
|
19
28
|
# Required scopes: repo (full control of private repositories)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
#
|
|
23
|
-
|
|
24
|
-
GITHUB_REPO_NAME=your-repo
|
|
29
|
+
# =============================================================================
|
|
30
|
+
# GITHUB_PERSONAL_ACCESS_TOKEN=ghp_...
|
|
31
|
+
# GITHUB_REPO_OWNER=your-org
|
|
32
|
+
# GITHUB_REPO_NAME=your-repo
|
|
25
33
|
|
|
26
34
|
# =============================================================================
|
|
27
|
-
# Firebase Configuration
|
|
35
|
+
# Firebase Configuration (auto-detected, rarely needed manually)
|
|
28
36
|
# =============================================================================
|
|
29
|
-
# Firebase Project ID (usually auto-detected from Firebase Admin SDK)
|
|
30
37
|
FIREBASE_PROJECT_ID=your-project-id
|
|
31
|
-
|
|
32
|
-
# Firebase Region (default: us-central1)
|
|
33
38
|
FIREBASE_REGION=us-central1
|
|
34
39
|
|
|
35
40
|
# =============================================================================
|
|
36
|
-
# Development
|
|
41
|
+
# Development
|
|
37
42
|
# =============================================================================
|
|
38
|
-
# Node Environment
|
|
39
43
|
NODE_ENV=development
|
|
40
|
-
|
|
41
|
-
# =============================================================================
|
|
42
|
-
# Setup Instructions
|
|
43
|
-
# =============================================================================
|
|
44
|
-
# 1. Get Stripe keys from: https://dashboard.stripe.com/apikeys
|
|
45
|
-
# 2. Get GitHub token from: https://github.com/settings/tokens
|
|
@@ -1,75 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
* @fileoverview Build script for {{APP_NAME}} functions
|
|
4
|
-
* @description Bundles @donotdev/types and imports framework functions
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { build } from 'esbuild';
|
|
8
|
-
import { writeFileSync } from 'fs';
|
|
9
|
-
import { createAppFunctionsConfig, generateFunctionsYamlWithInfo, filterEnvSecrets } from '@donotdev/core/functions';
|
|
2
|
+
import { buildFunctions } from '@donotdev/core/functions';
|
|
10
3
|
import { functionsConfig } from './functions.config.js';
|
|
11
4
|
|
|
12
|
-
|
|
13
|
-
console.log('🔨 Building {{APP_NAME}} functions...');
|
|
14
|
-
|
|
15
|
-
try {
|
|
16
|
-
const config = createAppFunctionsConfig({
|
|
17
|
-
entry: 'src/index.ts',
|
|
18
|
-
outDir: 'lib',
|
|
19
|
-
minify: process.env.NODE_ENV === 'production',
|
|
20
|
-
sourcemap: true,
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
console.log('📦 Bundling @donotdev/types and importing framework functions...');
|
|
24
|
-
|
|
25
|
-
const result = await build(config);
|
|
26
|
-
|
|
27
|
-
if (result.errors.length > 0) {
|
|
28
|
-
console.error('❌ Build errors:', result.errors);
|
|
29
|
-
process.exit(1);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
if (result.warnings.length > 0) {
|
|
33
|
-
console.warn('⚠️ Build warnings:', result.warnings);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
console.log('✅ {{APP_NAME}} functions built successfully!');
|
|
37
|
-
console.log('📁 Output directory: lib/');
|
|
38
|
-
|
|
39
|
-
// Generate functions.yaml from config + auto-detection
|
|
40
|
-
// Auto-detects: exported functions from src/index.ts + secrets from .env
|
|
41
|
-
const { yaml, staticFunctions, crudFunctions, autoDetected, autoSecrets } = generateFunctionsYamlWithInfo(
|
|
42
|
-
functionsConfig,
|
|
43
|
-
{ entryFile: 'src/index.ts', envPath: '.env' }
|
|
44
|
-
);
|
|
45
|
-
writeFileSync('functions.yaml', yaml);
|
|
46
|
-
console.log(`📄 Generated functions.yaml: ${staticFunctions.length} static + ${crudFunctions.length} CRUD functions`);
|
|
47
|
-
if (autoDetected.length > 0) {
|
|
48
|
-
console.log(`🔍 Auto-detected ${autoDetected.length} function(s) from src/index.ts: ${autoDetected.join(', ')}`);
|
|
49
|
-
}
|
|
50
|
-
if (autoSecrets.length > 0) {
|
|
51
|
-
console.log(`🔑 Auto-detected ${autoSecrets.length} secret(s) from .env: ${autoSecrets.join(', ')}`);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// Filter .env: move secret keys to .env.local (emulator-only, never deployed)
|
|
55
|
-
const { stripped } = filterEnvSecrets(functionsConfig);
|
|
56
|
-
if (stripped.length > 0) {
|
|
57
|
-
console.log(`🔒 Filtered ${stripped.length} secret(s) from .env → .env.local`);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Log bundle info if metafile is available
|
|
61
|
-
if (result.metafile) {
|
|
62
|
-
const { analyzeMetafile } = await import('esbuild');
|
|
63
|
-
const analysis = await analyzeMetafile(result.metafile);
|
|
64
|
-
console.log('\n📊 Bundle analysis:');
|
|
65
|
-
console.log(analysis);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
} catch (error) {
|
|
69
|
-
console.error('❌ Build failed:', error);
|
|
70
|
-
process.exit(1);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// Run the build
|
|
75
|
-
buildFunctions();
|
|
5
|
+
buildFunctions(functionsConfig);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// supabase/functions/cancel-subscription/index.ts
|
|
2
|
+
// Supabase Edge Function — Cancel Subscription
|
|
3
|
+
// Deploy: supabase functions deploy cancel-subscription
|
|
4
|
+
|
|
5
|
+
import { createCancelSubscription } from '@donotdev/functions/supabase';
|
|
6
|
+
|
|
7
|
+
Deno.serve(createCancelSubscription());
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// supabase/functions/change-plan/index.ts
|
|
2
|
+
// Supabase Edge Function — Change Subscription Plan
|
|
3
|
+
// Deploy: supabase functions deploy change-plan
|
|
4
|
+
|
|
5
|
+
import { createChangePlan } from '@donotdev/functions/supabase';
|
|
6
|
+
|
|
7
|
+
// Import your billing config
|
|
8
|
+
// import { billingConfig } from '../_shared/billingConfig.ts';
|
|
9
|
+
const billingConfig = {}; // TODO: Replace with your StripeBackConfig
|
|
10
|
+
|
|
11
|
+
Deno.serve(createChangePlan(billingConfig));
|
package/templates/functions-supabase/supabase/functions/create-checkout-session/index.ts.example
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// supabase/functions/create-checkout-session/index.ts
|
|
2
|
+
// Supabase Edge Function — Stripe Checkout Session
|
|
3
|
+
// Deploy: supabase functions deploy create-checkout-session
|
|
4
|
+
|
|
5
|
+
import { createCheckoutSession } from '@donotdev/functions/supabase';
|
|
6
|
+
|
|
7
|
+
// Import your billing config
|
|
8
|
+
// import { billingConfig } from '../_shared/billingConfig.ts';
|
|
9
|
+
const billingConfig = {}; // TODO: Replace with your StripeBackConfig
|
|
10
|
+
|
|
11
|
+
Deno.serve(createCheckoutSession(billingConfig));
|
package/templates/functions-supabase/supabase/functions/create-customer-portal/index.ts.example
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// supabase/functions/create-customer-portal/index.ts
|
|
2
|
+
// Supabase Edge Function — Stripe Customer Portal
|
|
3
|
+
// Deploy: supabase functions deploy create-customer-portal
|
|
4
|
+
|
|
5
|
+
import { createCustomerPortal } from '@donotdev/functions/supabase';
|
|
6
|
+
|
|
7
|
+
Deno.serve(createCustomerPortal());
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// supabase/functions/crud/index.ts
|
|
2
|
+
// Supabase Edge Function — CRUD Operations
|
|
3
|
+
// Deploy: supabase functions deploy crud
|
|
4
|
+
//
|
|
5
|
+
// This single Edge Function handles all CRUD operations for all entities.
|
|
6
|
+
// The SupabaseCallableProvider automatically routes CRUD calls here.
|
|
7
|
+
|
|
8
|
+
import { createSupabaseCrudFunctions } from '@donotdev/functions/supabase';
|
|
9
|
+
|
|
10
|
+
// Import your entities
|
|
11
|
+
// import * as entities from '../_shared/entities.ts';
|
|
12
|
+
const entities = {}; // TODO: Replace with your entity imports
|
|
13
|
+
|
|
14
|
+
const { serve } = createSupabaseCrudFunctions(entities);
|
|
15
|
+
|
|
16
|
+
Deno.serve(serve);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// supabase/functions/get-custom-claims/index.ts
|
|
2
|
+
// Supabase Edge Function — Get Custom Claims (app_metadata)
|
|
3
|
+
// Deploy: supabase functions deploy get-custom-claims
|
|
4
|
+
|
|
5
|
+
import { createGetCustomClaims } from '@donotdev/functions/supabase';
|
|
6
|
+
|
|
7
|
+
Deno.serve(createGetCustomClaims());
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// supabase/functions/get-user-auth-status/index.ts
|
|
2
|
+
// Supabase Edge Function — Get User Auth Status
|
|
3
|
+
// Deploy: supabase functions deploy get-user-auth-status
|
|
4
|
+
|
|
5
|
+
import { createGetUserAuthStatus } from '@donotdev/functions/supabase';
|
|
6
|
+
|
|
7
|
+
Deno.serve(createGetUserAuthStatus());
|
package/templates/functions-supabase/supabase/functions/refresh-subscription-status/index.ts.example
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// supabase/functions/refresh-subscription-status/index.ts
|
|
2
|
+
// Supabase Edge Function — Refresh Subscription Status
|
|
3
|
+
// Deploy: supabase functions deploy refresh-subscription-status
|
|
4
|
+
|
|
5
|
+
import { createRefreshSubscriptionStatus } from '@donotdev/functions/supabase';
|
|
6
|
+
|
|
7
|
+
Deno.serve(createRefreshSubscriptionStatus());
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// supabase/functions/remove-custom-claims/index.ts
|
|
2
|
+
// Supabase Edge Function — Remove Custom Claims from app_metadata
|
|
3
|
+
// Deploy: supabase functions deploy remove-custom-claims
|
|
4
|
+
|
|
5
|
+
import { createRemoveCustomClaims } from '@donotdev/functions/supabase';
|
|
6
|
+
|
|
7
|
+
Deno.serve(createRemoveCustomClaims());
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// supabase/functions/set-custom-claims/index.ts
|
|
2
|
+
// Supabase Edge Function — Set Custom Claims (app_metadata)
|
|
3
|
+
// Deploy: supabase functions deploy set-custom-claims
|
|
4
|
+
|
|
5
|
+
import { createSetCustomClaims } from '@donotdev/functions/supabase';
|
|
6
|
+
|
|
7
|
+
Deno.serve(createSetCustomClaims());
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
-- Migration: Create idempotency table for Supabase CRUD operations
|
|
2
|
+
-- Generated: 2026-02-19
|
|
3
|
+
-- Purpose: Store operation results to prevent duplicate processing
|
|
4
|
+
-- TTL: 24 hours default, configurable per operation
|
|
5
|
+
|
|
6
|
+
CREATE TABLE IF NOT EXISTS idempotency (
|
|
7
|
+
id TEXT PRIMARY KEY, -- Format: "{operation}_{idempotencyKey}"
|
|
8
|
+
operation TEXT NOT NULL, -- 'create', 'update', 'delete', etc.
|
|
9
|
+
idempotency_key TEXT NOT NULL UNIQUE, -- Client-provided key
|
|
10
|
+
result JSONB NOT NULL, -- Cached operation result
|
|
11
|
+
processed_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
12
|
+
processed_by TEXT NOT NULL, -- User ID
|
|
13
|
+
expires_at TIMESTAMPTZ NOT NULL -- TTL for cleanup (default: 24h)
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
-- Indexes for efficient lookups
|
|
17
|
+
CREATE INDEX IF NOT EXISTS idx_idempotency_expires ON idempotency(expires_at);
|
|
18
|
+
CREATE INDEX IF NOT EXISTS idx_idempotency_key ON idempotency(idempotency_key);
|
|
19
|
+
CREATE INDEX IF NOT EXISTS idx_idempotency_operation ON idempotency(operation, expires_at);
|
|
20
|
+
|
|
21
|
+
-- Comments
|
|
22
|
+
COMMENT ON TABLE idempotency IS 'Stores idempotency keys and cached operation results to prevent duplicate processing';
|
|
23
|
+
COMMENT ON COLUMN idempotency.id IS 'Composite key: {operation}_{idempotencyKey}';
|
|
24
|
+
COMMENT ON COLUMN idempotency.expires_at IS 'TTL for automatic cleanup - defaults to 24 hours from processed_at';
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
-- Migration: Create rate_limits table for Supabase Edge Functions
|
|
2
|
+
-- Generated: 2026-02-19
|
|
3
|
+
-- Purpose: Track API call rates per user/IP to prevent abuse
|
|
4
|
+
-- Pattern: Same as Firebase Firestore rateLimits collection
|
|
5
|
+
|
|
6
|
+
CREATE TABLE IF NOT EXISTS rate_limits (
|
|
7
|
+
key TEXT PRIMARY KEY, -- Format: "{operation}_{identifier}" (e.g., "create_apartment_uid_123")
|
|
8
|
+
attempts INTEGER NOT NULL DEFAULT 1,
|
|
9
|
+
window_start TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
10
|
+
block_until TIMESTAMPTZ, -- NULL if not blocked
|
|
11
|
+
last_updated TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
-- Indexes for efficient lookups and cleanup
|
|
15
|
+
CREATE INDEX IF NOT EXISTS idx_rate_limits_window ON rate_limits(window_start);
|
|
16
|
+
CREATE INDEX IF NOT EXISTS idx_rate_limits_block ON rate_limits(block_until) WHERE block_until IS NOT NULL;
|
|
17
|
+
CREATE INDEX IF NOT EXISTS idx_rate_limits_updated ON rate_limits(last_updated);
|
|
18
|
+
|
|
19
|
+
-- Comments
|
|
20
|
+
COMMENT ON TABLE rate_limits IS 'Tracks API call rates per operation and identifier (user ID or IP)';
|
|
21
|
+
COMMENT ON COLUMN rate_limits.key IS 'Composite key: {operation}_{identifier_type}_{identifier_value}';
|
|
22
|
+
COMMENT ON COLUMN rate_limits.block_until IS 'Timestamp when rate limit block expires (NULL if not blocked)';
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
-- Migration: Create cleanup cron jobs for idempotency and rate_limits tables
|
|
2
|
+
-- Generated: 2026-02-19
|
|
3
|
+
-- Purpose: Automatically clean up expired records to prevent table bloat
|
|
4
|
+
-- Schedule: Daily at 2 AM UTC (idempotency), 3 AM UTC (rate_limits), 4 AM UTC (metrics)
|
|
5
|
+
|
|
6
|
+
-- Enable pg_cron extension (if not already enabled)
|
|
7
|
+
CREATE EXTENSION IF NOT EXISTS pg_cron;
|
|
8
|
+
|
|
9
|
+
-- Cleanup expired idempotency records (daily at 2 AM UTC)
|
|
10
|
+
SELECT cron.schedule(
|
|
11
|
+
'cleanup-idempotency',
|
|
12
|
+
'0 2 * * *',
|
|
13
|
+
$$DELETE FROM idempotency WHERE expires_at < now()$$
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
-- Cleanup old rate limit records (daily at 3 AM UTC)
|
|
17
|
+
SELECT cron.schedule(
|
|
18
|
+
'cleanup-rate-limits',
|
|
19
|
+
'0 3 * * *',
|
|
20
|
+
$$DELETE FROM rate_limits WHERE window_start + interval '7 days' < now()$$
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
-- Cleanup old operation metrics (daily at 4 AM UTC)
|
|
24
|
+
SELECT cron.schedule(
|
|
25
|
+
'cleanup-operation-metrics',
|
|
26
|
+
'0 4 * * *',
|
|
27
|
+
$$DELETE FROM operation_metrics WHERE timestamp < now() - interval '90 days'$$
|
|
28
|
+
);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
-- Migration: Create operation_metrics table for Supabase Edge Functions monitoring
|
|
2
|
+
-- Generated: 2026-02-19
|
|
3
|
+
-- Purpose: Track operation success/failure rates, duration, and user activity
|
|
4
|
+
-- Retention: 90 days (configurable via cleanup job)
|
|
5
|
+
|
|
6
|
+
CREATE TABLE IF NOT EXISTS operation_metrics (
|
|
7
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
8
|
+
operation TEXT NOT NULL, -- e.g., 'create_apartment', 'get_user'
|
|
9
|
+
user_id TEXT, -- NULL for guest operations
|
|
10
|
+
status TEXT NOT NULL, -- 'success', 'failed', 'pending'
|
|
11
|
+
duration_ms INTEGER, -- Operation duration in milliseconds
|
|
12
|
+
timestamp TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
13
|
+
metadata JSONB, -- Additional context (request ID, etc.)
|
|
14
|
+
error_code TEXT, -- If status = 'failed'
|
|
15
|
+
error_message TEXT -- If status = 'failed'
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
-- Indexes for efficient queries
|
|
19
|
+
CREATE INDEX IF NOT EXISTS idx_metrics_operation ON operation_metrics(operation, timestamp DESC);
|
|
20
|
+
CREATE INDEX IF NOT EXISTS idx_metrics_user ON operation_metrics(user_id, timestamp DESC) WHERE user_id IS NOT NULL;
|
|
21
|
+
CREATE INDEX IF NOT EXISTS idx_metrics_status ON operation_metrics(status, timestamp DESC);
|
|
22
|
+
CREATE INDEX IF NOT EXISTS idx_metrics_timestamp ON operation_metrics(timestamp DESC);
|
|
23
|
+
|
|
24
|
+
-- Comments
|
|
25
|
+
COMMENT ON TABLE operation_metrics IS 'Tracks operation metrics for monitoring and analytics';
|
|
26
|
+
COMMENT ON COLUMN operation_metrics.operation IS 'Operation name (e.g., create_apartment, get_user)';
|
|
27
|
+
COMMENT ON COLUMN operation_metrics.duration_ms IS 'Operation duration in milliseconds';
|
|
28
|
+
COMMENT ON COLUMN operation_metrics.metadata IS 'Additional context as JSON (request ID, etc.)';
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
|
|
2
|
+
# =============================================================================
|
|
3
|
+
# Firebase Configuration
|
|
4
|
+
# =============================================================================
|
|
5
|
+
# Get these values from your Firebase project settings
|
|
6
|
+
# Run `dndev firebase:setup` to auto-populate, or copy from Firebase Console
|
|
7
|
+
VITE_FIREBASE_API_KEY=
|
|
8
|
+
VITE_FIREBASE_PROJECT_ID=
|
|
9
|
+
# Copy from Firebase Console. Framework uses APP_URL hostname in production automatically.
|
|
10
|
+
VITE_FIREBASE_AUTH_DOMAIN=
|
|
11
|
+
VITE_FIREBASE_STORAGE_BUCKET=
|
|
12
|
+
VITE_FIREBASE_MESSAGING_SENDER_ID=
|
|
13
|
+
VITE_FIREBASE_APP_ID=
|
|
14
|
+
VITE_FIREBASE_MEASUREMENT_ID=
|
|
15
|
+
VITE_FIREBASE_FUNCTIONS_REGION=
|
|
16
|
+
|
|
17
|
+
# =============================================================================
|
|
18
|
+
# Firebase Emulator (Development only)
|
|
19
|
+
# =============================================================================
|
|
20
|
+
# Set to true to use Firebase emulators instead of production services
|
|
21
|
+
VITE_USE_FIREBASE_EMULATOR=false
|
|
22
|
+
VITE_FIREBASE_EMULATOR_HOST=localhost
|
|
23
|
+
VITE_FIREBASE_EMULATOR_PORT=9099
|
|
24
|
+
VITE_FIREBASE_AUTH_EMULATOR_HOST=http://localhost:9099
|
|
25
|
+
VITE_FIREBASE_FIRESTORE_EMULATOR_HOST=localhost:8080
|
|
26
|
+
VITE_FIREBASE_FUNCTIONS_EMULATOR_PORT=5001
|
|
27
|
+
|
|
28
|
+
# =============================================================================
|
|
29
|
+
# Firebase App Check (Abuse Protection)
|
|
30
|
+
# =============================================================================
|
|
31
|
+
# reCAPTCHA v3 site key for App Check
|
|
32
|
+
# VITE_RECAPTCHA_SITE_KEY=6LcXXXX...
|
|
33
|
+
# Optional: Debug token for localhost testing
|
|
34
|
+
# VITE_APPCHECK_DEBUG_TOKEN=XXXX-XXXX-XXXX
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
|
|
2
|
+
# =============================================================================
|
|
3
|
+
# Firebase Configuration
|
|
4
|
+
# =============================================================================
|
|
5
|
+
# Get these values from your Firebase project settings
|
|
6
|
+
# Run `dndev firebase:setup` to auto-populate, or copy from Firebase Console
|
|
7
|
+
EXPO_PUBLIC_FIREBASE_API_KEY=
|
|
8
|
+
EXPO_PUBLIC_FIREBASE_PROJECT_ID=
|
|
9
|
+
# Copy from Firebase Console. Framework uses APP_URL hostname in production automatically.
|
|
10
|
+
EXPO_PUBLIC_FIREBASE_AUTH_DOMAIN=
|
|
11
|
+
EXPO_PUBLIC_FIREBASE_STORAGE_BUCKET=
|
|
12
|
+
EXPO_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=
|
|
13
|
+
EXPO_PUBLIC_FIREBASE_APP_ID=
|
|
14
|
+
EXPO_PUBLIC_FIREBASE_MEASUREMENT_ID=
|
|
15
|
+
EXPO_PUBLIC_FIREBASE_FUNCTIONS_REGION=
|
|
16
|
+
|
|
17
|
+
# =============================================================================
|
|
18
|
+
# Firebase Emulator (Development only)
|
|
19
|
+
# =============================================================================
|
|
20
|
+
# Set to true to use Firebase emulators instead of production services
|
|
21
|
+
EXPO_PUBLIC_USE_FIREBASE_EMULATOR=false
|
|
22
|
+
EXPO_PUBLIC_FIREBASE_EMULATOR_HOST=localhost
|
|
23
|
+
EXPO_PUBLIC_FIREBASE_EMULATOR_PORT=9099
|
|
24
|
+
EXPO_PUBLIC_FIREBASE_AUTH_EMULATOR_HOST=http://localhost:9099
|
|
25
|
+
EXPO_PUBLIC_FIREBASE_FIRESTORE_EMULATOR_HOST=localhost:8080
|
|
26
|
+
EXPO_PUBLIC_FIREBASE_FUNCTIONS_EMULATOR_PORT=5001
|
|
27
|
+
|
|
28
|
+
# =============================================================================
|
|
29
|
+
# Firebase App Check (Abuse Protection)
|
|
30
|
+
# =============================================================================
|
|
31
|
+
# reCAPTCHA v3 site key for App Check
|
|
32
|
+
# EXPO_PUBLIC_RECAPTCHA_SITE_KEY=6LcXXXX...
|
|
33
|
+
# Optional: Debug token for localhost testing
|
|
34
|
+
# EXPO_PUBLIC_APPCHECK_DEBUG_TOKEN=XXXX-XXXX-XXXX
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
|
|
2
|
+
# =============================================================================
|
|
3
|
+
# Firebase Configuration
|
|
4
|
+
# =============================================================================
|
|
5
|
+
# Get these values from your Firebase project settings
|
|
6
|
+
# Run `dndev firebase:setup` to auto-populate, or copy from Firebase Console
|
|
7
|
+
NEXT_PUBLIC_FIREBASE_API_KEY=
|
|
8
|
+
NEXT_PUBLIC_FIREBASE_PROJECT_ID=
|
|
9
|
+
# Copy from Firebase Console. Framework uses APP_URL hostname in production automatically.
|
|
10
|
+
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=
|
|
11
|
+
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=
|
|
12
|
+
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=
|
|
13
|
+
NEXT_PUBLIC_FIREBASE_APP_ID=
|
|
14
|
+
NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID=
|
|
15
|
+
NEXT_PUBLIC_FIREBASE_FUNCTIONS_REGION=
|
|
16
|
+
|
|
17
|
+
# =============================================================================
|
|
18
|
+
# Firebase Emulator (Development only)
|
|
19
|
+
# =============================================================================
|
|
20
|
+
# Set to true to use Firebase emulators instead of production services
|
|
21
|
+
NEXT_PUBLIC_USE_FIREBASE_EMULATOR=false
|
|
22
|
+
NEXT_PUBLIC_FIREBASE_EMULATOR_HOST=localhost
|
|
23
|
+
NEXT_PUBLIC_FIREBASE_EMULATOR_PORT=9099
|
|
24
|
+
NEXT_PUBLIC_FIREBASE_AUTH_EMULATOR_HOST=http://localhost:9099
|
|
25
|
+
NEXT_PUBLIC_FIREBASE_FIRESTORE_EMULATOR_HOST=localhost:8080
|
|
26
|
+
NEXT_PUBLIC_FIREBASE_FUNCTIONS_EMULATOR_PORT=5001
|
|
27
|
+
|
|
28
|
+
# =============================================================================
|
|
29
|
+
# Firebase App Check (Abuse Protection)
|
|
30
|
+
# =============================================================================
|
|
31
|
+
# reCAPTCHA v3 site key for App Check
|
|
32
|
+
# NEXT_PUBLIC_RECAPTCHA_SITE_KEY=6LcXXXX...
|
|
33
|
+
# Optional: Debug token for localhost testing
|
|
34
|
+
# NEXT_PUBLIC_APPCHECK_DEBUG_TOKEN=XXXX-XXXX-XXXX
|