added THIS_LINE_PLATFORM

This commit is contained in:
Zai Shi
2025-03-12 17:20:26 -07:00
parent 5c8efbd56a
commit bf2e7302c1
21 changed files with 60 additions and 80 deletions
@@ -20,8 +20,7 @@ On this page:
Basic information about a contact channel, as seen by a user themselves.
Usually obtained by calling [`user.listContactChannels()`](../types/user.mdx#currentuserlistcontactchannels)
{/* NEXT_LINE_PLATFORM react-like */}
or [`user.useContactChannels()`](../types/user.mdx#currentuserusecontactchannels)
or [`user.useContactChannels()`](../types/user.mdx#currentuserusecontactchannels) {/* THIS_LINE_PLATFORM react-like */}
.
### Table of Contents
@@ -279,8 +278,7 @@ await contactChannel.delete();
Like `ContactChannel`, but includes additional methods and properties that require the `SECRET_SERVER_KEY`.
Usually obtained by calling [`serverUser.listContactChannels()`](../types/user.mdx#serveruserlistcontactchannels)
{/* NEXT_LINE_PLATFORM react-like */}
or [`serverUser.useContactChannels()`](../types/user.mdx#serveruserusecontactchannels)
or [`serverUser.useContactChannels()`](../types/user.mdx#serveruserusecontactchannels) {/* THIS_LINE_PLATFORM react-like */}
.
### Table of Contents
@@ -8,8 +8,7 @@ slug: sdk/types/project
The `Project` object contains the information and configuration of a project, such as the name, description, and enabled authentication methods.
Each [Stack app](../../concepts/stack-app.mdx) corresponds to a project. You can obtain its `Project` object by calling [`stackApp.getProject()`](../objects/stack-app.mdx#stackappgetproject)
{/* NEXT_LINE_PLATFORM react-like */}
or [`stackApp.useProject()`](../objects/stack-app.mdx#stackappuseproject)
or [`stackApp.useProject()`](../objects/stack-app.mdx#stackappuseproject) {/* THIS_LINE_PLATFORM react-like */}
.
### Table of Contents
@@ -19,8 +19,7 @@ On this page:
The `TeamUser` object is used on the client side to represent a user in the context of a team, providing minimal information about the user, including their ID and team-specific profile.
It is usually obtained by calling
{/* NEXT_LINE_PLATFORM react-like */}
`team.useUsers()` or
`team.useUsers()` or {/* THIS_LINE_PLATFORM react-like */}
`team.listUsers()` on a [`Team` object](../types/team.mdx#team).
### Table of Contents
@@ -21,8 +21,7 @@ On this page:
A `Team` object contains basic information and functions about a team, to the extent of which a member of the team would have access to it.
You can get `Team` objects with the
{/* NEXT_LINE_PLATFORM react-like */}
`user.useTeams()` or
`user.useTeams()` or {/* THIS_LINE_PLATFORM react-like */}
`user.listTeams()` functions. The created team will then inherit the permissions of that user; for example, the `team.update(...)` function can only succeed if the user is allowed to make updates to the team.
### Table of Contents
@@ -1,8 +1,7 @@
import { StackAssertionError } from "@stackframe/stack-shared/dist/utils/errors";
import { FilterUndefined, filterUndefined, pick } from "@stackframe/stack-shared/dist/utils/objects";
import { getRelativePart } from "@stackframe/stack-shared/dist/utils/urls";
// NEXT_LINE_PLATFORM next
import { RedirectType, notFound, redirect } from 'next/navigation';
import { RedirectType, notFound, redirect } from 'next/navigation'; // THIS_LINE_PLATFORM next
import { useMemo } from 'react';
import { SignIn, SignUp, StackServerApp } from "..";
import { IframePreventer } from "../components/iframe-preventer";
+1 -2
View File
@@ -1,8 +1,7 @@
'use client';
import { cn } from "@stackframe/stack-ui";
// NEXT_LINE_PLATFORM next
import NextLink from 'next/link';
import NextLink from 'next/link'; // THIS_LINE_PLATFORM next
type LinkProps = {
href: string,
+1 -2
View File
@@ -1,5 +1,4 @@
// NEXT_LINE_PLATFORM next
import { cookies as rscCookies, headers as rscHeaders } from '@stackframe/stack-sc/force-react-server';
import { cookies as rscCookies, headers as rscHeaders } from '@stackframe/stack-sc/force-react-server'; // THIS_LINE_PLATFORM next
import { isBrowserLike } from '@stackframe/stack-shared/dist/utils/env';
import { StackAssertionError } from '@stackframe/stack-shared/dist/utils/errors';
import Cookies from "js-cookie";
@@ -7,8 +7,7 @@ import { InternalProjectsCrud } from "@stackframe/stack-shared/dist/interface/cr
import { StackAssertionError, throwErr } from "@stackframe/stack-shared/dist/utils/errors";
import { pick } from "@stackframe/stack-shared/dist/utils/objects";
import { Result } from "@stackframe/stack-shared/dist/utils/results";
// NEXT_LINE_PLATFORM react-like
import { useMemo } from "react";
import { useMemo } from "react"; // THIS_LINE_PLATFORM react-like
import { ApiKey, ApiKeyBase, ApiKeyBaseCrudRead, ApiKeyCreateOptions, ApiKeyFirstView, apiKeyCreateOptionsToCrud } from "../../api-keys";
import { EmailConfig, stackAppInternalsSymbol } from "../../common";
import { AdminEmailTemplate, AdminEmailTemplateUpdateOptions, adminEmailTemplateUpdateOptionsToCrud } from "../../email-templates";
@@ -16,10 +15,10 @@ import { AdminTeamPermission, AdminTeamPermissionDefinition, AdminTeamPermission
import { AdminOwnedProject, AdminProject, AdminProjectUpdateOptions, adminProjectUpdateOptionsToCrud } from "../../projects";
import { StackAdminApp, StackAdminAppConstructorOptions } from "../interfaces/admin-app";
import { clientVersion, createCache, getBaseUrl, getDefaultProjectId, getDefaultPublishableClientKey, getDefaultSecretServerKey, getDefaultSuperSecretAdminKey } from "./common";
// NEXT_LINE_PLATFORM react-like
import { useAsyncCache } from "./common";
import { _StackServerAppImplIncomplete } from "./server-app-impl";
import { useAsyncCache } from "./common"; // THIS_LINE_PLATFORM react-like
export class _StackAdminAppImplIncomplete<HasTokenStore extends boolean, ProjectId extends string> extends _StackServerAppImplIncomplete<HasTokenStore, ProjectId>
{
@@ -24,10 +24,8 @@ import { deindent, mergeScopeStrings } from "@stackframe/stack-shared/dist/utils
import { getRelativePart, isRelative } from "@stackframe/stack-shared/dist/utils/urls";
import { generateUuid } from "@stackframe/stack-shared/dist/utils/uuids";
import * as cookie from "cookie";
// NEXT_LINE_PLATFORM next
import * as NextNavigationUnscrambled from "next/navigation"; // import the entire module to get around some static compiler warnings emitted by Next.js in some cases
// NEXT_LINE_PLATFORM react-like
import React, { useCallback, useMemo } from "react";
import * as NextNavigationUnscrambled from "next/navigation"; // import the entire module to get around some static compiler warnings emitted by Next.js in some cases | THIS_LINE_PLATFORM next
import React, { useCallback, useMemo } from "react"; // THIS_LINE_PLATFORM react-like
import { constructRedirectUrl } from "../../../../utils/url";
import { addNewOAuthProviderOrScope, callOAuthCallback, signInWithOAuth } from "../../../auth";
import { CookieHelper, createBrowserCookieHelper, createCookieHelper, createPlaceholderCookieHelper, deleteCookieClient, getCookieClient, setOrDeleteCookie, setOrDeleteCookieClient } from "../../../cookie";
@@ -41,8 +39,8 @@ import { ActiveSession, Auth, BaseUser, CurrentUser, InternalUserExtra, ProjectC
import { StackClientApp, StackClientAppConstructorOptions, StackClientAppJson } from "../interfaces/client-app";
import { _StackAdminAppImplIncomplete } from "./admin-app-impl";
import { TokenObject, clientVersion, createCache, createCacheBySession, createEmptyTokenStore, getBaseUrl, getDefaultProjectId, getDefaultPublishableClientKey, getUrls } from "./common";
// NEXT_LINE_PLATFORM react-like
import { useAsyncCache } from "./common";
import { useAsyncCache } from "./common"; // THIS_LINE_PLATFORM react-like
let isReactServer = false;
// IF_PLATFORM next
@@ -55,8 +53,7 @@ const NextNavigation = scrambleDuringCompileTime(NextNavigationUnscrambled);
// END_PLATFORM
// hack to make sure process is defined in non-node environments
// NEXT_LINE_PLATFORM js react
const process = (globalThis as any).process ?? { env: {} };
const process = (globalThis as any).process ?? { env: {} }; // THIS_LINE_PLATFORM js react
const allClientApps = new Map<string, [checkString: string, app: StackClientApp<any, any>]>();
@@ -267,16 +264,14 @@ export class _StackClientAppImplIncomplete<HasTokenStore extends boolean, Projec
clientVersion,
publishableClientKey: _options.publishableClientKey ?? getDefaultPublishableClientKey(),
prepareRequest: async () => {
// NEXT_LINE_PLATFORM next
await cookies?.();
await cookies?.(); // THIS_LINE_PLATFORM next
}
});
}
this._tokenStoreInit = _options.tokenStore;
this._redirectMethod = _options.redirectMethod || "none";
// NEXT_LINE_PLATFORM next
this._redirectMethod = _options.redirectMethod || "nextjs";
this._redirectMethod = _options.redirectMethod || "nextjs"; // THIS_LINE_PLATFORM next
this._urlOptions = _options.urls ?? {};
this._oauthScopesOnSignIn = _options.oauthScopesOnSignIn ?? {};
@@ -832,8 +827,7 @@ export class _StackClientAppImplIncomplete<HasTokenStore extends boolean, Projec
await this.update({ selectedTeamId: team?.id ?? null });
},
getConnectedAccount,
// NEXT_LINE_PLATFORM react-like
useConnectedAccount,
useConnectedAccount, // THIS_LINE_PLATFORM react-like
async getTeam(teamId: string) {
const teams = await this.listTeams();
return teams.find((t) => t.id === teamId) ?? null;
@@ -7,13 +7,11 @@ import { ReactPromise } from "@stackframe/stack-shared/dist/utils/promises";
import { suspendIfSsr } from "@stackframe/stack-shared/dist/utils/react";
import { Result } from "@stackframe/stack-shared/dist/utils/results";
import { Store } from "@stackframe/stack-shared/dist/utils/stores";
import React, { useCallback } from "react"; // THIS_LINE_PLATFORM react-like
import { HandlerUrls } from "../../common";
// NEXT_LINE_PLATFORM react-like
import React, { useCallback } from "react";
// hack to make sure process is defined in non-node environments
// NEXT_LINE_PLATFORM js react
const process = (globalThis as any).process ?? { env: {} };
const process = (globalThis as any).process ?? { env: {} }; // THIS_LINE_PLATFORM js react
export const clientVersion = "STACK_COMPILE_TIME_CLIENT_PACKAGE_VERSION_SENTINEL";
if (clientVersion.startsWith("STACK_COMPILE_TIME")) {
@@ -11,8 +11,7 @@ import { ProviderType } from "@stackframe/stack-shared/dist/utils/oauth";
import { runAsynchronously } from "@stackframe/stack-shared/dist/utils/promises";
import { suspend } from "@stackframe/stack-shared/dist/utils/react";
import { Result } from "@stackframe/stack-shared/dist/utils/results";
// NEXT_LINE_PLATFORM react-like
import { useMemo } from "react";
import { useMemo } from "react"; // THIS_LINE_PLATFORM react-like
import { constructRedirectUrl } from "../../../../utils/url";
import { GetUserOptions, HandlerUrls, OAuthScopesOnSignIn, TokenStoreInit } from "../../common";
import { OAuthConnection } from "../../connected-accounts";
@@ -23,8 +22,8 @@ import { ProjectCurrentServerUser, ServerUser, ServerUserCreateOptions, ServerUs
import { StackServerAppConstructorOptions } from "../interfaces/server-app";
import { _StackClientAppImplIncomplete } from "./client-app-impl";
import { clientVersion, createCache, createCacheBySession, getBaseUrl, getDefaultProjectId, getDefaultPublishableClientKey, getDefaultSecretServerKey } from "./common";
// NEXT_LINE_PLATFORM react-like
import { useAsyncCache } from "./common";
import { useAsyncCache } from "./common"; // THIS_LINE_PLATFORM react-like
export class _StackServerAppImplIncomplete<HasTokenStore extends boolean, ProjectId extends string> extends _StackClientAppImplIncomplete<HasTokenStore, ProjectId>
@@ -269,8 +268,7 @@ export class _StackServerAppImplIncomplete<HasTokenStore extends boolean, Projec
return await this.update({ selectedTeamId: team?.id ?? null });
},
getConnectedAccount,
// NEXT_LINE_PLATFORM react-like
useConnectedAccount,
useConnectedAccount, // THIS_LINE_PLATFORM react-like
selectedTeam: crud.selected_team ? app._serverTeamFromCrud(crud.selected_team) : null,
async getTeam(teamId: string) {
const teams = await this.listTeams();
@@ -31,8 +31,7 @@ export type StackAdminApp<HasTokenStore extends boolean = boolean, ProjectId ext
& AsyncStoreProperty<"apiKeys", [], ApiKey[], true>
& AsyncStoreProperty<"teamPermissionDefinitions", [], AdminTeamPermissionDefinition[], true>
& {
// NEXT_LINE_PLATFORM react-like
useEmailTemplates(): AdminEmailTemplate[],
useEmailTemplates(): AdminEmailTemplate[], // THIS_LINE_PLATFORM react-like
listEmailTemplates(): Promise<AdminEmailTemplate[]>,
updateEmailTemplate(type: EmailTemplateType, data: AdminEmailTemplateUpdateOptions): Promise<void>,
resetEmailTemplate(type: EmailTemplateType): Promise<void>,
@@ -43,8 +42,7 @@ export type StackAdminApp<HasTokenStore extends boolean = boolean, ProjectId ext
updateTeamPermissionDefinition(permissionId: string, data: AdminTeamPermissionDefinitionUpdateOptions): Promise<void>,
deleteTeamPermissionDefinition(permissionId: string): Promise<void>,
// NEXT_LINE_PLATFORM react-like
useSvixToken(): string,
useSvixToken(): string, // THIS_LINE_PLATFORM react-like
sendTestEmail(options: {
recipientEmail: string,
@@ -63,8 +63,7 @@ export type StackClientApp<HasTokenStore extends boolean = boolean, ProjectId ex
getUser(options: GetUserOptions<HasTokenStore> & { or: 'throw' }): Promise<ProjectCurrentUser<ProjectId>>,
getUser(options?: GetUserOptions<HasTokenStore>): Promise<ProjectCurrentUser<ProjectId> | null>,
// NEXT_LINE_PLATFORM react-like
useNavigate(): (to: string) => void,
useNavigate(): (to: string) => void, // THIS_LINE_PLATFORM react-like
[stackAppInternalsSymbol]: {
toClientJson(): StackClientAppJson<HasTokenStore, ProjectId>,
@@ -29,8 +29,7 @@ export type StackServerApp<HasTokenStore extends boolean = boolean, ProjectId ex
getUser(options: GetUserOptions<HasTokenStore> & { or: 'throw' }): Promise<ProjectCurrentServerUser<ProjectId>>,
getUser(options?: GetUserOptions<HasTokenStore>): Promise<ProjectCurrentServerUser<ProjectId> | null>,
// NEXT_LINE_PLATFORM react-like
useUsers(options?: ServerListUsersOptions): ServerUser[] & { nextCursor: string | null },
useUsers(options?: ServerListUsersOptions): ServerUser[] & { nextCursor: string | null }, // THIS_LINE_PLATFORM react-like
listUsers(options?: ServerListUsersOptions): Promise<ServerUser[] & { nextCursor: string | null }>,
}
& AsyncStoreProperty<"user", [id: string], ServerUser | null, false>
@@ -7,8 +7,7 @@ export type RedirectToOptions = {
export type AsyncStoreProperty<Name extends string, Args extends any[], Value, IsMultiple extends boolean> =
& { [key in `${IsMultiple extends true ? "list" : "get"}${Capitalize<Name>}`]: (...args: Args) => Promise<Value> }
// NEXT_LINE_PLATFORM react-like
& { [key in `use${Capitalize<Name>}`]: (...args: Args) => Value }
& { [key in `use${Capitalize<Name>}`]: (...args: Args) => Value } // THIS_LINE_PLATFORM react-like
export type EmailConfig = {
host: string,
@@ -20,8 +19,7 @@ export type EmailConfig = {
}
export type RedirectMethod = "window"
// NEXT_LINE_PLATFORM next
| "nextjs"
| "nextjs" // THIS_LINE_PLATFORM next
| "none"
| {
useNavigate: () => (to: string) => void,
@@ -6,6 +6,5 @@ export type Connection = {
export type OAuthConnection = {
getAccessToken(): Promise<{ accessToken: string }>,
// NEXT_LINE_PLATFORM react-like
useAccessToken(): { accessToken: string },
useAccessToken(): { accessToken: string }, // THIS_LINE_PLATFORM react-like
} & Connection;
@@ -38,11 +38,9 @@ export type Team = {
clientReadOnlyMetadata: any,
inviteUser(options: { email: string, callbackUrl?: string }): Promise<void>,
listUsers(): Promise<TeamUser[]>,
// NEXT_LINE_PLATFORM react-like
useUsers(): TeamUser[],
useUsers(): TeamUser[], // THIS_LINE_PLATFORM react-like
listInvitations(): Promise<TeamInvitation[]>,
// NEXT_LINE_PLATFORM react-like
useInvitations(): TeamInvitation[],
useInvitations(): TeamInvitation[], // THIS_LINE_PLATFORM react-like
update(update: TeamUpdateOptions): Promise<void>,
delete(): Promise<void>,
};
@@ -83,8 +81,7 @@ export type ServerTeam = {
createdAt: Date,
serverMetadata: any,
listUsers(): Promise<ServerTeamUser[]>,
// NEXT_LINE_PLATFORM react-like
useUsers(): ServerUser[],
useUsers(): ServerUser[], // THIS_LINE_PLATFORM react-like
update(update: ServerTeamUpdateOptions): Promise<void>,
delete(): Promise<void>,
addUser(userId: string): Promise<void>,
@@ -172,8 +172,7 @@ export type UserExtra = {
*/
update(update: UserUpdateOptions): Promise<void>,
// NEXT_LINE_PLATFORM react-like
useContactChannels(): ContactChannel[],
useContactChannels(): ContactChannel[], // THIS_LINE_PLATFORM react-like
listContactChannels(): Promise<ContactChannel[]>,
createContactChannel(data: ContactChannelCreateOptions): Promise<ContactChannel>,
@@ -197,8 +196,7 @@ export type UserExtra = {
getActiveSessions(): Promise<ActiveSession[]>,
revokeSession(sessionId: string): Promise<void>,
getTeamProfile(team: Team): Promise<EditableTeamMemberProfile>,
// NEXT_LINE_PLATFORM react-like
useTeamProfile(team: Team): EditableTeamMemberProfile,
useTeamProfile(team: Team): EditableTeamMemberProfile, // THIS_LINE_PLATFORM react-like
}
& AsyncStoreProperty<"team", [id: string], Team | null, false>
& AsyncStoreProperty<"teams", [], Team[], true>
@@ -263,8 +261,7 @@ export type ServerBaseUser = {
createTeam(data: Omit<ServerTeamCreateOptions, "creatorUserId">): Promise<ServerTeam>,
// NEXT_LINE_PLATFORM react-like
useContactChannels(): ServerContactChannel[],
useContactChannels(): ServerContactChannel[], // THIS_LINE_PLATFORM react-like
listContactChannels(): Promise<ServerContactChannel[]>,
createContactChannel(data: ServerContactChannelCreateOptions): Promise<ServerContactChannel>,
+1 -2
View File
@@ -1,5 +1,4 @@
// NEXT_LINE_PLATFORM next
import "client-only";
import "client-only"; // THIS_LINE_PLATFORM next
import React from "react";
import { TranslationContext } from "../providers/translation-provider-client";
-2
View File
@@ -65,8 +65,6 @@ function processDocObject(obj: any, platforms: string[]): { result: any, validPa
}
}
withGeneratorLock(async () => {
const docsDir = path.resolve(__dirname, "..", "docs", "fern");
const templateDir = path.join(docsDir, "docs", "pages-template");
+21 -6
View File
@@ -139,18 +139,20 @@ export function processMacros(content: string, platforms: string[]): string {
* - ELSE_PLATFORM
* - END_PLATFORM
* - NEXT_LINE_PLATFORM
* - THIS_LINE_PLATFORM
*
* And then capture everything after that keyword up to the end of the line.
*
* Examples:
* "blah blah IF_PLATFORM platform1 platform2 ???" => captures "platform platform2 ???"
* "blah blah IF_PLATFORM platform1 platform2 ???" => captures "platform1 platform2 ???"
* "adsfasdf ELSE_PLATFORM blabla" => captures "blabla"
*/
const reBeginOnly = /\bIF_PLATFORM:?\s+(.+)/i;
const reElseIf = /\bELSE_IF_PLATFORM:?\s+(.+)/i;
const reElse = /\bELSE_PLATFORM\b/i;
const reEndOnly = /\bEND_PLATFORM\b/i;
const reNextLine = /\bNEXT_LINE_PLATFORM:?\s+(.+)/i;
const reBeginOnly = /\bIF_PLATFORM:?\s+(.+)/i;
const reElseIf = /\bELSE_IF_PLATFORM:?\s+(.+)/i;
const reElse = /\bELSE_PLATFORM\b/i;
const reEndOnly = /\bEND_PLATFORM\b/i;
const reNextLine = /\bNEXT_LINE_PLATFORM:?\s+(.+)/i;
const reThisLine = /\bTHIS_LINE_PLATFORM:?\s+(.+)/i; // New regex
for (const line of lines) {
// 1) Try detecting IF_PLATFORM ...
@@ -259,6 +261,19 @@ export function processMacros(content: string, platforms: string[]): string {
continue;
}
// 6) Try detecting THIS_LINE_PLATFORM ... (new behavior)
const thisLineMatch = line.match(reThisLine);
if (thisLineMatch) {
const platformList = parsePlatformList(thisLineMatch[1]);
const matched = platformList.some((e) => platforms.includes(e));
if (matched) {
// Output the line unchanged (including the directive itself)
result.push(line);
}
// Whether matched or not, skip further processing of this line
continue;
}
// If it's a normal line:
if (shouldOutputLine()) {
result.push(line);