@astrojs/db 0.0.0-10646-20240402132948

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.
Files changed (78) hide show
  1. package/LICENSE +59 -0
  2. package/README.md +38 -0
  3. package/dist/_internal/core/integration/error-map.d.ts +6 -0
  4. package/dist/_internal/core/schemas.d.ts +4034 -0
  5. package/dist/_internal/core/types.d.ts +59 -0
  6. package/dist/_internal/core/utils.d.ts +20 -0
  7. package/dist/_internal/runtime/config.d.ts +154 -0
  8. package/dist/_internal/runtime/types.d.ts +69 -0
  9. package/dist/core/cli/commands/execute/index.d.ts +8 -0
  10. package/dist/core/cli/commands/execute/index.js +66 -0
  11. package/dist/core/cli/commands/link/index.d.ts +20 -0
  12. package/dist/core/cli/commands/link/index.js +252 -0
  13. package/dist/core/cli/commands/login/index.d.ts +8 -0
  14. package/dist/core/cli/commands/login/index.js +55 -0
  15. package/dist/core/cli/commands/logout/index.d.ts +1 -0
  16. package/dist/core/cli/commands/logout/index.js +9 -0
  17. package/dist/core/cli/commands/push/index.d.ts +8 -0
  18. package/dist/core/cli/commands/push/index.js +93 -0
  19. package/dist/core/cli/commands/shell/index.d.ts +8 -0
  20. package/dist/core/cli/commands/shell/index.js +33 -0
  21. package/dist/core/cli/commands/verify/index.d.ts +8 -0
  22. package/dist/core/cli/commands/verify/index.js +46 -0
  23. package/dist/core/cli/index.d.ts +6 -0
  24. package/dist/core/cli/index.js +76 -0
  25. package/dist/core/cli/migration-queries.d.ts +23 -0
  26. package/dist/core/cli/migration-queries.js +386 -0
  27. package/dist/core/cli/print-help.d.ts +11 -0
  28. package/dist/core/cli/print-help.js +55 -0
  29. package/dist/core/consts.d.ts +8 -0
  30. package/dist/core/consts.js +21 -0
  31. package/dist/core/errors.d.ts +10 -0
  32. package/dist/core/errors.js +56 -0
  33. package/dist/core/integration/error-map.d.ts +6 -0
  34. package/dist/core/integration/error-map.js +79 -0
  35. package/dist/core/integration/file-url.d.ts +2 -0
  36. package/dist/core/integration/file-url.js +81 -0
  37. package/dist/core/integration/index.d.ts +2 -0
  38. package/dist/core/integration/index.js +160 -0
  39. package/dist/core/integration/typegen.d.ts +7 -0
  40. package/dist/core/integration/typegen.js +33 -0
  41. package/dist/core/integration/vite-plugin-db.d.ts +39 -0
  42. package/dist/core/integration/vite-plugin-db.js +134 -0
  43. package/dist/core/integration/vite-plugin-inject-env-ts.d.ts +11 -0
  44. package/dist/core/integration/vite-plugin-inject-env-ts.js +53 -0
  45. package/dist/core/load-file.d.ts +253 -0
  46. package/dist/core/load-file.js +170 -0
  47. package/dist/core/schemas.d.ts +4034 -0
  48. package/dist/core/schemas.js +186 -0
  49. package/dist/core/tokens.d.ts +11 -0
  50. package/dist/core/tokens.js +181 -0
  51. package/dist/core/types.d.ts +59 -0
  52. package/dist/core/types.js +0 -0
  53. package/dist/core/utils.d.ts +20 -0
  54. package/dist/core/utils.js +32 -0
  55. package/dist/index.d.ts +4 -0
  56. package/dist/index.js +8 -0
  57. package/dist/runtime/config.js +111 -0
  58. package/dist/runtime/db-client.d.ts +6 -0
  59. package/dist/runtime/db-client.js +148 -0
  60. package/dist/runtime/drizzle.d.ts +1 -0
  61. package/dist/runtime/drizzle.js +48 -0
  62. package/dist/runtime/errors.d.ts +5 -0
  63. package/dist/runtime/errors.js +31 -0
  64. package/dist/runtime/index.d.ts +26 -0
  65. package/dist/runtime/index.js +131 -0
  66. package/dist/runtime/queries.d.ts +71 -0
  67. package/dist/runtime/queries.js +169 -0
  68. package/dist/runtime/seed-local.d.ts +10 -0
  69. package/dist/runtime/seed-local.js +55 -0
  70. package/dist/runtime/types.d.ts +69 -0
  71. package/dist/runtime/types.js +8 -0
  72. package/dist/runtime/utils.d.ts +8 -0
  73. package/dist/runtime/utils.js +17 -0
  74. package/dist/utils.d.ts +2 -0
  75. package/dist/utils.js +6 -0
  76. package/index.d.ts +3 -0
  77. package/package.json +95 -0
  78. package/virtual.d.ts +45 -0
@@ -0,0 +1,59 @@
1
+ import type { AstroIntegration } from 'astro';
2
+ import type { z } from 'zod';
3
+ import type { MaybeArray, booleanColumnSchema, columnSchema, columnsSchema, dateColumnSchema, dbConfigSchema, indexSchema, jsonColumnSchema, numberColumnOptsSchema, numberColumnSchema, referenceableColumnSchema, resolvedIndexSchema, tableSchema, textColumnOptsSchema, textColumnSchema } from './schemas.js';
4
+ export type ResolvedIndexes = z.output<typeof dbConfigSchema>['tables'][string]['indexes'];
5
+ export type BooleanColumn = z.infer<typeof booleanColumnSchema>;
6
+ export type BooleanColumnInput = z.input<typeof booleanColumnSchema>;
7
+ export type NumberColumn = z.infer<typeof numberColumnSchema>;
8
+ export type NumberColumnInput = z.input<typeof numberColumnSchema>;
9
+ export type TextColumn = z.infer<typeof textColumnSchema>;
10
+ export type TextColumnInput = z.input<typeof textColumnSchema>;
11
+ export type DateColumn = z.infer<typeof dateColumnSchema>;
12
+ export type DateColumnInput = z.input<typeof dateColumnSchema>;
13
+ export type JsonColumn = z.infer<typeof jsonColumnSchema>;
14
+ export type JsonColumnInput = z.input<typeof jsonColumnSchema>;
15
+ export type ColumnType = BooleanColumn['type'] | NumberColumn['type'] | TextColumn['type'] | DateColumn['type'] | JsonColumn['type'];
16
+ export type DBColumn = z.infer<typeof columnSchema>;
17
+ export type DBColumnInput = DateColumnInput | BooleanColumnInput | NumberColumnInput | TextColumnInput | JsonColumnInput;
18
+ export type DBColumns = z.infer<typeof columnsSchema>;
19
+ export type DBTable = z.infer<typeof tableSchema>;
20
+ export type DBTables = Record<string, DBTable>;
21
+ export type ResolvedDBTables = z.output<typeof dbConfigSchema>['tables'];
22
+ export type ResolvedDBTable = z.output<typeof dbConfigSchema>['tables'][string];
23
+ export type DBSnapshot = {
24
+ schema: Record<string, ResolvedDBTable>;
25
+ version: string;
26
+ };
27
+ export type DBConfigInput = z.input<typeof dbConfigSchema>;
28
+ export type DBConfig = z.infer<typeof dbConfigSchema>;
29
+ export type ColumnsConfig = z.input<typeof tableSchema>['columns'];
30
+ export type OutputColumnsConfig = z.output<typeof tableSchema>['columns'];
31
+ export interface TableConfig<TColumns extends ColumnsConfig = ColumnsConfig> extends Pick<z.input<typeof tableSchema>, 'columns' | 'indexes' | 'foreignKeys'> {
32
+ columns: TColumns;
33
+ foreignKeys?: Array<{
34
+ columns: MaybeArray<Extract<keyof TColumns, string>>;
35
+ references: () => MaybeArray<z.input<typeof referenceableColumnSchema>>;
36
+ }>;
37
+ indexes?: Array<IndexConfig<TColumns>> | Record<string, LegacyIndexConfig<TColumns>>;
38
+ deprecated?: boolean;
39
+ }
40
+ interface IndexConfig<TColumns extends ColumnsConfig> extends z.input<typeof indexSchema> {
41
+ on: MaybeArray<Extract<keyof TColumns, string>>;
42
+ }
43
+ /** @deprecated */
44
+ interface LegacyIndexConfig<TColumns extends ColumnsConfig> extends z.input<typeof resolvedIndexSchema> {
45
+ on: MaybeArray<Extract<keyof TColumns, string>>;
46
+ }
47
+ export type NumberColumnOpts = z.input<typeof numberColumnOptsSchema>;
48
+ export type TextColumnOpts = z.input<typeof textColumnOptsSchema>;
49
+ export type AstroDbIntegration = AstroIntegration & {
50
+ hooks: {
51
+ 'astro:db:setup'?: (options: {
52
+ extendDb: (options: {
53
+ configEntrypoint?: URL | string;
54
+ seedEntrypoint?: URL | string;
55
+ }) => void;
56
+ }) => void | Promise<void>;
57
+ };
58
+ };
59
+ export {};
@@ -0,0 +1,20 @@
1
+ import type { AstroConfig, AstroIntegration } from 'astro';
2
+ import type { AstroDbIntegration } from './types.js';
3
+ export type VitePlugin = Required<AstroConfig['vite']>['plugins'][number];
4
+ export declare function getAstroStudioEnv(envMode?: string): Record<`ASTRO_STUDIO_${string}`, string>;
5
+ export declare function getRemoteDatabaseUrl(): string;
6
+ export declare function getAstroStudioUrl(): string;
7
+ export declare function getDbDirectoryUrl(root: URL | string): URL;
8
+ export declare function defineDbIntegration(integration: AstroDbIntegration): AstroIntegration;
9
+ export type Result<T> = {
10
+ success: true;
11
+ data: T;
12
+ } | {
13
+ success: false;
14
+ data: unknown;
15
+ };
16
+ /**
17
+ * Map an object's values to a new set of values
18
+ * while preserving types.
19
+ */
20
+ export declare function mapObject<T, U = T>(item: Record<string, T>, callback: (key: string, value: T) => U): Record<string, U>;
@@ -0,0 +1,154 @@
1
+ import { LibsqlError } from '@libsql/client';
2
+ import type { ColumnsConfig, DBConfigInput, TableConfig } from '../core/types.js';
3
+ import type { LibSQLDatabase } from 'drizzle-orm/libsql';
4
+ export type Database = Omit<LibSQLDatabase, 'transaction'>;
5
+ export declare function isDbError(err: unknown): err is LibsqlError;
6
+ export declare const column: {
7
+ number: <T extends ({
8
+ name?: string | undefined;
9
+ label?: string | undefined;
10
+ unique?: boolean | undefined;
11
+ deprecated?: boolean | undefined;
12
+ collection?: string | undefined;
13
+ } & ({
14
+ primaryKey?: false | undefined;
15
+ optional?: boolean | undefined;
16
+ default?: number | import("drizzle-orm").SQL<any> | undefined;
17
+ } | {
18
+ primaryKey: true;
19
+ optional?: false | undefined;
20
+ default?: undefined;
21
+ })) & {
22
+ references?: (() => {
23
+ type: "number";
24
+ schema: ({
25
+ name?: string | undefined;
26
+ label?: string | undefined;
27
+ unique?: boolean | undefined;
28
+ deprecated?: boolean | undefined;
29
+ collection?: string | undefined;
30
+ } & {
31
+ primaryKey?: false | undefined;
32
+ optional?: boolean | undefined;
33
+ default?: number | import("drizzle-orm").SQL<any> | undefined;
34
+ } & any) | ({
35
+ name?: string | undefined;
36
+ label?: string | undefined;
37
+ unique?: boolean | undefined;
38
+ deprecated?: boolean | undefined;
39
+ collection?: string | undefined;
40
+ } & {
41
+ primaryKey: true;
42
+ optional?: false | undefined;
43
+ default?: undefined;
44
+ } & any);
45
+ }) | undefined;
46
+ }>(opts?: T) => {
47
+ type: "number";
48
+ /**
49
+ * @internal
50
+ */
51
+ schema: T;
52
+ };
53
+ boolean: <T_1 extends {
54
+ name?: string | undefined;
55
+ label?: string | undefined;
56
+ optional?: boolean | undefined;
57
+ unique?: boolean | undefined;
58
+ deprecated?: boolean | undefined;
59
+ collection?: string | undefined;
60
+ default?: boolean | import("drizzle-orm").SQL<any> | undefined;
61
+ }>(opts?: T_1) => {
62
+ type: "boolean";
63
+ /**
64
+ * @internal
65
+ */
66
+ schema: T_1;
67
+ };
68
+ text: <T_2 extends ({
69
+ name?: string | undefined;
70
+ label?: string | undefined;
71
+ unique?: boolean | undefined;
72
+ deprecated?: boolean | undefined;
73
+ collection?: string | undefined;
74
+ default?: string | import("drizzle-orm").SQL<any> | undefined;
75
+ multiline?: boolean | undefined;
76
+ } & ({
77
+ primaryKey?: false | undefined;
78
+ optional?: boolean | undefined;
79
+ } | {
80
+ primaryKey: true;
81
+ optional?: false | undefined;
82
+ })) & {
83
+ references?: (() => {
84
+ type: "text";
85
+ schema: ({
86
+ name?: string | undefined;
87
+ label?: string | undefined;
88
+ unique?: boolean | undefined;
89
+ deprecated?: boolean | undefined;
90
+ collection?: string | undefined;
91
+ default?: string | import("drizzle-orm").SQL<any> | undefined;
92
+ multiline?: boolean | undefined;
93
+ } & {
94
+ primaryKey?: false | undefined;
95
+ optional?: boolean | undefined;
96
+ } & any) | ({
97
+ name?: string | undefined;
98
+ label?: string | undefined;
99
+ unique?: boolean | undefined;
100
+ deprecated?: boolean | undefined;
101
+ collection?: string | undefined;
102
+ default?: string | import("drizzle-orm").SQL<any> | undefined;
103
+ multiline?: boolean | undefined;
104
+ } & {
105
+ primaryKey: true;
106
+ optional?: false | undefined;
107
+ } & any);
108
+ }) | undefined;
109
+ }>(opts?: T_2) => {
110
+ type: "text";
111
+ /**
112
+ * @internal
113
+ */
114
+ schema: T_2;
115
+ };
116
+ date<T_3 extends {
117
+ name?: string | undefined;
118
+ label?: string | undefined;
119
+ optional?: boolean | undefined;
120
+ unique?: boolean | undefined;
121
+ deprecated?: boolean | undefined;
122
+ collection?: string | undefined;
123
+ default?: Date | import("drizzle-orm").SQL<any> | undefined;
124
+ }>(opts?: T_3): {
125
+ type: "date";
126
+ /**
127
+ * @internal
128
+ */
129
+ schema: T_3;
130
+ };
131
+ json<T_4 extends {
132
+ name?: string | undefined;
133
+ label?: string | undefined;
134
+ optional?: boolean | undefined;
135
+ unique?: boolean | undefined;
136
+ deprecated?: boolean | undefined;
137
+ collection?: string | undefined;
138
+ default?: unknown;
139
+ }>(opts?: T_4): {
140
+ type: "json";
141
+ /**
142
+ * @internal
143
+ */
144
+ schema: T_4;
145
+ };
146
+ };
147
+ export declare function defineTable<TColumns extends ColumnsConfig>(userConfig: TableConfig<TColumns>): TableConfig<TColumns>;
148
+ export declare function defineDb(userConfig: DBConfigInput): {
149
+ tables?: unknown;
150
+ };
151
+ export declare const NOW: import("drizzle-orm").SQL<unknown>;
152
+ export declare const TRUE: import("drizzle-orm").SQL<unknown>;
153
+ export declare const FALSE: import("drizzle-orm").SQL<unknown>;
154
+ export { sql, eq, gt, gte, lt, lte, ne, isNull, isNotNull, inArray, notInArray, exists, notExists, between, notBetween, like, notIlike, not, asc, desc, and, or, count, countDistinct, avg, avgDistinct, sum, sumDistinct, max, min, } from 'drizzle-orm';
@@ -0,0 +1,69 @@
1
+ import type { ColumnBaseConfig, ColumnDataType } from 'drizzle-orm';
2
+ import type { SQLiteColumn, SQLiteTableWithColumns } from 'drizzle-orm/sqlite-core';
3
+ import type { ColumnsConfig, DBColumn, OutputColumnsConfig } from '../core/types.js';
4
+ type GeneratedConfig<T extends ColumnDataType = ColumnDataType> = Pick<ColumnBaseConfig<T, string>, 'name' | 'tableName' | 'notNull' | 'hasDefault'>;
5
+ export type AstroText<T extends GeneratedConfig<'string'>> = SQLiteColumn<T & {
6
+ data: string;
7
+ dataType: 'string';
8
+ columnType: 'SQLiteText';
9
+ driverParam: string;
10
+ enumValues: never;
11
+ baseColumn: never;
12
+ }>;
13
+ export type AstroDate<T extends GeneratedConfig<'custom'>> = SQLiteColumn<T & {
14
+ data: Date;
15
+ dataType: 'custom';
16
+ columnType: 'SQLiteCustomColumn';
17
+ driverParam: string;
18
+ enumValues: never;
19
+ baseColumn: never;
20
+ }>;
21
+ export type AstroBoolean<T extends GeneratedConfig<'boolean'>> = SQLiteColumn<T & {
22
+ data: boolean;
23
+ dataType: 'boolean';
24
+ columnType: 'SQLiteBoolean';
25
+ driverParam: number;
26
+ enumValues: never;
27
+ baseColumn: never;
28
+ }>;
29
+ export type AstroNumber<T extends GeneratedConfig<'number'>> = SQLiteColumn<T & {
30
+ data: number;
31
+ dataType: 'number';
32
+ columnType: 'SQLiteInteger';
33
+ driverParam: number;
34
+ enumValues: never;
35
+ baseColumn: never;
36
+ }>;
37
+ export type AstroJson<T extends GeneratedConfig<'custom'>> = SQLiteColumn<T & {
38
+ data: unknown;
39
+ dataType: 'custom';
40
+ columnType: 'SQLiteCustomColumn';
41
+ driverParam: string;
42
+ enumValues: never;
43
+ baseColumn: never;
44
+ }>;
45
+ export type Column<T extends DBColumn['type'], S extends GeneratedConfig> = T extends 'boolean' ? AstroBoolean<S> : T extends 'number' ? AstroNumber<S> : T extends 'text' ? AstroText<S> : T extends 'date' ? AstroDate<S> : T extends 'json' ? AstroJson<S> : never;
46
+ export type Table<TTableName extends string, TColumns extends OutputColumnsConfig | ColumnsConfig> = SQLiteTableWithColumns<{
47
+ name: TTableName;
48
+ schema: undefined;
49
+ dialect: 'sqlite';
50
+ columns: {
51
+ [K in Extract<keyof TColumns, string>]: Column<TColumns[K]['type'], {
52
+ tableName: TTableName;
53
+ name: K;
54
+ hasDefault: TColumns[K]['schema'] extends {
55
+ default: NonNullable<unknown>;
56
+ } ? true : TColumns[K]['schema'] extends {
57
+ primaryKey: true;
58
+ } ? true : false;
59
+ notNull: TColumns[K]['schema']['optional'] extends true ? false : true;
60
+ }>;
61
+ };
62
+ }>;
63
+ export declare const SERIALIZED_SQL_KEY = "__serializedSQL";
64
+ export type SerializedSQL = {
65
+ [SERIALIZED_SQL_KEY]: true;
66
+ sql: string;
67
+ };
68
+ export declare function isSerializedSQL(value: any): value is SerializedSQL;
69
+ export {};
@@ -0,0 +1,8 @@
1
+ import type { AstroConfig } from 'astro';
2
+ import type { Arguments } from 'yargs-parser';
3
+ import { type DBConfig } from '../../../types.js';
4
+ export declare function cmd({ astroConfig, dbConfig, flags, }: {
5
+ astroConfig: AstroConfig;
6
+ dbConfig: DBConfig;
7
+ flags: Arguments;
8
+ }): Promise<void>;
@@ -0,0 +1,66 @@
1
+ import { existsSync } from "node:fs";
2
+ import { LibsqlError } from "@libsql/client";
3
+ import { green } from "kleur/colors";
4
+ import {
5
+ EXEC_DEFAULT_EXPORT_ERROR,
6
+ EXEC_ERROR,
7
+ FILE_NOT_FOUND_ERROR,
8
+ MISSING_EXECUTE_PATH_ERROR
9
+ } from "../../../errors.js";
10
+ import {
11
+ getLocalVirtualModContents,
12
+ getStudioVirtualModContents
13
+ } from "../../../integration/vite-plugin-db.js";
14
+ import { bundleFile, importBundledFile } from "../../../load-file.js";
15
+ import { getManagedAppTokenOrExit } from "../../../tokens.js";
16
+ import {} from "../../../types.js";
17
+ async function cmd({
18
+ astroConfig,
19
+ dbConfig,
20
+ flags
21
+ }) {
22
+ const filePath = flags._[4];
23
+ if (typeof filePath !== "string") {
24
+ console.error(MISSING_EXECUTE_PATH_ERROR);
25
+ process.exit(1);
26
+ }
27
+ const fileUrl = new URL(filePath, astroConfig.root);
28
+ if (!existsSync(fileUrl)) {
29
+ console.error(FILE_NOT_FOUND_ERROR(filePath));
30
+ process.exit(1);
31
+ }
32
+ let virtualModContents;
33
+ if (flags.remote) {
34
+ const appToken = await getManagedAppTokenOrExit(flags.token);
35
+ virtualModContents = getStudioVirtualModContents({
36
+ tables: dbConfig.tables ?? {},
37
+ appToken: appToken.token,
38
+ isBuild: false
39
+ });
40
+ } else {
41
+ virtualModContents = getLocalVirtualModContents({
42
+ tables: dbConfig.tables ?? {},
43
+ root: astroConfig.root,
44
+ shouldSeed: false,
45
+ seedFiles: []
46
+ });
47
+ }
48
+ const { code } = await bundleFile({ virtualModContents, root: astroConfig.root, fileUrl });
49
+ const mod = await importBundledFile({ code, root: astroConfig.root });
50
+ if (typeof mod.default !== "function") {
51
+ console.error(EXEC_DEFAULT_EXPORT_ERROR(filePath));
52
+ process.exit(1);
53
+ }
54
+ try {
55
+ await mod.default();
56
+ console.info(`${green("\u2714")} File run successfully.`);
57
+ } catch (e) {
58
+ if (e instanceof LibsqlError) {
59
+ throw new Error(EXEC_ERROR(e.message));
60
+ }
61
+ throw e;
62
+ }
63
+ }
64
+ export {
65
+ cmd
66
+ };
@@ -0,0 +1,20 @@
1
+ export declare function cmd(): Promise<void>;
2
+ export declare function createNewProject({ workspaceId, name, region, }: {
3
+ workspaceId: string;
4
+ name: string;
5
+ region: string;
6
+ }): Promise<{
7
+ id: string;
8
+ idName: string;
9
+ }>;
10
+ export declare function promptExistingProjectName({ workspaceId }: {
11
+ workspaceId: string;
12
+ }): Promise<{
13
+ id: string;
14
+ idName: string;
15
+ }>;
16
+ export declare function promptBegin(): Promise<void>;
17
+ export declare function promptLinkExisting(): Promise<boolean>;
18
+ export declare function promptLinkNew(): Promise<boolean>;
19
+ export declare function promptNewProjectName(): Promise<string>;
20
+ export declare function promptNewProjectRegion(): Promise<string>;
@@ -0,0 +1,252 @@
1
+ import { mkdir, writeFile } from "node:fs/promises";
2
+ import { homedir } from "node:os";
3
+ import { basename } from "node:path";
4
+ import { slug } from "github-slugger";
5
+ import { bgRed, cyan } from "kleur/colors";
6
+ import ora from "ora";
7
+ import prompts from "prompts";
8
+ import { safeFetch } from "../../../../runtime/utils.js";
9
+ import { MISSING_SESSION_ID_ERROR } from "../../../errors.js";
10
+ import { PROJECT_ID_FILE, getSessionIdFromFile } from "../../../tokens.js";
11
+ import { getAstroStudioUrl } from "../../../utils.js";
12
+ async function cmd() {
13
+ const sessionToken = await getSessionIdFromFile();
14
+ if (!sessionToken) {
15
+ console.error(MISSING_SESSION_ID_ERROR);
16
+ process.exit(1);
17
+ }
18
+ const getWorkspaceIdAsync = getWorkspaceId();
19
+ await promptBegin();
20
+ const isLinkExisting = await promptLinkExisting();
21
+ if (isLinkExisting) {
22
+ const workspaceId = await getWorkspaceIdAsync;
23
+ const existingProjectData = await promptExistingProjectName({ workspaceId });
24
+ return await linkProject(existingProjectData.id);
25
+ }
26
+ const isLinkNew = await promptLinkNew();
27
+ if (isLinkNew) {
28
+ const workspaceId = await getWorkspaceIdAsync;
29
+ const newProjectName = await promptNewProjectName();
30
+ const newProjectRegion = await promptNewProjectRegion();
31
+ const spinner = ora("Creating new project...").start();
32
+ const newProjectData = await createNewProject({
33
+ workspaceId,
34
+ name: newProjectName,
35
+ region: newProjectRegion
36
+ });
37
+ await new Promise((r) => setTimeout(r, 4e3));
38
+ spinner.succeed("Project created!");
39
+ return await linkProject(newProjectData.id);
40
+ }
41
+ }
42
+ async function linkProject(id) {
43
+ await mkdir(new URL(".", PROJECT_ID_FILE), { recursive: true });
44
+ await writeFile(PROJECT_ID_FILE, `${id}`);
45
+ console.info("Project linked.");
46
+ }
47
+ async function getWorkspaceId() {
48
+ const linkUrl = new URL(getAstroStudioUrl() + "/api/cli/workspaces.list");
49
+ const response = await safeFetch(
50
+ linkUrl,
51
+ {
52
+ method: "POST",
53
+ headers: {
54
+ Authorization: `Bearer ${await getSessionIdFromFile()}`,
55
+ "Content-Type": "application/json"
56
+ }
57
+ },
58
+ (res) => {
59
+ if (res.status === 401) {
60
+ console.error(
61
+ `${bgRed("Unauthorized")}
62
+
63
+ Are you logged in?
64
+ Run ${cyan(
65
+ "astro db login"
66
+ )} to authenticate and then try linking again.
67
+
68
+ `
69
+ );
70
+ process.exit(1);
71
+ }
72
+ console.error(`Failed to fetch user workspace: ${res.status} ${res.statusText}`);
73
+ process.exit(1);
74
+ }
75
+ );
76
+ const { data, success } = await response.json();
77
+ if (!success) {
78
+ console.error(`Failed to fetch user's workspace.`);
79
+ process.exit(1);
80
+ }
81
+ return data[0].id;
82
+ }
83
+ async function createNewProject({
84
+ workspaceId,
85
+ name,
86
+ region
87
+ }) {
88
+ const linkUrl = new URL(getAstroStudioUrl() + "/api/cli/projects.create");
89
+ const response = await safeFetch(
90
+ linkUrl,
91
+ {
92
+ method: "POST",
93
+ headers: {
94
+ Authorization: `Bearer ${await getSessionIdFromFile()}`,
95
+ "Content-Type": "application/json"
96
+ },
97
+ body: JSON.stringify({ workspaceId, name, region })
98
+ },
99
+ (res) => {
100
+ if (res.status === 401) {
101
+ console.error(
102
+ `${bgRed("Unauthorized")}
103
+
104
+ Are you logged in?
105
+ Run ${cyan(
106
+ "astro db login"
107
+ )} to authenticate and then try linking again.
108
+
109
+ `
110
+ );
111
+ process.exit(1);
112
+ }
113
+ console.error(`Failed to create project: ${res.status} ${res.statusText}`);
114
+ process.exit(1);
115
+ }
116
+ );
117
+ const { data, success } = await response.json();
118
+ if (!success) {
119
+ console.error(`Failed to create project.`);
120
+ process.exit(1);
121
+ }
122
+ return { id: data.id, idName: data.idName };
123
+ }
124
+ async function promptExistingProjectName({ workspaceId }) {
125
+ const linkUrl = new URL(getAstroStudioUrl() + "/api/cli/projects.list");
126
+ const response = await safeFetch(
127
+ linkUrl,
128
+ {
129
+ method: "POST",
130
+ headers: {
131
+ Authorization: `Bearer ${await getSessionIdFromFile()}`,
132
+ "Content-Type": "application/json"
133
+ },
134
+ body: JSON.stringify({ workspaceId })
135
+ },
136
+ (res) => {
137
+ if (res.status === 401) {
138
+ console.error(
139
+ `${bgRed("Unauthorized")}
140
+
141
+ Are you logged in?
142
+ Run ${cyan(
143
+ "astro db login"
144
+ )} to authenticate and then try linking again.
145
+
146
+ `
147
+ );
148
+ process.exit(1);
149
+ }
150
+ console.error(`Failed to fetch projects: ${res.status} ${res.statusText}`);
151
+ process.exit(1);
152
+ }
153
+ );
154
+ const { data, success } = await response.json();
155
+ if (!success) {
156
+ console.error(`Failed to fetch projects.`);
157
+ process.exit(1);
158
+ }
159
+ const { projectId } = await prompts({
160
+ type: "autocomplete",
161
+ name: "projectId",
162
+ message: "What is your project name?",
163
+ limit: 5,
164
+ choices: data.map((p) => ({ title: p.name, value: p.id }))
165
+ });
166
+ if (typeof projectId !== "string") {
167
+ console.log("Canceled.");
168
+ process.exit(0);
169
+ }
170
+ const selectedProjectData = data.find((p) => p.id === projectId);
171
+ return selectedProjectData;
172
+ }
173
+ async function promptBegin() {
174
+ const prettyCwd = process.cwd().replace(homedir(), "~");
175
+ const { begin } = await prompts({
176
+ type: "confirm",
177
+ name: "begin",
178
+ message: `Link "${prettyCwd}" with Astro Studio?`,
179
+ initial: true
180
+ });
181
+ if (!begin) {
182
+ console.log("Canceled.");
183
+ process.exit(0);
184
+ }
185
+ }
186
+ async function promptLinkExisting() {
187
+ const { linkExisting } = await prompts({
188
+ type: "confirm",
189
+ name: "linkExisting",
190
+ message: `Link with an existing project in Astro Studio?`,
191
+ initial: true
192
+ });
193
+ return !!linkExisting;
194
+ }
195
+ async function promptLinkNew() {
196
+ const { linkNew } = await prompts({
197
+ type: "confirm",
198
+ name: "linkNew",
199
+ message: `Create a new project in Astro Studio?`,
200
+ initial: true
201
+ });
202
+ if (!linkNew) {
203
+ console.log("Canceled.");
204
+ process.exit(0);
205
+ }
206
+ return true;
207
+ }
208
+ async function promptNewProjectName() {
209
+ const { newProjectName } = await prompts({
210
+ type: "text",
211
+ name: "newProjectName",
212
+ message: `What is your new project's name?`,
213
+ initial: basename(process.cwd()),
214
+ format: (val) => slug(val)
215
+ });
216
+ if (!newProjectName) {
217
+ console.log("Canceled.");
218
+ process.exit(0);
219
+ }
220
+ return newProjectName;
221
+ }
222
+ async function promptNewProjectRegion() {
223
+ const { newProjectRegion } = await prompts({
224
+ type: "select",
225
+ name: "newProjectRegion",
226
+ message: `Where should your new database live?`,
227
+ choices: [
228
+ { title: "North America (East)", value: "NorthAmericaEast" },
229
+ { title: "North America (West)", value: "NorthAmericaWest" },
230
+ { title: "Europe (Amsterdam)", value: "EuropeCentral" },
231
+ { title: "South America (Brazil)", value: "SouthAmericaEast" },
232
+ { title: "Asia (India)", value: "AsiaSouth" },
233
+ { title: "Asia (Japan)", value: "AsiaNorthEast" }
234
+ ],
235
+ initial: 0
236
+ });
237
+ if (!newProjectRegion) {
238
+ console.log("Canceled.");
239
+ process.exit(0);
240
+ }
241
+ return newProjectRegion;
242
+ }
243
+ export {
244
+ cmd,
245
+ createNewProject,
246
+ promptBegin,
247
+ promptExistingProjectName,
248
+ promptLinkExisting,
249
+ promptLinkNew,
250
+ promptNewProjectName,
251
+ promptNewProjectRegion
252
+ };
@@ -0,0 +1,8 @@
1
+ import type { AstroConfig } from 'astro';
2
+ import type { Arguments } from 'yargs-parser';
3
+ import type { DBConfig } from '../../../types.js';
4
+ export declare function cmd({ flags, }: {
5
+ astroConfig: AstroConfig;
6
+ dbConfig: DBConfig;
7
+ flags: Arguments;
8
+ }): Promise<void>;