From b8dded3987fc546d4584bc2a3c4956cb1c48dff9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20C=C3=B3rdova=20Nieto?= Date: Thu, 28 Nov 2024 14:04:27 -0600 Subject: [PATCH 01/11] allow missing media files witouth breaking --- .../scripts/import/generate-sql-statements.ts | 54 ++++++++++--------- packages/scripts/package.json | 6 +-- 2 files changed, 33 insertions(+), 27 deletions(-) diff --git a/packages/scripts/import/generate-sql-statements.ts b/packages/scripts/import/generate-sql-statements.ts index e5edf127a..aceb98c99 100644 --- a/packages/scripts/import/generate-sql-statements.ts +++ b/packages/scripts/import/generate-sql-statements.ts @@ -287,15 +287,18 @@ export async function generate_sql_statements({ if (!value) continue const { storage_path } = await upload_audio(value, entry_id) - const audio_id = randomUUID() - const audio: TablesInsert<'audio'> = { - ...c_u_meta, - id: audio_id, - dictionary_id, - entry_id, - storage_path, + let audio_id: string + if (storage_path) { + audio_id = randomUUID() + const audio: TablesInsert<'audio'> = { + ...c_u_meta, + id: audio_id, + dictionary_id, + entry_id, + storage_path, + } + sql_statements += sql_file_string('audio', audio) } - sql_statements += sql_file_string('audio', audio) // TODO: the code above will properly import multiple audio files to the same entry but the code below will only import the metadata from the first audio file. Late on when adding multiple audio import ability, use the next line to get the number suffix from the key // const number_suffix_with_period = key.replace('soundFile', '') as Number_Suffix @@ -327,23 +330,26 @@ export async function generate_sql_statements({ } if (row.photoFile) { - const { storage_path, serving_url } = await upload_photo(row.photoFile, entry_id) - const photo_id = randomUUID() - const photo: TablesInsert<'photos'> = { - ...c_u_meta, - id: photo_id, - dictionary_id, - storage_path, - serving_url, - } - sql_statements += sql_file_string('photos', photo) - const sense_id = senses[0].id - const sense_photo: TablesInsert<'sense_photos'> = { - ...c_meta, - photo_id, - sense_id, + const photo_media_result = await upload_photo(row.photoFile, entry_id) + if (photo_media_result) { + const { storage_path, serving_url } = photo_media_result + const photo_id = randomUUID() + const photo: TablesInsert<'photos'> = { + ...c_u_meta, + id: photo_id, + dictionary_id, + storage_path, + serving_url, + } + sql_statements += sql_file_string('photos', photo) + const sense_id = senses[0].id + const sense_photo: TablesInsert<'sense_photos'> = { + ...c_meta, + photo_id, + sense_id, + } + sql_statements += sql_file_string('sense_photos', sense_photo) } - sql_statements += sql_file_string('sense_photos', sense_photo) } // TablesInsert<'videos'> diff --git a/packages/scripts/package.json b/packages/scripts/package.json index 8e4ada7c3..c253b106b 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -14,9 +14,9 @@ }, "main": "index.ts", "scripts": { - "import-dictionary:dev:dry": "tsx import/import.ts --id tseltal", - "import-dictionary:dev:live": "tsx import/import.ts --id tseltal --live", - "import-dictionary:prod:live": "tsx import/import.ts --id tseltal -e prod --live", + "import-dictionary:dev:dry": "tsx import/import.ts --id example-v4", + "import-dictionary:dev:live": "tsx import/import.ts --id example-v4 --live", + "import-dictionary:prod:live": "tsx import/import.ts --id example-v4 -e prod --live", "update-locales": "tsx locales/update-locales.ts", "create-indexes": "tsx create-indexes/add-to-cloudflare.ts", "migrate-users": "tsx migrate-to-supabase/auth.ts", From eeb6737ae7451c0ede3f9d504a1bd48577b370e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20C=C3=B3rdova=20Nieto?= Date: Thu, 28 Nov 2024 17:10:56 -0600 Subject: [PATCH 02/11] fix speakers import --- .../import/data/example-v4/example-v4.csv | 20 ++++---- .../scripts/import/generate-sql-statements.ts | 48 +++++++++---------- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/packages/scripts/import/data/example-v4/example-v4.csv b/packages/scripts/import/data/example-v4/example-v4.csv index d3d72f636..ea1877786 100644 --- a/packages/scripts/import/data/example-v4/example-v4.csv +++ b/packages/scripts/import/data/example-v4/example-v4.csv @@ -1,10 +1,10 @@ -lexeme,phonetic,localOrthography,morphology,interlinearization,en_gloss,es_gloss,scientificName,partOfSpeech,,dialects,semanticDomain,,semanticDomain.2,,semanticDomain_custom,notes,soundFile,speakerName,speakerAge,speakerGender,speakerHometown,photoFile,vernacular_exampleSentence,en_exampleSentence,es_exampleSentence,source,pluralForm -(word/phrase),,,,,English,Spanish,,abbrev.,,,key,,key,,"(try not to use, separate multiples with a |)",,,,,,,,,English,Spanish,, -voiture,vwatyʁ,,,,car,auto,,"n,v",noun,Modern Parisian French,5.15,Transportation,5,Daily life,vehicle|cars,small automobile,helloworld.mp3,Celine Dorion,43,f,"Paris, France",mountain.jpg,Je conduis ma voiture,I drive my car,Conduzco mi auto,, -arbre,aʁbʁ,,,,tree,árbol,Acer rubrum,"n, adj",noun,"Modern Parisian French, Quebec French",1.4,"Plants, trees and other vegetation",1.2,"Earth, geology and landscape",,generic term for all kinds of trees,missing.mp3,Celine Dorion,43,f,"Paris, France",,L'arbre nous donne de l'ombre,The tree gives us shade,El árbol nos da sombra,, -tube,tyb,,,,tube,tubo,,n,noun,Modern Parisian French,5.9,Tools and weapons,,,plumbing,a cylindrical device for liquids,,,,,,missing.jpg,L'eau passe à travers les tubes,The water goes through the tubes,El agua pasa a través de los tubos,,tubes -voiture,vwɑtYʁ,,,,car,auto,,n,noun,Quebec French,5.15,Transportation,,,vehicle,small automobile,,,,,,,Je conduis ma voiture,I drive my car,Conduzco mi auto,testing sources, -neutre,nøʏ̯tʁ̥,,,,neutral,neutro,,adj,adjective,Quebec French,,,,,,,0005-neutre.mp3,David Boucher,31,m,"Montreal, Canada",,Ma chambre est peinte d'une couleur neutre.,My room is painted with a neutral color.,Mi habitación está pintada con un color neutro.,, -fêter,fɛɪ̯te,,,,to celebrate,celebrar,,v,verb,Quebec French,,,,,,to have a party,0006-feter.mp3,David Boucher,31,m,"Montreal, Canada",,On va vraiment fêter à soir,We will really party tonight,Vamos a celebrar esta noche,"test source|with multiples sources, test|https://example.com", -njakulaba,,,n-ja-ku-lab-a,1SG-Fut-2SG-see-Fin.V,I will see you,Voy a verte,,vp,verb phrase,Central Luganda,,,,,,,751-I-will-see-you.mp3,EB,50,m,,,,,,, -vale,,,,,bye,adiós,,,,,,,,,,,,,,,,,,,,, \ No newline at end of file +lexeme,phonetic,localOrthography,morphology,interlinearization,en_gloss,es_gloss,scientificName,partOfSpeech,,partOfSpeech.2,,dialects,semanticDomain,,semanticDomain.2,,notes,soundFile,speakerName,speakerAge,speakerGender,speakerHometown,photoFile,vernacular_exampleSentence,en_exampleSentence,es_exampleSentence,source,pluralForm +(word/phrase),,,,,English,Spanish,,abbrev.,,abbrev.,,,key,,key,,,,,,,,,,English,Spanish,, +voiture,vwatyʁ,,,,car,auto,,n,noun,v,verb,Modern Parisian French,5.15,Transportation,5,Daily life,small automobile,helloworld.mp3,Celine Dorion,43,f,"Paris, France",mountain.jpg,Je conduis ma voiture,I drive my car,Conduzco mi auto,, +arbre,aʁbʁ,,,,tree,árbol,Acer rubrum,n,noun,adj,adjective,Modern Parisian French | Quebec French,1.4,"Plants, trees and other vegetation",1.2,"Earth, geology and landscape",generic term for all kinds of trees,missing.mp3,Celine Dorion,43,f,"Paris, France",,L'arbre nous donne de l'ombre,The tree gives us shade,El árbol nos da sombra,, +tube,tyb,,,,tube,tubo,,n,noun,,,Modern Parisian French,5.9,Tools and weapons,,,a cylindrical device for liquids,,,,,,missing.jpg,L'eau passe à travers les tubes,The water goes through the tubes,El agua pasa a través de los tubos,,tubes +voiture,vwɑtYʁ,,,,car,auto,,n,noun,,,Quebec French,5.15,Transportation,,,small automobile,,,,,,,Je conduis ma voiture,I drive my car,Conduzco mi auto,testing sources, +neutre,nøʏ̯tʁ̥,,,,neutral,neutro,,adj,adjective,,,Quebec French,,,,,,0005-neutre.mp3,David Boucher,31,m,"Montreal, Canada",,Ma chambre est peinte d'une couleur neutre.,My room is painted with a neutral color.,Mi habitación está pintada con un color neutro.,, +fêter,fɛɪ̯te,,,,to celebrate,celebrar,,v,verb,,,Quebec French,,,,,to have a party,0006-feter.mp3,David Boucher,31,m,"Montreal, Canada",,On va vraiment fêter à soir,We will really party tonight,Vamos a celebrar esta noche,"test source|with multiples sources, test|https://example.com", +njakulaba,,,n-ja-ku-lab-a,1SG-Fut-2SG-see-Fin.V,I will see you,Voy a verte,,vp,verb phrase,,,Central Luganda,,,,,,751-I-will-see-you.mp3,EB,50,m,,,,,,, +vale,,,,,bye,adiós,,,,,,,,,,,,,,,,,,,,,, \ No newline at end of file diff --git a/packages/scripts/import/generate-sql-statements.ts b/packages/scripts/import/generate-sql-statements.ts index aceb98c99..e733a8bd8 100644 --- a/packages/scripts/import/generate-sql-statements.ts +++ b/packages/scripts/import/generate-sql-statements.ts @@ -298,34 +298,34 @@ export async function generate_sql_statements({ storage_path, } sql_statements += sql_file_string('audio', audio) - } - - // TODO: the code above will properly import multiple audio files to the same entry but the code below will only import the metadata from the first audio file. Late on when adding multiple audio import ability, use the next line to get the number suffix from the key - // const number_suffix_with_period = key.replace('soundFile', '') as Number_Suffix - if (row.speakerName) { - let speaker_id = speakers.find(({ name }) => name === row.speakerName)?.id - if (!speaker_id) { - speaker_id = randomUUID() - const speaker: TablesInsert<'speakers'> = { - ...c_u_meta, - id: speaker_id, - dictionary_id, - name: row.speakerName, - birthplace: row.speakerHometown || '', - decade: Number.parseInt(row.speakerAge) || null, - gender: row.speakerGender as 'm' | 'f' | 'o' || null, + // TODO: the code above will properly import multiple audio files to the same entry but the code below will only import the metadata from the first audio file. Late on when adding multiple audio import ability, use the next line to get the number suffix from the key + // const number_suffix_with_period = key.replace('soundFile', '') as Number_Suffix + if (row.speakerName) { + let speaker_id = speakers.find(({ name }) => name === row.speakerName)?.id + if (!speaker_id) { + speaker_id = randomUUID() + + const speaker: TablesInsert<'speakers'> = { + ...c_u_meta, + id: speaker_id, + dictionary_id, + name: row.speakerName, + birthplace: row.speakerHometown || '', + decade: Number.parseInt(row.speakerAge) || null, + gender: row.speakerGender as 'm' | 'f' | 'o' || null, + } + + sql_statements += sql_file_string('speakers', speaker) + speakers.push({ id: speaker_id, name: row.speakerName }) } - sql_statements += sql_file_string('speakers', speaker) - speakers.push({ id: speaker_id, name: row.speakerName }) + sql_statements += sql_file_string('audio_speakers', { + ...c_meta, + audio_id, + speaker_id, + }) } - - sql_statements += sql_file_string('audio_speakers', { - ...c_meta, - audio_id, - speaker_id, - }) } } From 8527585dbce55cc23cd1ffea5175ae446095a6e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20C=C3=B3rdova=20Nieto?= Date: Thu, 28 Nov 2024 17:11:39 -0600 Subject: [PATCH 03/11] fix file name --- ...ampe-sentence.interface.ts => example-sentence.interface.ts} | 0 packages/types/index.ts | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename packages/types/{exampe-sentence.interface.ts => example-sentence.interface.ts} (100%) diff --git a/packages/types/exampe-sentence.interface.ts b/packages/types/example-sentence.interface.ts similarity index 100% rename from packages/types/exampe-sentence.interface.ts rename to packages/types/example-sentence.interface.ts diff --git a/packages/types/index.ts b/packages/types/index.ts index 0599c87a8..bfe23990e 100644 --- a/packages/types/index.ts +++ b/packages/types/index.ts @@ -4,7 +4,7 @@ export type { IAbout, IDictionary, IGrammar, Citation, Partner } from './diction export type { Coordinates, IPoint, IRegion } from './coordinates.interface' export type { IGlossLanguages, IGlossLanguage } from './gloss-language.interface' export type { MultiString } from './gloss.interface' -export type { IExampleSentence } from './exampe-sentence.interface' +export type { IExampleSentence } from './example-sentence.interface' export type { DictionaryPhoto, PartnerPhoto } from './photo.interface' export type { SemanticDomain } from './semantic-domain.interface' export type { IUser, GoogleAuthUserMetaData } from './user.interface' From b3a17f121bb8341be19284bb648e94fa89a921a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20C=C3=B3rdova=20Nieto?= Date: Thu, 28 Nov 2024 17:40:32 -0600 Subject: [PATCH 04/11] fix vernacular example sentences in example-v4 --- packages/scripts/import/data/example-v4/example-v4.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/scripts/import/data/example-v4/example-v4.csv b/packages/scripts/import/data/example-v4/example-v4.csv index ea1877786..50377fb62 100644 --- a/packages/scripts/import/data/example-v4/example-v4.csv +++ b/packages/scripts/import/data/example-v4/example-v4.csv @@ -1,4 +1,4 @@ -lexeme,phonetic,localOrthography,morphology,interlinearization,en_gloss,es_gloss,scientificName,partOfSpeech,,partOfSpeech.2,,dialects,semanticDomain,,semanticDomain.2,,notes,soundFile,speakerName,speakerAge,speakerGender,speakerHometown,photoFile,vernacular_exampleSentence,en_exampleSentence,es_exampleSentence,source,pluralForm +lexeme,phonetic,localOrthography,morphology,interlinearization,en_gloss,es_gloss,scientificName,partOfSpeech,,partOfSpeech.2,,dialects,semanticDomain,,semanticDomain.2,,notes,soundFile,speakerName,speakerAge,speakerGender,speakerHometown,photoFile,default_vernacular_exampleSentence,en_exampleSentence,es_exampleSentence,source,pluralForm (word/phrase),,,,,English,Spanish,,abbrev.,,abbrev.,,,key,,key,,,,,,,,,,English,Spanish,, voiture,vwatyʁ,,,,car,auto,,n,noun,v,verb,Modern Parisian French,5.15,Transportation,5,Daily life,small automobile,helloworld.mp3,Celine Dorion,43,f,"Paris, France",mountain.jpg,Je conduis ma voiture,I drive my car,Conduzco mi auto,, arbre,aʁbʁ,,,,tree,árbol,Acer rubrum,n,noun,adj,adjective,Modern Parisian French | Quebec French,1.4,"Plants, trees and other vegetation",1.2,"Earth, geology and landscape",generic term for all kinds of trees,missing.mp3,Celine Dorion,43,f,"Paris, France",,L'arbre nous donne de l'ombre,The tree gives us shade,El árbol nos da sombra,, From 11f74efe4468fc84803550a5195a6aa6581aa24f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20C=C3=B3rdova=20Nieto?= Date: Fri, 29 Nov 2024 12:43:54 -0600 Subject: [PATCH 05/11] import senses only when they exist --- .../scripts/import/data/example-v4-senses/example-v4-senses.csv | 2 +- packages/scripts/import/generate-sql-statements.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/scripts/import/data/example-v4-senses/example-v4-senses.csv b/packages/scripts/import/data/example-v4-senses/example-v4-senses.csv index cb4f919e4..155f6c2d9 100644 --- a/packages/scripts/import/data/example-v4-senses/example-v4-senses.csv +++ b/packages/scripts/import/data/example-v4-senses/example-v4-senses.csv @@ -1,4 +1,4 @@ -lexeme,variant,es_gloss,partOfSpeech ,vernacular_exampleSentence ,es_exampleSentence ,s2.es_gloss,s2.partOfSpeech,s2.default_vernacular_exampleSentence,s2.es_exampleSentence,s3.es_gloss,s3.partOfSpeech,s3.default_vernacular_exampleSentence,s3.es_exampleSentence,s4.es_gloss,s4.partOfSpeech,s4.default_vernacular_exampleSentence,s4.es_exampleSentence,notes +lexeme,variant,es_gloss,partOfSpeech,default_vernacular_exampleSentence,es_exampleSentence,s2.es_gloss,s2.partOfSpeech,s2.default_vernacular_exampleSentence,s2.es_exampleSentence,s3.es_gloss,s3.partOfSpeech,s3.default_vernacular_exampleSentence,s3.es_exampleSentence,s4.es_gloss,s4.partOfSpeech,s4.default_vernacular_exampleSentence,s4.es_exampleSentence,notes kꞌahkꞌal,kꞌajkꞌal,sol,n,Lokꞌix tal kꞌahkꞌal,Ya salió el sol,fiebre,n,Ay ta kꞌahkꞌal te chꞌin alale,El niño tiene fiebre,día,n,Cheb kꞌahkꞌal ya x-aꞌtejotik,Trabajaremos dos días,calor,n,Toyol kꞌahkꞌal ya kaꞌiy,Siento mucho calor,16/jul./2019. Bachajon kꞌaal,kꞌahkꞌal,sol,n,Jaꞌnix lek-a lokꞌix tel kꞌaal,"Que bueno, ya salió el sol",fiebre,n,Ay bayal skꞌaal te chꞌin x-Ixchele,Mi hijita Ixchel tiene mucha fiebre,día,n,"Bajtix kaal mamtik, yorailix ich lewa","Ya transcurrió el día mi estimado señor, es momento de tomar un descanso",calor,n,Toyol kꞌaal ya jkaꞌiy,Siento mucho calor,26/dic./2020 kꞌajkꞌal,kꞌahkꞌal,sol,n,,,día,n,,,calor,n,,,fiebre,n,,,14/dic./2019 diff --git a/packages/scripts/import/generate-sql-statements.ts b/packages/scripts/import/generate-sql-statements.ts index e733a8bd8..416d61c81 100644 --- a/packages/scripts/import/generate-sql-statements.ts +++ b/packages/scripts/import/generate-sql-statements.ts @@ -202,7 +202,7 @@ export async function generate_sql_statements({ } } - senses.push(sense) + if (Object.keys(sense.glosses).length > 0) senses.push(sense) //* It only adds a sense if it has any glosses, otherwise it won't be added const sense_sentence_number_suffix = new Set() From d334d7ef11f22956ac6b7856cf7458ac6a5c715b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20C=C3=B3rdova=20Nieto?= Date: Fri, 29 Nov 2024 13:41:27 -0600 Subject: [PATCH 06/11] import first row when it is not a helper row --- packages/scripts/import/import.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/scripts/import/import.ts b/packages/scripts/import/import.ts index 79a136010..92ee31211 100644 --- a/packages/scripts/import/import.ts +++ b/packages/scripts/import/import.ts @@ -28,7 +28,7 @@ async function import_from_spreadsheet({ dictionary_id, live }: { dictionary_id: const file = readFileSync(`./import/data/${dictionary_id}/${dictionary_id}.csv`, 'utf8') const rows = parseCSVFrom(file) - rows.shift() // remove header row + if (rows[0].lexeme.startsWith('(word/phrase)')) rows.shift() // remove header row await import_data({ dictionary_id, rows, import_id, live, upload_operations: { upload_photo, upload_audio } }) console.log( From 6f1a24b7c8478a50ef3bbf75e76813a43f38dd35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20C=C3=B3rdova=20Nieto?= Date: Fri, 29 Nov 2024 13:57:52 -0600 Subject: [PATCH 07/11] allow import entries without any glosses (only available for first sense) --- packages/scripts/import/generate-sql-statements.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/scripts/import/generate-sql-statements.ts b/packages/scripts/import/generate-sql-statements.ts index 416d61c81..fd47394e1 100644 --- a/packages/scripts/import/generate-sql-statements.ts +++ b/packages/scripts/import/generate-sql-statements.ts @@ -202,7 +202,7 @@ export async function generate_sql_statements({ } } - if (Object.keys(sense.glosses).length > 0) senses.push(sense) //* It only adds a sense if it has any glosses, otherwise it won't be added + if (Object.keys(sense.glosses).length > 0 || sense_label[1] === '1') senses.push(sense) //* It only adds an additional sense if it has any glosses, otherwise it won't be added const sense_sentence_number_suffix = new Set() From 609013c1a6c0865db5d8f81872141f5f91e000e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20C=C3=B3rdova=20Nieto?= Date: Tue, 3 Dec 2024 10:54:33 -0600 Subject: [PATCH 08/11] small change --- packages/scripts/import/import.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/scripts/import/import.ts b/packages/scripts/import/import.ts index 92ee31211..4b8f020a2 100644 --- a/packages/scripts/import/import.ts +++ b/packages/scripts/import/import.ts @@ -28,7 +28,7 @@ async function import_from_spreadsheet({ dictionary_id, live }: { dictionary_id: const file = readFileSync(`./import/data/${dictionary_id}/${dictionary_id}.csv`, 'utf8') const rows = parseCSVFrom(file) - if (rows[0].lexeme.startsWith('(word/phrase)')) rows.shift() // remove header row + if (rows[0].lexeme.includes('word/phrase')) rows.shift() // remove header row await import_data({ dictionary_id, rows, import_id, live, upload_operations: { upload_photo, upload_audio } }) console.log( From df2f6363812af71ef8eafadd6d61ef32493f957c Mon Sep 17 00:00:00 2001 From: jacob-8 Date: Wed, 4 Dec 2024 12:44:48 +0800 Subject: [PATCH 09/11] make tests sense ordering fixed, handle media errors better, handle multiple photo uploads for 1 sense --- .../scripts/import/generate-sql-statements.ts | 174 ++++++++-------- packages/scripts/import/import-data.snap.json | 188 +++++++++--------- packages/scripts/import/import-data.test.ts | 46 +++-- packages/scripts/import/import-media.ts | 51 +++-- 4 files changed, 239 insertions(+), 220 deletions(-) diff --git a/packages/scripts/import/generate-sql-statements.ts b/packages/scripts/import/generate-sql-statements.ts index fd47394e1..4ffcdf5be 100644 --- a/packages/scripts/import/generate-sql-statements.ts +++ b/packages/scripts/import/generate-sql-statements.ts @@ -7,9 +7,11 @@ import { sql_file_string } from './to-sql-string' import { millisecond_incrementing_timestamp } from './incrementing-timestamp' export interface Upload_Operations { - upload_photo: (filepath: string, entry_id: string) => Promise<{ storage_path: string, serving_url: string }> - upload_audio: (filepath: string, entry_id: string) => Promise<{ storage_path: string }> - // upload_video: (filepath: string) => Promise<{ storage_path: string }> + upload_photo: (filepath: string, entry_id: string) => Promise< + { storage_path: string, serving_url: string, error: null } | { storage_path: null, serving_url: null, error: string } + > + upload_audio: (filepath: string, entry_id: string) => Promise<{ storage_path: string, error: null } | { storage_path: null, error: string }> + // upload_video: (filepath: string) => Promise<{ storage_path: string, error: null } | { storage_path: null, error: string }> } export async function generate_sql_statements({ @@ -38,14 +40,17 @@ export async function generate_sql_statements({ const entry_id = randomUUID() - const c_meta = { + const c_meta = () => ({ created_by: diego_ld_user_id, created_at: millisecond_incrementing_timestamp(), - } - const c_u_meta = { - ...c_meta, - updated_by: c_meta.created_by, - updated_at: c_meta.created_at, + }) + const c_u_meta = () => { + const meta = c_meta() + return { + ...meta, + updated_by: meta.created_by, + updated_at: meta.created_at, + } } const assemble_content_update = ({ data, ...rest }: ImportContentUpdate) => { const data_without_meta = { ...data } @@ -66,8 +71,8 @@ export async function generate_sql_statements({ id: randomUUID(), import_id, dictionary_id, - user_id: c_meta.created_by, - timestamp: c_meta.created_at, + user_id: c_meta().created_by, + timestamp: c_meta().created_at, data: data_without_meta, } return content_update @@ -76,7 +81,7 @@ export async function generate_sql_statements({ const entry: TablesInsert<'entries'> = { id: entry_id, dictionary_id, - ...c_u_meta, + ...c_u_meta(), lexeme: { default: row.lexeme, ...(row.localOrthography && { lo1: row.localOrthography }), @@ -104,7 +109,7 @@ export async function generate_sql_statements({ dialect_id = randomUUID() const dialect: TablesInsert<'dialects'> = { id: dialect_id, - ...c_u_meta, + ...c_u_meta(), dictionary_id, name: { default: dialect_to_assign }, } @@ -113,7 +118,7 @@ export async function generate_sql_statements({ } sql_statements += sql_file_string('entry_dialects', { - ...c_meta, + ...c_meta(), dialect_id, entry_id, }) @@ -128,7 +133,7 @@ export async function generate_sql_statements({ tag_id = randomUUID() const tag: TablesInsert<'tags'> = { id: tag_id, - ...c_u_meta, + ...c_u_meta(), dictionary_id, name: tag_to_assign, } @@ -137,7 +142,7 @@ export async function generate_sql_statements({ } sql_statements += sql_file_string('entry_tags', { - ...c_meta, + ...c_meta(), tag_id, entry_id, }) @@ -151,12 +156,13 @@ export async function generate_sql_statements({ const row_entries = (Object.entries(row) as [keyof Row, string][]) .sort(([keyA], [keyB]) => keyA.localeCompare(keyB)) + type Sense_Label = 's1' | 's2' | 's3' | 's4'// etc, for type-safety we just need a few here const first_sense_label = 's1' - const sense_labels = new Set([first_sense_label]) // always have at least one sense + const sense_labels = new Set([first_sense_label]) // always have at least one sense const sense_regex = /^(?s\d+)\./ for (const key of Object.keys(row)) { const match = key.match(sense_regex) - if (match) sense_labels.add(match.groups.sense_index) + if (match) sense_labels.add(match.groups.sense_index as Sense_Label) } for (const sense_label of sense_labels) { @@ -164,7 +170,7 @@ export async function generate_sql_statements({ const sense: TablesInsert<'senses'> = { entry_id, - ...c_u_meta, + ...c_u_meta(), id: sense_id, glosses: {}, } @@ -202,7 +208,7 @@ export async function generate_sql_statements({ } } - if (Object.keys(sense.glosses).length > 0 || sense_label[1] === '1') senses.push(sense) //* It only adds an additional sense if it has any glosses, otherwise it won't be added + if (sense_label === 's1' || Object.keys(sense.glosses).length > 0) senses.push(sense) //* It only adds an additional sense if it has any glosses, otherwise it won't be added const sense_sentence_number_suffix = new Set() @@ -225,7 +231,7 @@ export async function generate_sql_statements({ const sentence_id = randomUUID() const sentence: TablesInsert<'sentences'> = { dictionary_id, - ...c_u_meta, + ...c_u_meta(), id: sentence_id, text: {}, } @@ -263,7 +269,7 @@ export async function generate_sql_statements({ sentences.push(sentence) senses_in_sentences.push({ - ...c_meta, + ...c_meta(), sentence_id, sense_id, }) @@ -286,70 +292,76 @@ export async function generate_sql_statements({ if (!key.includes('soundFile')) continue if (!value) continue - const { storage_path } = await upload_audio(value, entry_id) - let audio_id: string - if (storage_path) { - audio_id = randomUUID() - const audio: TablesInsert<'audio'> = { - ...c_u_meta, - id: audio_id, - dictionary_id, - entry_id, - storage_path, - } - sql_statements += sql_file_string('audio', audio) - - // TODO: the code above will properly import multiple audio files to the same entry but the code below will only import the metadata from the first audio file. Late on when adding multiple audio import ability, use the next line to get the number suffix from the key - // const number_suffix_with_period = key.replace('soundFile', '') as Number_Suffix - if (row.speakerName) { - let speaker_id = speakers.find(({ name }) => name === row.speakerName)?.id - if (!speaker_id) { - speaker_id = randomUUID() - - const speaker: TablesInsert<'speakers'> = { - ...c_u_meta, - id: speaker_id, - dictionary_id, - name: row.speakerName, - birthplace: row.speakerHometown || '', - decade: Number.parseInt(row.speakerAge) || null, - gender: row.speakerGender as 'm' | 'f' | 'o' || null, - } - - sql_statements += sql_file_string('speakers', speaker) - speakers.push({ id: speaker_id, name: row.speakerName }) + const { storage_path, error } = await upload_audio(value, entry_id) + if (error) { + console.log(error) + continue + } + + const audio_id = randomUUID() + const audio: TablesInsert<'audio'> = { + ...c_u_meta(), + id: audio_id, + dictionary_id, + entry_id, + storage_path, + } + sql_statements += sql_file_string('audio', audio) + + // TODO: the code above will properly import multiple audio files to the same entry but the code below will only import the metadata from the first audio file. Late on when adding multiple audio import ability, use the next line to get the number suffix from the key + // const number_suffix_with_period = key.replace('soundFile', '') as Number_Suffix + if (row.speakerName) { + let speaker_id = speakers.find(({ name }) => name === row.speakerName)?.id + if (!speaker_id) { + speaker_id = randomUUID() + + const speaker: TablesInsert<'speakers'> = { + ...c_u_meta(), + id: speaker_id, + dictionary_id, + name: row.speakerName, + birthplace: row.speakerHometown || '', + decade: Number.parseInt(row.speakerAge) || null, + gender: row.speakerGender as 'm' | 'f' | 'o' || null, } - sql_statements += sql_file_string('audio_speakers', { - ...c_meta, - audio_id, - speaker_id, - }) + sql_statements += sql_file_string('speakers', speaker) + speakers.push({ id: speaker_id, name: row.speakerName }) } + + sql_statements += sql_file_string('audio_speakers', { + ...c_meta(), + audio_id, + speaker_id, + }) } } - if (row.photoFile) { - const photo_media_result = await upload_photo(row.photoFile, entry_id) - if (photo_media_result) { - const { storage_path, serving_url } = photo_media_result - const photo_id = randomUUID() - const photo: TablesInsert<'photos'> = { - ...c_u_meta, - id: photo_id, - dictionary_id, - storage_path, - serving_url, - } - sql_statements += sql_file_string('photos', photo) - const sense_id = senses[0].id - const sense_photo: TablesInsert<'sense_photos'> = { - ...c_meta, - photo_id, - sense_id, - } - sql_statements += sql_file_string('sense_photos', sense_photo) + for (const [key, value] of row_entries) { + if (!key.includes('photoFile')) continue + if (!value) continue + + const { storage_path, serving_url, error } = await upload_photo(value, entry_id) + if (error) { + console.log(error) + continue + } + const photo_id = randomUUID() + const photo: TablesInsert<'photos'> = { + ...c_u_meta(), + id: photo_id, + dictionary_id, + storage_path, + serving_url, } + sql_statements += sql_file_string('photos', photo) + const sense_id = senses[0].id + const sense_photo: TablesInsert<'sense_photos'> = { + ...c_meta(), + photo_id, + sense_id, + } + sql_statements += sql_file_string('sense_photos', sense_photo) } // TablesInsert<'videos'> @@ -362,7 +374,3 @@ export async function generate_sql_statements({ console.error(err) } } - -function returnArrayFromCommaSeparatedItems(string: string): string[] { - return string?.split(',').map(item => item.trim()) || null -} diff --git a/packages/scripts/import/import-data.snap.json b/packages/scripts/import/import-data.snap.json index 203236adc..e0d630bcd 100644 --- a/packages/scripts/import/import-data.snap.json +++ b/packages/scripts/import/import-data.snap.json @@ -2,7 +2,7 @@ "entries": [ { "audios": null, - "created_at": "2024-03-08T00:44:04.6+00:00", + "created_at": "2024-03-08T00:44:04.666+00:00", "deleted": null, "dialect_ids": null, "dictionary_id": "example-v4-senses", @@ -16,18 +16,6 @@ }, }, "senses": [ - { - "glosses": { - "es": "calor", - }, - "id": "11111111-1111-1111-1111-111111100050", - "parts_of_speech": [ - "n", - ], - "sentence_ids": [ - "11111111-1111-1111-1111-111111100051", - ], - }, { "glosses": { "es": "sol", @@ -67,13 +55,25 @@ "11111111-1111-1111-1111-111111100049", ], }, + { + "glosses": { + "es": "calor", + }, + "id": "11111111-1111-1111-1111-111111100050", + "parts_of_speech": [ + "n", + ], + "sentence_ids": [ + "11111111-1111-1111-1111-111111100051", + ], + }, ], "tag_ids": null, - "updated_at": "2024-03-08T00:44:04.6+00:00", + "updated_at": "2024-03-08T00:44:04.68+00:00", }, { "audios": null, - "created_at": "2024-03-08T00:44:04.6+00:00", + "created_at": "2024-03-08T00:44:04.681+00:00", "deleted": null, "dialect_ids": null, "dictionary_id": "example-v4-senses", @@ -89,24 +89,24 @@ "senses": [ { "glosses": { - "es": "fiebre", + "es": "sol", }, - "id": "11111111-1111-1111-1111-111111100057", + "id": "11111111-1111-1111-1111-111111100054", "parts_of_speech": [ "n", ], + "variant": { + "default": "kꞌahkꞌal", + }, }, { "glosses": { - "es": "sol", + "es": "día", }, - "id": "11111111-1111-1111-1111-111111100054", + "id": "11111111-1111-1111-1111-111111100055", "parts_of_speech": [ "n", ], - "variant": { - "default": "kꞌahkꞌal", - }, }, { "glosses": { @@ -119,20 +119,20 @@ }, { "glosses": { - "es": "día", + "es": "fiebre", }, - "id": "11111111-1111-1111-1111-111111100055", + "id": "11111111-1111-1111-1111-111111100057", "parts_of_speech": [ "n", ], }, ], "tag_ids": null, - "updated_at": "2024-03-08T00:44:04.6+00:00", + "updated_at": "2024-03-08T00:44:04.687+00:00", }, { "audios": null, - "created_at": "2024-03-08T00:44:04.6+00:00", + "created_at": "2024-03-08T00:44:04.688+00:00", "deleted": null, "dialect_ids": null, "dictionary_id": "example-v4-senses", @@ -148,26 +148,29 @@ "senses": [ { "glosses": { - "es": "bravo", + "es": "fuego", }, - "id": "11111111-1111-1111-1111-111111100062", + "id": "11111111-1111-1111-1111-111111100060", "parts_of_speech": [ - "adj", + "n", ], "sentence_ids": [ - "11111111-1111-1111-1111-111111100063", + "11111111-1111-1111-1111-111111100061", ], + "variant": { + "default": "kꞌahkꞌ", + }, }, { "glosses": { - "es": "caliente", + "es": "bravo", }, - "id": "11111111-1111-1111-1111-111111100066", + "id": "11111111-1111-1111-1111-111111100062", "parts_of_speech": [ "adj", ], "sentence_ids": [ - "11111111-1111-1111-1111-111111100067", + "11111111-1111-1111-1111-111111100063", ], }, { @@ -184,26 +187,23 @@ }, { "glosses": { - "es": "fuego", + "es": "caliente", }, - "id": "11111111-1111-1111-1111-111111100060", + "id": "11111111-1111-1111-1111-111111100066", "parts_of_speech": [ - "n", + "adj", ], "sentence_ids": [ - "11111111-1111-1111-1111-111111100061", + "11111111-1111-1111-1111-111111100067", ], - "variant": { - "default": "kꞌahkꞌ", - }, }, ], "tag_ids": null, - "updated_at": "2024-03-08T00:44:04.6+00:00", + "updated_at": "2024-03-08T00:44:04.702+00:00", }, { "audios": null, - "created_at": "2024-03-08T00:44:04.6+00:00", + "created_at": "2024-03-08T00:44:04.703+00:00", "deleted": null, "dialect_ids": null, "dictionary_id": "example-v4-senses", @@ -267,11 +267,11 @@ }, ], "tag_ids": null, - "updated_at": "2024-03-08T00:44:04.6+00:00", + "updated_at": "2024-03-08T00:44:04.717+00:00", }, { "audios": null, - "created_at": "2024-03-08T00:44:04.6+00:00", + "created_at": "2024-03-08T00:44:04.718+00:00", "deleted": null, "dialect_ids": null, "dictionary_id": "example-v4-senses", @@ -285,15 +285,6 @@ }, }, "senses": [ - { - "glosses": { - "es": "abrir", - }, - "id": "11111111-1111-1111-1111-111111100082", - "sentence_ids": [ - "11111111-1111-1111-1111-111111100083", - ], - }, { "glosses": { "es": "abierto", @@ -310,36 +301,38 @@ }, }, { - "glosses": {}, - "id": "11111111-1111-1111-1111-111111100085", - }, - { - "glosses": {}, - "id": "11111111-1111-1111-1111-111111100084", + "glosses": { + "es": "abrir", + }, + "id": "11111111-1111-1111-1111-111111100082", + "sentence_ids": [ + "11111111-1111-1111-1111-111111100083", + ], }, ], "tag_ids": null, - "updated_at": "2024-03-08T00:44:04.6+00:00", + "updated_at": "2024-03-08T00:44:04.726+00:00", }, ], "sentences": [ { - "created_at": "2024-03-08T00:44:04.6+00:00", + "created_at": "2024-03-08T00:44:04.67+00:00", "created_by": "be43b1dd-6c64-494d-b5da-10d70c384433", "deleted": null, "dictionary_id": "example-v4-senses", "id": "11111111-1111-1111-1111-111111100045", - "text": {}, + "text": { + "default": "Jaꞌnix lek-a lokꞌix tel kꞌaal", + }, "text_id": null, "translation": { "es": "Que bueno, ya salió el sol", - "vernacular": "Jaꞌnix lek-a lokꞌix tel kꞌaal", }, - "updated_at": "2024-03-08T00:44:04.6+00:00", + "updated_at": "2024-03-08T00:44:04.67+00:00", "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433", }, { - "created_at": "2024-03-08T00:44:04.6+00:00", + "created_at": "2024-03-08T00:44:04.673+00:00", "created_by": "be43b1dd-6c64-494d-b5da-10d70c384433", "deleted": null, "dictionary_id": "example-v4-senses", @@ -351,11 +344,11 @@ "translation": { "es": "Mi hijita Ixchel tiene mucha fiebre", }, - "updated_at": "2024-03-08T00:44:04.6+00:00", + "updated_at": "2024-03-08T00:44:04.673+00:00", "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433", }, { - "created_at": "2024-03-08T00:44:04.6+00:00", + "created_at": "2024-03-08T00:44:04.676+00:00", "created_by": "be43b1dd-6c64-494d-b5da-10d70c384433", "deleted": null, "dictionary_id": "example-v4-senses", @@ -367,11 +360,11 @@ "translation": { "es": "Ya transcurrió el día mi estimado señor, es momento de tomar un descanso", }, - "updated_at": "2024-03-08T00:44:04.6+00:00", + "updated_at": "2024-03-08T00:44:04.676+00:00", "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433", }, { - "created_at": "2024-03-08T00:44:04.6+00:00", + "created_at": "2024-03-08T00:44:04.679+00:00", "created_by": "be43b1dd-6c64-494d-b5da-10d70c384433", "deleted": null, "dictionary_id": "example-v4-senses", @@ -383,26 +376,27 @@ "translation": { "es": "Siento mucho calor", }, - "updated_at": "2024-03-08T00:44:04.6+00:00", + "updated_at": "2024-03-08T00:44:04.679+00:00", "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433", }, { - "created_at": "2024-03-08T00:44:04.6+00:00", + "created_at": "2024-03-08T00:44:04.692+00:00", "created_by": "be43b1dd-6c64-494d-b5da-10d70c384433", "deleted": null, "dictionary_id": "example-v4-senses", "id": "11111111-1111-1111-1111-111111100061", - "text": {}, + "text": { + "default": "Tilix kuꞌun-i kꞌajkꞌi", + }, "text_id": null, "translation": { "es": "Ya hice el fuego", - "vernacular": "Tilix kuꞌun-i kꞌajkꞌi", }, - "updated_at": "2024-03-08T00:44:04.6+00:00", + "updated_at": "2024-03-08T00:44:04.692+00:00", "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433", }, { - "created_at": "2024-03-08T00:44:04.6+00:00", + "created_at": "2024-03-08T00:44:04.695+00:00", "created_by": "be43b1dd-6c64-494d-b5da-10d70c384433", "deleted": null, "dictionary_id": "example-v4-senses", @@ -414,11 +408,11 @@ "translation": { "es": "El mestizo es muy bravo", }, - "updated_at": "2024-03-08T00:44:04.6+00:00", + "updated_at": "2024-03-08T00:44:04.695+00:00", "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433", }, { - "created_at": "2024-03-08T00:44:04.6+00:00", + "created_at": "2024-03-08T00:44:04.698+00:00", "created_by": "be43b1dd-6c64-494d-b5da-10d70c384433", "deleted": null, "dictionary_id": "example-v4-senses", @@ -430,11 +424,11 @@ "translation": { "es": "El bebé tiene mucha fiebre", }, - "updated_at": "2024-03-08T00:44:04.6+00:00", + "updated_at": "2024-03-08T00:44:04.698+00:00", "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433", }, { - "created_at": "2024-03-08T00:44:04.6+00:00", + "created_at": "2024-03-08T00:44:04.701+00:00", "created_by": "be43b1dd-6c64-494d-b5da-10d70c384433", "deleted": null, "dictionary_id": "example-v4-senses", @@ -446,26 +440,27 @@ "translation": { "es": "Kꞌajkꞌ te kajpele, kꞌume xa awuchꞌ", }, - "updated_at": "2024-03-08T00:44:04.6+00:00", + "updated_at": "2024-03-08T00:44:04.701+00:00", "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433", }, { - "created_at": "2024-03-08T00:44:04.6+00:00", + "created_at": "2024-03-08T00:44:04.707+00:00", "created_by": "be43b1dd-6c64-494d-b5da-10d70c384433", "deleted": null, "dictionary_id": "example-v4-senses", "id": "11111111-1111-1111-1111-111111100071", - "text": {}, + "text": { + "default": "¿Beluk apas? - Yakalon ta skꞌoponel jun", + }, "text_id": null, "translation": { "es": "¿Qué haces? - Estoy leyendo un libro", - "vernacular": "¿Beluk apas? - Yakalon ta skꞌoponel jun", }, - "updated_at": "2024-03-08T00:44:04.6+00:00", + "updated_at": "2024-03-08T00:44:04.707+00:00", "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433", }, { - "created_at": "2024-03-08T00:44:04.6+00:00", + "created_at": "2024-03-08T00:44:04.71+00:00", "created_by": "be43b1dd-6c64-494d-b5da-10d70c384433", "deleted": null, "dictionary_id": "example-v4-senses", @@ -477,11 +472,11 @@ "translation": { "es": "Alcancé a rayar mi cuaderno", }, - "updated_at": "2024-03-08T00:44:04.6+00:00", + "updated_at": "2024-03-08T00:44:04.71+00:00", "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433", }, { - "created_at": "2024-03-08T00:44:04.6+00:00", + "created_at": "2024-03-08T00:44:04.713+00:00", "created_by": "be43b1dd-6c64-494d-b5da-10d70c384433", "deleted": null, "dictionary_id": "example-v4-senses", @@ -493,11 +488,11 @@ "translation": { "es": "No vayas a arrugar tu documento", }, - "updated_at": "2024-03-08T00:44:04.6+00:00", + "updated_at": "2024-03-08T00:44:04.713+00:00", "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433", }, { - "created_at": "2024-03-08T00:44:04.6+00:00", + "created_at": "2024-03-08T00:44:04.716+00:00", "created_by": "be43b1dd-6c64-494d-b5da-10d70c384433", "deleted": null, "dictionary_id": "example-v4-senses", @@ -509,26 +504,27 @@ "translation": { "es": "La schꞌiꞌ jun te Zoe", }, - "updated_at": "2024-03-08T00:44:04.6+00:00", + "updated_at": "2024-03-08T00:44:04.716+00:00", "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433", }, { - "created_at": "2024-03-08T00:44:04.6+00:00", + "created_at": "2024-03-08T00:44:04.722+00:00", "created_by": "be43b1dd-6c64-494d-b5da-10d70c384433", "deleted": null, "dictionary_id": "example-v4-senses", "id": "11111111-1111-1111-1111-111111100081", - "text": {}, + "text": { + "default": "Jeꞌel jilel stiꞌ jna", + }, "text_id": null, "translation": { "es": "La puerta de mi casa quedó abierta", - "vernacular": "Jeꞌel jilel stiꞌ jna", }, - "updated_at": "2024-03-08T00:44:04.6+00:00", + "updated_at": "2024-03-08T00:44:04.722+00:00", "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433", }, { - "created_at": "2024-03-08T00:44:04.6+00:00", + "created_at": "2024-03-08T00:44:04.725+00:00", "created_by": "be43b1dd-6c64-494d-b5da-10d70c384433", "deleted": null, "dictionary_id": "example-v4-senses", @@ -540,7 +536,7 @@ "translation": { "es": "Abre un poco la puerta, hace mucho calor", }, - "updated_at": "2024-03-08T00:44:04.6+00:00", + "updated_at": "2024-03-08T00:44:04.725+00:00", "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433", }, ], diff --git a/packages/scripts/import/import-data.test.ts b/packages/scripts/import/import-data.test.ts index 4be8ef2e5..dbbb6debf 100644 --- a/packages/scripts/import/import-data.test.ts +++ b/packages/scripts/import/import-data.test.ts @@ -23,8 +23,14 @@ vi.mock('node:crypto', () => { }) vi.mock('./incrementing-timestamp', () => { + const yesterday = new Date('2024-03-08T00:44:04.600392+00:00') + let milliseconds_to_add = 0 + return { - millisecond_incrementing_timestamp: () => new Date('2024-03-08T00:44:04.600392+00:00').toISOString(), + millisecond_incrementing_timestamp: () => { + milliseconds_to_add += 1 + return new Date(yesterday.getTime() + milliseconds_to_add).toISOString() + }, } }) @@ -76,7 +82,7 @@ describe(import_data, () => { "storage_path": "2.mp3", }, ], - "created_at": "2024-03-08T00:44:04.6+00:00", + "created_at": "2024-03-08T00:44:04.601+00:00", "deleted": null, "dialect_ids": null, "dictionary_id": "test_dictionary_id", @@ -98,7 +104,7 @@ describe(import_data, () => { }, ], "tag_ids": null, - "updated_at": "2024-03-08T00:44:04.6+00:00", + "updated_at": "2024-03-08T00:44:04.608+00:00", }, ] `) @@ -110,7 +116,7 @@ describe(import_data, () => { [ { "audios": null, - "created_at": "2024-03-08T00:44:04.6+00:00", + "created_at": "2024-03-08T00:44:04.609+00:00", "deleted": null, "dialect_ids": null, "dictionary_id": "test_dictionary_id", @@ -129,7 +135,7 @@ describe(import_data, () => { }, ], "tag_ids": null, - "updated_at": "2024-03-08T00:44:04.6+00:00", + "updated_at": "2024-03-08T00:44:04.612+00:00", }, ] `) @@ -156,7 +162,7 @@ describe(import_data, () => { "table": null, "tag_id": null, "text_id": null, - "timestamp": "2024-03-08T00:44:04.6+00:00", + "timestamp": "2024-03-08T00:44:04.611+00:00", "type": "insert_entry", "user_id": "be43b1dd-6c64-494d-b5da-10d70c384433", "video_id": null, @@ -185,14 +191,14 @@ describe(import_data, () => { expect(speakers[0]).toMatchInlineSnapshot(` { "birthplace": "Whoville", - "created_at": "2024-03-08T00:44:04.6+00:00", + "created_at": "2024-03-08T00:44:04.632+00:00", "decade": 12, "deleted": null, "dictionary_id": "test_dictionary_id", "gender": "m", "id": "11111111-1111-1111-1111-111111100021", "name": "speaker 1", - "updated_at": "2024-03-08T00:44:04.6+00:00", + "updated_at": "2024-03-08T00:44:04.632+00:00", } `) expect(entries[0].audios[0].speaker_ids[0]).toEqual(speakers[0].id) @@ -251,7 +257,7 @@ describe(import_data, () => { [ { "audios": null, - "created_at": "2024-03-08T00:44:04.6+00:00", + "created_at": "2024-03-08T00:44:04.646+00:00", "deleted": null, "dialect_ids": [ "11111111-1111-1111-1111-111111100032", @@ -301,16 +307,6 @@ describe(import_data, () => { "default": "variant", }, }, - { - "glosses": { - "fr": "auch", - }, - "id": "11111111-1111-1111-1111-111111100039", - "sentence_ids": [ - "11111111-1111-1111-1111-111111100040", - "11111111-1111-1111-1111-111111100041", - ], - }, { "glosses": { "en": "bye", @@ -321,12 +317,22 @@ describe(import_data, () => { "2.3", ], }, + { + "glosses": { + "fr": "auch", + }, + "id": "11111111-1111-1111-1111-111111100039", + "sentence_ids": [ + "11111111-1111-1111-1111-111111100040", + "11111111-1111-1111-1111-111111100041", + ], + }, ], "tag_ids": [ "11111111-1111-1111-1111-111111100034", "11111111-1111-1111-1111-111111100035", ], - "updated_at": "2024-03-08T00:44:04.6+00:00", + "updated_at": "2024-03-08T00:44:04.665+00:00", }, ] `) diff --git a/packages/scripts/import/import-media.ts b/packages/scripts/import/import-media.ts index bd5fccc6b..d09ae6174 100644 --- a/packages/scripts/import/import-media.ts +++ b/packages/scripts/import/import-media.ts @@ -19,30 +19,35 @@ export async function upload_audio_to_gcs({ entry_id: string dictionary_id: string live?: boolean -}): Promise { +}) { const audioDir = join(__dirname, `data/${dictionary_id}/audio`) const audioFilePath = join(audioDir, filepath) if (!fs.existsSync(audioFilePath)) { - console.log(`>> Missing audio file: ${filepath}`) - return null + return { + error: `!!! Missing audio file: ${filepath}`, + } } try { const [fileTypeSuffix] = filepath.match(/\.[0-9a-z]+$/i) - const uploadedAudioPath = `${dictionary_id}/audio/${entry_id}_${new Date().getTime()}${fileTypeSuffix}` + const storage_path = `${dictionary_id}/audio/${entry_id}_${new Date().getTime()}${fileTypeSuffix}` if (live) { await storage.bucket(fileBucket).upload(audioFilePath, { - destination: uploadedAudioPath, + destination: storage_path, metadata: { originalFileName: filepath, }, }) } - return uploadedAudioPath + return { + storage_path, + } } catch (err) { - throw new Error(`Not adding audio ${filepath} as the server had trouble uploading it. Double-check the file to see if there is a problem with it or perhaps there is code/server/network-connection problem. Error: ${err}`) + return { + error: `!!! Trouble uploading ${filepath}. Error: ${err}`, + } } } @@ -61,35 +66,39 @@ export async function upload_photo_to_gcs({ const imageFilePath = join(imageDir, filepath) if (!fs.existsSync(imageFilePath)) { - console.log(`>> Missing image file: ${filepath}`) - return null + return { + error: `!!! Missing image file: ${filepath}`, + } } - try { - const [fileTypeSuffix] = filepath.match(/\.[0-9a-z]+$/i) - const storage_path = `${dictionary_id}/images/${entry_id}_${new Date().getTime()}${fileTypeSuffix}` - if (!live) - return { storage_path, serving_url: 'no-serving_url-bc-dry-run' } + const [fileTypeSuffix] = filepath.match(/\.[0-9a-z]+$/i) + const storage_path = `${dictionary_id}/images/${entry_id}_${new Date().getTime()}${fileTypeSuffix}` + + if (!live) + return { storage_path, serving_url: 'no-serving_url-bc-dry-run' } + try { await storage.bucket(fileBucket).upload(imageFilePath, { destination: storage_path, metadata: { originalFileName: filepath, }, }) - - let serving_url - try { - serving_url = await getImageServingUrl(storage_path, environment) - } catch (err) { - throw new Error(`!!! Error getting image serving URL: ${err}`) + } catch (err) { + return { + error: `!!! Trouble uploading ${filepath}. Double-check the file to see if it is just a corrupted jpg (as some are) or if the file is good and perhaps there is code/server/network-connection problem. Error: ${err}`, } + } + try { + const serving_url = await getImageServingUrl(storage_path, environment) return { storage_path, serving_url, } } catch (err) { - throw new Error(`!!! Not adding image ${filepath} as the server had trouble digesting it. Double-check the file to see if it is just a corrupted jpg (as some are) or if the file is good and perhaps there is code/server/network-connection problem. Error: ${err}`) + return { + error: `!!! Error getting image serving URL for ${storage_path}: ${err}`, + } } } From a898b3661d79d9d6e519117ad59b6f587c7d292c Mon Sep 17 00:00:00 2001 From: jacob-8 Date: Wed, 4 Dec 2024 14:08:43 +0800 Subject: [PATCH 10/11] use tags to record import and not content_update --- .../scripts/import/generate-sql-statements.ts | 67 ++---- packages/scripts/import/import-data.snap.json | 198 +++++++++--------- packages/scripts/import/import-data.test.ts | 89 ++++---- packages/scripts/import/import-data.ts | 2 +- 4 files changed, 165 insertions(+), 191 deletions(-) diff --git a/packages/scripts/import/generate-sql-statements.ts b/packages/scripts/import/generate-sql-statements.ts index 4ffcdf5be..d3aff023a 100644 --- a/packages/scripts/import/generate-sql-statements.ts +++ b/packages/scripts/import/generate-sql-statements.ts @@ -1,6 +1,5 @@ import { randomUUID } from 'node:crypto' import type { MultiString, TablesInsert } from '@living-dictionaries/types' -import type { ImportContentUpdate } from '@living-dictionaries/types/supabase/content-import.interface' import { diego_ld_user_id } from '../config-supabase' import type { Number_Suffix, Row, Sense_Prefix } from './row.type' import { sql_file_string } from './to-sql-string' @@ -52,31 +51,6 @@ export async function generate_sql_statements({ updated_at: meta.created_at, } } - const assemble_content_update = ({ data, ...rest }: ImportContentUpdate) => { - const data_without_meta = { ...data } - // @ts-expect-error - delete data_without_meta.id - // @ts-expect-error - delete data_without_meta.dictionary_id - delete data_without_meta.created_at - // @ts-expect-error - delete data_without_meta.created_by - // @ts-expect-error - delete data_without_meta.updated_at - // @ts-expect-error - delete data_without_meta.updated_by - - const content_update: TablesInsert<'content_updates'> = { - ...rest, - id: randomUUID(), - import_id, - dictionary_id, - user_id: c_meta().created_by, - timestamp: c_meta().created_at, - data: data_without_meta, - } - return content_update - } const entry: TablesInsert<'entries'> = { id: entry_id, @@ -99,7 +73,6 @@ export async function generate_sql_statements({ if (row.notes) entry.notes = { default: row.notes } sql_statements += sql_file_string('entries', entry) - sql_statements += sql_file_string('content_updates', assemble_content_update({ type: 'insert_entry', entry_id, data: entry })) if (row.dialects) { const dialect_strings = row.dialects.split('|').map(dialect => dialect.trim()).filter(Boolean) @@ -125,28 +98,28 @@ export async function generate_sql_statements({ } } - if (row.tags) { - const tag_strings = row.tags.split('|').map(tag => tag.trim()).filter(Boolean) - for (const tag_to_assign of tag_strings) { - let tag_id = tags.find(({ name }) => name === tag_to_assign)?.id - if (!tag_id) { - tag_id = randomUUID() - const tag: TablesInsert<'tags'> = { - id: tag_id, - ...c_u_meta(), - dictionary_id, - name: tag_to_assign, - } - sql_statements += sql_file_string('tags', tag) - tags.push({ id: tag.id, name: tag.name }) + const tag_strings = (row.tags || '').split('|').map(tag => tag.trim()).filter(Boolean) + tag_strings.push(import_id) + for (const tag_to_assign of tag_strings) { + let tag_id = tags.find(({ name }) => name === tag_to_assign)?.id + if (!tag_id) { + tag_id = randomUUID() + const tag: TablesInsert<'tags'> = { + id: tag_id, + ...c_u_meta(), + dictionary_id, + ...(tag_to_assign === import_id && { private: true }), + name: tag_to_assign, } - - sql_statements += sql_file_string('entry_tags', { - ...c_meta(), - tag_id, - entry_id, - }) + sql_statements += sql_file_string('tags', tag) + tags.push({ id: tag.id, name: tag.name }) } + + sql_statements += sql_file_string('entry_tags', { + ...c_meta(), + tag_id, + entry_id, + }) } const senses: TablesInsert<'senses'>[] = [] diff --git a/packages/scripts/import/import-data.snap.json b/packages/scripts/import/import-data.snap.json index e0d630bcd..7deef5e5d 100644 --- a/packages/scripts/import/import-data.snap.json +++ b/packages/scripts/import/import-data.snap.json @@ -2,11 +2,11 @@ "entries": [ { "audios": null, - "created_at": "2024-03-08T00:44:04.666+00:00", + "created_at": "2024-03-08T00:44:04.664+00:00", "deleted": null, "dialect_ids": null, "dictionary_id": "example-v4-senses", - "id": "11111111-1111-1111-1111-111111100042", + "id": "11111111-1111-1111-1111-111111100040", "main": { "lexeme": { "default": "kꞌaal", @@ -20,12 +20,12 @@ "glosses": { "es": "sol", }, - "id": "11111111-1111-1111-1111-111111100044", + "id": "11111111-1111-1111-1111-111111100042", "parts_of_speech": [ "n", ], "sentence_ids": [ - "11111111-1111-1111-1111-111111100045", + "11111111-1111-1111-1111-111111100043", ], "variant": { "default": "kꞌahkꞌal", @@ -35,49 +35,51 @@ "glosses": { "es": "fiebre", }, - "id": "11111111-1111-1111-1111-111111100046", + "id": "11111111-1111-1111-1111-111111100044", "parts_of_speech": [ "n", ], "sentence_ids": [ - "11111111-1111-1111-1111-111111100047", + "11111111-1111-1111-1111-111111100045", ], }, { "glosses": { "es": "día", }, - "id": "11111111-1111-1111-1111-111111100048", + "id": "11111111-1111-1111-1111-111111100046", "parts_of_speech": [ "n", ], "sentence_ids": [ - "11111111-1111-1111-1111-111111100049", + "11111111-1111-1111-1111-111111100047", ], }, { "glosses": { "es": "calor", }, - "id": "11111111-1111-1111-1111-111111100050", + "id": "11111111-1111-1111-1111-111111100048", "parts_of_speech": [ "n", ], "sentence_ids": [ - "11111111-1111-1111-1111-111111100051", + "11111111-1111-1111-1111-111111100049", ], }, ], - "tag_ids": null, - "updated_at": "2024-03-08T00:44:04.68+00:00", + "tag_ids": [ + "11111111-1111-1111-1111-111111100041", + ], + "updated_at": "2024-03-08T00:44:04.678+00:00", }, { "audios": null, - "created_at": "2024-03-08T00:44:04.681+00:00", + "created_at": "2024-03-08T00:44:04.679+00:00", "deleted": null, "dialect_ids": null, "dictionary_id": "example-v4-senses", - "id": "11111111-1111-1111-1111-111111100052", + "id": "11111111-1111-1111-1111-111111100050", "main": { "lexeme": { "default": "kꞌajkꞌal", @@ -91,7 +93,7 @@ "glosses": { "es": "sol", }, - "id": "11111111-1111-1111-1111-111111100054", + "id": "11111111-1111-1111-1111-111111100051", "parts_of_speech": [ "n", ], @@ -103,7 +105,7 @@ "glosses": { "es": "día", }, - "id": "11111111-1111-1111-1111-111111100055", + "id": "11111111-1111-1111-1111-111111100052", "parts_of_speech": [ "n", ], @@ -112,7 +114,7 @@ "glosses": { "es": "calor", }, - "id": "11111111-1111-1111-1111-111111100056", + "id": "11111111-1111-1111-1111-111111100053", "parts_of_speech": [ "n", ], @@ -121,22 +123,24 @@ "glosses": { "es": "fiebre", }, - "id": "11111111-1111-1111-1111-111111100057", + "id": "11111111-1111-1111-1111-111111100054", "parts_of_speech": [ "n", ], }, ], - "tag_ids": null, - "updated_at": "2024-03-08T00:44:04.687+00:00", + "tag_ids": [ + "11111111-1111-1111-1111-111111100041", + ], + "updated_at": "2024-03-08T00:44:04.684+00:00", }, { "audios": null, - "created_at": "2024-03-08T00:44:04.688+00:00", + "created_at": "2024-03-08T00:44:04.685+00:00", "deleted": null, "dialect_ids": null, "dictionary_id": "example-v4-senses", - "id": "11111111-1111-1111-1111-111111100058", + "id": "11111111-1111-1111-1111-111111100055", "main": { "lexeme": { "default": "kꞌajkꞌ", @@ -150,12 +154,12 @@ "glosses": { "es": "fuego", }, - "id": "11111111-1111-1111-1111-111111100060", + "id": "11111111-1111-1111-1111-111111100056", "parts_of_speech": [ "n", ], "sentence_ids": [ - "11111111-1111-1111-1111-111111100061", + "11111111-1111-1111-1111-111111100057", ], "variant": { "default": "kꞌahkꞌ", @@ -165,49 +169,51 @@ "glosses": { "es": "bravo", }, - "id": "11111111-1111-1111-1111-111111100062", + "id": "11111111-1111-1111-1111-111111100058", "parts_of_speech": [ "adj", ], "sentence_ids": [ - "11111111-1111-1111-1111-111111100063", + "11111111-1111-1111-1111-111111100059", ], }, { "glosses": { "es": "fiebre", }, - "id": "11111111-1111-1111-1111-111111100064", + "id": "11111111-1111-1111-1111-111111100060", "parts_of_speech": [ "n", ], "sentence_ids": [ - "11111111-1111-1111-1111-111111100065", + "11111111-1111-1111-1111-111111100061", ], }, { "glosses": { "es": "caliente", }, - "id": "11111111-1111-1111-1111-111111100066", + "id": "11111111-1111-1111-1111-111111100062", "parts_of_speech": [ "adj", ], "sentence_ids": [ - "11111111-1111-1111-1111-111111100067", + "11111111-1111-1111-1111-111111100063", ], }, ], - "tag_ids": null, - "updated_at": "2024-03-08T00:44:04.702+00:00", + "tag_ids": [ + "11111111-1111-1111-1111-111111100041", + ], + "updated_at": "2024-03-08T00:44:04.698+00:00", }, { "audios": null, - "created_at": "2024-03-08T00:44:04.703+00:00", + "created_at": "2024-03-08T00:44:04.699+00:00", "deleted": null, "dialect_ids": null, "dictionary_id": "example-v4-senses", - "id": "11111111-1111-1111-1111-111111100068", + "id": "11111111-1111-1111-1111-111111100064", "main": { "lexeme": { "default": "jun", @@ -221,61 +227,63 @@ "glosses": { "es": "libro", }, - "id": "11111111-1111-1111-1111-111111100070", + "id": "11111111-1111-1111-1111-111111100065", "parts_of_speech": [ "n", ], "sentence_ids": [ - "11111111-1111-1111-1111-111111100071", + "11111111-1111-1111-1111-111111100066", ], }, { "glosses": { "es": "cuaderno", }, - "id": "11111111-1111-1111-1111-111111100072", + "id": "11111111-1111-1111-1111-111111100067", "parts_of_speech": [ "n", ], "sentence_ids": [ - "11111111-1111-1111-1111-111111100073", + "11111111-1111-1111-1111-111111100068", ], }, { "glosses": { "es": "documento", }, - "id": "11111111-1111-1111-1111-111111100074", + "id": "11111111-1111-1111-1111-111111100069", "parts_of_speech": [ "n", ], "sentence_ids": [ - "11111111-1111-1111-1111-111111100075", + "11111111-1111-1111-1111-111111100070", ], }, { "glosses": { "es": "papel", }, - "id": "11111111-1111-1111-1111-111111100076", + "id": "11111111-1111-1111-1111-111111100071", "parts_of_speech": [ "n", ], "sentence_ids": [ - "11111111-1111-1111-1111-111111100077", + "11111111-1111-1111-1111-111111100072", ], }, ], - "tag_ids": null, - "updated_at": "2024-03-08T00:44:04.717+00:00", + "tag_ids": [ + "11111111-1111-1111-1111-111111100041", + ], + "updated_at": "2024-03-08T00:44:04.712+00:00", }, { "audios": null, - "created_at": "2024-03-08T00:44:04.718+00:00", + "created_at": "2024-03-08T00:44:04.713+00:00", "deleted": null, "dialect_ids": null, "dictionary_id": "example-v4-senses", - "id": "11111111-1111-1111-1111-111111100078", + "id": "11111111-1111-1111-1111-111111100073", "main": { "lexeme": { "default": "jeꞌel", @@ -289,12 +297,12 @@ "glosses": { "es": "abierto", }, - "id": "11111111-1111-1111-1111-111111100080", + "id": "11111111-1111-1111-1111-111111100074", "parts_of_speech": [ "adj", ], "sentence_ids": [ - "11111111-1111-1111-1111-111111100081", + "11111111-1111-1111-1111-111111100075", ], "variant": { "default": "makal", @@ -304,23 +312,25 @@ "glosses": { "es": "abrir", }, - "id": "11111111-1111-1111-1111-111111100082", + "id": "11111111-1111-1111-1111-111111100076", "sentence_ids": [ - "11111111-1111-1111-1111-111111100083", + "11111111-1111-1111-1111-111111100077", ], }, ], - "tag_ids": null, - "updated_at": "2024-03-08T00:44:04.726+00:00", + "tag_ids": [ + "11111111-1111-1111-1111-111111100041", + ], + "updated_at": "2024-03-08T00:44:04.72+00:00", }, ], "sentences": [ { - "created_at": "2024-03-08T00:44:04.67+00:00", + "created_at": "2024-03-08T00:44:04.668+00:00", "created_by": "be43b1dd-6c64-494d-b5da-10d70c384433", "deleted": null, "dictionary_id": "example-v4-senses", - "id": "11111111-1111-1111-1111-111111100045", + "id": "11111111-1111-1111-1111-111111100043", "text": { "default": "Jaꞌnix lek-a lokꞌix tel kꞌaal", }, @@ -328,15 +338,15 @@ "translation": { "es": "Que bueno, ya salió el sol", }, - "updated_at": "2024-03-08T00:44:04.67+00:00", + "updated_at": "2024-03-08T00:44:04.668+00:00", "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433", }, { - "created_at": "2024-03-08T00:44:04.673+00:00", + "created_at": "2024-03-08T00:44:04.671+00:00", "created_by": "be43b1dd-6c64-494d-b5da-10d70c384433", "deleted": null, "dictionary_id": "example-v4-senses", - "id": "11111111-1111-1111-1111-111111100047", + "id": "11111111-1111-1111-1111-111111100045", "text": { "default": "Ay bayal skꞌaal te chꞌin x-Ixchele", }, @@ -344,15 +354,15 @@ "translation": { "es": "Mi hijita Ixchel tiene mucha fiebre", }, - "updated_at": "2024-03-08T00:44:04.673+00:00", + "updated_at": "2024-03-08T00:44:04.671+00:00", "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433", }, { - "created_at": "2024-03-08T00:44:04.676+00:00", + "created_at": "2024-03-08T00:44:04.674+00:00", "created_by": "be43b1dd-6c64-494d-b5da-10d70c384433", "deleted": null, "dictionary_id": "example-v4-senses", - "id": "11111111-1111-1111-1111-111111100049", + "id": "11111111-1111-1111-1111-111111100047", "text": { "default": "Bajtix kaal mamtik, yorailix ich lewa", }, @@ -360,15 +370,15 @@ "translation": { "es": "Ya transcurrió el día mi estimado señor, es momento de tomar un descanso", }, - "updated_at": "2024-03-08T00:44:04.676+00:00", + "updated_at": "2024-03-08T00:44:04.674+00:00", "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433", }, { - "created_at": "2024-03-08T00:44:04.679+00:00", + "created_at": "2024-03-08T00:44:04.677+00:00", "created_by": "be43b1dd-6c64-494d-b5da-10d70c384433", "deleted": null, "dictionary_id": "example-v4-senses", - "id": "11111111-1111-1111-1111-111111100051", + "id": "11111111-1111-1111-1111-111111100049", "text": { "default": "Toyol kꞌaal ya jkaꞌiy", }, @@ -376,15 +386,15 @@ "translation": { "es": "Siento mucho calor", }, - "updated_at": "2024-03-08T00:44:04.679+00:00", + "updated_at": "2024-03-08T00:44:04.677+00:00", "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433", }, { - "created_at": "2024-03-08T00:44:04.692+00:00", + "created_at": "2024-03-08T00:44:04.688+00:00", "created_by": "be43b1dd-6c64-494d-b5da-10d70c384433", "deleted": null, "dictionary_id": "example-v4-senses", - "id": "11111111-1111-1111-1111-111111100061", + "id": "11111111-1111-1111-1111-111111100057", "text": { "default": "Tilix kuꞌun-i kꞌajkꞌi", }, @@ -392,15 +402,15 @@ "translation": { "es": "Ya hice el fuego", }, - "updated_at": "2024-03-08T00:44:04.692+00:00", + "updated_at": "2024-03-08T00:44:04.688+00:00", "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433", }, { - "created_at": "2024-03-08T00:44:04.695+00:00", + "created_at": "2024-03-08T00:44:04.691+00:00", "created_by": "be43b1dd-6c64-494d-b5da-10d70c384433", "deleted": null, "dictionary_id": "example-v4-senses", - "id": "11111111-1111-1111-1111-111111100063", + "id": "11111111-1111-1111-1111-111111100059", "text": { "default": "Lom kꞌajkꞌ te mamal jkaxlane", }, @@ -408,15 +418,15 @@ "translation": { "es": "El mestizo es muy bravo", }, - "updated_at": "2024-03-08T00:44:04.695+00:00", + "updated_at": "2024-03-08T00:44:04.691+00:00", "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433", }, { - "created_at": "2024-03-08T00:44:04.698+00:00", + "created_at": "2024-03-08T00:44:04.694+00:00", "created_by": "be43b1dd-6c64-494d-b5da-10d70c384433", "deleted": null, "dictionary_id": "example-v4-senses", - "id": "11111111-1111-1111-1111-111111100065", + "id": "11111111-1111-1111-1111-111111100061", "text": { "default": "Tsakbil ta kꞌajkꞌ te alale", }, @@ -424,15 +434,15 @@ "translation": { "es": "El bebé tiene mucha fiebre", }, - "updated_at": "2024-03-08T00:44:04.698+00:00", + "updated_at": "2024-03-08T00:44:04.694+00:00", "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433", }, { - "created_at": "2024-03-08T00:44:04.701+00:00", + "created_at": "2024-03-08T00:44:04.697+00:00", "created_by": "be43b1dd-6c64-494d-b5da-10d70c384433", "deleted": null, "dictionary_id": "example-v4-senses", - "id": "11111111-1111-1111-1111-111111100067", + "id": "11111111-1111-1111-1111-111111100063", "text": { "default": "El café está caliente, tómalo despacio", }, @@ -440,15 +450,15 @@ "translation": { "es": "Kꞌajkꞌ te kajpele, kꞌume xa awuchꞌ", }, - "updated_at": "2024-03-08T00:44:04.701+00:00", + "updated_at": "2024-03-08T00:44:04.697+00:00", "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433", }, { - "created_at": "2024-03-08T00:44:04.707+00:00", + "created_at": "2024-03-08T00:44:04.702+00:00", "created_by": "be43b1dd-6c64-494d-b5da-10d70c384433", "deleted": null, "dictionary_id": "example-v4-senses", - "id": "11111111-1111-1111-1111-111111100071", + "id": "11111111-1111-1111-1111-111111100066", "text": { "default": "¿Beluk apas? - Yakalon ta skꞌoponel jun", }, @@ -456,15 +466,15 @@ "translation": { "es": "¿Qué haces? - Estoy leyendo un libro", }, - "updated_at": "2024-03-08T00:44:04.707+00:00", + "updated_at": "2024-03-08T00:44:04.702+00:00", "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433", }, { - "created_at": "2024-03-08T00:44:04.71+00:00", + "created_at": "2024-03-08T00:44:04.705+00:00", "created_by": "be43b1dd-6c64-494d-b5da-10d70c384433", "deleted": null, "dictionary_id": "example-v4-senses", - "id": "11111111-1111-1111-1111-111111100073", + "id": "11111111-1111-1111-1111-111111100068", "text": { "default": "La jta ta kitsel te june", }, @@ -472,15 +482,15 @@ "translation": { "es": "Alcancé a rayar mi cuaderno", }, - "updated_at": "2024-03-08T00:44:04.71+00:00", + "updated_at": "2024-03-08T00:44:04.705+00:00", "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433", }, { - "created_at": "2024-03-08T00:44:04.713+00:00", + "created_at": "2024-03-08T00:44:04.708+00:00", "created_by": "be43b1dd-6c64-494d-b5da-10d70c384433", "deleted": null, "dictionary_id": "example-v4-senses", - "id": "11111111-1111-1111-1111-111111100075", + "id": "11111111-1111-1111-1111-111111100070", "text": { "default": "Maꞌme xa awochꞌ te ajune", }, @@ -488,15 +498,15 @@ "translation": { "es": "No vayas a arrugar tu documento", }, - "updated_at": "2024-03-08T00:44:04.713+00:00", + "updated_at": "2024-03-08T00:44:04.708+00:00", "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433", }, { - "created_at": "2024-03-08T00:44:04.716+00:00", + "created_at": "2024-03-08T00:44:04.711+00:00", "created_by": "be43b1dd-6c64-494d-b5da-10d70c384433", "deleted": null, "dictionary_id": "example-v4-senses", - "id": "11111111-1111-1111-1111-111111100077", + "id": "11111111-1111-1111-1111-111111100072", "text": { "default": "Zoe rompió el papel", }, @@ -504,15 +514,15 @@ "translation": { "es": "La schꞌiꞌ jun te Zoe", }, - "updated_at": "2024-03-08T00:44:04.716+00:00", + "updated_at": "2024-03-08T00:44:04.711+00:00", "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433", }, { - "created_at": "2024-03-08T00:44:04.722+00:00", + "created_at": "2024-03-08T00:44:04.716+00:00", "created_by": "be43b1dd-6c64-494d-b5da-10d70c384433", "deleted": null, "dictionary_id": "example-v4-senses", - "id": "11111111-1111-1111-1111-111111100081", + "id": "11111111-1111-1111-1111-111111100075", "text": { "default": "Jeꞌel jilel stiꞌ jna", }, @@ -520,15 +530,15 @@ "translation": { "es": "La puerta de mi casa quedó abierta", }, - "updated_at": "2024-03-08T00:44:04.722+00:00", + "updated_at": "2024-03-08T00:44:04.716+00:00", "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433", }, { - "created_at": "2024-03-08T00:44:04.725+00:00", + "created_at": "2024-03-08T00:44:04.719+00:00", "created_by": "be43b1dd-6c64-494d-b5da-10d70c384433", "deleted": null, "dictionary_id": "example-v4-senses", - "id": "11111111-1111-1111-1111-111111100083", + "id": "11111111-1111-1111-1111-111111100077", "text": { "default": "Jeꞌa tel tebuk i tiꞌnai ay bayal kꞌaal", }, @@ -536,7 +546,7 @@ "translation": { "es": "Abre un poco la puerta, hace mucho calor", }, - "updated_at": "2024-03-08T00:44:04.725+00:00", + "updated_at": "2024-03-08T00:44:04.719+00:00", "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433", }, ], diff --git a/packages/scripts/import/import-data.test.ts b/packages/scripts/import/import-data.test.ts index dbbb6debf..26f293354 100644 --- a/packages/scripts/import/import-data.test.ts +++ b/packages/scripts/import/import-data.test.ts @@ -40,9 +40,9 @@ async function import_data(rows: Row[], dictionary_id = test_dictionary_id) { rows, import_id, upload_operations: { - upload_photo: async (filepath: string) => ({ storage_path: filepath, serving_url: filepath }), - upload_audio: async (filepath: string) => ({ storage_path: filepath }), - // upload_video: async (filepath: string) => ({ storage_path: filepath }), + upload_photo: async (filepath: string) => ({ storage_path: filepath, serving_url: filepath, error: null }), + upload_audio: async (filepath: string) => ({ storage_path: filepath, error: null }), + // upload_video: async (filepath: string) => ({ storage_path: filepath, error: null }), }, live: true, }) @@ -103,7 +103,9 @@ describe(import_data, () => { ], }, ], - "tag_ids": null, + "tag_ids": [ + "11111111-1111-1111-1111-111111100001", + ], "updated_at": "2024-03-08T00:44:04.608+00:00", }, ] @@ -134,38 +136,26 @@ describe(import_data, () => { "id": "11111111-1111-1111-1111-111111100008", }, ], - "tag_ids": null, + "tag_ids": [ + "11111111-1111-1111-1111-111111100007", + ], "updated_at": "2024-03-08T00:44:04.612+00:00", }, ] `) - const { data: content_updates } = await admin_supabase.from('content_updates').select() - expect(content_updates).toMatchInlineSnapshot(` + const { data: tags } = await admin_supabase.from('tags').select() + expect(tags).toMatchInlineSnapshot(` [ { - "audio_id": null, - "change": null, - "data": { - "lexeme": { - "default": "hi", - }, - }, - "dialect_id": null, + "created_at": "2024-03-08T00:44:04.61+00:00", + "created_by": "be43b1dd-6c64-494d-b5da-10d70c384433", + "deleted": null, "dictionary_id": "test_dictionary_id", - "entry_id": "11111111-1111-1111-1111-111111100006", "id": "11111111-1111-1111-1111-111111100007", - "import_id": "v4-test", - "photo_id": null, - "sense_id": null, - "sentence_id": null, - "speaker_id": null, - "table": null, - "tag_id": null, - "text_id": null, - "timestamp": "2024-03-08T00:44:04.611+00:00", - "type": "insert_entry", - "user_id": "be43b1dd-6c64-494d-b5da-10d70c384433", - "video_id": null, + "name": "v4-test", + "private": true, + "updated_at": "2024-03-08T00:44:04.61+00:00", + "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433", }, ] `) @@ -177,7 +167,7 @@ describe(import_data, () => { { lexeme: 'world', dialects: 'dialect 1', tags: 'archaic' }, ]) expect(entries[0].dialect_ids).toHaveLength(1) - expect(entries[0].tag_ids).toHaveLength(1) + expect(entries[0].tag_ids).toHaveLength(2) // also have import tag expect(entries[0].dialect_ids).toEqual(entries[1].dialect_ids) expect(entries[0].tag_ids).toEqual(entries[1].tag_ids) }) @@ -191,14 +181,14 @@ describe(import_data, () => { expect(speakers[0]).toMatchInlineSnapshot(` { "birthplace": "Whoville", - "created_at": "2024-03-08T00:44:04.632+00:00", + "created_at": "2024-03-08T00:44:04.631+00:00", "decade": 12, "deleted": null, "dictionary_id": "test_dictionary_id", "gender": "m", - "id": "11111111-1111-1111-1111-111111100021", + "id": "11111111-1111-1111-1111-111111100020", "name": "speaker 1", - "updated_at": "2024-03-08T00:44:04.632+00:00", + "updated_at": "2024-03-08T00:44:04.631+00:00", } `) expect(entries[0].audios[0].speaker_ids[0]).toEqual(speakers[0].id) @@ -211,7 +201,7 @@ describe(import_data, () => { ]) expect(entries[0].senses[0].photo_ids).toMatchInlineSnapshot(` [ - "11111111-1111-1111-1111-111111100029", + "11111111-1111-1111-1111-111111100027", ] `) }) @@ -257,14 +247,14 @@ describe(import_data, () => { [ { "audios": null, - "created_at": "2024-03-08T00:44:04.646+00:00", + "created_at": "2024-03-08T00:44:04.644+00:00", "deleted": null, "dialect_ids": [ - "11111111-1111-1111-1111-111111100032", - "11111111-1111-1111-1111-111111100033", + "11111111-1111-1111-1111-111111100029", + "11111111-1111-1111-1111-111111100030", ], "dictionary_id": "test_dictionary_id", - "id": "11111111-1111-1111-1111-111111100030", + "id": "11111111-1111-1111-1111-111111100028", "main": { "elicitation_id": "A1", "lexeme": { @@ -291,7 +281,7 @@ describe(import_data, () => { "glosses": { "es": "hola", }, - "id": "11111111-1111-1111-1111-111111100036", + "id": "11111111-1111-1111-1111-111111100034", "noun_class": "12", "parts_of_speech": [ "n", @@ -301,7 +291,7 @@ describe(import_data, () => { "default": "his", }, "sentence_ids": [ - "11111111-1111-1111-1111-111111100037", + "11111111-1111-1111-1111-111111100035", ], "variant": { "default": "variant", @@ -311,7 +301,7 @@ describe(import_data, () => { "glosses": { "en": "bye", }, - "id": "11111111-1111-1111-1111-111111100038", + "id": "11111111-1111-1111-1111-111111100036", "semantic_domains": [ "2", "2.3", @@ -321,18 +311,19 @@ describe(import_data, () => { "glosses": { "fr": "auch", }, - "id": "11111111-1111-1111-1111-111111100039", + "id": "11111111-1111-1111-1111-111111100037", "sentence_ids": [ - "11111111-1111-1111-1111-111111100040", - "11111111-1111-1111-1111-111111100041", + "11111111-1111-1111-1111-111111100038", + "11111111-1111-1111-1111-111111100039", ], }, ], "tag_ids": [ - "11111111-1111-1111-1111-111111100034", - "11111111-1111-1111-1111-111111100035", + "11111111-1111-1111-1111-111111100031", + "11111111-1111-1111-1111-111111100032", + "11111111-1111-1111-1111-111111100033", ], - "updated_at": "2024-03-08T00:44:04.665+00:00", + "updated_at": "2024-03-08T00:44:04.663+00:00", }, ] `) @@ -340,7 +331,7 @@ describe(import_data, () => { expect(sentences).toMatchInlineSnapshot(` [ { - "id": "11111111-1111-1111-1111-111111100037", + "id": "11111111-1111-1111-1111-111111100035", "text": { "default": "we say hi like this", }, @@ -349,7 +340,7 @@ describe(import_data, () => { }, }, { - "id": "11111111-1111-1111-1111-111111100040", + "id": "11111111-1111-1111-1111-111111100038", "text": { "default": "hi doc", }, @@ -358,7 +349,7 @@ describe(import_data, () => { }, }, { - "id": "11111111-1111-1111-1111-111111100041", + "id": "11111111-1111-1111-1111-111111100039", "text": { "default": "bye doc", }, diff --git a/packages/scripts/import/import-data.ts b/packages/scripts/import/import-data.ts index 9cd1a5eab..77b81e9ef 100644 --- a/packages/scripts/import/import-data.ts +++ b/packages/scripts/import/import-data.ts @@ -1,5 +1,5 @@ import { writeFileSync } from 'node:fs' -import { admin_supabase, anon_supabase, postgres } from '../config-supabase' +import { anon_supabase, postgres } from '../config-supabase' import type { Upload_Operations } from './generate-sql-statements' import { generate_sql_statements } from './generate-sql-statements' import type { Row } from './row.type' From dfa260e4bcbd6ca8e379f0e85ad1a53807833ed1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20C=C3=B3rdova=20Nieto?= Date: Fri, 6 Dec 2024 11:32:41 -0600 Subject: [PATCH 11/11] update import-data snap --- packages/scripts/import/import-data.snap.json | 294 +++++++++--------- 1 file changed, 147 insertions(+), 147 deletions(-) diff --git a/packages/scripts/import/import-data.snap.json b/packages/scripts/import/import-data.snap.json index 7deef5e5d..d63c1d946 100644 --- a/packages/scripts/import/import-data.snap.json +++ b/packages/scripts/import/import-data.snap.json @@ -9,69 +9,69 @@ "id": "11111111-1111-1111-1111-111111100040", "main": { "lexeme": { - "default": "kꞌaal", + "default": "kꞌaal" }, "notes": { - "default": "26/dic./2020", - }, + "default": "26/dic./2020" + } }, "senses": [ { "glosses": { - "es": "sol", + "es": "sol" }, "id": "11111111-1111-1111-1111-111111100042", "parts_of_speech": [ - "n", + "n" ], "sentence_ids": [ - "11111111-1111-1111-1111-111111100043", + "11111111-1111-1111-1111-111111100043" ], "variant": { - "default": "kꞌahkꞌal", - }, + "default": "kꞌahkꞌal" + } }, { "glosses": { - "es": "fiebre", + "es": "fiebre" }, "id": "11111111-1111-1111-1111-111111100044", "parts_of_speech": [ - "n", + "n" ], "sentence_ids": [ - "11111111-1111-1111-1111-111111100045", - ], + "11111111-1111-1111-1111-111111100045" + ] }, { "glosses": { - "es": "día", + "es": "día" }, "id": "11111111-1111-1111-1111-111111100046", "parts_of_speech": [ - "n", + "n" ], "sentence_ids": [ - "11111111-1111-1111-1111-111111100047", - ], + "11111111-1111-1111-1111-111111100047" + ] }, { "glosses": { - "es": "calor", + "es": "calor" }, "id": "11111111-1111-1111-1111-111111100048", "parts_of_speech": [ - "n", + "n" ], "sentence_ids": [ - "11111111-1111-1111-1111-111111100049", - ], - }, + "11111111-1111-1111-1111-111111100049" + ] + } ], "tag_ids": [ - "11111111-1111-1111-1111-111111100041", + "11111111-1111-1111-1111-111111100041" ], - "updated_at": "2024-03-08T00:44:04.678+00:00", + "updated_at": "2024-03-08T00:44:04.678+00:00" }, { "audios": null, @@ -82,57 +82,57 @@ "id": "11111111-1111-1111-1111-111111100050", "main": { "lexeme": { - "default": "kꞌajkꞌal", + "default": "kꞌajkꞌal" }, "notes": { - "default": "14/dic./2019", - }, + "default": "14/dic./2019" + } }, "senses": [ { "glosses": { - "es": "sol", + "es": "sol" }, "id": "11111111-1111-1111-1111-111111100051", "parts_of_speech": [ - "n", + "n" ], "variant": { - "default": "kꞌahkꞌal", - }, + "default": "kꞌahkꞌal" + } }, { "glosses": { - "es": "día", + "es": "día" }, "id": "11111111-1111-1111-1111-111111100052", "parts_of_speech": [ - "n", - ], + "n" + ] }, { "glosses": { - "es": "calor", + "es": "calor" }, "id": "11111111-1111-1111-1111-111111100053", "parts_of_speech": [ - "n", - ], + "n" + ] }, { "glosses": { - "es": "fiebre", + "es": "fiebre" }, "id": "11111111-1111-1111-1111-111111100054", "parts_of_speech": [ - "n", - ], - }, + "n" + ] + } ], "tag_ids": [ - "11111111-1111-1111-1111-111111100041", + "11111111-1111-1111-1111-111111100041" ], - "updated_at": "2024-03-08T00:44:04.684+00:00", + "updated_at": "2024-03-08T00:44:04.684+00:00" }, { "audios": null, @@ -143,69 +143,69 @@ "id": "11111111-1111-1111-1111-111111100055", "main": { "lexeme": { - "default": "kꞌajkꞌ", + "default": "kꞌajkꞌ" }, "notes": { - "default": "23/sep./2023", - }, + "default": "23/sep./2023" + } }, "senses": [ { "glosses": { - "es": "fuego", + "es": "fuego" }, "id": "11111111-1111-1111-1111-111111100056", "parts_of_speech": [ - "n", + "n" ], "sentence_ids": [ - "11111111-1111-1111-1111-111111100057", + "11111111-1111-1111-1111-111111100057" ], "variant": { - "default": "kꞌahkꞌ", - }, + "default": "kꞌahkꞌ" + } }, { "glosses": { - "es": "bravo", + "es": "bravo" }, "id": "11111111-1111-1111-1111-111111100058", "parts_of_speech": [ - "adj", + "adj" ], "sentence_ids": [ - "11111111-1111-1111-1111-111111100059", - ], + "11111111-1111-1111-1111-111111100059" + ] }, { "glosses": { - "es": "fiebre", + "es": "fiebre" }, "id": "11111111-1111-1111-1111-111111100060", "parts_of_speech": [ - "n", + "n" ], "sentence_ids": [ - "11111111-1111-1111-1111-111111100061", - ], + "11111111-1111-1111-1111-111111100061" + ] }, { "glosses": { - "es": "caliente", + "es": "caliente" }, "id": "11111111-1111-1111-1111-111111100062", "parts_of_speech": [ - "adj", + "adj" ], "sentence_ids": [ - "11111111-1111-1111-1111-111111100063", - ], - }, + "11111111-1111-1111-1111-111111100063" + ] + } ], "tag_ids": [ - "11111111-1111-1111-1111-111111100041", + "11111111-1111-1111-1111-111111100041" ], - "updated_at": "2024-03-08T00:44:04.698+00:00", + "updated_at": "2024-03-08T00:44:04.698+00:00" }, { "audios": null, @@ -216,66 +216,66 @@ "id": "11111111-1111-1111-1111-111111100064", "main": { "lexeme": { - "default": "jun", + "default": "jun" }, "notes": { - "default": "26/sep./2023", - }, + "default": "26/sep./2023" + } }, "senses": [ { "glosses": { - "es": "libro", + "es": "libro" }, "id": "11111111-1111-1111-1111-111111100065", "parts_of_speech": [ - "n", + "n" ], "sentence_ids": [ - "11111111-1111-1111-1111-111111100066", - ], + "11111111-1111-1111-1111-111111100066" + ] }, { "glosses": { - "es": "cuaderno", + "es": "cuaderno" }, "id": "11111111-1111-1111-1111-111111100067", "parts_of_speech": [ - "n", + "n" ], "sentence_ids": [ - "11111111-1111-1111-1111-111111100068", - ], + "11111111-1111-1111-1111-111111100068" + ] }, { "glosses": { - "es": "documento", + "es": "documento" }, "id": "11111111-1111-1111-1111-111111100069", "parts_of_speech": [ - "n", + "n" ], "sentence_ids": [ - "11111111-1111-1111-1111-111111100070", - ], + "11111111-1111-1111-1111-111111100070" + ] }, { "glosses": { - "es": "papel", + "es": "papel" }, "id": "11111111-1111-1111-1111-111111100071", "parts_of_speech": [ - "n", + "n" ], "sentence_ids": [ - "11111111-1111-1111-1111-111111100072", - ], - }, + "11111111-1111-1111-1111-111111100072" + ] + } ], "tag_ids": [ - "11111111-1111-1111-1111-111111100041", + "11111111-1111-1111-1111-111111100041" ], - "updated_at": "2024-03-08T00:44:04.712+00:00", + "updated_at": "2024-03-08T00:44:04.712+00:00" }, { "audios": null, @@ -286,43 +286,43 @@ "id": "11111111-1111-1111-1111-111111100073", "main": { "lexeme": { - "default": "jeꞌel", + "default": "jeꞌel" }, "notes": { - "default": "08/abr./2019", - }, + "default": "08/abr./2019" + } }, "senses": [ { "glosses": { - "es": "abierto", + "es": "abierto" }, "id": "11111111-1111-1111-1111-111111100074", "parts_of_speech": [ - "adj", + "adj" ], "sentence_ids": [ - "11111111-1111-1111-1111-111111100075", + "11111111-1111-1111-1111-111111100075" ], "variant": { - "default": "makal", - }, + "default": "makal" + } }, { "glosses": { - "es": "abrir", + "es": "abrir" }, "id": "11111111-1111-1111-1111-111111100076", "sentence_ids": [ - "11111111-1111-1111-1111-111111100077", - ], - }, + "11111111-1111-1111-1111-111111100077" + ] + } ], "tag_ids": [ - "11111111-1111-1111-1111-111111100041", + "11111111-1111-1111-1111-111111100041" ], - "updated_at": "2024-03-08T00:44:04.72+00:00", - }, + "updated_at": "2024-03-08T00:44:04.72+00:00" + } ], "sentences": [ { @@ -332,14 +332,14 @@ "dictionary_id": "example-v4-senses", "id": "11111111-1111-1111-1111-111111100043", "text": { - "default": "Jaꞌnix lek-a lokꞌix tel kꞌaal", + "default": "Jaꞌnix lek-a lokꞌix tel kꞌaal" }, "text_id": null, "translation": { - "es": "Que bueno, ya salió el sol", + "es": "Que bueno, ya salió el sol" }, "updated_at": "2024-03-08T00:44:04.668+00:00", - "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433", + "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433" }, { "created_at": "2024-03-08T00:44:04.671+00:00", @@ -348,14 +348,14 @@ "dictionary_id": "example-v4-senses", "id": "11111111-1111-1111-1111-111111100045", "text": { - "default": "Ay bayal skꞌaal te chꞌin x-Ixchele", + "default": "Ay bayal skꞌaal te chꞌin x-Ixchele" }, "text_id": null, "translation": { - "es": "Mi hijita Ixchel tiene mucha fiebre", + "es": "Mi hijita Ixchel tiene mucha fiebre" }, "updated_at": "2024-03-08T00:44:04.671+00:00", - "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433", + "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433" }, { "created_at": "2024-03-08T00:44:04.674+00:00", @@ -364,14 +364,14 @@ "dictionary_id": "example-v4-senses", "id": "11111111-1111-1111-1111-111111100047", "text": { - "default": "Bajtix kaal mamtik, yorailix ich lewa", + "default": "Bajtix kaal mamtik, yorailix ich lewa" }, "text_id": null, "translation": { - "es": "Ya transcurrió el día mi estimado señor, es momento de tomar un descanso", + "es": "Ya transcurrió el día mi estimado señor, es momento de tomar un descanso" }, "updated_at": "2024-03-08T00:44:04.674+00:00", - "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433", + "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433" }, { "created_at": "2024-03-08T00:44:04.677+00:00", @@ -380,14 +380,14 @@ "dictionary_id": "example-v4-senses", "id": "11111111-1111-1111-1111-111111100049", "text": { - "default": "Toyol kꞌaal ya jkaꞌiy", + "default": "Toyol kꞌaal ya jkaꞌiy" }, "text_id": null, "translation": { - "es": "Siento mucho calor", + "es": "Siento mucho calor" }, "updated_at": "2024-03-08T00:44:04.677+00:00", - "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433", + "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433" }, { "created_at": "2024-03-08T00:44:04.688+00:00", @@ -396,14 +396,14 @@ "dictionary_id": "example-v4-senses", "id": "11111111-1111-1111-1111-111111100057", "text": { - "default": "Tilix kuꞌun-i kꞌajkꞌi", + "default": "Tilix kuꞌun-i kꞌajkꞌi" }, "text_id": null, "translation": { - "es": "Ya hice el fuego", + "es": "Ya hice el fuego" }, "updated_at": "2024-03-08T00:44:04.688+00:00", - "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433", + "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433" }, { "created_at": "2024-03-08T00:44:04.691+00:00", @@ -412,14 +412,14 @@ "dictionary_id": "example-v4-senses", "id": "11111111-1111-1111-1111-111111100059", "text": { - "default": "Lom kꞌajkꞌ te mamal jkaxlane", + "default": "Lom kꞌajkꞌ te mamal jkaxlane" }, "text_id": null, "translation": { - "es": "El mestizo es muy bravo", + "es": "El mestizo es muy bravo" }, "updated_at": "2024-03-08T00:44:04.691+00:00", - "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433", + "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433" }, { "created_at": "2024-03-08T00:44:04.694+00:00", @@ -428,14 +428,14 @@ "dictionary_id": "example-v4-senses", "id": "11111111-1111-1111-1111-111111100061", "text": { - "default": "Tsakbil ta kꞌajkꞌ te alale", + "default": "Tsakbil ta kꞌajkꞌ te alale" }, "text_id": null, "translation": { - "es": "El bebé tiene mucha fiebre", + "es": "El bebé tiene mucha fiebre" }, "updated_at": "2024-03-08T00:44:04.694+00:00", - "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433", + "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433" }, { "created_at": "2024-03-08T00:44:04.697+00:00", @@ -444,14 +444,14 @@ "dictionary_id": "example-v4-senses", "id": "11111111-1111-1111-1111-111111100063", "text": { - "default": "El café está caliente, tómalo despacio", + "default": "El café está caliente, tómalo despacio" }, "text_id": null, "translation": { - "es": "Kꞌajkꞌ te kajpele, kꞌume xa awuchꞌ", + "es": "Kꞌajkꞌ te kajpele, kꞌume xa awuchꞌ" }, "updated_at": "2024-03-08T00:44:04.697+00:00", - "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433", + "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433" }, { "created_at": "2024-03-08T00:44:04.702+00:00", @@ -460,14 +460,14 @@ "dictionary_id": "example-v4-senses", "id": "11111111-1111-1111-1111-111111100066", "text": { - "default": "¿Beluk apas? - Yakalon ta skꞌoponel jun", + "default": "¿Beluk apas? - Yakalon ta skꞌoponel jun" }, "text_id": null, "translation": { - "es": "¿Qué haces? - Estoy leyendo un libro", + "es": "¿Qué haces? - Estoy leyendo un libro" }, "updated_at": "2024-03-08T00:44:04.702+00:00", - "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433", + "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433" }, { "created_at": "2024-03-08T00:44:04.705+00:00", @@ -476,14 +476,14 @@ "dictionary_id": "example-v4-senses", "id": "11111111-1111-1111-1111-111111100068", "text": { - "default": "La jta ta kitsel te june", + "default": "La jta ta kitsel te june" }, "text_id": null, "translation": { - "es": "Alcancé a rayar mi cuaderno", + "es": "Alcancé a rayar mi cuaderno" }, "updated_at": "2024-03-08T00:44:04.705+00:00", - "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433", + "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433" }, { "created_at": "2024-03-08T00:44:04.708+00:00", @@ -492,14 +492,14 @@ "dictionary_id": "example-v4-senses", "id": "11111111-1111-1111-1111-111111100070", "text": { - "default": "Maꞌme xa awochꞌ te ajune", + "default": "Maꞌme xa awochꞌ te ajune" }, "text_id": null, "translation": { - "es": "No vayas a arrugar tu documento", + "es": "No vayas a arrugar tu documento" }, "updated_at": "2024-03-08T00:44:04.708+00:00", - "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433", + "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433" }, { "created_at": "2024-03-08T00:44:04.711+00:00", @@ -508,14 +508,14 @@ "dictionary_id": "example-v4-senses", "id": "11111111-1111-1111-1111-111111100072", "text": { - "default": "Zoe rompió el papel", + "default": "Zoe rompió el papel" }, "text_id": null, "translation": { - "es": "La schꞌiꞌ jun te Zoe", + "es": "La schꞌiꞌ jun te Zoe" }, "updated_at": "2024-03-08T00:44:04.711+00:00", - "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433", + "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433" }, { "created_at": "2024-03-08T00:44:04.716+00:00", @@ -524,14 +524,14 @@ "dictionary_id": "example-v4-senses", "id": "11111111-1111-1111-1111-111111100075", "text": { - "default": "Jeꞌel jilel stiꞌ jna", + "default": "Jeꞌel jilel stiꞌ jna" }, "text_id": null, "translation": { - "es": "La puerta de mi casa quedó abierta", + "es": "La puerta de mi casa quedó abierta" }, "updated_at": "2024-03-08T00:44:04.716+00:00", - "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433", + "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433" }, { "created_at": "2024-03-08T00:44:04.719+00:00", @@ -540,14 +540,14 @@ "dictionary_id": "example-v4-senses", "id": "11111111-1111-1111-1111-111111100077", "text": { - "default": "Jeꞌa tel tebuk i tiꞌnai ay bayal kꞌaal", + "default": "Jeꞌa tel tebuk i tiꞌnai ay bayal kꞌaal" }, "text_id": null, "translation": { - "es": "Abre un poco la puerta, hace mucho calor", + "es": "Abre un poco la puerta, hace mucho calor" }, "updated_at": "2024-03-08T00:44:04.719+00:00", - "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433", - }, - ], -} \ No newline at end of file + "updated_by": "be43b1dd-6c64-494d-b5da-10d70c384433" + } + ] +}