From c42713607c4db95dbd009cafe9067da6693d9405 Mon Sep 17 00:00:00 2001 From: AayushTyagi1 Date: Wed, 11 Oct 2023 15:12:33 +0530 Subject: [PATCH 1/2] DA#313: Added: Create Document with Schema Template --- src/commands/documents/createDocument.ts | 106 +++++++++++++++++++++-- 1 file changed, 100 insertions(+), 6 deletions(-) diff --git a/src/commands/documents/createDocument.ts b/src/commands/documents/createDocument.ts index 7a57a1f0..8a22c79b 100644 --- a/src/commands/documents/createDocument.ts +++ b/src/commands/documents/createDocument.ts @@ -22,27 +22,121 @@ import { DocumentNotFoundError } from "couchbase"; import { MemFS } from "../../util/fileSystemProvider"; import { Constants } from "../../util/constants"; +interface JsonTemplate { + [x: string]: any; +} + +// Create a JSON Template out from tree data +function createJsonTemplate(treeNode: any, documentId: string | number): JsonTemplate { + const jsonTemplate: JsonTemplate = {}; + + if (!treeNode) { + return []; + } + + Object.entries(treeNode).map(property => { + let propertyValue: any = property[1]; + let type = propertyValue.type; + + if (Array.isArray(type)) { + type = type.filter(t => t !== null && t !== "null")[0] || null; + } + if (property[0] === "id") { + jsonTemplate[property[0]] = documentId; + } + else if (type === 'object') { + jsonTemplate[property[0]] = createJsonTemplate(propertyValue.properties, documentId); + } else if (type === 'array') { + const arrayItemType = type.match(/of (\w+)/); + if (arrayItemType) { + const itemType = arrayItemType[1]; + jsonTemplate[property[0]] = [createDefaultItem(itemType)]; + } else { + jsonTemplate[property[0]] = []; + } + } else { + jsonTemplate[property[0]] = createDefaultItem(type); + } + }); + return jsonTemplate; +}; + +function createDefaultItem(typeName: string) { + // Create an empty item based on the type + switch (typeName) { + case 'string': + return ''; + case 'number': + return 0; + case 'boolean': + return false; + case 'null': + return null; + case 'array': + return []; + case 'object': + return {}; + default: + return null; + } +}; + export const createDocument = async (node: CollectionNode, memFs: MemFS, uriToCasMap: Map) => { const connection = Memory.state.get(Constants.ACTIVE_CONNECTION); if (!connection) { return; } - const documentName = await vscode.window.showInputBox({ + const documentId = await vscode.window.showInputBox({ prompt: "Document Id", placeHolder: "Document Id", ignoreFocusOut: true, value: "", }); - if (!documentName) { + if (!documentId) { vscode.window.showErrorMessage("Document Id is required."); return; } - const uri = vscode.Uri.parse( - `couchbase:/${node.bucketName}/${node.scopeName}/Collections/${node.collectionName}/${documentName}.json` + const documentWithSchema = await vscode.window.showQuickPick( + ['Yes', 'No'], + { + placeHolder: 'Do you want to create a Document with Schema Template?', + } ); let documentContent = Buffer.from("{}"); + + if (documentWithSchema === 'Yes') { + let query = "INFER `" + node.bucketName + "`.`" + node.scopeName + "`.`" + node.collectionName + "` WITH {\"sample_size\": 2000}"; + const result = await connection?.cluster?.query(query); + let patternCnt: number = result?.rows[0].length || 0; + + const patternOptions = []; + for (let i = 0; i < patternCnt; i++) { + patternOptions.push(`Pattern#${i + 1}`); + } + + const selectedPattern = await vscode.window.showQuickPick(patternOptions, { + placeHolder: 'Choose a pattern for the document. You can review patterns in Schema Section', + ignoreFocusOut: true + }); + if (selectedPattern) { + const selectedPatternIndex = patternOptions.indexOf(selectedPattern!); + + let row = result?.rows[0][selectedPatternIndex]; + if (!row.properties) { + console.log({}); + } + else { + let childrenNode = createJsonTemplate(row.properties, documentId); + documentContent = Buffer.from(JSON.stringify(childrenNode, null, 2)); + } + } + } + + const uri = vscode.Uri.parse( + `couchbase:/${node.bucketName}/${node.scopeName}/Collections/${node.collectionName}/${documentId}.json` + ); // Try block is trying to retrieve the document with the same key first // If returns an error go to catch block create a new empty document try { @@ -50,7 +144,7 @@ export const createDocument = async (node: CollectionNode, memFs: MemFS, uriToCa ?.bucket(node.bucketName) .scope(node.scopeName) .collection(node.collectionName) - .get(documentName); + .get(documentId); if (result) { uriToCasMap.set(uri.toString(), result.cas.toString()); } @@ -68,5 +162,5 @@ export const createDocument = async (node: CollectionNode, memFs: MemFS, uriToCa }); const document = await vscode.workspace.openTextDocument(uri); await vscode.window.showTextDocument(document, { preview: false }); - logger.info(`${node.bucketName}: ${node.scopeName}: ${node.collectionName}: Successfully created the document: ${documentName}`); + logger.info(`${node.bucketName}: ${node.scopeName}: ${node.collectionName}: Successfully created the document: ${documentId}`); }; From 10b91fa555c455869b9d0cf5af0e49ae02216305 Mon Sep 17 00:00:00 2001 From: AayushTyagi1 Date: Wed, 11 Oct 2023 16:16:42 +0530 Subject: [PATCH 2/2] DA#313: Added: Handle the case with no patterns, one pattern, index not available --- src/commands/documents/createDocument.ts | 56 ++++++++++++++---------- 1 file changed, 32 insertions(+), 24 deletions(-) diff --git a/src/commands/documents/createDocument.ts b/src/commands/documents/createDocument.ts index 8a22c79b..991530f7 100644 --- a/src/commands/documents/createDocument.ts +++ b/src/commands/documents/createDocument.ts @@ -97,43 +97,51 @@ export const createDocument = async (node: CollectionNode, memFs: MemFS, uriToCa vscode.window.showErrorMessage("Document Id is required."); return; } - - const documentWithSchema = await vscode.window.showQuickPick( - ['Yes', 'No'], - { - placeHolder: 'Do you want to create a Document with Schema Template?', - } - ); let documentContent = Buffer.from("{}"); - - if (documentWithSchema === 'Yes') { + let patternCnt = 0; + try { let query = "INFER `" + node.bucketName + "`.`" + node.scopeName + "`.`" + node.collectionName + "` WITH {\"sample_size\": 2000}"; const result = await connection?.cluster?.query(query); - let patternCnt: number = result?.rows[0].length || 0; - - const patternOptions = []; - for (let i = 0; i < patternCnt; i++) { - patternOptions.push(`Pattern#${i + 1}`); + patternCnt = result?.rows[0].length || 0; + let documentWithSchema = undefined; + if (patternCnt > 0) { + documentWithSchema = await vscode.window.showQuickPick( + ['Yes', 'No'], + { + placeHolder: 'Do you want to create a Document with Schema Template?', + ignoreFocusOut: true + } + ); } + if (documentWithSchema === 'Yes') { + let selectedPatternIndex = 0; + if (patternCnt > 1) { + const patternOptions = []; + for (let i = 0; i < patternCnt; i++) { + patternOptions.push(`Pattern#${i + 1}`); + } - const selectedPattern = await vscode.window.showQuickPick(patternOptions, { - placeHolder: 'Choose a pattern for the document. You can review patterns in Schema Section', - ignoreFocusOut: true - }); - if (selectedPattern) { - const selectedPatternIndex = patternOptions.indexOf(selectedPattern!); + const selectedPattern = await vscode.window.showQuickPick(patternOptions, { + placeHolder: 'Choose a pattern for the document. You can review patterns in Schema Section', + ignoreFocusOut: true + }); + if (selectedPattern) { + selectedPatternIndex = patternOptions.indexOf(selectedPattern!); + } + } let row = result?.rows[0][selectedPatternIndex]; - if (!row.properties) { - console.log({}); - } - else { + if (row.properties) { let childrenNode = createJsonTemplate(row.properties, documentId); documentContent = Buffer.from(JSON.stringify(childrenNode, null, 2)); } } + } catch (err) { + logger.info("Error while loading schema patterns for document creatiion"); + logger.debug(err); } + const uri = vscode.Uri.parse( `couchbase:/${node.bucketName}/${node.scopeName}/Collections/${node.collectionName}/${documentId}.json` );