Skip to content

Commit

Permalink
Merge branch 'master' into leoortizz/frameworksActionFixes
Browse files Browse the repository at this point in the history
  • Loading branch information
leoortizz committed May 11, 2024
2 parents 6db3e92 + 24b6041 commit 2290198
Show file tree
Hide file tree
Showing 58 changed files with 1,819 additions and 546 deletions.
3 changes: 0 additions & 3 deletions CHANGELOG.md
@@ -1,3 +0,0 @@
- Increased the timeout for waiting for emulators to start to 60s. (#7091)
- Fixes infinite loop when trying to create a Hosting site.
- Fix copied functions dist dir files for Next.js when source config ends with slash (#7099)
4 changes: 3 additions & 1 deletion firebase-vscode/CHANGELOG.md
Expand Up @@ -4,7 +4,9 @@

- Update Extensions page Logo
- Update README for Extensions page
- Emulator Bump 1.1.15
- Surface emulator issues as notifications
- Generate .graphqlrc automatically
- Emulator Bump 1.1.16

## 0.1.7

Expand Down
3 changes: 3 additions & 0 deletions firebase-vscode/common/messaging/protocol.ts
Expand Up @@ -110,6 +110,9 @@ export interface WebviewToExtensionParamsMap {

/** Deploy all connectors/services to production */
"fdc.deploy-all": void;

// Initialize "result" tab.
getDataConnectResults: void;
}

export interface DataConnectResults {
Expand Down
4 changes: 2 additions & 2 deletions firebase-vscode/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion firebase-vscode/package.json
Expand Up @@ -4,7 +4,7 @@
"publisher": "firebase",
"icon": "./resources/firebase_logo.png",
"description": "VSCode Extension for Firebase",
"version": "0.1.6",
"version": "0.1.8",
"engines": {
"vscode": "^1.69.0"
},
Expand All @@ -13,6 +13,7 @@
"categories": [
"Other"
],
"extensionDependencies": ["graphql.vscode-graphql-syntax"],
"activationEvents": [
"onStartupFinished",
"onLanguage:graphql",
Expand Down
130 changes: 111 additions & 19 deletions firebase-vscode/src/data-connect/ad-hoc-mutations.ts
@@ -1,13 +1,8 @@
import vscode, { Disposable, ExtensionContext } from "vscode";
import { ExtensionBrokerImpl } from "../extension-broker";
import { ObjectTypeDefinitionNode } from "graphql";
import { checkIfFileExists } from "./file-utils";

export function registerAdHoc(
context: ExtensionContext,
broker: ExtensionBrokerImpl
): Disposable {
const pathSuffix = "_insert.gql";
import vscode, { Disposable } from "vscode";
import { DocumentNode, Kind, ObjectTypeDefinitionNode } from "graphql";
import { checkIfFileExists, upsertFile } from "./file-utils";

export function registerAdHoc(): Disposable {
const defaultScalarValues = {
Any: "{}",
AuthUID: '""',
Expand All @@ -25,23 +20,113 @@ export function registerAdHoc(
function isDataConnectScalarType(fieldType: string): boolean {
return fieldType in defaultScalarValues;
}

/**
* Creates a playground file with an ad-hoc mutation
* File will be created (unsaved) in operations/ folder, with an auto-generated named based on the schema type
* Mutation will be generated with all
* */
async function schemaAddData(
async function schemaReadData(
document: DocumentNode,
ast: ObjectTypeDefinitionNode,
{ documentPath, position }
) {
// TODO(rrousselGit) - this is a temporary solution due to the lack of a "schema".
// As such, we hardcoded the list of allowed primitives.
// We should ideally refactor this to allow any scalar type.
const primitiveTypes = new Set([
"String",
"Int",
"Int64",
"Boolean",
"Date",
"Timestamp",
"Float",
"Any",
]);

const basePath = vscode.workspace.rootPath + "/dataconnect/";
const filePath = vscode.Uri.file(`${basePath}${ast.name.value}_read.gql`);

// Recursively build a query for the object type.
// Returns undefined if the query is empty.
function buildRecursiveObjectQuery(
ast: ObjectTypeDefinitionNode,
level: number = 1,
): string | undefined {
const indent = " ".repeat(level);

// Whether the query is non-empty. Used to determine whether to return undefined.
var hasField = false;
let query = "{\n";
for (const field of ast.fields) {
// We unwrap NonNullType to obtain the actual type
let fieldType = field.type;
if (fieldType.kind === Kind.NON_NULL_TYPE) {
fieldType = fieldType.type;
}

// Deference, for the sake of enabling TS to upcast to NamedType later
const targetType = fieldType;
if (targetType.kind === Kind.NAMED_TYPE) {
// Check if the type is a primitive type, such that no recursion is needed.
if (primitiveTypes.has(targetType.name.value)) {
query += ` ${indent}${field.name.value}\n`;
hasField = true;
continue;
}

// Check relational types.
// Since we lack a schema, we can only build queries for types that are defined in the same document.
const targetTypeDefinition = document.definitions.find(
(def) =>
def.kind === Kind.OBJECT_TYPE_DEFINITION &&
def.name.value === targetType.name.value,
) as ObjectTypeDefinitionNode;

if (targetTypeDefinition) {
const subQuery = buildRecursiveObjectQuery(
targetTypeDefinition,
level + 1,
);
if (!subQuery) {
continue;
}
query += ` ${indent}${field.name.value} ${subQuery}\n`;
hasField = true;
}
}
}

query += `${indent}}`;
return query;
}

await upsertFile(filePath, () => {
const queryName = `${ast.name.value.charAt(0).toLowerCase()}${ast.name.value.slice(1)}s`;

return `
# This is a file for you to write an un-named queries.
# Only one un-named query is allowed per file.
query {
${queryName}${buildRecursiveObjectQuery(ast)!}
}`;
});
}

/**
* Creates a playground file with an ad-hoc mutation
* File will be created (unsaved) in operations/ folder, with an auto-generated named based on the schema type
* Mutation will be generated with all
* */
async function schemaAddData(ast: ObjectTypeDefinitionNode) {
// generate content for the file
const preamble =
"# This is a file for you to write an un-named mutation. \n# Only one un-named mutation is allowed per file.";
const adhocMutation = generateMutation(ast);
const content = [preamble, adhocMutation].join("\n");

const basePath = vscode.workspace.rootPath + "/dataconnect/";
const filePath = vscode.Uri.file(basePath + ast.name.value + pathSuffix);
const filePath = vscode.Uri.file(`${basePath}${ast.name.value}_insert.gql`);
const doesFileExist = await checkIfFileExists(filePath);

if (!doesFileExist) {
Expand Down Expand Up @@ -75,18 +160,21 @@ export function registerAdHoc(
mutation.push(`${functionSpacing}${name}_insert(data: {`); // insert function
for (const field of ast.fields) {
// necessary to avoid type error
const fieldType: any = field.type;
let fieldTypeName: string = fieldType.type.name.value;
let fieldType: any = field.type;
// We unwrap NonNullType to obtain the actual type
if (fieldType.kind === Kind.NON_NULL_TYPE) {
fieldType = fieldType.type;
}
let fieldTypeName: string = fieldType.name.value;
let fieldName: string = field.name.value;
let defaultValue = defaultScalarValues[fieldTypeName] as string;

if (!isDataConnectScalarType(fieldTypeName)) {
fieldTypeName += "Id";
fieldName += "Id";
defaultValue = '""';
}
mutation.push(
`${fieldSpacing}${fieldName}: ${defaultValue} # ${fieldTypeName}`
`${fieldSpacing}${fieldName}: ${defaultValue} # ${fieldTypeName}`,
); // field name + temp value + comment
}
mutation.push(`${functionSpacing}})`, "}"); // closing braces/paren
Expand All @@ -96,7 +184,11 @@ export function registerAdHoc(
return Disposable.from(
vscode.commands.registerCommand(
"firebase.dataConnect.schemaAddData",
schemaAddData
)
schemaAddData,
),
vscode.commands.registerCommand(
"firebase.dataConnect.schemaReadData",
schemaReadData,
),
);
}
9 changes: 9 additions & 0 deletions firebase-vscode/src/data-connect/code-lens-provider.ts
Expand Up @@ -154,6 +154,15 @@ export class SchemaCodeLensProvider extends ComputedCodeLensProvider {
arguments: [x, schemaLocation],
})
);

codeLenses.push(
new vscode.CodeLens(range, {
title: `$(database) Read data`,
command: "firebase.dataConnect.schemaReadData",
tooltip: "Generate a query to read data of this type",
arguments: [documentNode, x],
})
);
}
}

Expand Down
20 changes: 20 additions & 0 deletions firebase-vscode/src/data-connect/config.ts
Expand Up @@ -144,6 +144,26 @@ export class ResolvedDataConnectConfig {
return result;
}

get connectorDirs(): string[] {
return this.value.connectorDirs;
}

get schemaDir(): string {
return this.value.schema.source;
}

get relativePath(): string {
return this.path.split("/").pop();
}

get relativeSchemaPath(): string {
return this.schemaDir.replace(".", this.relativePath);
}

get relativeConnectorPaths(): string[] {
return this.connectorDirs.map((connectorDir) => connectorDir.replace(".", this.relativePath));
}

containsPath(path: string) {
return isPathInside(path, this.path);
}
Expand Down
6 changes: 3 additions & 3 deletions firebase-vscode/src/data-connect/emulator-stream.ts
Expand Up @@ -37,9 +37,9 @@ export async function runEmulatorIssuesStream(
) {
const obsErrors = await getEmulatorIssuesStream(configs, fdcEndpoint);
const obsConverter = {
next(nextCompilerResponse: CompilerResponse) {
if (nextCompilerResponse.result?.issues?.length) {
for (const issue of nextCompilerResponse.result.issues) {
next(nextResponse: EmulatorIssueResponse) {
if (nextResponse.result?.issues?.length) {
for (const issue of nextResponse.result.issues) {
displayIssue(issue);
}
}
Expand Down

0 comments on commit 2290198

Please sign in to comment.