From 4d1afff9fcf51bbe9205fd0d40e83cd1092ed8bd Mon Sep 17 00:00:00 2001 From: Luan Cazarine Date: Mon, 17 Mar 2025 16:59:29 -0300 Subject: [PATCH 1/3] evernote init --- .../actions/create-note/create-note.mjs | 37 +++ .../create-notebook/create-notebook.mjs | 31 +++ .../actions/update-note/update-note.mjs | 31 +++ components/evernote/evernote.app.mjs | 225 +++++++++++++++++- components/evernote/package.json | 2 +- .../evernote/sources/new-note/new-note.mjs | 95 ++++++++ .../sources/new-notebook/new-notebook.mjs | 91 +++++++ .../evernote/sources/new-tag/new-tag.mjs | 64 +++++ 8 files changed, 572 insertions(+), 4 deletions(-) create mode 100644 components/evernote/actions/create-note/create-note.mjs create mode 100644 components/evernote/actions/create-notebook/create-notebook.mjs create mode 100644 components/evernote/actions/update-note/update-note.mjs create mode 100644 components/evernote/sources/new-note/new-note.mjs create mode 100644 components/evernote/sources/new-notebook/new-notebook.mjs create mode 100644 components/evernote/sources/new-tag/new-tag.mjs diff --git a/components/evernote/actions/create-note/create-note.mjs b/components/evernote/actions/create-note/create-note.mjs new file mode 100644 index 0000000000000..83a28d1b5c75a --- /dev/null +++ b/components/evernote/actions/create-note/create-note.mjs @@ -0,0 +1,37 @@ +import evernote from "../../evernote.app.mjs"; +import { axios } from "@pipedream/platform"; + +export default { + key: "evernote-create-note", + name: "Create Note", + description: "Creates a new note in Evernote. [See the documentation]()", + version: "0.0.{{ts}}", + type: "action", + props: { + evernote, + noteTitle: { + propDefinition: [ + "evernote", + "noteTitle", + ], + }, + noteContent: { + propDefinition: [ + "evernote", + "noteContent", + ], + }, + noteAdditionalFields: { + propDefinition: [ + "evernote", + "noteAdditionalFields", + ], + optional: true, + }, + }, + async run({ $ }) { + const note = await this.evernote.createNote(); + $.export("$summary", `Created note "${note.title}" with ID ${note.id}`); + return note; + }, +}; diff --git a/components/evernote/actions/create-notebook/create-notebook.mjs b/components/evernote/actions/create-notebook/create-notebook.mjs new file mode 100644 index 0000000000000..ef2706ac1fd54 --- /dev/null +++ b/components/evernote/actions/create-notebook/create-notebook.mjs @@ -0,0 +1,31 @@ +import evernote from "../../evernote.app.mjs"; +import { axios } from "@pipedream/platform"; + +export default { + key: "evernote-create-notebook", + name: "Create Notebook", + description: "Creates a new notebook in Evernote. [See the documentation]()", + version: "0.0.{{ts}}", + type: "action", + props: { + evernote, + notebookName: { + propDefinition: [ + "evernote", + "notebookName", + ], + }, + notebookAdditionalFields: { + propDefinition: [ + "evernote", + "notebookAdditionalFields", + ], + optional: true, + }, + }, + async run({ $ }) { + const notebook = await this.evernote.createNotebook(); + $.export("$summary", `Created notebook ${notebook.name}`); + return notebook; + }, +}; diff --git a/components/evernote/actions/update-note/update-note.mjs b/components/evernote/actions/update-note/update-note.mjs new file mode 100644 index 0000000000000..a29b531009160 --- /dev/null +++ b/components/evernote/actions/update-note/update-note.mjs @@ -0,0 +1,31 @@ +import evernote from "../../evernote.app.mjs"; +import { axios } from "@pipedream/platform"; + +export default { + key: "evernote-update-note", + name: "Update Note", + description: "Updates an existing note in Evernote. [See the documentation](https://dev.evernote.com/doc/reference/notestore.html)", + version: "0.0.{{ts}}", + type: "action", + props: { + evernote, + noteId: { + propDefinition: [ + "evernote", + "noteId", + ], + }, + noteUpdateFields: { + propDefinition: [ + "evernote", + "noteUpdateFields", + ], + optional: true, + }, + }, + async run({ $ }) { + const response = await this.evernote.updateNote(); + $.export("$summary", `Note ${this.noteId} updated successfully.`); + return response; + }, +}; diff --git a/components/evernote/evernote.app.mjs b/components/evernote/evernote.app.mjs index 419af9191f9e3..aa9551ff85c51 100644 --- a/components/evernote/evernote.app.mjs +++ b/components/evernote/evernote.app.mjs @@ -1,11 +1,230 @@ +import { axios } from "@pipedream/platform"; + export default { type: "app", app: "evernote", - propDefinitions: {}, + version: "0.0.{{ts}}", + propDefinitions: { + notebookFilter: { + type: "string", + label: "Notebook", + description: "Filter events by notebook", + optional: true, + async options() { + const notebooks = await this.listNotebooks(); + return notebooks.map((notebook) => ({ + label: notebook.name, + value: notebook.id, + })); + }, + }, + tagFilter: { + type: "string", + label: "Tag", + description: "Filter events by tag", + optional: true, + async options() { + const tags = await this.listTags(); + return tags.map((tag) => ({ + label: tag.name, + value: tag.id, + })); + }, + }, + notebookIdFilter: { + type: "string", + label: "Notebook ID Filter", + description: "Filter events by notebook ID", + optional: true, + async options() { + const notebooks = await this.listNotebooks(); + return notebooks.map((notebook) => ({ + label: notebook.name, + value: notebook.id, + })); + }, + }, + noteTitle: { + type: "string", + label: "Title", + description: "Title of the note", + }, + noteContent: { + type: "string", + label: "Content", + description: "Content of the note in ENML format", + }, + noteAdditionalFields: { + type: "string[]", + label: "Additional Fields", + description: "Optional additional fields as JSON objects", + optional: true, + }, + noteId: { + type: "string", + label: "Note ID", + description: "ID of the note to update", + }, + noteUpdateFields: { + type: "string[]", + label: "Fields to Update", + description: "Optional fields to update as JSON objects", + optional: true, + }, + notebookName: { + type: "string", + label: "Notebook Name", + description: "Name of the new notebook", + }, + notebookAdditionalFields: { + type: "string[]", + label: "Additional Fields", + description: "Optional additional fields as JSON objects", + optional: true, + }, + }, methods: { - // this.$auth contains connected account data + // Existing authKeys method authKeys() { console.log(Object.keys(this.$auth)); }, + _baseUrl() { + return "https://api.evernote.com/v1"; + }, + async _makeRequest(opts = {}) { + const { + $, method = "GET", path = "/", headers, ...otherOpts + } = opts; + return axios($ || this, { + method, + url: this._baseUrl() + path, + headers: { + ...headers, + "Authorization": `Bearer ${this.$auth.access_token}`, + "Content-Type": "application/json", + }, + ...otherOpts, + }); + }, + async listNotebooks(opts = {}) { + return this._makeRequest({ + path: "/notebooks", + ...opts, + }); + }, + async listTags(opts = {}) { + return this._makeRequest({ + path: "/tags", + ...opts, + }); + }, + async createNote(opts = {}) { + const additionalFields = this.noteAdditionalFields + ? this.noteAdditionalFields.reduce((acc, field) => { + const parsed = JSON.parse(field); + return { + ...acc, + ...parsed, + }; + }, {}) + : {}; + return this._makeRequest({ + method: "POST", + path: "/notes", + data: { + title: this.noteTitle, + content: this.noteContent, + ...additionalFields, + }, + ...opts, + }); + }, + async updateNote(opts = {}) { + if (!this.noteId) { + throw new Error("Note ID is required to update a note."); + } + const updateFields = this.noteUpdateFields + ? this.noteUpdateFields.reduce((acc, field) => { + const parsed = JSON.parse(field); + return { + ...acc, + ...parsed, + }; + }, {}) + : {}; + return this._makeRequest({ + method: "PUT", + path: `/notes/${this.noteId}`, + data: { + ...updateFields, + }, + ...opts, + }); + }, + async createNotebook(opts = {}) { + const additionalFields = this.notebookAdditionalFields + ? this.notebookAdditionalFields.reduce((acc, field) => { + const parsed = JSON.parse(field); + return { + ...acc, + ...parsed, + }; + }, {}) + : {}; + return this._makeRequest({ + method: "POST", + path: "/notebooks", + data: { + name: this.notebookName, + ...additionalFields, + }, + ...opts, + }); + }, + async emitNewNoteEvent(note) { + this.$emit(note, { + summary: `New note created: ${note.title}`, + id: note.id, + labels: [ + "new_note", + ], + }); + }, + async emitNewTagEvent(tag) { + this.$emit(tag, { + summary: `New tag created: ${tag.name}`, + id: tag.id, + labels: [ + "new_tag", + ], + }); + }, + async emitNewNotebookEvent(notebook) { + this.$emit(notebook, { + summary: `New notebook created: ${notebook.name}`, + id: notebook.id, + labels: [ + "new_notebook", + ], + }); + }, + async paginate(fn, opts = {}) { + let results = []; + let hasMore = true; + let page = 1; + while (hasMore) { + const response = await fn({ + ...opts, + page, + }); + if (!response || response.length === 0) { + hasMore = false; + } else { + results = results.concat(response); + page += 1; + } + } + return results; + }, }, -}; \ No newline at end of file +}; diff --git a/components/evernote/package.json b/components/evernote/package.json index bfcbd790d5563..e100f769dc707 100644 --- a/components/evernote/package.json +++ b/components/evernote/package.json @@ -12,4 +12,4 @@ "publishConfig": { "access": "public" } -} \ No newline at end of file +} diff --git a/components/evernote/sources/new-note/new-note.mjs b/components/evernote/sources/new-note/new-note.mjs new file mode 100644 index 0000000000000..7e48d3a1fafdc --- /dev/null +++ b/components/evernote/sources/new-note/new-note.mjs @@ -0,0 +1,95 @@ +import { + axios, DEFAULT_POLLING_SOURCE_TIMER_INTERVAL, +} from "@pipedream/platform"; +import evernoteApp from "../../evernote.app.mjs"; + +export default { + key: "evernote-new-note", + name: "New Note Created", + description: "Emits a new event when a note is created in Evernote. Optionally filter by notebook. [See the documentation]().", + version: "0.0.{{ts}}", + type: "source", + dedupe: "unique", + props: { + evernote: { + type: "app", + app: "evernote", + }, + db: "$.service.db", + timer: { + type: "$.interface.timer", + default: { + intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL, + }, + }, + notebookFilter: { + propDefinition: [ + evernoteApp, + "notebookFilter", + ], + optional: true, + }, + }, + methods: { + async getLastRunTime() { + return (await this.db.get("lastRun")) || 0; + }, + async setLastRunTime(timestamp) { + await this.db.set("lastRun", timestamp); + }, + async emitNoteEvents(notes) { + for (const note of notes) { + const ts = Date.parse(note.created) || Date.now(); + const eventData = { + id: note.id, + summary: `New note created: ${note.title}`, + ts, + }; + this.$emit(note, eventData); + } + }, + }, + hooks: { + async deploy() { + const lastRun = await this.getLastRunTime(); + const notes = await this.evernote.listNotes({ + notebookId: this.notebookFilter || undefined, + since: lastRun, + limit: 50, + sort: "created", + }); + + const recentNotes = notes.slice(-50).reverse(); + await this.emitNoteEvents(recentNotes); + + if (recentNotes.length > 0) { + const latestNote = recentNotes[recentNotes.length - 1]; + const latestTs = Date.parse(latestNote.created) || Date.now(); + await this.setLastRunTime(latestTs); + } + }, + async activate() { + // No webhook setup needed for polling source + }, + async deactivate() { + // No webhook teardown needed for polling source + }, + }, + async run() { + const lastRun = await this.getLastRunTime(); + const notes = await this.evernote.listNotes({ + notebookId: this.notebookFilter || undefined, + since: lastRun, + limit: 50, + sort: "created", + }); + + await this.emitNoteEvents(notes); + + if (notes.length > 0) { + const latestNote = notes[notes.length - 1]; + const latestTs = Date.parse(latestNote.created) || Date.now(); + await this.setLastRunTime(latestTs); + } + }, +}; diff --git a/components/evernote/sources/new-notebook/new-notebook.mjs b/components/evernote/sources/new-notebook/new-notebook.mjs new file mode 100644 index 0000000000000..4a67a7a060048 --- /dev/null +++ b/components/evernote/sources/new-notebook/new-notebook.mjs @@ -0,0 +1,91 @@ +import { + axios, DEFAULT_POLLING_SOURCE_TIMER_INTERVAL, +} from "@pipedream/platform"; +import evernote from "../../evernote.app.mjs"; + +export default { + key: "evernote-new-notebook", + name: "New Notebook Created", + description: "Emit a new event when a notebook is created in Evernote. [See the documentation](),", + version: "0.0.{{ts}}", + type: "source", + dedupe: "unique", + props: { + evernote, + db: "$.service.db", + timer: { + type: "$.interface.timer", + default: { + intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL, + }, + }, + notebookFilter: { + propDefinition: [ + evernote, + "notebookFilter", + ], + }, + }, + methods: { + async fetchNotebooks() { + const notebooks = await this.evernote.listNotebooks(); + return notebooks; + }, + getStoredNotebooks() { + return this.db.get("notebooks") || []; + }, + storeNotebooks(notebooks) { + this.db.set("notebooks", notebooks); + }, + findNewNotebooks(currentNotebooks, storedNotebooks) { + const storedIds = new Set(storedNotebooks.map((nb) => nb.id)); + return currentNotebooks.filter((nb) => !storedIds.has(nb.id)); + }, + async emitNotebookEvents(newNotebooks) { + for (const notebook of newNotebooks) { + const timestamp = notebook.created + ? Date.parse(notebook.created) + : Date.now(); + this.$emit(notebook, { + id: notebook.id, + summary: `New notebook created: ${notebook.name}`, + ts: timestamp, + }); + } + }, + }, + hooks: { + async deploy() { + const notebooks = await this.fetchNotebooks(); + this.storeNotebooks(notebooks); + + const recentNotebooks = notebooks.slice(-50).reverse(); + for (const notebook of recentNotebooks) { + const timestamp = notebook.created + ? Date.parse(notebook.created) + : Date.now(); + this.$emit(notebook, { + id: notebook.id, + summary: `New notebook created: ${notebook.name}`, + ts: timestamp, + }); + } + }, + async activate() { + // No webhook subscription needed for polling + }, + async deactivate() { + // No webhook subscription to remove + }, + }, + async run() { + const currentNotebooks = await this.fetchNotebooks(); + const storedNotebooks = this.getStoredNotebooks(); + + const newNotebooks = this.findNewNotebooks(currentNotebooks, storedNotebooks); + if (newNotebooks.length > 0) { + await this.emitNotebookEvents(newNotebooks); + this.storeNotebooks(currentNotebooks); + } + }, +}; diff --git a/components/evernote/sources/new-tag/new-tag.mjs b/components/evernote/sources/new-tag/new-tag.mjs new file mode 100644 index 0000000000000..bbb657da62e06 --- /dev/null +++ b/components/evernote/sources/new-tag/new-tag.mjs @@ -0,0 +1,64 @@ +import { + axios, DEFAULT_POLLING_SOURCE_TIMER_INTERVAL, +} from "@pipedream/platform"; +import evernote from "../../evernote.app.mjs"; + +export default { + key: "evernote-new-tag", + name: "New Tag Created", + description: "Emit new event when a new tag is created in Evernote. Useful for tracking new organizational labels. [See the documentation]()", + version: "0.0.{{ts}}", + type: "source", + dedupe: "unique", + props: { + evernote, + db: "$.service.db", + timer: { + type: "$.interface.timer", + default: { + intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL, + }, + }, + tagFilter: { + propDefinition: [ + "evernote", + "tagFilter", + ], + optional: true, + }, + }, + hooks: { + async deploy() { + const tags = await this.evernote.listTags(); + const sortedTags = tags.sort((a, b) => new Date(b.created) - new Date(a.created)); + const recentTags = sortedTags.slice(0, 50); + for (const tag of recentTags) { + this.evernote.emitNewTagEvent(tag); + } + const tagIds = tags.map((tag) => tag.id); + await this.db.set("tagIds", tagIds); + }, + async activate() { + // No activation logic required + }, + async deactivate() { + // No deactivation logic required + }, + }, + async run() { + const currentTags = await this.evernote.listTags(); + const storedTagIds = (await this.db.get("tagIds")) || []; + let newTags = currentTags.filter((tag) => !storedTagIds.includes(tag.id)); + + if (this.tagFilter) { + newTags = newTags.filter((tag) => tag.id === this.tagFilter); + } + + for (const tag of newTags) { + this.evernote.emitNewTagEvent(tag); + } + + const currentTagIds = currentTags.map((tag) => tag.id); + await this.db.set("tagIds", currentTagIds); + }, +}; From 3cbb2bc9e1944c5704eada969458e48484ab702f Mon Sep 17 00:00:00 2001 From: Luan Cazarine Date: Wed, 19 Mar 2025 17:33:52 -0300 Subject: [PATCH 2/3] [Components] evernote #15892 Sources - New Note - New Tag - New Notebook Actions - Create Note - Update Note - Create Notebook --- .../actions/create-note/create-note.mjs | 104 +++++-- .../create-notebook/create-notebook.mjs | 70 +++-- .../actions/update-note/update-note.mjs | 105 ++++++- components/evernote/common/constants.mjs | 1 + components/evernote/common/utils.mjs | 24 ++ components/evernote/evernote.app.mjs | 268 ++++++------------ components/evernote/package.json | 5 +- components/evernote/sources/common/base.mjs | 58 ++++ .../evernote/sources/new-note/new-note.mjs | 118 +++----- .../evernote/sources/new-note/test-event.mjs | 46 +++ .../sources/new-notebook/new-notebook.mjs | 98 ++----- .../sources/new-notebook/test-event.mjs | 45 +++ .../evernote/sources/new-tag/new-tag.mjs | 76 ++--- .../evernote/sources/new-tag/test-event.mjs | 6 + 14 files changed, 586 insertions(+), 438 deletions(-) create mode 100644 components/evernote/common/constants.mjs create mode 100644 components/evernote/common/utils.mjs create mode 100644 components/evernote/sources/common/base.mjs create mode 100644 components/evernote/sources/new-note/test-event.mjs create mode 100644 components/evernote/sources/new-notebook/test-event.mjs create mode 100644 components/evernote/sources/new-tag/test-event.mjs diff --git a/components/evernote/actions/create-note/create-note.mjs b/components/evernote/actions/create-note/create-note.mjs index 83a28d1b5c75a..43caeded0f6cd 100644 --- a/components/evernote/actions/create-note/create-note.mjs +++ b/components/evernote/actions/create-note/create-note.mjs @@ -1,37 +1,107 @@ +import { ConfigurationError } from "@pipedream/platform"; +import { parseObject } from "../../common/utils.mjs"; import evernote from "../../evernote.app.mjs"; -import { axios } from "@pipedream/platform"; export default { key: "evernote-create-note", name: "Create Note", - description: "Creates a new note in Evernote. [See the documentation]()", - version: "0.0.{{ts}}", + description: "Creates a new note in Evernote. [See the documentation](https://dev.evernote.com/doc/reference/NoteStore.html#Fn_NoteStore_createNote)", + version: "0.0.1", type: "action", props: { evernote, - noteTitle: { - propDefinition: [ - "evernote", - "noteTitle", - ], + title: { + type: "string", + label: "Title", + description: "The subject of the note. Can't begin or end with a space.", + }, + content: { + type: "string", + label: "Content", + description: "The XHTML block that makes up the note. This is the canonical form of the note's contents, so will include abstract Evernote tags for internal resource references. A client may create a separate transformed version of this content for internal presentation, but the same canonical bytes should be used for transmission and comparison unless the user chooses to modify their content.", + default: "", + optional: true, + }, + active: { + type: "boolean", + label: "Active", + description: "If the note is available for normal actions and viewing", + optional: true, }, - noteContent: { + notebookGuid: { propDefinition: [ - "evernote", - "noteContent", + evernote, + "notebookGuid", ], + optional: true, }, - noteAdditionalFields: { + tagGuids: { propDefinition: [ - "evernote", - "noteAdditionalFields", + evernote, + "tagGuids", ], optional: true, }, + attributes: { + type: "object", + label: "Attributes", + description: "A list of the attributes for this note. [See the documentation](https://dev.evernote.com/doc/reference/Types.html#Struct_NoteAttributes) for further details.", + optional: true, + }, + noUpdateTitle: { + type: "boolean", + label: "No Update Title", + description: "The client may not update the note's title.", + optional: true, + }, + noUpdateContent: { + type: "boolean", + label: "No Update Content", + description: "The client may not update the note's content. Content includes `content` and `resources`, as well as the related fields `contentHash` and `contentLength`.", + optional: true, + }, + noUpdateEmail: { + type: "boolean", + label: "No Update Email", + description: "The client may not email the note.", + optional: true, + }, + noUpdateShare: { + type: "boolean", + label: "No Update Share", + description: "The client may not share the note with specific recipients.", + optional: true, + }, + noUpdateSharePublicly: { + type: "boolean", + label: "No Update Share Publicly", + description: "The client may not make the note public.", + optional: true, + }, }, async run({ $ }) { - const note = await this.evernote.createNote(); - $.export("$summary", `Created note "${note.title}" with ID ${note.id}`); - return note; + try { + const note = await this.evernote.createNote({ + title: this.title, + content: this.content, + active: this.active, + notebookGuid: this.notebookGuid, + tagGuids: this.tagGuids, + resources: this.resources, + attributes: parseObject(this.attributes), + restrictions: { + noUpdateTitle: this.noUpdateTitle, + noUpdateContent: this.noUpdateContent, + noUpdateEmail: this.noUpdateEmail, + noUpdateShare: this.noUpdateShare, + noUpdateSharePublicly: this.noUpdateSharePublicly, + }, + }); + + $.export("$summary", `Created note "${note.title}" with ID ${note.guid}`); + return note; + } catch ({ parameter }) { + throw new ConfigurationError(parameter); + } }, }; diff --git a/components/evernote/actions/create-notebook/create-notebook.mjs b/components/evernote/actions/create-notebook/create-notebook.mjs index ef2706ac1fd54..56d6c8d83373a 100644 --- a/components/evernote/actions/create-notebook/create-notebook.mjs +++ b/components/evernote/actions/create-notebook/create-notebook.mjs @@ -1,31 +1,69 @@ +import { ConfigurationError } from "@pipedream/platform"; +import { parseObject } from "../../common/utils.mjs"; import evernote from "../../evernote.app.mjs"; -import { axios } from "@pipedream/platform"; export default { key: "evernote-create-notebook", name: "Create Notebook", - description: "Creates a new notebook in Evernote. [See the documentation]()", - version: "0.0.{{ts}}", + description: "Creates a new notebook in Evernote. [See the documentation](https://dev.evernote.com/doc/reference/NoteStore.html#Fn_NoteStore_createNotebook)", + version: "0.0.1", type: "action", props: { evernote, - notebookName: { - propDefinition: [ - "evernote", - "notebookName", - ], + name: { + type: "string", + label: "Name", + description: "The name of the notebook.", }, - notebookAdditionalFields: { - propDefinition: [ - "evernote", - "notebookAdditionalFields", - ], + defaultNotebook: { + type: "boolean", + label: "Default Notebook", + description: "If true, this notebook should be used for new notes whenever the user has not (or cannot) specify a desired target notebook.", optional: true, }, + published: { + type: "boolean", + label: "Published", + description: "If this is set to true, then the Notebook will be accessible either to the public, or for business users to their business, via the 'publishing' or 'businessNotebook' specifications, which must also be set. If this is set to false, the Notebook will not be available to the public (or business).", + optional: true, + reloadProps: true, + }, + publishing: { + type: "object", + label: "Publishing", + description: "If the Notebook has been opened for public access, then this will point to the set of publishing information for the Notebook (URI, description, etc.). A Notebook cannot be published without providing this information, but it will persist for later use if publishing is ever disabled on the Notebook. [See the documentation](https://dev.evernote.com/doc/reference/Types.html#Struct_Publishing) for further details.", + hidden: true, + }, + stack: { + type: "string", + label: "Stack", + description: "If this is set, then the notebook is visually contained within a stack of notebooks with this name. All notebooks in the same account with the same 'stack' field are considered to be in the same stack. Notebooks with no stack set are \"top level\" and not contained within a stack.", + optional: true, + }, + }, + async additionalProps(props) { + props.publishing.hidden = !this.published; + + return {}; }, async run({ $ }) { - const notebook = await this.evernote.createNotebook(); - $.export("$summary", `Created notebook ${notebook.name}`); - return notebook; + try { + const data = { + name: this.name, + defaultNotebook: this.defaultNotebook, + published: this.published, + stack: this.stack, + }; + const publishing = parseObject(this.publishing); + if (publishing) data.publishing = publishing; + const response = await this.evernote.createNotebook({ + ...data, + }); + + $.export("$summary", `Created notebook ${response.name} with ID: ${response.guid}`); + return response; + } catch ({ parameter }) { + throw new ConfigurationError(parameter); + } }, }; diff --git a/components/evernote/actions/update-note/update-note.mjs b/components/evernote/actions/update-note/update-note.mjs index a29b531009160..73578363de24b 100644 --- a/components/evernote/actions/update-note/update-note.mjs +++ b/components/evernote/actions/update-note/update-note.mjs @@ -1,31 +1,116 @@ +import { ConfigurationError } from "@pipedream/platform"; +import { parseObject } from "../../common/utils.mjs"; import evernote from "../../evernote.app.mjs"; -import { axios } from "@pipedream/platform"; export default { key: "evernote-update-note", name: "Update Note", - description: "Updates an existing note in Evernote. [See the documentation](https://dev.evernote.com/doc/reference/notestore.html)", - version: "0.0.{{ts}}", + description: "Updates an existing note in Evernote. [See the documentation](https://dev.evernote.com/doc/reference/NoteStore.html#Fn_NoteStore_updateNote)", + version: "0.0.1", type: "action", props: { evernote, noteId: { propDefinition: [ - "evernote", + evernote, "noteId", ], }, - noteUpdateFields: { + title: { + type: "string", + label: "Title", + description: "The subject of the note. Can't begin or end with a space.", + optional: true, + }, + content: { + type: "string", + label: "Content", + description: "The XHTML block that makes up the note. This is the canonical form of the note's contents, so will include abstract Evernote tags for internal resource references. A client may create a separate transformed version of this content for internal presentation, but the same canonical bytes should be used for transmission and comparison unless the user chooses to modify their content.", + default: "", + optional: true, + }, + active: { + type: "boolean", + label: "Active", + description: "If the note is available for normal actions and viewing", + optional: true, + }, + notebookGuid: { propDefinition: [ - "evernote", - "noteUpdateFields", + evernote, + "notebookGuid", ], optional: true, }, + tagGuids: { + propDefinition: [ + evernote, + "tagGuids", + ], + optional: true, + }, + attributes: { + type: "object", + label: "Attributes", + description: "A list of the attributes for this note. [See the documentation](https://dev.evernote.com/doc/reference/Types.html#Struct_NoteAttributes) for further details.", + optional: true, + }, + noUpdateTitle: { + type: "boolean", + label: "No Update Title", + description: "The client may not update the note's title.", + optional: true, + }, + noUpdateContent: { + type: "boolean", + label: "No Update Content", + description: "The client may not update the note's content. Content includes `content` and `resources`, as well as the related fields `contentHash` and `contentLength`.", + optional: true, + }, + noUpdateEmail: { + type: "boolean", + label: "No Update Email", + description: "The client may not email the note.", + optional: true, + }, + noUpdateShare: { + type: "boolean", + label: "No Update Share", + description: "The client may not share the note with specific recipients.", + optional: true, + }, + noUpdateSharePublicly: { + type: "boolean", + label: "No Update Share Publicly", + description: "The client may not make the note public.", + optional: true, + }, }, async run({ $ }) { - const response = await this.evernote.updateNote(); - $.export("$summary", `Note ${this.noteId} updated successfully.`); - return response; + try { + const response = await this.evernote.updateNote({ + guid: this.noteId, + title: this.title, + content: this.content, + active: this.active, + notebookGuid: this.notebookGuid, + tagGuids: this.tagGuids, + resources: this.resources, + attributes: parseObject(this.attributes), + restrictions: { + noUpdateTitle: this.noUpdateTitle, + noUpdateContent: this.noUpdateContent, + noUpdateEmail: this.noUpdateEmail, + noUpdateShare: this.noUpdateShare, + noUpdateSharePublicly: this.noUpdateSharePublicly, + }, + }); + $.export("$summary", `Note ${this.noteId} updated successfully.`); + return response; + } catch ({ + parameter, message, + }) { + throw new ConfigurationError(message || parameter); + } }, }; diff --git a/components/evernote/common/constants.mjs b/components/evernote/common/constants.mjs new file mode 100644 index 0000000000000..ea830c15a04cb --- /dev/null +++ b/components/evernote/common/constants.mjs @@ -0,0 +1 @@ +export const LIMIT = 100; diff --git a/components/evernote/common/utils.mjs b/components/evernote/common/utils.mjs new file mode 100644 index 0000000000000..dcc9cc61f6f41 --- /dev/null +++ b/components/evernote/common/utils.mjs @@ -0,0 +1,24 @@ +export const parseObject = (obj) => { + if (!obj) return undefined; + + if (Array.isArray(obj)) { + return obj.map((item) => { + if (typeof item === "string") { + try { + return JSON.parse(item); + } catch (e) { + return item; + } + } + return item; + }); + } + if (typeof obj === "string") { + try { + return JSON.parse(obj); + } catch (e) { + return obj; + } + } + return obj; +}; diff --git a/components/evernote/evernote.app.mjs b/components/evernote/evernote.app.mjs index aa9551ff85c51..cdb68588f1186 100644 --- a/components/evernote/evernote.app.mjs +++ b/components/evernote/evernote.app.mjs @@ -1,230 +1,126 @@ -import { axios } from "@pipedream/platform"; +import Evernote from "evernote"; +import { LIMIT } from "./common/constants.mjs"; export default { type: "app", app: "evernote", - version: "0.0.{{ts}}", propDefinitions: { - notebookFilter: { + noteId: { + type: "string", + label: "Note ID", + description: "ID of the note to update", + async options({ page }) { + const { notes } = await this.listNotes({ + offset: LIMIT * page, + maxNotes: LIMIT, + }); + return notes.map((note) => ({ + label: note.title, + value: note.guid, + })); + }, + }, + notebookGuid: { type: "string", - label: "Notebook", - description: "Filter events by notebook", - optional: true, + label: "Notebook ID", + description: "The notebook ID that contains this note. If no Notebook ID is provided, the default notebook will be used instead.", async options() { const notebooks = await this.listNotebooks(); return notebooks.map((notebook) => ({ label: notebook.name, - value: notebook.id, + value: notebook.guid, })); }, }, - tagFilter: { - type: "string", - label: "Tag", - description: "Filter events by tag", - optional: true, + tagGuids: { + type: "string[]", + label: "Tag IDs", + description: "A list of tag IDs that are applied to this note.", async options() { const tags = await this.listTags(); return tags.map((tag) => ({ label: tag.name, - value: tag.id, + value: tag.guid, })); }, }, - notebookIdFilter: { - type: "string", - label: "Notebook ID Filter", - description: "Filter events by notebook ID", - optional: true, - async options() { - const notebooks = await this.listNotebooks(); - return notebooks.map((notebook) => ({ - label: notebook.name, - value: notebook.id, - })); - }, - }, - noteTitle: { - type: "string", - label: "Title", - description: "Title of the note", - }, - noteContent: { - type: "string", - label: "Content", - description: "Content of the note in ENML format", - }, - noteAdditionalFields: { - type: "string[]", - label: "Additional Fields", - description: "Optional additional fields as JSON objects", - optional: true, - }, - noteId: { - type: "string", - label: "Note ID", - description: "ID of the note to update", - }, - noteUpdateFields: { - type: "string[]", - label: "Fields to Update", - description: "Optional fields to update as JSON objects", - optional: true, - }, - notebookName: { - type: "string", - label: "Notebook Name", - description: "Name of the new notebook", - }, - notebookAdditionalFields: { - type: "string[]", - label: "Additional Fields", - description: "Optional additional fields as JSON objects", - optional: true, - }, }, methods: { - // Existing authKeys method - authKeys() { - console.log(Object.keys(this.$auth)); - }, _baseUrl() { return "https://api.evernote.com/v1"; }, - async _makeRequest(opts = {}) { - const { - $, method = "GET", path = "/", headers, ...otherOpts - } = opts; - return axios($ || this, { - method, - url: this._baseUrl() + path, - headers: { - ...headers, - "Authorization": `Bearer ${this.$auth.access_token}`, - "Content-Type": "application/json", - }, - ...otherOpts, + client() { + const client = new Evernote.Client({ + token: this.$auth.developer_token, + sandbox: false, }); + return client.getNoteStore(); }, - async listNotebooks(opts = {}) { - return this._makeRequest({ - path: "/notebooks", - ...opts, - }); + async list({ method }) { + const noteStore = await this.client(); + return await noteStore[method](); }, - async listTags(opts = {}) { - return this._makeRequest({ - path: "/tags", + async post({ + method, ...opts + }) { + const noteStore = await this.client(); + return await noteStore[method]({ ...opts, }); }, - async createNote(opts = {}) { - const additionalFields = this.noteAdditionalFields - ? this.noteAdditionalFields.reduce((acc, field) => { - const parsed = JSON.parse(field); - return { - ...acc, - ...parsed, - }; - }, {}) - : {}; - return this._makeRequest({ - method: "POST", - path: "/notes", - data: { - title: this.noteTitle, - content: this.noteContent, - ...additionalFields, - }, - ...opts, + async listNotes({ + maxNotes, offset, + }) { + const noteStore = await this.client(); + return await noteStore.findNotesMetadata( + new Evernote.NoteStore.NoteFilter({ + order: "created", + ascending: false, + }), + offset, + maxNotes, + new Evernote.NoteStore.NotesMetadataResultSpec({ + includeTitle: true, + includeContentLength: true, + includeCreated: true, + includeUpdated: true, + includeDeleted: true, + includeUpdateSequenceNum: true, + includeNotebookGuid: true, + includeTagGuids: true, + includeAttributes: true, + includeLargestResourceMime: true, + includeLargestResourceSize: true, + }), + ); + }, + listNotebooks() { + return this.list({ + method: "listNotebooks", }); }, - async updateNote(opts = {}) { - if (!this.noteId) { - throw new Error("Note ID is required to update a note."); - } - const updateFields = this.noteUpdateFields - ? this.noteUpdateFields.reduce((acc, field) => { - const parsed = JSON.parse(field); - return { - ...acc, - ...parsed, - }; - }, {}) - : {}; - return this._makeRequest({ - method: "PUT", - path: `/notes/${this.noteId}`, - data: { - ...updateFields, - }, - ...opts, + listTags() { + return this.list({ + method: "listTags", }); }, - async createNotebook(opts = {}) { - const additionalFields = this.notebookAdditionalFields - ? this.notebookAdditionalFields.reduce((acc, field) => { - const parsed = JSON.parse(field); - return { - ...acc, - ...parsed, - }; - }, {}) - : {}; - return this._makeRequest({ - method: "POST", - path: "/notebooks", - data: { - name: this.notebookName, - ...additionalFields, - }, + createNote(opts = {}) { + return this.post({ + method: "createNote", ...opts, }); }, - async emitNewNoteEvent(note) { - this.$emit(note, { - summary: `New note created: ${note.title}`, - id: note.id, - labels: [ - "new_note", - ], - }); - }, - async emitNewTagEvent(tag) { - this.$emit(tag, { - summary: `New tag created: ${tag.name}`, - id: tag.id, - labels: [ - "new_tag", - ], + createNotebook(opts = {}) { + return this.post({ + method: "createNotebook", + ...opts, }); }, - async emitNewNotebookEvent(notebook) { - this.$emit(notebook, { - summary: `New notebook created: ${notebook.name}`, - id: notebook.id, - labels: [ - "new_notebook", - ], + updateNote(opts = {}) { + return this.post({ + method: "updateNote", + ...opts, }); }, - async paginate(fn, opts = {}) { - let results = []; - let hasMore = true; - let page = 1; - while (hasMore) { - const response = await fn({ - ...opts, - page, - }); - if (!response || response.length === 0) { - hasMore = false; - } else { - results = results.concat(response); - page += 1; - } - } - return results; - }, }, }; diff --git a/components/evernote/package.json b/components/evernote/package.json index e100f769dc707..e72b4526779a6 100644 --- a/components/evernote/package.json +++ b/components/evernote/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/evernote", - "version": "0.0.1", + "version": "0.1.0", "description": "Pipedream Evernote Components", "main": "evernote.app.mjs", "keywords": [ @@ -11,5 +11,8 @@ "author": "Pipedream (https://pipedream.com/)", "publishConfig": { "access": "public" + }, + "dependencies": { + "evernote": "^2.0.5" } } diff --git a/components/evernote/sources/common/base.mjs b/components/evernote/sources/common/base.mjs new file mode 100644 index 0000000000000..9b56544b87eba --- /dev/null +++ b/components/evernote/sources/common/base.mjs @@ -0,0 +1,58 @@ +import { DEFAULT_POLLING_SOURCE_TIMER_INTERVAL } from "@pipedream/platform"; +import evernote from "../../evernote.app.mjs"; + +export default { + props: { + evernote, + db: "$.service.db", + timer: { + type: "$.interface.timer", + default: { + intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL, + }, + }, + }, + methods: { + _getLastData() { + return this.db.get("lastData") || this.getDefaultData(); + }, + _setLastData(lastData) { + this.db.set("lastData", lastData); + }, + getDefaultData() { + return 0; + }, + checkBreak() { + return false; + }, + prepareResults(responseArray) { + return responseArray; + }, + async emitEvent(maxResults = false) { + const lastData = this._getLastData(); + let responseArray = await this.getData(lastData); + + responseArray = this.prepareResults(responseArray, lastData, maxResults); + + if (responseArray.length) { + this._setLastData(this.lastData(responseArray)); + } + + for (const item of responseArray) { + this.$emit(item, { + id: item.guid, + summary: this.getSummary(item), + ts: Date.parse(item.created || item.serviceCreated || new Date()), + }); + } + }, + }, + hooks: { + async deploy() { + await this.emitEvent(25); + }, + }, + async run() { + await this.emitEvent(); + }, +}; diff --git a/components/evernote/sources/new-note/new-note.mjs b/components/evernote/sources/new-note/new-note.mjs index 7e48d3a1fafdc..5d943271758f2 100644 --- a/components/evernote/sources/new-note/new-note.mjs +++ b/components/evernote/sources/new-note/new-note.mjs @@ -1,95 +1,51 @@ -import { - axios, DEFAULT_POLLING_SOURCE_TIMER_INTERVAL, -} from "@pipedream/platform"; -import evernoteApp from "../../evernote.app.mjs"; +import { LIMIT } from "../../common/constants.mjs"; +import common from "../common/base.mjs"; +import sampleEmit from "./test-event.mjs"; export default { + ...common, key: "evernote-new-note", name: "New Note Created", - description: "Emits a new event when a note is created in Evernote. Optionally filter by notebook. [See the documentation]().", - version: "0.0.{{ts}}", + description: "Emit new event when a note is created in Evernote.", + version: "0.0.1", type: "source", dedupe: "unique", - props: { - evernote: { - type: "app", - app: "evernote", - }, - db: "$.service.db", - timer: { - type: "$.interface.timer", - default: { - intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL, - }, - }, - notebookFilter: { - propDefinition: [ - evernoteApp, - "notebookFilter", - ], - optional: true, - }, - }, methods: { - async getLastRunTime() { - return (await this.db.get("lastRun")) || 0; - }, - async setLastRunTime(timestamp) { - await this.db.set("lastRun", timestamp); - }, - async emitNoteEvents(notes) { - for (const note of notes) { - const ts = Date.parse(note.created) || Date.now(); - const eventData = { - id: note.id, - summary: `New note created: ${note.title}`, - ts, - }; - this.$emit(note, eventData); - } - }, - }, - hooks: { - async deploy() { - const lastRun = await this.getLastRunTime(); - const notes = await this.evernote.listNotes({ - notebookId: this.notebookFilter || undefined, - since: lastRun, - limit: 50, - sort: "created", - }); + ...common.methods, + getSummary(item) { + return `New note created: ${item.title || item.guid}`; + }, + async getData(lastData) { + const responseArray = []; + let hasMore = true; + let page = 0; - const recentNotes = notes.slice(-50).reverse(); - await this.emitNoteEvents(recentNotes); + do { + const { notes } = await this.evernote.listNotes({ + offset: LIMIT * page, + maxNotes: LIMIT, + }); + for (const note of notes) { + if (note.created <= lastData) break; + responseArray.push(note); + } + page++; + hasMore = notes.length; + } while (hasMore); - if (recentNotes.length > 0) { - const latestNote = recentNotes[recentNotes.length - 1]; - const latestTs = Date.parse(latestNote.created) || Date.now(); - await this.setLastRunTime(latestTs); - } + return responseArray; }, - async activate() { - // No webhook setup needed for polling source + prepareResults(results, maxResults) { + if (results.length) { + if (maxResults && (results.length > maxResults)) { + results.length = maxResults; + } + } + return results.reverse(); }, - async deactivate() { - // No webhook teardown needed for polling source + lastData(results) { + return results.map((item) => item.guid); }, }, - async run() { - const lastRun = await this.getLastRunTime(); - const notes = await this.evernote.listNotes({ - notebookId: this.notebookFilter || undefined, - since: lastRun, - limit: 50, - sort: "created", - }); - - await this.emitNoteEvents(notes); - - if (notes.length > 0) { - const latestNote = notes[notes.length - 1]; - const latestTs = Date.parse(latestNote.created) || Date.now(); - await this.setLastRunTime(latestTs); - } - }, + sampleEmit, }; diff --git a/components/evernote/sources/new-note/test-event.mjs b/components/evernote/sources/new-note/test-event.mjs new file mode 100644 index 0000000000000..6c4f7457f87bf --- /dev/null +++ b/components/evernote/sources/new-note/test-event.mjs @@ -0,0 +1,46 @@ +export default { + "course_title": "Class title", + "course_subject": "Course subject", + "course_level": "Course level", + "school_id": 16385, + "start_date": "2024-10-21", + "end_date": "2024-10-28", + "recurrence": "weekly", + "payment_frequency": "free", + "id": 153319, + "photo": null, + "payment_fee": "0", + "course_description": "", + "course_full_title": "Class title [Online Lesson]", + "created": "2024-10-17 18:20:13", + "modified": "2024-10-17 18:20:15", + "color": "color1", + "course_started": false, + "course_ended": false, + "course_status": 1, + "num_enrolled_students": 0, + "teachers": "66792", + "classrooms": "39627", + "billing_month_start_date": "2024-10-01", + "billing_month_end_date": "2024-10-01", + "custom_payments": null, + "archived": false, + "awarding_body": "", + "course_code": "", + "book_code": "", + "total_lessons": 2, + "total_lessons_hrs": "02:00", + "skype_meeting_link": "", + "year": null, + "credit_hours": "", + "class_type": "", + "is_ended": null, + "teacher_hourly_fees": null, + "is_booking_class": false, + "subscription_plan_id": null, + "is_stripe_sub_allow": 0, + "created_by": 66114, + "modified_by": 66114, + "exception_dates": null, + "removed_exception_dates": null +} \ No newline at end of file diff --git a/components/evernote/sources/new-notebook/new-notebook.mjs b/components/evernote/sources/new-notebook/new-notebook.mjs index 4a67a7a060048..d8e525ba9c820 100644 --- a/components/evernote/sources/new-notebook/new-notebook.mjs +++ b/components/evernote/sources/new-notebook/new-notebook.mjs @@ -1,91 +1,37 @@ -import { - axios, DEFAULT_POLLING_SOURCE_TIMER_INTERVAL, -} from "@pipedream/platform"; -import evernote from "../../evernote.app.mjs"; +import common from "../common/base.mjs"; +import sampleEmit from "./test-event.mjs"; export default { + ...common, key: "evernote-new-notebook", name: "New Notebook Created", - description: "Emit a new event when a notebook is created in Evernote. [See the documentation](),", - version: "0.0.{{ts}}", + description: "Emit new event when a notebook is created in Evernote.", + version: "0.0.1", type: "source", dedupe: "unique", - props: { - evernote, - db: "$.service.db", - timer: { - type: "$.interface.timer", - default: { - intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL, - }, - }, - notebookFilter: { - propDefinition: [ - evernote, - "notebookFilter", - ], - }, - }, methods: { - async fetchNotebooks() { - const notebooks = await this.evernote.listNotebooks(); - return notebooks; + ...common.methods, + getSummary(item) { + return `New notebook created: ${item.name}`; }, - getStoredNotebooks() { - return this.db.get("notebooks") || []; + getData() { + return this.evernote.listNotebooks(); }, - storeNotebooks(notebooks) { - this.db.set("notebooks", notebooks); - }, - findNewNotebooks(currentNotebooks, storedNotebooks) { - const storedIds = new Set(storedNotebooks.map((nb) => nb.id)); - return currentNotebooks.filter((nb) => !storedIds.has(nb.id)); - }, - async emitNotebookEvents(newNotebooks) { - for (const notebook of newNotebooks) { - const timestamp = notebook.created - ? Date.parse(notebook.created) - : Date.now(); - this.$emit(notebook, { - id: notebook.id, - summary: `New notebook created: ${notebook.name}`, - ts: timestamp, - }); - } - }, - }, - hooks: { - async deploy() { - const notebooks = await this.fetchNotebooks(); - this.storeNotebooks(notebooks); + prepareResults(results, lastData, maxResults) { + results = results + .filter((item) => item.serviceCreated > lastData) + .sort((a, b) => b.serviceCreated - a.serviceCreated); - const recentNotebooks = notebooks.slice(-50).reverse(); - for (const notebook of recentNotebooks) { - const timestamp = notebook.created - ? Date.parse(notebook.created) - : Date.now(); - this.$emit(notebook, { - id: notebook.id, - summary: `New notebook created: ${notebook.name}`, - ts: timestamp, - }); + if (results.length) { + if (maxResults && (results.length > maxResults)) { + results.length = maxResults; + } } + return results.reverse(); }, - async activate() { - // No webhook subscription needed for polling - }, - async deactivate() { - // No webhook subscription to remove + lastData(results) { + return results[results.length - 1].serviceCreated; }, }, - async run() { - const currentNotebooks = await this.fetchNotebooks(); - const storedNotebooks = this.getStoredNotebooks(); - - const newNotebooks = this.findNewNotebooks(currentNotebooks, storedNotebooks); - if (newNotebooks.length > 0) { - await this.emitNotebookEvents(newNotebooks); - this.storeNotebooks(currentNotebooks); - } - }, + sampleEmit, }; diff --git a/components/evernote/sources/new-notebook/test-event.mjs b/components/evernote/sources/new-notebook/test-event.mjs new file mode 100644 index 0000000000000..7886065264f26 --- /dev/null +++ b/components/evernote/sources/new-notebook/test-event.mjs @@ -0,0 +1,45 @@ +export default { + guid: 'c0c123ca-4ec7-08a4-b6bb-9a68ce4c321a', + name: 'Notebook Name', + updateSequenceNum: 11, + defaultNotebook: false, + serviceCreated: 1742321666000, + serviceUpdated: 1742321666000, + publishing: null, + published: null, + stack: null, + sharedNotebookIds: null, + sharedNotebooks: null, + businessNotebook: null, + contact: null, + restrictions: { + noReadNotes: null, + noCreateNotes: null, + noUpdateNotes: null, + noExpungeNotes: null, + noShareNotes: null, + noEmailNotes: null, + noSendMessageToRecipients: null, + noUpdateNotebook: null, + noExpungeNotebook: null, + noSetDefaultNotebook: null, + noSetNotebookStack: null, + noPublishToPublic: null, + noPublishToBusinessLibrary: true, + noCreateTags: null, + noUpdateTags: null, + noExpungeTags: null, + noSetParentTag: null, + noCreateSharedNotebooks: null, + updateWhichSharedNotebookRestrictions: null, + expungeWhichSharedNotebookRestrictions: null, + noShareNotesWithBusiness: true, + noRenameNotebook: null + }, + recipientSettings: { + reminderNotifyEmail: true, + reminderNotifyInApp: true, + inMyList: true, + stack: null + } +} \ No newline at end of file diff --git a/components/evernote/sources/new-tag/new-tag.mjs b/components/evernote/sources/new-tag/new-tag.mjs index bbb657da62e06..34e5b11d44ea1 100644 --- a/components/evernote/sources/new-tag/new-tag.mjs +++ b/components/evernote/sources/new-tag/new-tag.mjs @@ -1,64 +1,38 @@ -import { - axios, DEFAULT_POLLING_SOURCE_TIMER_INTERVAL, -} from "@pipedream/platform"; -import evernote from "../../evernote.app.mjs"; +import common from "../common/base.mjs"; +import sampleEmit from "./test-event.mjs"; export default { + ...common, key: "evernote-new-tag", name: "New Tag Created", - description: "Emit new event when a new tag is created in Evernote. Useful for tracking new organizational labels. [See the documentation]()", - version: "0.0.{{ts}}", + description: "Emit new event when a new tag is created in Evernote. Useful for tracking new organizational labels.", + version: "0.0.1", type: "source", dedupe: "unique", - props: { - evernote, - db: "$.service.db", - timer: { - type: "$.interface.timer", - default: { - intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL, - }, + methods: { + ...common.methods, + getSummary(item) { + return `New tag created: ${item.name}`; }, - tagFilter: { - propDefinition: [ - "evernote", - "tagFilter", - ], - optional: true, + getData() { + return this.evernote.listTags(); }, - }, - hooks: { - async deploy() { - const tags = await this.evernote.listTags(); - const sortedTags = tags.sort((a, b) => new Date(b.created) - new Date(a.created)); - const recentTags = sortedTags.slice(0, 50); - for (const tag of recentTags) { - this.evernote.emitNewTagEvent(tag); - } - const tagIds = tags.map((tag) => tag.id); - await this.db.set("tagIds", tagIds); + getDefaultData() { + return []; }, - async activate() { - // No activation logic required + prepareResults(results, lastData, maxResults) { + results = results.filter((item) => !lastData.includes(item.guid)); + + if (results.length) { + if (maxResults && (results.length > maxResults)) { + results.length = maxResults; + } + } + return results; }, - async deactivate() { - // No deactivation logic required + lastData(results) { + return results[results.length - 1].created; }, }, - async run() { - const currentTags = await this.evernote.listTags(); - const storedTagIds = (await this.db.get("tagIds")) || []; - let newTags = currentTags.filter((tag) => !storedTagIds.includes(tag.id)); - - if (this.tagFilter) { - newTags = newTags.filter((tag) => tag.id === this.tagFilter); - } - - for (const tag of newTags) { - this.evernote.emitNewTagEvent(tag); - } - - const currentTagIds = currentTags.map((tag) => tag.id); - await this.db.set("tagIds", currentTagIds); - }, + sampleEmit, }; diff --git a/components/evernote/sources/new-tag/test-event.mjs b/components/evernote/sources/new-tag/test-event.mjs new file mode 100644 index 0000000000000..84df8cc815506 --- /dev/null +++ b/components/evernote/sources/new-tag/test-event.mjs @@ -0,0 +1,6 @@ +export default { + "guid": "c6a42313-443c-907d-975c-444323291f0a", + "name": "Tag Name", + "parentGuid": null, + "updateSequenceNum": 43 +} \ No newline at end of file From 76f360ac5cb6d01961ecceea9895ea4ecc6a12df Mon Sep 17 00:00:00 2001 From: Luan Cazarine Date: Wed, 19 Mar 2025 17:35:04 -0300 Subject: [PATCH 3/3] pnpm update --- pnpm-lock.yaml | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 94cfeaf239cd4..833950bff214b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4166,7 +4166,11 @@ importers: specifier: ^3.0.3 version: 3.0.3 - components/evernote: {} + components/evernote: + dependencies: + evernote: + specifier: ^2.0.5 + version: 2.0.5 components/eversign: dependencies: @@ -22353,6 +22357,9 @@ packages: resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} engines: {node: '>=0.8.x'} + evernote@2.0.5: + resolution: {integrity: sha512-DuOk3t9HKwkxZBaZU1Mz8vmZSEM2LVI3eLdML90Is3+8WlPwpYcLeo4z+eklT8NUGD3GA6oOnlP+6e0z0rDX1Q==} + execa@1.0.0: resolution: {integrity: sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==} engines: {node: '>=6'} @@ -25641,6 +25648,9 @@ packages: oauth4webapi@3.1.4: resolution: {integrity: sha512-eVfN3nZNbok2s/ROifO0UAc5G8nRoLSbrcKJ09OqmucgnhXEfdIQOR4gq1eJH1rN3gV7rNw62bDEgftsgFtBEg==} + oauth@0.9.15: + resolution: {integrity: sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA==} + object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} @@ -39485,6 +39495,10 @@ snapshots: events@3.3.0: {} + evernote@2.0.5: + dependencies: + oauth: 0.9.15 + execa@1.0.0: dependencies: cross-spawn: 6.0.6 @@ -44047,6 +44061,8 @@ snapshots: oauth4webapi@3.1.4: {} + oauth@0.9.15: {} + object-assign@4.1.1: {} object-hash@3.0.0: {}