@getjack/jack 0.1.28 → 0.1.30
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/package.json +1 -1
- package/src/commands/cd.ts +163 -0
- package/src/commands/clone.ts +112 -68
- package/src/commands/domain.ts +506 -0
- package/src/commands/domains.ts +215 -0
- package/src/commands/down.ts +18 -12
- package/src/commands/hack.ts +185 -8
- package/src/commands/init.ts +52 -1
- package/src/commands/link.ts +25 -43
- package/src/commands/logs.ts +2 -2
- package/src/commands/mcp.ts +74 -3
- package/src/commands/new.ts +48 -54
- package/src/commands/projects.ts +53 -10
- package/src/commands/secrets.ts +5 -1
- package/src/commands/services.ts +16 -4
- package/src/commands/shell-init.ts +43 -0
- package/src/commands/ship.ts +2 -11
- package/src/commands/skills.ts +335 -0
- package/src/commands/update.ts +31 -0
- package/src/commands/upgrade.ts +14 -0
- package/src/index.ts +116 -24
- package/src/lib/agent-integration.ts +1 -2
- package/src/lib/agents.ts +2 -2
- package/src/lib/auth/login-flow.ts +1 -1
- package/src/lib/clone-core.ts +252 -0
- package/src/lib/config.ts +22 -0
- package/src/lib/control-plane.ts +31 -5
- package/src/lib/fuzzy.ts +93 -0
- package/src/lib/managed-deploy.ts +4 -1
- package/src/lib/managed-down.ts +20 -5
- package/src/lib/output.ts +90 -9
- package/src/lib/picker.ts +406 -0
- package/src/lib/project-detection.ts +5 -2
- package/src/lib/project-list.ts +66 -5
- package/src/lib/project-operations.ts +68 -6
- package/src/lib/prompts.ts +1 -1
- package/src/lib/services/db-execute.ts +8 -1
- package/src/lib/services/db-list.ts +4 -1
- package/src/lib/services/domain-operations.ts +379 -0
- package/src/lib/services/storage-config.ts +1 -5
- package/src/lib/services/storage-delete.ts +1 -1
- package/src/lib/services/storage-info.ts +2 -4
- package/src/lib/services/vectorize-config.ts +1 -5
- package/src/lib/services/vectorize-create.ts +3 -1
- package/src/lib/shell-integration.ts +202 -0
- package/src/lib/telemetry-config.ts +50 -4
- package/src/lib/telemetry.ts +71 -2
- package/src/lib/version-check.ts +1 -3
- package/src/lib/wrangler-config.test.ts +2 -2
- package/src/lib/wrangler-config.ts +1 -1
- package/src/lib/zip-packager.ts +1 -3
- package/src/mcp/tools/index.ts +261 -7
- package/src/templates/index.ts +10 -1
- package/templates/ai-chat/.jack.json +1 -5
- package/templates/ai-chat/public/chat.js +130 -130
- package/templates/ai-chat/src/index.ts +9 -13
- package/templates/ai-chat/src/jack-ai.ts +6 -2
- package/templates/saas/.jack.json +6 -1
- package/templates/saas/src/auth.ts +8 -4
- package/templates/saas/src/client/App.tsx +22 -7
- package/templates/saas/src/client/components/ProtectedRoute.tsx +9 -2
- package/templates/saas/src/client/components/ThemeToggle.tsx +1 -6
- package/templates/saas/src/client/components/ui/accordion.tsx +1 -1
- package/templates/saas/src/client/components/ui/alert-dialog.tsx +2 -2
- package/templates/saas/src/client/components/ui/alert.tsx +2 -2
- package/templates/saas/src/client/components/ui/avatar.tsx +1 -1
- package/templates/saas/src/client/components/ui/badge.tsx +2 -2
- package/templates/saas/src/client/components/ui/breadcrumb.tsx +1 -1
- package/templates/saas/src/client/components/ui/button-group.tsx +2 -2
- package/templates/saas/src/client/components/ui/button.tsx +2 -2
- package/templates/saas/src/client/components/ui/card.tsx +1 -1
- package/templates/saas/src/client/components/ui/carousel.tsx +2 -2
- package/templates/saas/src/client/components/ui/checkbox.tsx +1 -1
- package/templates/saas/src/client/components/ui/command.tsx +2 -2
- package/templates/saas/src/client/components/ui/context-menu.tsx +1 -1
- package/templates/saas/src/client/components/ui/dialog.tsx +1 -1
- package/templates/saas/src/client/components/ui/drawer.tsx +1 -1
- package/templates/saas/src/client/components/ui/dropdown-menu.tsx +1 -1
- package/templates/saas/src/client/components/ui/empty.tsx +1 -1
- package/templates/saas/src/client/components/ui/field.tsx +2 -2
- package/templates/saas/src/client/components/ui/form.tsx +5 -5
- package/templates/saas/src/client/components/ui/hover-card.tsx +1 -1
- package/templates/saas/src/client/components/ui/input-group.tsx +3 -3
- package/templates/saas/src/client/components/ui/input-otp.tsx +1 -1
- package/templates/saas/src/client/components/ui/input.tsx +1 -1
- package/templates/saas/src/client/components/ui/item.tsx +3 -3
- package/templates/saas/src/client/components/ui/label.tsx +1 -1
- package/templates/saas/src/client/components/ui/menubar.tsx +1 -1
- package/templates/saas/src/client/components/ui/navigation-menu.tsx +1 -1
- package/templates/saas/src/client/components/ui/pagination.tsx +2 -2
- package/templates/saas/src/client/components/ui/popover.tsx +1 -1
- package/templates/saas/src/client/components/ui/progress.tsx +1 -1
- package/templates/saas/src/client/components/ui/radio-group.tsx +1 -1
- package/templates/saas/src/client/components/ui/resizable.tsx +1 -1
- package/templates/saas/src/client/components/ui/scroll-area.tsx +1 -1
- package/templates/saas/src/client/components/ui/select.tsx +1 -1
- package/templates/saas/src/client/components/ui/separator.tsx +1 -1
- package/templates/saas/src/client/components/ui/sheet.tsx +1 -1
- package/templates/saas/src/client/components/ui/sidebar.tsx +4 -4
- package/templates/saas/src/client/components/ui/slider.tsx +1 -1
- package/templates/saas/src/client/components/ui/switch.tsx +1 -1
- package/templates/saas/src/client/components/ui/table.tsx +1 -1
- package/templates/saas/src/client/components/ui/tabs.tsx +1 -1
- package/templates/saas/src/client/components/ui/textarea.tsx +1 -1
- package/templates/saas/src/client/components/ui/toggle-group.tsx +3 -3
- package/templates/saas/src/client/components/ui/toggle.tsx +2 -2
- package/templates/saas/src/client/components/ui/tooltip.tsx +1 -1
- package/templates/saas/src/client/hooks/useSubscription.ts +5 -4
- package/templates/saas/src/client/lib/auth-client.ts +1 -1
- package/templates/saas/src/client/lib/plans.ts +1 -6
- package/templates/saas/src/client/lib/utils.ts +1 -1
- package/templates/saas/src/client/main.tsx +1 -1
- package/templates/saas/src/client/pages/DashboardPage.tsx +41 -9
- package/templates/saas/src/client/pages/ForgotPasswordPage.tsx +11 -2
- package/templates/saas/src/client/pages/HomePage.tsx +11 -2
- package/templates/saas/src/client/pages/LoginPage.tsx +11 -2
- package/templates/saas/src/client/pages/PricingPage.tsx +20 -10
- package/templates/saas/src/client/pages/ResetPasswordPage.tsx +14 -11
- package/templates/saas/src/client/pages/SignupPage.tsx +11 -2
- package/templates/saas/src/index.ts +28 -19
- package/templates/saas/vite.config.ts +1 -1
- package/templates/semantic-search/.jack.json +1 -5
- package/templates/semantic-search/src/index.ts +8 -4
- package/templates/semantic-search/src/jack-ai.ts +6 -2
- package/templates/semantic-search/src/jack-vectorize.ts +5 -1
|
@@ -1,11 +1,20 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { authClient } from "../lib/auth-client";
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
3
2
|
import { toast } from "sonner";
|
|
4
3
|
import { ThemeToggle } from "../components/ThemeToggle";
|
|
5
4
|
import { Button } from "../components/ui/button";
|
|
5
|
+
import { authClient } from "../lib/auth-client";
|
|
6
6
|
|
|
7
7
|
interface ResetPasswordPageProps {
|
|
8
|
-
navigate: (
|
|
8
|
+
navigate: (
|
|
9
|
+
route:
|
|
10
|
+
| "/"
|
|
11
|
+
| "/login"
|
|
12
|
+
| "/signup"
|
|
13
|
+
| "/pricing"
|
|
14
|
+
| "/dashboard"
|
|
15
|
+
| "/forgot-password"
|
|
16
|
+
| "/reset-password",
|
|
17
|
+
) => void;
|
|
9
18
|
}
|
|
10
19
|
|
|
11
20
|
export default function ResetPasswordPage({ navigate }: ResetPasswordPageProps) {
|
|
@@ -92,9 +101,7 @@ export default function ResetPasswordPage({ navigate }: ResetPasswordPageProps)
|
|
|
92
101
|
<p className="text-muted-foreground mb-6">
|
|
93
102
|
This password reset link is invalid or has expired. Please request a new one.
|
|
94
103
|
</p>
|
|
95
|
-
<Button onClick={() => navigate("/forgot-password")}>
|
|
96
|
-
Request new reset link
|
|
97
|
-
</Button>
|
|
104
|
+
<Button onClick={() => navigate("/forgot-password")}>Request new reset link</Button>
|
|
98
105
|
</div>
|
|
99
106
|
</div>
|
|
100
107
|
</div>
|
|
@@ -167,11 +174,7 @@ export default function ResetPasswordPage({ navigate }: ResetPasswordPageProps)
|
|
|
167
174
|
<Button type="submit" className="w-full" disabled={isLoading}>
|
|
168
175
|
{isLoading ? (
|
|
169
176
|
<>
|
|
170
|
-
<svg
|
|
171
|
-
className="animate-spin -ml-1 mr-2 h-4 w-4"
|
|
172
|
-
fill="none"
|
|
173
|
-
viewBox="0 0 24 24"
|
|
174
|
-
>
|
|
177
|
+
<svg className="animate-spin -ml-1 mr-2 h-4 w-4" fill="none" viewBox="0 0 24 24">
|
|
175
178
|
<circle
|
|
176
179
|
className="opacity-25"
|
|
177
180
|
cx="12"
|
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
import { useState } from "react";
|
|
2
|
-
import { authClient } from "../lib/auth-client";
|
|
3
2
|
import { ThemeToggle } from "../components/ThemeToggle";
|
|
3
|
+
import { authClient } from "../lib/auth-client";
|
|
4
4
|
|
|
5
5
|
interface SignupPageProps {
|
|
6
|
-
navigate: (
|
|
6
|
+
navigate: (
|
|
7
|
+
route:
|
|
8
|
+
| "/"
|
|
9
|
+
| "/login"
|
|
10
|
+
| "/signup"
|
|
11
|
+
| "/pricing"
|
|
12
|
+
| "/dashboard"
|
|
13
|
+
| "/forgot-password"
|
|
14
|
+
| "/reset-password",
|
|
15
|
+
) => void;
|
|
7
16
|
}
|
|
8
17
|
|
|
9
18
|
export default function SignupPage({ navigate }: SignupPageProps) {
|
|
@@ -75,21 +75,23 @@ app.get("/api/subscription-status", async (c) => {
|
|
|
75
75
|
// Get subscriptions for this customer (active or scheduled to cancel)
|
|
76
76
|
const subscriptions = await stripeClient.subscriptions.list({
|
|
77
77
|
customer: customers.data[0].id,
|
|
78
|
-
limit: 10,
|
|
79
|
-
expand: ["data.default_payment_method"],
|
|
78
|
+
limit: 10, // Get more to find the right one
|
|
79
|
+
expand: ["data.default_payment_method"], // Force fresh data
|
|
80
80
|
});
|
|
81
81
|
|
|
82
82
|
// Find active or trialing subscription (even if set to cancel at period end)
|
|
83
|
-
const sub = subscriptions.data.find(
|
|
84
|
-
(s) => s.status === "active" || s.status === "trialing"
|
|
85
|
-
);
|
|
83
|
+
const sub = subscriptions.data.find((s) => s.status === "active" || s.status === "trialing");
|
|
86
84
|
|
|
87
85
|
if (!sub) {
|
|
88
|
-
console.log(
|
|
86
|
+
console.log(
|
|
87
|
+
`[subscription-status] No active subscriptions for customer: ${customers.data[0].id}`,
|
|
88
|
+
);
|
|
89
89
|
return c.json({ subscription: null });
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
-
console.log(
|
|
92
|
+
console.log(
|
|
93
|
+
`[subscription-status] Found: id=${sub.id}, status=${sub.status}, cancel_at_period_end=${sub.cancel_at_period_end}`,
|
|
94
|
+
);
|
|
93
95
|
|
|
94
96
|
return c.json({
|
|
95
97
|
subscription: {
|
|
@@ -104,10 +106,13 @@ app.get("/api/subscription-status", async (c) => {
|
|
|
104
106
|
});
|
|
105
107
|
} catch (err) {
|
|
106
108
|
console.error("[subscription-status] Error:", err);
|
|
107
|
-
return c.json(
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
109
|
+
return c.json(
|
|
110
|
+
{
|
|
111
|
+
error: "Failed to fetch subscription status",
|
|
112
|
+
details: err instanceof Error ? err.message : String(err),
|
|
113
|
+
},
|
|
114
|
+
500,
|
|
115
|
+
);
|
|
111
116
|
}
|
|
112
117
|
});
|
|
113
118
|
|
|
@@ -154,17 +159,20 @@ app.post("/api/resubscribe", async (c) => {
|
|
|
154
159
|
}
|
|
155
160
|
|
|
156
161
|
// Also clear the local cancelAt in Better Auth's database
|
|
157
|
-
await c.env.DB.prepare(
|
|
158
|
-
|
|
159
|
-
|
|
162
|
+
await c.env.DB.prepare("UPDATE subscription SET cancelAt = NULL WHERE stripeSubscriptionId = ?")
|
|
163
|
+
.bind(sub.id)
|
|
164
|
+
.run();
|
|
160
165
|
|
|
161
166
|
return c.json({ success: true });
|
|
162
167
|
} catch (err) {
|
|
163
168
|
console.error("[resubscribe] Error:", err);
|
|
164
|
-
return c.json(
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
169
|
+
return c.json(
|
|
170
|
+
{
|
|
171
|
+
error: "Failed to resubscribe",
|
|
172
|
+
details: err instanceof Error ? err.message : String(err),
|
|
173
|
+
},
|
|
174
|
+
500,
|
|
175
|
+
);
|
|
168
176
|
}
|
|
169
177
|
});
|
|
170
178
|
|
|
@@ -190,7 +198,8 @@ app.get("/api/billing-portal", async (c) => {
|
|
|
190
198
|
return c.json({ error: "No billing account found" }, 404);
|
|
191
199
|
}
|
|
192
200
|
|
|
193
|
-
const returnUrl =
|
|
201
|
+
const returnUrl =
|
|
202
|
+
c.req.header("origin") || c.req.header("referer") || c.env.BETTER_AUTH_URL || "/";
|
|
194
203
|
|
|
195
204
|
const portalSession = await stripeClient.billingPortal.sessions.create({
|
|
196
205
|
customer: customers.data[0].id,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { resolve } from "node:path";
|
|
1
2
|
import { cloudflare } from "@cloudflare/vite-plugin";
|
|
2
3
|
import tailwindcss from "@tailwindcss/vite";
|
|
3
4
|
import react from "@vitejs/plugin-react";
|
|
4
|
-
import { resolve } from "node:path";
|
|
5
5
|
import { defineConfig } from "vite";
|
|
6
6
|
|
|
7
7
|
export default defineConfig({
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { type JackAI, createJackAI } from "./jack-ai";
|
|
2
|
+
import { type JackVectorize, createJackVectorize } from "./jack-vectorize";
|
|
3
3
|
|
|
4
4
|
interface Env {
|
|
5
5
|
// Direct bindings (for local dev with wrangler)
|
|
@@ -26,7 +26,9 @@ type AIClient = {
|
|
|
26
26
|
function getAI(env: Env): AIClient {
|
|
27
27
|
// Prefer jack cloud proxy if available (for metering)
|
|
28
28
|
if (env.__AI_PROXY && env.__JACK_PROJECT_ID && env.__JACK_ORG_ID) {
|
|
29
|
-
return createJackAI(
|
|
29
|
+
return createJackAI(
|
|
30
|
+
env as Required<Pick<Env, "__AI_PROXY" | "__JACK_PROJECT_ID" | "__JACK_ORG_ID">>,
|
|
31
|
+
) as AIClient;
|
|
30
32
|
}
|
|
31
33
|
// Fallback to direct binding for local dev
|
|
32
34
|
if (env.AI) {
|
|
@@ -37,7 +39,9 @@ function getAI(env: Env): AIClient {
|
|
|
37
39
|
|
|
38
40
|
// Minimal Vectorize interface
|
|
39
41
|
type VectorizeClient = {
|
|
40
|
-
insert: (
|
|
42
|
+
insert: (
|
|
43
|
+
vectors: { id: string; values: number[]; metadata?: Record<string, unknown> }[],
|
|
44
|
+
) => Promise<unknown>;
|
|
41
45
|
query: (
|
|
42
46
|
vector: number[],
|
|
43
47
|
options?: { topK?: number; returnMetadata?: "none" | "indexed" | "all" },
|
|
@@ -65,9 +65,13 @@ export function createJackAI(env: JackAIEnv): {
|
|
|
65
65
|
// Handle quota exceeded
|
|
66
66
|
if (response.status === 429) {
|
|
67
67
|
const error = await response.json();
|
|
68
|
-
const quotaError = new Error(
|
|
68
|
+
const quotaError = new Error(
|
|
69
|
+
(error as { message?: string }).message || "AI quota exceeded",
|
|
70
|
+
);
|
|
69
71
|
(quotaError as Error & { code: string }).code = "AI_QUOTA_EXCEEDED";
|
|
70
|
-
(quotaError as Error & { resetIn?: number }).resetIn = (
|
|
72
|
+
(quotaError as Error & { resetIn?: number }).resetIn = (
|
|
73
|
+
error as { resetIn?: number }
|
|
74
|
+
).resetIn;
|
|
71
75
|
throw quotaError;
|
|
72
76
|
}
|
|
73
77
|
|
|
@@ -106,7 +106,11 @@ export function createJackVectorize(
|
|
|
106
106
|
|
|
107
107
|
// Handle quota exceeded
|
|
108
108
|
if (response.status === 429) {
|
|
109
|
-
const error = (await response.json()) as {
|
|
109
|
+
const error = (await response.json()) as {
|
|
110
|
+
message?: string;
|
|
111
|
+
code?: string;
|
|
112
|
+
resetIn?: number;
|
|
113
|
+
};
|
|
110
114
|
const quotaError = new Error(error.message || "Vectorize quota exceeded");
|
|
111
115
|
(quotaError as Error & { code: string }).code = error.code || "VECTORIZE_QUOTA_EXCEEDED";
|
|
112
116
|
(quotaError as Error & { resetIn?: number }).resetIn = error.resetIn;
|