@wasp.sh/wasp-cli-darwin-arm64-unknown 0.20.2 → 0.21.0-rc.1
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/data/Cli/starters/basic/README.md +1 -1
- package/data/Cli/starters/basic/package.json +10 -7
- package/data/Cli/starters/basic/src/App.css +30 -12
- package/data/Cli/starters/basic/src/App.tsx +1 -1
- package/data/Cli/starters/basic/src/auth/AuthLayout.tsx +3 -1
- package/data/Cli/starters/basic/src/auth/email/EmailVerificationPage.tsx +2 -2
- package/data/Cli/starters/basic/src/auth/email/LoginPage.tsx +3 -3
- package/data/Cli/starters/basic/src/auth/email/PasswordResetPage.tsx +2 -2
- package/data/Cli/starters/basic/src/auth/email/SignupPage.tsx +2 -2
- package/data/Cli/starters/basic/src/shared/components/Button.tsx +3 -2
- package/data/Cli/starters/basic/src/shared/components/Dialog.tsx +23 -41
- package/data/Cli/starters/basic/src/shared/components/Header.tsx +2 -2
- package/data/Cli/starters/basic/src/shared/components/Input.tsx +25 -28
- package/data/Cli/starters/basic/src/tags/components/ColorRadioButton.tsx +8 -9
- package/data/Cli/starters/basic/src/tags/components/CreateTagDialog.tsx +29 -29
- package/data/Cli/starters/basic/src/tags/components/CreateTagForm.tsx +6 -8
- package/data/Cli/starters/basic/src/tasks/components/CreateTaskForm.tsx +2 -2
- package/data/Cli/starters/basic/src/tasks/components/TaskListItem.tsx +3 -2
- package/data/Cli/starters/basic/vite.config.ts +3 -0
- package/data/Cli/starters/minimal/package.json +2 -3
- package/data/Cli/starters/minimal/vite.config.ts +2 -0
- package/data/Cli/starters/skeleton/src/vite-env.d.ts +2 -6
- package/data/Generator/libs/auth/wasp.sh-lib-auth-0.21.0.tgz +0 -0
- package/data/Generator/templates/Dockerfile +13 -12
- package/data/Generator/templates/sdk/wasp/auth/forms/Auth.tsx +2 -11
- package/data/Generator/templates/sdk/wasp/auth/forms/internal/common/LoginSignupForm.tsx +10 -4
- package/data/Generator/templates/sdk/wasp/auth/forms/internal/email/ForgotPasswordForm.tsx +4 -3
- package/data/Generator/templates/sdk/wasp/auth/forms/internal/email/ResetPasswordForm.tsx +4 -4
- package/data/Generator/templates/sdk/wasp/auth/forms/internal/email/VerifyEmailForm.tsx +3 -4
- package/data/Generator/templates/sdk/wasp/auth/forms/internal/social/SocialIcons.tsx +11 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/types.ts +0 -6
- package/data/Generator/templates/sdk/wasp/auth/jwt.ts +9 -16
- package/data/Generator/templates/sdk/wasp/auth/password.ts +1 -36
- package/data/Generator/templates/sdk/wasp/auth/utils.ts +2 -0
- package/data/Generator/templates/{react-app/src → sdk/wasp/client/app}/components/DefaultRootErrorBoundary.tsx +1 -1
- package/data/Generator/templates/sdk/wasp/client/app/components/WaspApp.tsx +45 -0
- package/data/Generator/templates/sdk/wasp/client/app/index.tsx +26 -0
- package/data/Generator/templates/{react-app/src/auth → sdk/wasp/client/app}/pages/OAuthCallback.tsx +9 -8
- package/data/Generator/templates/{react-app/src/auth → sdk/wasp/client/app}/pages/createAuthRequiredPage.jsx +7 -9
- package/data/Generator/templates/sdk/wasp/client/app/router/router.tsx +47 -0
- package/data/Generator/templates/sdk/wasp/client/auth/index.ts +3 -0
- package/data/Generator/templates/sdk/wasp/client/auth/microsoft.ts +2 -0
- package/data/Generator/templates/sdk/wasp/client/auth/ui.ts +3 -0
- package/data/Generator/templates/sdk/wasp/client/router/Link.tsx +2 -2
- package/data/Generator/templates/sdk/wasp/client/test/vitest/helpers.tsx +10 -12
- package/data/Generator/templates/sdk/wasp/client/vite/index.ts +1 -0
- package/data/Generator/templates/sdk/wasp/client/vite/plugins/detectServerImports.ts +50 -0
- package/data/Generator/templates/sdk/wasp/client/vite/plugins/envFile.ts +112 -0
- package/data/Generator/templates/sdk/wasp/client/vite/plugins/html/build.ts +38 -0
- package/data/Generator/templates/sdk/wasp/client/vite/plugins/html/dev.ts +35 -0
- package/data/Generator/templates/sdk/wasp/client/vite/plugins/typescriptCheck.ts +32 -0
- package/data/Generator/templates/{react-app/vite → sdk/wasp/client/vite/plugins}/validateEnv.ts +17 -7
- package/data/Generator/templates/sdk/wasp/client/vite/plugins/virtualModules.ts +29 -0
- package/data/Generator/templates/sdk/wasp/client/vite/plugins/wasp.ts +36 -0
- package/data/Generator/templates/sdk/wasp/client/vite/plugins/waspConfig.ts +56 -0
- package/data/Generator/templates/{react-app → sdk/wasp/client/vite/virtual-files/files}/index.html +1 -2
- package/data/Generator/templates/sdk/wasp/client/vite/virtual-files/files/index.tsx +34 -0
- package/data/Generator/templates/sdk/wasp/client/vite/virtual-files/files/routes.tsx +17 -0
- package/data/Generator/templates/sdk/wasp/client/vite/virtual-files/index.ts +20 -0
- package/data/Generator/templates/sdk/wasp/client/vite/virtual-files/resolver.ts +28 -0
- package/data/Generator/templates/sdk/wasp/package.json +6 -4
- package/data/Generator/templates/sdk/wasp/scripts/copy-assets.js +67 -7
- package/data/Generator/templates/sdk/wasp/server/auth/hooks.ts +3 -0
- package/data/Generator/templates/sdk/wasp/server/auth/oauth/index.ts +4 -0
- package/data/Generator/templates/sdk/wasp/server/auth/oauth/providers/microsoft.ts +23 -0
- package/data/Generator/templates/sdk/wasp/server/auth/user.ts +6 -0
- package/data/Generator/templates/sdk/wasp/server/env.ts +11 -0
- package/data/Generator/templates/sdk/wasp/tsconfig.json +5 -1
- package/data/Generator/templates/server/src/auth/providers/config/microsoft.ts +65 -0
- package/data/Generator/templates/server/src/auth/providers/oauth/cookies.ts +1 -1
- package/data/packages/deploy/dist/common/clientApp.js +4 -11
- package/data/packages/deploy/dist/common/terminal.js +7 -0
- package/data/packages/deploy/dist/common/waspProject.js +11 -7
- package/data/packages/deploy/dist/providers/fly/CommonOps.js +3 -3
- package/data/packages/deploy/dist/providers/fly/commands/cmd/cmd.js +1 -1
- package/data/packages/deploy/dist/providers/fly/commands/deploy/deploy.js +6 -5
- package/data/packages/deploy/dist/providers/fly/commands/setup/setup.js +3 -3
- package/data/packages/deploy/dist/providers/fly/index.js +5 -0
- package/data/packages/deploy/dist/providers/railway/commands/deploy/client.js +2 -1
- package/data/packages/deploy/dist/providers/railway/commands/setup/setup.js +21 -10
- package/data/packages/deploy/dist/providers/railway/index.js +5 -0
- package/data/packages/deploy/dist/providers/railway/jsonOutputSchemas.js +9 -3
- package/data/packages/deploy/dist/providers/railway/railwayService/url.js +8 -1
- package/data/packages/studio/dist/public/assets/Flow-_d98T2dd.js +26 -0
- package/data/packages/studio/dist/public/assets/index-B6X8EdJH.js +21 -0
- package/data/packages/studio/dist/public/assets/index-CXlD_bzV.js +1 -0
- package/data/packages/studio/dist/public/assets/index-IWX3d-Jz.css +1 -0
- package/data/packages/studio/dist/public/index.html +2 -3
- package/package.json +1 -1
- package/wasp-bin +0 -0
- package/data/Cli/starters/basic/postcss.config.js +0 -6
- package/data/Cli/starters/basic/src/shared/components/Portal.tsx +0 -26
- package/data/Cli/starters/basic/tailwind.config.js +0 -30
- package/data/Generator/templates/react-app/README.md +0 -21
- package/data/Generator/templates/react-app/gitignore +0 -23
- package/data/Generator/templates/react-app/netlify.toml +0 -8
- package/data/Generator/templates/react-app/npmrc +0 -1
- package/data/Generator/templates/react-app/package.json +0 -31
- package/data/Generator/templates/react-app/public/manifest.json +0 -15
- package/data/Generator/templates/react-app/src/index.tsx +0 -47
- package/data/Generator/templates/react-app/src/logo.png +0 -0
- package/data/Generator/templates/react-app/src/router.tsx +0 -59
- package/data/Generator/templates/react-app/src/utils.js +0 -3
- package/data/Generator/templates/react-app/src/vite-env.d.ts +0 -1
- package/data/Generator/templates/react-app/tsconfig.app.json +0 -28
- package/data/Generator/templates/react-app/tsconfig.json +0 -11
- package/data/Generator/templates/react-app/tsconfig.vite.json +0 -16
- package/data/Generator/templates/react-app/vite/detectServerImports.ts +0 -53
- package/data/Generator/templates/react-app/vite.config.ts +0 -74
- package/data/Generator/templates/sdk/wasp/dev/index.ts +0 -19
- package/data/packages/studio/dist/public/assets/Flow-b5112d3d.js +0 -26
- package/data/packages/studio/dist/public/assets/index-17ce6ed4.css +0 -1
- package/data/packages/studio/dist/public/assets/index-62a9d21a.js +0 -120
- /package/data/Generator/templates/{react-app/src → sdk/wasp/client/app}/components/FullPageWrapper.tsx +0 -0
- /package/data/Generator/templates/{react-app/src → sdk/wasp/client/app}/components/Loader.module.css +0 -0
- /package/data/Generator/templates/{react-app/src → sdk/wasp/client/app}/components/Loader.tsx +0 -0
- /package/data/Generator/templates/{react-app/src → sdk/wasp/client/app}/components/Message.tsx +0 -0
- /package/data/Generator/templates/{react-app/src/test/vitest → sdk/wasp/client/test}/setup.ts +0 -0
|
@@ -52,6 +52,9 @@ export type AuthUserData = Omit<CompleteUserEntityWithAuth, '{= authFieldOnUserE
|
|
|
52
52
|
{=# enabledProviders.isGitHubAuthEnabled =}
|
|
53
53
|
github: Expand<UserFacingProviderData<'github'>> | null
|
|
54
54
|
{=/ enabledProviders.isGitHubAuthEnabled =}
|
|
55
|
+
{=# enabledProviders.isMicrosoftAuthEnabled =}
|
|
56
|
+
microsoft: Expand<UserFacingProviderData<'microsoft'>> | null
|
|
57
|
+
{=/ enabledProviders.isMicrosoftAuthEnabled =}
|
|
55
58
|
},
|
|
56
59
|
}
|
|
57
60
|
|
|
@@ -117,6 +120,9 @@ This should never happen, but it did which means there is a bug in the code.`)
|
|
|
117
120
|
{=# enabledProviders.isGitHubAuthEnabled =}
|
|
118
121
|
github: getProviderInfo<'github'>({= authFieldOnUserEntityName =}, 'github'),
|
|
119
122
|
{=/ enabledProviders.isGitHubAuthEnabled =}
|
|
123
|
+
{=# enabledProviders.isMicrosoftAuthEnabled =}
|
|
124
|
+
microsoft: getProviderInfo<'microsoft'>({= authFieldOnUserEntityName =}, 'microsoft'),
|
|
125
|
+
{=/ enabledProviders.isMicrosoftAuthEnabled =}
|
|
120
126
|
}
|
|
121
127
|
return {
|
|
122
128
|
...rest,
|
|
@@ -102,6 +102,17 @@ const waspServerCommonSchema = z.object({
|
|
|
102
102
|
message: 'KEYCLOAK_REALM_URL must be a valid URL',
|
|
103
103
|
}),
|
|
104
104
|
{=/ enabledAuthProviders.isKeycloakAuthEnabled =}
|
|
105
|
+
{=# enabledAuthProviders.isMicrosoftAuthEnabled =}
|
|
106
|
+
MICROSOFT_TENANT_ID: z.string({
|
|
107
|
+
required_error: getRequiredEnvVarErrorMessage('Microsoft auth provider', 'MICROSOFT_TENANT_ID'),
|
|
108
|
+
}),
|
|
109
|
+
MICROSOFT_CLIENT_ID: z.string({
|
|
110
|
+
required_error: getRequiredEnvVarErrorMessage('Microsoft auth provider', 'MICROSOFT_CLIENT_ID'),
|
|
111
|
+
}),
|
|
112
|
+
MICROSOFT_CLIENT_SECRET: z.string({
|
|
113
|
+
required_error: getRequiredEnvVarErrorMessage('Microsoft auth provider', 'MICROSOFT_CLIENT_SECRET'),
|
|
114
|
+
}),
|
|
115
|
+
{=/ enabledAuthProviders.isMicrosoftAuthEnabled =}
|
|
105
116
|
{=/ isAuthEnabled =}
|
|
106
117
|
})
|
|
107
118
|
|
|
@@ -89,6 +89,10 @@
|
|
|
89
89
|
],
|
|
90
90
|
"exclude": [
|
|
91
91
|
"node_modules",
|
|
92
|
-
"dist"
|
|
92
|
+
"dist",
|
|
93
|
+
// Virtual modules don't belong in the SDK runtime, they are used by the
|
|
94
|
+
// web-app runtime via Vite virtual modules. That's why we don't want the
|
|
95
|
+
// SDK to compile them.
|
|
96
|
+
"client/vite/virtual-files/files",
|
|
93
97
|
]
|
|
94
98
|
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{{={= =}=}}
|
|
2
|
+
import type { ProviderConfig } from "wasp/auth/providers/types";
|
|
3
|
+
import { microsoft } from "wasp/server/auth";
|
|
4
|
+
|
|
5
|
+
import { mergeDefaultAndUserConfig } from "../oauth/config.js";
|
|
6
|
+
import { createOAuthProviderRouter } from "../oauth/handler.js";
|
|
7
|
+
|
|
8
|
+
{=# userSignupFields.isDefined =}
|
|
9
|
+
{=& userSignupFields.importStatement =}
|
|
10
|
+
const _waspUserSignupFields = {= userSignupFields.importIdentifier =}
|
|
11
|
+
{=/ userSignupFields.isDefined =}
|
|
12
|
+
{=^ userSignupFields.isDefined =}
|
|
13
|
+
const _waspUserSignupFields = undefined
|
|
14
|
+
{=/ userSignupFields.isDefined =}
|
|
15
|
+
{=# configFn.isDefined =}
|
|
16
|
+
{=& configFn.importStatement =}
|
|
17
|
+
const _waspUserDefinedConfigFn = {= configFn.importIdentifier =}
|
|
18
|
+
{=/ configFn.isDefined =}
|
|
19
|
+
{=^ configFn.isDefined =}
|
|
20
|
+
const _waspUserDefinedConfigFn = undefined
|
|
21
|
+
{=/ configFn.isDefined =}
|
|
22
|
+
|
|
23
|
+
const _waspConfig: ProviderConfig = {
|
|
24
|
+
id: microsoft.id,
|
|
25
|
+
displayName: microsoft.displayName,
|
|
26
|
+
createRouter(provider) {
|
|
27
|
+
const config = mergeDefaultAndUserConfig({
|
|
28
|
+
scopes: {=& requiredScopes =},
|
|
29
|
+
}, _waspUserDefinedConfigFn);
|
|
30
|
+
|
|
31
|
+
async function getMicrosoftProfile(accessToken: string): Promise<{
|
|
32
|
+
providerProfile: unknown;
|
|
33
|
+
providerUserId: string;
|
|
34
|
+
}> {
|
|
35
|
+
const response = await fetch(
|
|
36
|
+
"https://graph.microsoft.com/oidc/userinfo",
|
|
37
|
+
{
|
|
38
|
+
headers: {
|
|
39
|
+
Authorization: `Bearer ${accessToken}`,
|
|
40
|
+
},
|
|
41
|
+
}
|
|
42
|
+
);
|
|
43
|
+
const providerProfile = (await response.json()) as {
|
|
44
|
+
sub?: string;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
if (!providerProfile.sub) {
|
|
48
|
+
throw new Error("Invalid profile");
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return { providerProfile, providerUserId: providerProfile.sub };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return createOAuthProviderRouter({
|
|
55
|
+
provider,
|
|
56
|
+
oAuthType: 'OAuth2WithPKCE',
|
|
57
|
+
userSignupFields: _waspUserSignupFields,
|
|
58
|
+
getAuthorizationUrl: ({ state, codeVerifier }) => microsoft.oAuthClient.createAuthorizationURL(state, codeVerifier, config),
|
|
59
|
+
getProviderTokens: ({ code, codeVerifier }) => microsoft.oAuthClient.validateAuthorizationCode(code, codeVerifier),
|
|
60
|
+
getProviderInfo: ({ accessToken }) => getMicrosoftProfile(accessToken),
|
|
61
|
+
});
|
|
62
|
+
},
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export default _waspConfig;
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
Request as ExpressRequest,
|
|
3
3
|
Response as ExpressResponse,
|
|
4
4
|
} from 'express';
|
|
5
|
-
import { parseCookies } from '
|
|
5
|
+
import { parseCookies } from '@wasp.sh/lib-auth/node';
|
|
6
6
|
|
|
7
7
|
import type { ProviderConfig } from 'wasp/auth/providers/types';
|
|
8
8
|
import { config } from 'wasp/server';
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import { waspSays } from "./terminal.js";
|
|
2
2
|
import { getClientBuildArtefactsDir, getClientBuildDir, } from "./waspProject.js";
|
|
3
3
|
import { createCommandWithCwd } from "./zx.js";
|
|
4
|
-
|
|
5
|
-
export async function buildClient(
|
|
4
|
+
const serverUrlEnvVarName = "REACT_APP_API_URL";
|
|
5
|
+
export async function buildClient(serverUrl, { waspProjectDir }) {
|
|
6
6
|
waspSays("Building web client for production...");
|
|
7
|
-
waspSays(`If you configured a custom domain for the server, you should run the command with an env variable: ${serverUrlEnvVarName}=https://serverUrl.com <command>`);
|
|
8
7
|
const clientBuildDir = getClientBuildDir(waspProjectDir);
|
|
9
8
|
const npmCli = createCommandWithCwd("npm", clientBuildDir);
|
|
9
|
+
const npxCli = createCommandWithCwd("npx", clientBuildDir);
|
|
10
10
|
await npmCli(["install"]);
|
|
11
|
-
|
|
12
|
-
await npmCli(["run", "build"], {
|
|
11
|
+
await npxCli(["vite", "build"], {
|
|
13
12
|
env: {
|
|
14
13
|
...process.env,
|
|
15
14
|
[serverUrlEnvVarName]: serverUrl,
|
|
@@ -17,10 +16,4 @@ export async function buildClient(defaultServerAppUrl, { waspProjectDir }) {
|
|
|
17
16
|
});
|
|
18
17
|
return getClientBuildArtefactsDir(waspProjectDir);
|
|
19
18
|
}
|
|
20
|
-
// We allow users to specify the server URL that the client will connect to
|
|
21
|
-
// using an environment variable.
|
|
22
|
-
// TODO: improve this API to allow specifying the server URL via options or a config file.
|
|
23
|
-
function getServerAppUrlEnvValue() {
|
|
24
|
-
return process.env[serverUrlEnvVarName];
|
|
25
|
-
}
|
|
26
19
|
//# sourceMappingURL=clientApp.js.map
|
|
@@ -6,6 +6,13 @@ export function waspSays(str) {
|
|
|
6
6
|
.join("\n");
|
|
7
7
|
console.log(chalk.yellow(formattedStr));
|
|
8
8
|
}
|
|
9
|
+
export function waspInfo(str) {
|
|
10
|
+
const formattedStr = str
|
|
11
|
+
.split("\n")
|
|
12
|
+
.map((line) => `👉 ${line}`)
|
|
13
|
+
.join("\n");
|
|
14
|
+
console.log(chalk.blue(formattedStr));
|
|
15
|
+
}
|
|
9
16
|
export function displayWaspRocketImage() {
|
|
10
17
|
// Escaping backslashes makes it look weird here, but it works in console.
|
|
11
18
|
const asciiArt = `
|
|
@@ -24,20 +24,24 @@ export function buildDirExists(waspProjectDir) {
|
|
|
24
24
|
return fs.existsSync(getWaspBuildDir(waspProjectDir));
|
|
25
25
|
}
|
|
26
26
|
export function getServerBuildArtefactsDir(waspProjectDir) {
|
|
27
|
-
return
|
|
27
|
+
return getServerDeploymentDir(waspProjectDir);
|
|
28
28
|
}
|
|
29
29
|
export function getClientBuildArtefactsDir(waspProjectDir) {
|
|
30
|
-
|
|
31
|
-
return path.join(clientBuildDir, "build");
|
|
30
|
+
return path.join(getClientDeploymentDir(waspProjectDir), "build");
|
|
32
31
|
}
|
|
33
32
|
function getWaspBuildDir(waspProjectDir) {
|
|
34
|
-
return path.join(waspProjectDir, ".wasp", "
|
|
33
|
+
return path.join(waspProjectDir, ".wasp", "out");
|
|
35
34
|
}
|
|
36
|
-
export function
|
|
37
|
-
// The server is built from the Wasp
|
|
35
|
+
export function getServerDeploymentDir(waspProjectDir) {
|
|
36
|
+
// The server is built from the Wasp out directory.
|
|
38
37
|
return path.join(getWaspBuildDir(waspProjectDir), ".");
|
|
39
38
|
}
|
|
40
|
-
export function
|
|
39
|
+
export function getClientDeploymentDir(waspProjectDir) {
|
|
40
|
+
// The client is deployed from the `.out/web-app` dir.
|
|
41
41
|
return path.join(getWaspBuildDir(waspProjectDir), "web-app");
|
|
42
42
|
}
|
|
43
|
+
export function getClientBuildDir(waspProjectDir) {
|
|
44
|
+
// The client is built from the project root dir.
|
|
45
|
+
return path.join(waspProjectDir, ".");
|
|
46
|
+
}
|
|
43
47
|
//# sourceMappingURL=waspProject.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { cd } from "zx";
|
|
2
|
-
import {
|
|
2
|
+
import { getClientDeploymentDir, getServerDeploymentDir, } from "../../common/waspProject.js";
|
|
3
3
|
import { clientTomlExistsInProject, copyLocalClientTomlToProject, copyLocalServerTomlToProject, copyProjectClientTomlLocally, copyProjectServerTomlLocally, serverTomlExistsInProject, } from "./tomlFile.js";
|
|
4
4
|
export var ContextOption;
|
|
5
5
|
(function (ContextOption) {
|
|
@@ -17,7 +17,7 @@ function createClientCommonOps(waspProjectDir, paths) {
|
|
|
17
17
|
return {
|
|
18
18
|
waspProjectDir,
|
|
19
19
|
paths,
|
|
20
|
-
|
|
20
|
+
cdToDeploymentDir: () => cd(getClientDeploymentDir(waspProjectDir)),
|
|
21
21
|
tomlExistsInProject: () => clientTomlExistsInProject(paths),
|
|
22
22
|
copyLocalTomlToProject: () => copyLocalClientTomlToProject(paths),
|
|
23
23
|
copyProjectTomlLocally: () => copyProjectClientTomlLocally(paths),
|
|
@@ -27,7 +27,7 @@ function createServerCommonOps(waspProjectDir, paths) {
|
|
|
27
27
|
return {
|
|
28
28
|
waspProjectDir,
|
|
29
29
|
paths,
|
|
30
|
-
|
|
30
|
+
cdToDeploymentDir: () => cd(getServerDeploymentDir(waspProjectDir)),
|
|
31
31
|
tomlExistsInProject: () => serverTomlExistsInProject(paths),
|
|
32
32
|
copyLocalTomlToProject: () => copyLocalServerTomlToProject(paths),
|
|
33
33
|
copyProjectTomlLocally: () => copyProjectServerTomlLocally(paths),
|
|
@@ -16,7 +16,7 @@ export async function cmd(flyctlArgs, cmdOptions) {
|
|
|
16
16
|
await runFlyctlCommand(commonOps, flyctlArgs);
|
|
17
17
|
}
|
|
18
18
|
async function runFlyctlCommand(commonOps, flyctlArgs) {
|
|
19
|
-
commonOps.
|
|
19
|
+
commonOps.cdToDeploymentDir();
|
|
20
20
|
deleteLocalToml();
|
|
21
21
|
if (commonOps.tomlExistsInProject()) {
|
|
22
22
|
commonOps.copyProjectTomlLocally();
|
|
@@ -3,7 +3,7 @@ import { buildClient } from "../../../../common/clientApp.js";
|
|
|
3
3
|
import { getFullCommandName } from "../../../../common/commander.js";
|
|
4
4
|
import { displayWaspRocketImage, waspSays, } from "../../../../common/terminal.js";
|
|
5
5
|
import { ensureWaspProjectIsBuilt } from "../../../../common/waspBuild.js";
|
|
6
|
-
import {
|
|
6
|
+
import { getClientDeploymentDir, getServerDeploymentDir, } from "../../../../common/waspProject.js";
|
|
7
7
|
import { createDeploymentInstructions, } from "../../DeploymentInstructions.js";
|
|
8
8
|
import { getFlyAppUrl } from "../../flyAppUrl.js";
|
|
9
9
|
import { secretExists } from "../../flyCli.js";
|
|
@@ -48,7 +48,7 @@ export async function deploy(cmdOptions) {
|
|
|
48
48
|
}
|
|
49
49
|
async function deployServer(deploymentInstructions, { buildLocally }) {
|
|
50
50
|
waspSays("Deploying your server now...");
|
|
51
|
-
cd(
|
|
51
|
+
cd(getServerDeploymentDir(deploymentInstructions.cmdOptions.waspProjectDir));
|
|
52
52
|
copyProjectServerTomlLocally(deploymentInstructions.tomlFilePaths);
|
|
53
53
|
// Make sure we have a DATABASE_URL present. If not, they need to create/attach their DB first.
|
|
54
54
|
const databaseUrlSet = await secretExists("DATABASE_URL");
|
|
@@ -65,10 +65,11 @@ async function deployServer(deploymentInstructions, { buildLocally }) {
|
|
|
65
65
|
}
|
|
66
66
|
async function deployClient(deploymentInstructions, { buildLocally }) {
|
|
67
67
|
waspSays("Deploying your client now...");
|
|
68
|
-
cd(
|
|
68
|
+
cd(getClientDeploymentDir(deploymentInstructions.cmdOptions.waspProjectDir));
|
|
69
69
|
copyProjectClientTomlLocally(deploymentInstructions.tomlFilePaths);
|
|
70
|
-
const
|
|
71
|
-
|
|
70
|
+
const serverUrl = deploymentInstructions.cmdOptions.customServerUrl ??
|
|
71
|
+
getFlyAppUrl(deploymentInstructions.serverFlyAppName);
|
|
72
|
+
await buildClient(serverUrl, deploymentInstructions.cmdOptions);
|
|
72
73
|
// Creates the necessary Dockerfile for deploying static websites to Fly.io.
|
|
73
74
|
// Adds dummy .dockerignore to supress CLI question.
|
|
74
75
|
// Ref: https://fly.io/docs/languages-and-frameworks/static/
|
|
@@ -3,7 +3,7 @@ import { getFullCommandName } from "../../../../common/commander.js";
|
|
|
3
3
|
import { generateRandomHexString } from "../../../../common/random.js";
|
|
4
4
|
import { waspSays } from "../../../../common/terminal.js";
|
|
5
5
|
import { ensureWaspProjectIsBuilt } from "../../../../common/waspBuild.js";
|
|
6
|
-
import {
|
|
6
|
+
import { getClientDeploymentDir, getServerDeploymentDir, } from "../../../../common/waspProject.js";
|
|
7
7
|
import { createDeploymentInstructions, } from "../../DeploymentInstructions.js";
|
|
8
8
|
import { getFlyAppUrl } from "../../flyAppUrl.js";
|
|
9
9
|
import { createFlyDbCommand } from "../../index.js";
|
|
@@ -37,7 +37,7 @@ export async function setup(baseName, region, cmdOptions) {
|
|
|
37
37
|
}
|
|
38
38
|
async function setupServer(deploymentInstructions) {
|
|
39
39
|
waspSays(`Setting up server app with name ${deploymentInstructions.serverFlyAppName}`);
|
|
40
|
-
cd(
|
|
40
|
+
cd(getServerDeploymentDir(deploymentInstructions.cmdOptions.waspProjectDir));
|
|
41
41
|
deleteLocalToml();
|
|
42
42
|
const launchArgs = [
|
|
43
43
|
"--name",
|
|
@@ -104,7 +104,7 @@ Press any key to continue or Ctrl+C to cancel.`);
|
|
|
104
104
|
}
|
|
105
105
|
async function setupClient(deploymentInstructions) {
|
|
106
106
|
waspSays(`Setting up client app with name ${deploymentInstructions.clientFlyAppName}`);
|
|
107
|
-
cd(
|
|
107
|
+
cd(getClientDeploymentDir(deploymentInstructions.cmdOptions.waspProjectDir));
|
|
108
108
|
deleteLocalToml();
|
|
109
109
|
const launchArgs = [
|
|
110
110
|
"--name",
|
|
@@ -30,6 +30,9 @@ class FlyCommand extends Command {
|
|
|
30
30
|
}
|
|
31
31
|
return this.option("--server-secret <serverSecret>", "secret to set on the server app (of form FOO=BAR)", collect, []).option("--client-secret <clientSecret>", "secret to set on the client app (of form FOO=BAR)", collect, []);
|
|
32
32
|
}
|
|
33
|
+
addCustomServerUrlOption() {
|
|
34
|
+
return this.option("--custom-server-url <url>", "URL of the server that the client will connect to");
|
|
35
|
+
}
|
|
33
36
|
}
|
|
34
37
|
const flyLaunchCommand = makeFlyLaunchCommand();
|
|
35
38
|
export const flySetupCommand = makeFlySetupCommand();
|
|
@@ -83,6 +86,7 @@ function makeFlyLaunchCommand() {
|
|
|
83
86
|
.addDbOptions()
|
|
84
87
|
.addLocalBuildOption()
|
|
85
88
|
.addSecretsOptions()
|
|
89
|
+
.addCustomServerUrlOption()
|
|
86
90
|
.action(launchFn);
|
|
87
91
|
}
|
|
88
92
|
function makeFlySetupCommand() {
|
|
@@ -99,6 +103,7 @@ function makeFlyDeployCommand() {
|
|
|
99
103
|
.option("--skip-client", "do not deploy the web client")
|
|
100
104
|
.option("--skip-server", "do not deploy the server")
|
|
101
105
|
.addLocalBuildOption()
|
|
106
|
+
.addCustomServerUrlOption()
|
|
102
107
|
.action(deployFn);
|
|
103
108
|
}
|
|
104
109
|
function makeExecuteFlyCommand() {
|
|
@@ -5,7 +5,8 @@ import { generateServiceUrl } from "../../railwayService/url.js";
|
|
|
5
5
|
import { deployServiceWithStreamingLogs, ServiceDeploymentStatus, } from "./common.js";
|
|
6
6
|
export async function deployClient({ cmdOptions: options, serverServiceName, clientServiceName, }) {
|
|
7
7
|
waspSays("Deploying your client now...");
|
|
8
|
-
const serverServiceUrl =
|
|
8
|
+
const serverServiceUrl = options.customServerUrl ??
|
|
9
|
+
(await generateServiceUrl(serverServiceName, serverAppPort, options));
|
|
9
10
|
const clientBuildArtefactsDir = await buildClient(serverServiceUrl, options);
|
|
10
11
|
const deploymentStatus = await deployServiceWithStreamingLogs({
|
|
11
12
|
name: clientServiceName,
|
|
@@ -2,7 +2,7 @@ import { $ } from "zx";
|
|
|
2
2
|
import { generateRandomHexString } from "../../../../common/random.js";
|
|
3
3
|
import { waspSays } from "../../../../common/terminal.js";
|
|
4
4
|
import { ensureWaspProjectIsBuilt } from "../../../../common/waspBuild.js";
|
|
5
|
-
import {
|
|
5
|
+
import { getClientDeploymentDir, getServerDeploymentDir, } from "../../../../common/waspProject.js";
|
|
6
6
|
import { createCommandWithCwd } from "../../../../common/zx.js";
|
|
7
7
|
import { createDeploymentInstructions, } from "../../DeploymentInstructions.js";
|
|
8
8
|
import { clientAppPort, serverAppPort } from "../../ports.js";
|
|
@@ -104,12 +104,14 @@ async function setupServer({ cmdOptions: options, serverServiceName, clientServi
|
|
|
104
104
|
// The client service needs a URL so it can be referenced in the
|
|
105
105
|
// server service env variables.
|
|
106
106
|
await generateServiceUrl(clientServiceName, clientAppPort, options);
|
|
107
|
-
const
|
|
108
|
-
const railwayCli = createCommandWithCwd(options.railwayExe,
|
|
109
|
-
const clientUrl = `https://${getRailwayEnvVarValueReference(
|
|
107
|
+
const serverDeploymentDir = getServerDeploymentDir(options.waspProjectDir);
|
|
108
|
+
const railwayCli = createCommandWithCwd(options.railwayExe, serverDeploymentDir);
|
|
109
|
+
const clientUrl = `https://${getRailwayEnvVarValueReference("RAILWAY_PUBLIC_DOMAIN", { serviceName: clientServiceName })}`;
|
|
110
110
|
// If we reference the service URL in its OWN env variables, we don't prefix it with the service name.
|
|
111
111
|
const serverUrl = `https://${getRailwayEnvVarValueReference("RAILWAY_PUBLIC_DOMAIN")}`;
|
|
112
|
-
const databaseUrl = getRailwayEnvVarValueReference(
|
|
112
|
+
const databaseUrl = getRailwayEnvVarValueReference("DATABASE_URL", {
|
|
113
|
+
serviceName: dbServiceName,
|
|
114
|
+
});
|
|
113
115
|
const jwtSecret = generateRandomHexString();
|
|
114
116
|
await railwayCli([
|
|
115
117
|
"add",
|
|
@@ -128,10 +130,10 @@ async function setupServer({ cmdOptions: options, serverServiceName, clientServi
|
|
|
128
130
|
}
|
|
129
131
|
async function setupClient({ cmdOptions: options, clientServiceName, }) {
|
|
130
132
|
waspSays(`Setting up client app with name ${clientServiceName}`);
|
|
131
|
-
const
|
|
132
|
-
const railwayCli = createCommandWithCwd(options.railwayExe,
|
|
133
|
+
const clientDeploymentDir = getClientDeploymentDir(options.waspProjectDir);
|
|
134
|
+
const railwayCli = createCommandWithCwd(options.railwayExe, clientDeploymentDir);
|
|
133
135
|
// Having a Staticfile tells Railway to use a static file server.
|
|
134
|
-
await $({ cwd:
|
|
136
|
+
await $({ cwd: clientDeploymentDir }) `touch Staticfile`;
|
|
135
137
|
await railwayCli([
|
|
136
138
|
"add",
|
|
137
139
|
["--service", clientServiceName],
|
|
@@ -140,7 +142,16 @@ async function setupClient({ cmdOptions: options, clientServiceName, }) {
|
|
|
140
142
|
].flat());
|
|
141
143
|
waspSays("Client setup complete!");
|
|
142
144
|
}
|
|
143
|
-
function getRailwayEnvVarValueReference(name) {
|
|
144
|
-
|
|
145
|
+
function getRailwayEnvVarValueReference(name, { serviceName } = {}) {
|
|
146
|
+
// Railway variable references have the format ${{VARIABLE}} for local variables
|
|
147
|
+
// or ${{serviceName.VARIABLE}} for cross-service references.
|
|
148
|
+
// When the service name contains special characters (like hyphens with numbers),
|
|
149
|
+
// Railway requires it to be quoted: ${{"service-name".VARIABLE}}
|
|
150
|
+
const parts = [name];
|
|
151
|
+
if (serviceName) {
|
|
152
|
+
// JSON.stringify wraps the string in quotes and escapes any special characters.
|
|
153
|
+
parts.unshift(JSON.stringify(serviceName));
|
|
154
|
+
}
|
|
155
|
+
return "${{" + parts.join(".") + "}}";
|
|
145
156
|
}
|
|
146
157
|
//# sourceMappingURL=setup.js.map
|
|
@@ -14,6 +14,9 @@ class RailwayCommand extends Command {
|
|
|
14
14
|
}
|
|
15
15
|
return this.option("--server-secret <serverSecret>", "secret to set on the server app (of form FOO=BAR)", collect, []).option("--client-secret <clientSecret>", "secret to set on the client app (of form FOO=BAR)", collect, []);
|
|
16
16
|
}
|
|
17
|
+
addCustomServerUrlOption() {
|
|
18
|
+
return this.option("--custom-server-url <url>", "URL of the server that the client will connect to");
|
|
19
|
+
}
|
|
17
20
|
}
|
|
18
21
|
export const railwaySetupCommand = makeRailwaySetupCommand();
|
|
19
22
|
export const railwayDeployCommand = makeRailwayDeployCommand();
|
|
@@ -68,6 +71,7 @@ function makeRailwayDeployCommand() {
|
|
|
68
71
|
.option("--skip-client", "do not deploy the web client")
|
|
69
72
|
.option("--skip-server", "do not deploy the server")
|
|
70
73
|
.option("--existing-project-id [projectId]", "use existing project for deployment")
|
|
74
|
+
.addCustomServerUrlOption()
|
|
71
75
|
.action(deployFn);
|
|
72
76
|
}
|
|
73
77
|
function makeRailwayLaunchCommand() {
|
|
@@ -78,6 +82,7 @@ function makeRailwayLaunchCommand() {
|
|
|
78
82
|
.option("--existing-project-id [projectId]", "use existing project instead of creating a new one")
|
|
79
83
|
.option("--workspace [workspace]", "the Railway workspace to use if a new project needs to be created (if not provided, will ask interactively)")
|
|
80
84
|
.option("--db-image <dbImage>", "custom Docker image for the PostgreSQL database")
|
|
85
|
+
.addCustomServerUrlOption()
|
|
81
86
|
.action(launchFn);
|
|
82
87
|
}
|
|
83
88
|
//# sourceMappingURL=index.js.map
|
|
@@ -13,7 +13,13 @@ export const RailwayCliProjectSchema = z.object({
|
|
|
13
13
|
}),
|
|
14
14
|
});
|
|
15
15
|
export const RailwayProjectListSchema = z.array(RailwayCliProjectSchema);
|
|
16
|
-
export const RailwayCliDomainSchema = z.
|
|
17
|
-
|
|
18
|
-
})
|
|
16
|
+
export const RailwayCliDomainSchema = z.union([
|
|
17
|
+
// Railway CLI >=4.18.1
|
|
18
|
+
z.object({ domains: z.array(z.string()).min(1) }),
|
|
19
|
+
// Railway CLI <4.18.1
|
|
20
|
+
z
|
|
21
|
+
.object({ domain: z.string() })
|
|
22
|
+
// Convert to the newer format
|
|
23
|
+
.transform(({ domain }) => ({ domains: [domain] })),
|
|
24
|
+
]);
|
|
19
25
|
//# sourceMappingURL=jsonOutputSchemas.js.map
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { waspInfo } from "../../../common/terminal.js";
|
|
1
2
|
import { createCommandWithCwd } from "../../../common/zx.js";
|
|
2
3
|
import { RailwayCliDomainSchema } from "../jsonOutputSchemas.js";
|
|
3
4
|
export var ServiceUrlStatus;
|
|
@@ -19,7 +20,13 @@ export async function generateServiceUrl(serviceName, port, options) {
|
|
|
19
20
|
return extractServiceUrlFromString(result.stdout);
|
|
20
21
|
}
|
|
21
22
|
else {
|
|
22
|
-
|
|
23
|
+
const { domains } = RailwayCliDomainSchema.parse(result.json());
|
|
24
|
+
const domain = domains[0];
|
|
25
|
+
if (domains.length > 1) {
|
|
26
|
+
waspInfo(`Multiple domains detected, using the first one: ${domain}.`);
|
|
27
|
+
waspInfo('If you want to use a custom domain for the server, you should add the "--custom-server-url <url>" flag.');
|
|
28
|
+
}
|
|
29
|
+
return domain;
|
|
23
30
|
}
|
|
24
31
|
}
|
|
25
32
|
function extractServiceUrlFromString(text) {
|