diff --git a/packages/main/src/config/SchemaConfig.ts b/packages/main/src/config/SchemaConfig.ts index 3202854..3f6a2b3 100644 --- a/packages/main/src/config/SchemaConfig.ts +++ b/packages/main/src/config/SchemaConfig.ts @@ -1,3 +1,4 @@ +import { DataTypes, LiteralDataTypes } from "@src/core/DDL/abstracts/BaseFieldBuilder"; import Schema from "@src/core/DDL/implements/Schema" export type MissingSchemaStrategy = 'create' | 'ignore' | 'error' @@ -5,6 +6,8 @@ export type MissingSchemaStrategy = 'create' | 'ignore' | 'error' // 이 인터페이스는 이제 Configs.ts에서 직접 정의되므로 주석 처리하거나 삭제할 수 있습니다. export interface SchemaConfigOptions { onMissingSchema?: MissingSchemaStrategy; + recordDetailType?:boolean, + parseDetailType?:boolean, schemas?: T; } @@ -13,11 +16,38 @@ export type SchemaMap = { } class SchemaConfig{ - missingSchemaStartegy: MissingSchemaStrategy readonly DEFAULT_MISSING_STRATEGY: MissingSchemaStrategy = 'create' + + missingSchemaStartegy: MissingSchemaStrategy + recordDetailType: boolean + parseDetailType: boolean readonly schemaList: T; readonly schemaMap: SchemaMap; + schemaSetted:boolean + + // type parser for spreadsheet values + typeParsers:Record DataTypes> = { + boolean:(value) => value === "true", + date: (value) => new Date(value), + number: (value) => Number(value), + string: (value) => value, + } + + constructor({ + onMissingSchema = this.DEFAULT_MISSING_STRATEGY, + recordDetailType = true, + parseDetailType = true, + schemas = [] as unknown as T, + }: SchemaConfigOptions) { + this.missingSchemaStartegy = onMissingSchema; + this.recordDetailType = recordDetailType; + this.parseDetailType = parseDetailType; + + this.schemaList = schemas; + this.schemaSetted = this.schemaList.length > 0; + this.schemaMap = this.makeSchemaMap(this.schemaList); + } private makeSchemaMap(schemas:T){ const schemaMap = schemas.reduce((schemaDefinition, schema) => { @@ -27,12 +57,6 @@ class SchemaConfig{ }, {} as SchemaMap) return schemaMap } - - constructor(options: SchemaConfigOptions) { - this.missingSchemaStartegy = options.onMissingSchema ?? this.DEFAULT_MISSING_STRATEGY - this.schemaList = (options.schemas ?? []) as T - this.schemaMap = this.makeSchemaMap(this.schemaList) - } } export default SchemaConfig diff --git a/packages/main/src/config/SpreadConfig.ts b/packages/main/src/config/SpreadConfig.ts index 6f8e513..48a63a7 100644 --- a/packages/main/src/config/SpreadConfig.ts +++ b/packages/main/src/config/SpreadConfig.ts @@ -25,6 +25,18 @@ class SpreadConfig{ return false } + // Google Sheets 시리얼 번호로 변환하는 헬퍼 함수 + static jsDateToSheetsSerial(jsDate:Date) { + const sheetsEpoch = new Date(1899, 11, 30, 0, 0, 0); + const diffMillis = jsDate.getTime() - sheetsEpoch.getTime(); + const millisPerDay = 24 * 60 * 60 * 1000; + let sheetsSerial = diffMillis / millisPerDay; + if (jsDate.getFullYear() > 1900 || (jsDate.getFullYear() === 1900 && jsDate.getMonth() > 1)) { + sheetsSerial += 1; + } + + return sheetsSerial; + } /** * instance properties @@ -72,14 +84,16 @@ class SpreadConfig{ } async batchUpdateQuery(requests: sheets_v4.Schema$Request[], spreadsheetId?: string,) { - const response = await this.API.spreadsheets.batchUpdate({ - spreadsheetId:spreadsheetId ?? this.ID, - requestBody: { requests } - }); + const request = { + spreadsheetId:spreadsheetId ?? this.ID, + requestBody: { requests } + } + const response = await this.API.spreadsheets.batchUpdate(request); if (response.status !== 200) throw new Error("Batch failed"); return response.data.replies; } + private checkFormat(options:SpreadConfigOptions){ if (!this.isValidEmail(options.email)){ throw Error("Invalid email format") diff --git a/packages/main/src/core/DDL/SchemaManager.ts b/packages/main/src/core/DDL/SchemaManager.ts index 0326d61..74c7f84 100644 --- a/packages/main/src/core/DDL/SchemaManager.ts +++ b/packages/main/src/core/DDL/SchemaManager.ts @@ -149,16 +149,17 @@ class SchemaManager { if (dataType !== "number" && dataType !== "date") continue - const startColumnIndex = this.config.sheet.columnToNumber(this.config.sheet.DEFAULT_RECORDING_START_COLUMN) + idx - const request = SheetQueries.repeatTypedCell(sheetId, dataType, { - startRowIndex: this.config.sheet.DATA_STARTING_ROW, + const startColumnIndex = this.config.sheet.columnToNumber(this.config.sheet.DEFAULT_RECORDING_START_COLUMN) - 1 + idx + const request = SheetQueries.setNumberTypedCell(dataType, { + sheetId, + startRowIndex: this.config.sheet.DATA_STARTING_ROW - 1, startColumnIndex, endColumnIndex: startColumnIndex + 1 }) setTypedColumnRequests.push(request) } } - this.config.spread.batchUpdateQuery(setTypedColumnRequests) + await this.config.spread.batchUpdateQuery(setTypedColumnRequests) console.log("set type to column successfully") return result diff --git a/packages/main/src/core/DML/implements/InsertBuilder.ts b/packages/main/src/core/DML/implements/InsertBuilder.ts index dce7d9d..cdb1aea 100644 --- a/packages/main/src/core/DML/implements/InsertBuilder.ts +++ b/packages/main/src/core/DML/implements/InsertBuilder.ts @@ -4,6 +4,7 @@ import Schema from "@src/core/DDL/implements/Schema"; import AndAbleQueryStore from "../abstracts/mixins/AndAbleQueryStore"; import QueryStore, { BasicQueryQueueType } from "../abstracts/QueryStore"; import { SchemaMap } from "@src/config/SchemaConfig"; +import SpreadConfig from "@src/config/SpreadConfig"; interface InsertQueryQueueType extends BasicQueryQueueType{ insertValues:DataTypes[] @@ -75,7 +76,7 @@ class SettedInsertBuilder { const newRow = [...row]; // 원본 행 복사 @@ -83,9 +84,8 @@ class SettedInsertBuilder= 61) { - return serial + 1; - } - return serial; - } + } \ No newline at end of file diff --git a/packages/main/src/core/DML/implements/SelectBuilder.ts b/packages/main/src/core/DML/implements/SelectBuilder.ts index 918baaa..0fe9b34 100644 --- a/packages/main/src/core/DML/implements/SelectBuilder.ts +++ b/packages/main/src/core/DML/implements/SelectBuilder.ts @@ -50,9 +50,7 @@ extends WhereableAndQueryStore, SelectQueryQueueType>{ const composedRange = this.config.sheet.composeRange(query.sheetName, this.config.sheet.DATA_STARTING_ROW, specifiedColumn) return composedRange }) - console.log("composedRanges",composedRanges) const requestBody = this.makeRequestBody(composedRanges) - console.log("requestBody",requestBody) const response = await this.config.spread.API.spreadsheets.values.batchGetByDataFilter({ spreadsheetId:this.config.spread.ID, @@ -85,19 +83,8 @@ extends WhereableAndQueryStore, SelectQueryQueueType>{ if (!(queriedFrom in this.config.schema.schemaMap)) return sheetValue const currentSchema = this.config.schema.schemaMap[queriedFrom as keyof SchemaMap] - const typeConverters:((value:string)=>DataTypes)[] = currentSchema.orderedColumns.map((column) => { - const type = currentSchema.fields[column].dataType - switch (type){ - case "boolean": - return (value:string) => value.toLowerCase() === "true" - case "date": - return (value:string) => new Date(value) - case "number": - return (value:string) => Number(value) - default: - return (value:string) => value - } - }) + // orderColumns 를 기준으로 typeParser메서드들이 indexing된 배열을 + const typeConverters:((value:string)=>DataTypes)[] = currentSchema.orderedColumns.map((column) => this.config.schema.typeParsers[currentSchema.fields[column].dataType]) const result = sheetValue.map((row) => row.map((value,idx) => typeConverters[idx](value))) return result diff --git a/packages/main/src/generators/SheetQueries.ts b/packages/main/src/generators/SheetQueries.ts index d74df23..3eaa846 100644 --- a/packages/main/src/generators/SheetQueries.ts +++ b/packages/main/src/generators/SheetQueries.ts @@ -20,30 +20,28 @@ export class SheetQueries { } } - static repeatTypedCell( - sheetId:number, + static setNumberTypedCell( type:"number" | "date", - range:Omit = {endRowIndex:1000000}) + range:sheets_v4.Schema$GridRange) :sheets_v4.Schema$Request{ const numberFormat = { "number":{ - type:"NUMBER" + type:"NUMBER", }, "date":{ type:"DATE_TIME", - pattern: "yyyy-mm-dd hh:mm:ss" } } - return { repeatCell:{ range:{ - sheetId, - ...range, + startRowIndex:2, + endRowIndex:1000000, + ...range }, cell:{ userEnteredFormat: { - numberFormat:numberFormat[type] + numberFormat:numberFormat[type], } }, fields:"userEnteredFormat.numberFormat" diff --git a/packages/test/index.ts b/packages/test/index.ts index f2849fa..fb14547 100644 --- a/packages/test/index.ts +++ b/packages/test/index.ts @@ -1,6 +1,5 @@ import createSpreadsheetClient, { Credentials, defineTable, fieldBuilder } from "spreadsheet-orm" import credentials from "./security/credentials.json" - const connectionParameters:Credentials = credentials const userSchemaFields = { @@ -36,14 +35,14 @@ const spreadsheetClient = createSpreadsheetClient({ }) // spreadsheetClient.configs.schema.schemaMap.cars await spreadsheetClient.schemaManager.sync({mode:"force"}) -await spreadsheetClient.queryBuilder.insert(["volvo", 1960]).into("cars").execute() -// await spreadsheetClient.queryBuilder.insert(["volvo",1960]).into("cars").execute() + +await spreadsheetClient.queryBuilder.insert(["volvo",1960]).into("cars").execute() // await spreadsheetClient.queryBuilder.delete().from("cars").where((data) => data[2] === "1960").execute() // index0 = index // await spreadsheetClient.queryBuilder.update(["hyundai", 2000]).from("cars").execute() // await spreadsheetClient.queryBuilder.insert(["volvo",1960]).into("cars").and(["hyundai", 2020]).into("cars").execute() // // await spreadsheetClient.queryBuilder.insert(["volve", 1960]).into("cars").and() -const result = await spreadsheetClient.queryBuilder.select().from("cars").and().from("user").execute({detail:false}) -console.log(result) +// const result = await spreadsheetClient.queryBuilder.select().from("cars").and().from("user").execute({detail:false}) +// console.log(result) // await spreadsheetClient.queryBuilder.update()