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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
},
"scripts": {
"build": "turbo run build --cache-dir=.turbo --no-update-notifier",
"dev": "turbo run dev --filter=@instantdb/version --filter=@instantdb/core --filter=@instantdb/react-common --filter=@instantdb/react --filter=@instantdb/react-native --filter=@instantdb/admin --filter=@instantdb/platform --filter=instant-www --filter=sb-react-nextjs --filter=sb-admin-sdk-express --filter=@instantdb/components --filter instant-cli --parallel --concurrency=20 --no-update-notifier",
"dev": "turbo run dev --filter=@instantdb/version --filter=@instantdb/core --filter=@instantdb/react-common --filter=@instantdb/react --filter=@instantdb/react-native --filter=@instantdb/admin --filter=@instantdb/platform --filter=instant-www --filter=sb-react-nextjs --filter=sb-admin-sdk-express --filter=@instantdb/components --filter=instant-cli --filter=create-instant-app --parallel --concurrency=20 --no-update-notifier",
"test": "turbo run test:ci --no-update-notifier",
"clean": "turbo run clean",
"bench": "turbo run bench:ci --no-update-notifier",
Expand Down
21 changes: 20 additions & 1 deletion client/packages/cli/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -769,6 +769,7 @@ async function login(options) {
debugName: 'Login register',
errorMessage: 'Failed to register login.',
noAuth: true,
command: 'login',
});

if (!registerRes.ok) {
Expand Down Expand Up @@ -934,6 +935,7 @@ async function promptCreateApp(opts) {
method: 'GET',
path: '/dash',
errorMessage: 'Failed to fetch apps.',
command: 'init',
});
if (!res.ok) {
return { ok: false };
Expand Down Expand Up @@ -966,6 +968,7 @@ async function promptCreateApp(opts) {
debugName: 'App create',
errorMessage: 'Failed to create app.',
body: app,
command: 'init',
});

if (!appRes.ok) return { ok: false };
Expand All @@ -984,6 +987,7 @@ async function promptImportAppOrCreateApp() {
method: 'GET',
path: '/dash',
errorMessage: 'Failed to fetch apps.',
command: 'init',
});
if (!res.ok) {
return { ok: false };
Expand All @@ -1003,6 +1007,7 @@ async function promptImportAppOrCreateApp() {
method: 'GET',
path: `/dash/orgs/${orgId}`,
errorMessage: 'Failed to fetch apps.',
command: 'init',
});
if (!orgsRes.ok) {
throw new Error('Failed to fetch org apps');
Expand Down Expand Up @@ -1032,6 +1037,7 @@ async function createApp(title, orgId) {
debugName: 'App create',
errorMessage: 'Failed to create app.',
body: app,
command: 'init',
});
if (!appRes.ok) throw new Error('Failed to create app');
return { appId: id, adminToken: token };
Expand Down Expand Up @@ -1198,6 +1204,7 @@ async function pullSchema(
path: `/dash/apps/${appId}/schema/pull`,
debugName: 'Schema pull',
errorMessage: 'Failed to pull schema.',
command: 'pull',
});

if (!pullRes.ok) return pullRes;
Expand Down Expand Up @@ -1261,6 +1268,7 @@ async function pullPerms(appId, { pkgDir, instantModuleName }) {
path: `/dash/apps/${appId}/perms/pull`,
debugName: 'Perms pull',
errorMessage: 'Failed to pull perms.',
command: 'pull',
});

if (!pullRes.ok) return pullRes;
Expand Down Expand Up @@ -1507,6 +1515,7 @@ async function waitForIndexingJobsToFinish(appId, data) {
method: 'GET',
path: `/dash/apps/${appId}/indexing-jobs/group/${groupId}`,
errorMessage: 'Failed to check indexing status.',
command: 'push',
});
if (!res.ok) {
break;
Expand Down Expand Up @@ -1576,6 +1585,7 @@ async function pushSchema(appId, opts) {
path: `/dash/apps/${appId}/schema/pull`,
debugName: 'Schema plan',
errorMessage: 'Failed to get old schema.',
command: 'push',
});

if (!pulledSchemaResponse.ok) return pulledSchemaResponse;
Expand Down Expand Up @@ -1666,6 +1676,7 @@ async function pushSchema(appId, opts) {
body: {
steps: txSteps,
},
command: 'push',
});
console.log(chalk.green('Schema updated!'));
if (!applyRes.ok) return applyRes;
Expand All @@ -1690,6 +1701,7 @@ async function claimEphemeralApp(appId, adminToken) {
path: `/dash/apps/ephemeral/${appId}/claim`,
debugName: 'Claim ephemeral app',
errorMessage: 'Failed to claim ephemeral app.',
command: 'claim',
});

if (!res.ok) return res;
Expand All @@ -1710,6 +1722,7 @@ async function pushPerms(appId) {
path: `/dash/apps/${appId}/perms/pull`,
debugName: 'Perms pull',
errorMessage: 'Failed to pull perms.',
command: 'push',
});

if (!prodPerms.ok) return prodPerms;
Expand Down Expand Up @@ -1749,6 +1762,7 @@ async function pushPerms(appId) {
body: {
code: res.perms,
},
command: 'push',
});

if (!permsRes.ok) return permsRes;
Expand All @@ -1769,6 +1783,7 @@ async function waitForAuthToken({ secret }) {
body: { secret },
noAuth: true,
noLogError: true,
command: 'login',
});
if (authCheckRes.ok) {
return authCheckRes.data;
Expand Down Expand Up @@ -1797,6 +1812,7 @@ async function waitForAuthToken({ secret }) {
* @param {Object} [options.body=undefined]
* @param {boolean} [options.noAuth]
* @param {boolean} [options.noLogError]
* @param {string} [options.command] - The CLI command being executed (e.g., 'push', 'pull', 'login')
* @returns {Promise<{ ok: boolean; data: any }>}
*/
async function fetchJson({
Expand All @@ -1807,6 +1823,7 @@ async function fetchJson({
method,
noAuth,
noLogError,
command,
}) {
const withAuth = !noAuth;
const withErrorLogging = !noLogError;
Expand All @@ -1825,7 +1842,9 @@ async function fetchJson({
headers: {
...(withAuth ? { Authorization: `Bearer ${authToken}` } : {}),
'Content-Type': 'application/json',
'Instant-CLI-Version': version,
'X-Instant-Source': 'instant-cli',
'X-Instant-Version': version,
...(command ? { 'X-Instant-Command': command } : {}),
},
body: body ? JSON.stringify(body) : undefined,
signal: AbortSignal.timeout(timeoutMs),
Expand Down
8 changes: 7 additions & 1 deletion client/packages/create-instant-app/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,13 @@ const main = async () => {
ruleFilesToAdd: project.ruleFiles,
});

const possibleAppTokenPair = await tryConnectApp(appFlags);
const scaffoldMetadata = {
template: project.base,
aiTool: project.ruleFiles ?? 'none',
usedAiPrompt: !!project.prompt,
};

const possibleAppTokenPair = await tryConnectApp(appFlags, scaffoldMetadata);
if (possibleAppTokenPair) {
applyEnvFile(
project,
Expand Down
15 changes: 12 additions & 3 deletions client/packages/create-instant-app/src/login.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
fetchJson,
instantBackendOrigin,
instantDashOrigin,
ScaffoldMetadata,
} from './utils/fetch.js';
import { renderUnwrap, UI } from 'instant-cli/ui';

Expand Down Expand Up @@ -40,6 +41,7 @@ export const createApp = async (
title: string,
authToken: string,
orgId?: string | null,
metadata?: ScaffoldMetadata,
) => {
const id = randomUUID();
const token = randomUUID();
Expand All @@ -49,6 +51,7 @@ export const createApp = async (
authToken,
path: '/dash/apps',
body: app,
metadata,
});
return { appID: id, adminToken: token, source: 'created' };
};
Expand Down Expand Up @@ -168,7 +171,10 @@ type AppTokenResponse = {
approach: 'ephemeral' | 'import' | 'create';
};

const createPermissiveEphemeralApp = async (title: string) => {
const createPermissiveEphemeralApp = async (
title: string,
metadata?: ScaffoldMetadata,
) => {
const response = await fetchJson<{
app: { id: string; 'admin-token': string };
}>({
Expand All @@ -190,12 +196,14 @@ const createPermissiveEphemeralApp = async (title: string) => {
},
},
},
metadata,
});
return { appId: response.app.id, adminToken: response.app['admin-token'] };
};

export const tryConnectApp = async (
appFlags?: AppFlags,
metadata?: ScaffoldMetadata,
): Promise<AppTokenResponse | null> => {
let authToken = await getAuthToken();

Expand Down Expand Up @@ -302,7 +310,7 @@ export const tryConnectApp = async (
modifyOutput: UI.ciaModifier(),
}),
);
const app = await createPermissiveEphemeralApp(name);
const app = await createPermissiveEphemeralApp(name, metadata);
return { ...app, approach: 'ephemeral' };
}
}
Expand All @@ -323,7 +331,7 @@ export const tryConnectApp = async (
},

createEphemeralApp(title) {
return createPermissiveEphemeralApp(title);
return createPermissiveEphemeralApp(title, metadata);
},

getAppsForOrg: async (orgId: string) => {
Expand All @@ -336,6 +344,7 @@ export const tryConnectApp = async (
title,
authToken,
orgId,
metadata,
);
return { appId: appID, adminToken };
},
Expand Down
30 changes: 26 additions & 4 deletions client/packages/create-instant-app/src/utils/fetch.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { version } from '@instantdb/version';

const dev = Boolean(process.env.INSTANT_CLI_DEV);

export const instantDashOrigin = dev
Expand All @@ -8,25 +10,45 @@ export const instantBackendOrigin =
process.env.INSTANT_CLI_API_URI ||
(dev ? 'http://localhost:8888' : 'https://api.instantdb.com');

export type ScaffoldMetadata = {
template?: string;
aiTool?: string;
usedAiPrompt?: boolean;
};

export async function fetchJson<T>({
path,
body,
method = 'GET',
authToken,
metadata,
}: {
path: string;
body?: any;
method?: 'POST' | 'GET';
authToken: string | null;
metadata?: ScaffoldMetadata;
}): Promise<T> {
const timeoutMs = 1000 * 60 * 5; // 5 minutes

const headers: Record<string, string> = {
'Content-Type': 'application/json',
'X-Instant-Source': 'create-instant-app',
'X-Instant-Version': version,
'X-Instant-Command': 'create',
};

if (authToken) {
headers['Authorization'] = `Bearer ${authToken}`;
}

if (metadata) {
headers['X-Instant-Metadata'] = JSON.stringify(metadata);
}

const res = await fetch(`${instantBackendOrigin}${path}`, {
method: method ?? 'GET',
headers: {
Authorization: authToken ? `Bearer ${authToken}` : '',
'Content-Type': 'application/json',
},
headers,
body: body ? JSON.stringify(body) : undefined,
signal: AbortSignal.timeout(timeoutMs),
});
Expand Down
2 changes: 2 additions & 0 deletions client/packages/platform/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,8 @@ async function jsonFetch<T>(
...(init?.headers || {}),
'Instant-Platform-Version': version,
'Instant-Core-Version': coreVersion,
'X-Instant-Source': 'platform-sdk',
'X-Instant-Version': version,
};
const res = await fetch(input, { ...init, headers });
if (res.status === 200) {
Expand Down
2 changes: 1 addition & 1 deletion client/packages/version/src/version.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
// Update the version here and merge your code to main to
// publish a new version of all of the packages to npm.

const version = 'v0.22.95';
const version = 'v0.22.96';

export { version };
4 changes: 2 additions & 2 deletions client/www/lib/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Cookies from 'js-cookie';
import { useContext, useEffect, useState } from 'react';
import useSwr, { SWRResponse } from 'swr';
import config from './config';
import { jsonFetch, jsonMutate } from './fetch';
import { jsonFetch, jsonMutate, trackingHeaders } from './fetch';
import { TokenContext } from '@/lib/contexts';
import produce, { Draft } from 'immer';

Expand Down Expand Up @@ -118,7 +118,7 @@ export function useTokenFetch<Res>(
path && token ? [path, token] : null,
async ([path, token]) => {
const res = await fetch(path, {
headers: { authorization: `Bearer ${token}` },
headers: { authorization: `Bearer ${token}`, ...trackingHeaders },
});
const jsonRes = await res.json();
if (!res.ok) {
Expand Down
12 changes: 11 additions & 1 deletion client/www/lib/fetch.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
const trackingHeaders = {
'X-Instant-Source': 'dashboard',
};

export async function jsonFetch(
input: RequestInfo,
init: RequestInit | undefined,
): Promise<any> {
const res = await fetch(input, init);
const headers = {
...(init?.headers || {}),
...trackingHeaders,
};
const res = await fetch(input, { ...init, headers });
const json = await res.json();
return res.status === 200
? Promise.resolve(json)
Expand All @@ -26,3 +34,5 @@ export async function jsonMutate<T>(
body: body ? JSON.stringify(body) : undefined,
});
}

export { trackingHeaders };
Loading